LCOV - code coverage report
Current view: top level - cltools - PdbRenumber.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 52 55 94.5 %
Date: 2025-04-08 21:11:17 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2018-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "CLTool.h"
      23             : #include "core/CLToolRegister.h"
      24             : #include "tools/Tools.h"
      25             : #include "core/ActionRegister.h"
      26             : #include "tools/IFile.h"
      27             : #include "tools/OFile.h"
      28             : #include "tools/h36.h"
      29             : #include <cstdio>
      30             : #include <string>
      31             : #include <vector>
      32             : #include <array>
      33             : #include <limits>
      34             : 
      35             : namespace PLMD {
      36             : namespace cltools {
      37             : 
      38             : //+PLUMEDOC TOOLS pdbrenumber
      39             : /*
      40             : Modify atom numbers in a PDB file, possibly using hybrid-36 coding.
      41             : 
      42             : When reading a PDB files, PLUMED honors the serial number of each atom.
      43             : This command can be used to process a PDB file and change the atom serial numbers.
      44             : Notice that the resulting list might have gaps. It is however fundamental
      45             : that the atom numbers in your PDB file correspond to those used within the MD code.
      46             : 
      47             : Notice, if the serial number of an atom is greater than 99999, it has to be
      48             : written in [hybrid 36](http://cci.lbl.gov/hybrid_36/) notation (see [PDB2CONSTANT](PDB2CONSTANT.md) ).
      49             : The main use for this command is to produce files where atoms are numbered using the hybrid-36 convention.
      50             : 
      51             : The output PDB file is identical to the input PDB file, except for the atom number
      52             : field.
      53             : The rest of the line is written unchanged
      54             : to the output file, even if it is incorrectly formatted. Residue numbers are not touched,
      55             : and atom numbers in the input file are ignored.
      56             : 
      57             : ## Examples
      58             : 
      59             : By default, pdbreader  just sets the numbers progressively starting from 1.
      60             : For instance the following command:
      61             : 
      62             : ```plumed
      63             : plumed pdbrenumber --ipdb input.pdb --opdb output.pdb
      64             : ```
      65             : 
      66             : will copy file `input.pdb` to `output.pdb` replacing all the serial atoms with
      67             : increasing numbers starting from one. Atoms that have an index that is greater than 99999 will be written
      68             : in the output PDB file in hybrid-36 code.
      69             : 
      70             : It is possible to set a different serial number for the first atom, letting the
      71             : following ones grow by one at each line. Here for instance the first atom
      72             : will be assigned serial 1000, the second serial 1001, etc:
      73             : 
      74             : ```plumed
      75             : plumed pdbrenumber --ipdb input.pdb --opdb output.pdb --firstatomnumber 1000
      76             : ```
      77             : 
      78             : If the first atom number is $>99999$, it should be given as a decimal number (not in hybrid-36 code).
      79             : However, numbers $>99999$ in the output PDB file will be written in hybrid-36 format.
      80             : 
      81             : As an alternative, one can provide a list of atoms numbers with one number per line in an auxiliary file
      82             : as has been done with the following example.
      83             : 
      84             : ```plumed
      85             : plumed pdbrenumber --ipdb input.pdb --opdb output.pdb --atomnumbers list.txt
      86             : ```
      87             : 
      88             : The `list.txt` file that is used above might be something like this
      89             : 
      90             : ````
      91             : 120000
      92             : 120001
      93             : 120002
      94             : 1
      95             : 2
      96             : 3
      97             : ````
      98             : 
      99             : Numbers $>99999$ in the list should be provided as decimal numbers (not in hybrid-36 format).
     100             : However, numbers $>999994 in the output PDB file will be written in hybrid-36 mat.
     101             : Notice that there should be at least as many lines in `list.txt` as there atoms in the PDB file.
     102             : Additional lines in `list.txt` will just be ignored.
     103             : 
     104             : */
     105             : //+ENDPLUMEDOC
     106             : 
     107             : class PdbRenumber:
     108             :   public CLTool {
     109             : public:
     110             :   static void registerKeywords( Keywords& keys );
     111             :   explicit PdbRenumber(const CLToolOptions& co );
     112             :   int main(FILE* in, FILE*out,Communicator& pc) override;
     113           5 :   std::string description()const override {
     114           5 :     return "Modify atom numbers in a PDB, possibly using hybrid-36 coding";
     115             :   }
     116             : };
     117             : 
     118       16262 : PLUMED_REGISTER_CLTOOL(PdbRenumber,"pdbrenumber")
     119             : 
     120        5418 : void PdbRenumber::registerKeywords( Keywords& keys ) {
     121        5418 :   CLTool::registerKeywords( keys );
     122        5418 :   keys.add("compulsory","--ipdb","specify the name of the input PDB file");
     123        5418 :   keys.add("compulsory","--opdb","specify the name of the output PDB file");
     124        5418 :   keys.add("optional","--firstatomnumber","specify the desired serial number of the first atom of the output file");
     125        5418 :   keys.add("optional","--atomnumbers","specify the desired serial numbers of the atoms of the output file using a separate list");
     126        5418 : }
     127             : 
     128           8 : PdbRenumber::PdbRenumber(const CLToolOptions& co ):
     129           8 :   CLTool(co) {
     130           8 :   inputdata=commandline;
     131           8 : }
     132             : 
     133           3 : int PdbRenumber::main(FILE* in, FILE*out,Communicator& pc) {
     134             : 
     135             :   std::string ipdb;
     136           6 :   parse("--ipdb",ipdb);
     137             :   std::string opdb;
     138           3 :   parse("--opdb",opdb);
     139             : 
     140           3 :   unsigned iat=0;
     141             : 
     142           6 :   parse("--firstatomnumber",iat);
     143             : 
     144             :   std::string atomnumbers;
     145           6 :   parse("--atomnumbers",atomnumbers);
     146             : 
     147           3 :   plumed_assert(ipdb.length()>0) << "please specify the input PDB with --ipdb";
     148           3 :   plumed_assert(opdb.length()>0) << "please specify the onput PDB with --opdb";
     149             :   std::fprintf(out,"  with input PDB: %s\n",ipdb.c_str());
     150             :   std::fprintf(out,"  with output PDB: %s\n",opdb.c_str());
     151             : 
     152             :   std::vector<unsigned> serials;
     153             : 
     154           3 :   if(atomnumbers.length()>0) {
     155           1 :     plumed_assert(iat==0) << "it is not possible to use both --atomnumbers and --firstatomnumber";
     156             :     std::fprintf(out,"  reading atom numbers from file %s\n",atomnumbers.c_str());
     157           1 :     IFile ifile;
     158           1 :     ifile.open(atomnumbers);
     159             :     std::string line;
     160           7 :     while(ifile.getline(line)) {
     161             :       int i;
     162           6 :       Tools::convert(line,i);
     163           6 :       serials.push_back(i);
     164             :     }
     165           1 :   } else {
     166           2 :     if(iat==0) {
     167           1 :       iat=1;
     168             :     }
     169           2 :     std::fprintf(out,"  with atoms starting from %u\n",iat);
     170             :   }
     171             : 
     172           3 :   IFile ifile;
     173           3 :   ifile.open(ipdb);
     174             : 
     175           3 :   OFile ofile;
     176           3 :   ofile.open(opdb);
     177             : 
     178             :   std::string line;
     179      100112 :   while(ifile.getline(line)) {
     180      100109 :     std::string record=line.substr(0,6);
     181      100109 :     Tools::trim(record);
     182             : 
     183      100109 :     if(record=="ATOM" || record=="HETATM") {
     184             :       std::array<char,6> at;
     185      100109 :       unsigned ii=iat;
     186      100109 :       if(serials.size()>0) {
     187           6 :         plumed_assert(iat<serials.size()) << "there are more atoms in the PDB than serials in the file";
     188           6 :         ii=serials[iat];
     189             :       }
     190      100109 :       const char* msg = h36::hy36encode(5,ii,&at[0]);
     191      100109 :       plumed_assert(msg==nullptr) << msg;
     192      100109 :       at[5]=0;
     193      200218 :       ofile << line.substr(0,6) << &at[0] << line.substr(11) << "\n";
     194      100109 :       iat++;
     195             :     } else {
     196           0 :       if(record=="END" || record=="ENDMDL") {
     197           0 :         iat=0;
     198             :       }
     199           0 :       ofile << line << "\n";
     200             :     }
     201             :   }
     202             : 
     203           3 :   return 0;
     204           3 : }
     205             : }
     206             : 
     207             : } // End of namespace

Generated by: LCOV version 1.16