Coverage Report

Created: 2025-08-24 07:05

/src/openbabel/src/formats/pcmodelformat.cpp
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************************
2
Copyright (C) 2005-2006 by Geoffrey R. Hutchison
3
4
Thanks to Kevin Gilbert from Serena Software for documentation and examples!
5
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation version 2 of the License.
9
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14
***********************************************************************/
15
16
#include <openbabel/obmolecformat.h>
17
#include <openbabel/mol.h>
18
#include <openbabel/atom.h>
19
#include <openbabel/elements.h>
20
#include <openbabel/data.h>
21
#include <openbabel/obiter.h>
22
#include <openbabel/bond.h>
23
#include <cstdlib>
24
25
26
using namespace std;
27
namespace OpenBabel
28
{
29
30
  class PCModelFormat : public OBMoleculeFormat
31
  {
32
  public:
33
    //Register this format type ID
34
    PCModelFormat()
35
6
    {
36
6
      OBConversion::RegisterFormat("pcm", this);
37
6
    }
38
39
    const char* Description() override //required
40
0
    {
41
0
      return
42
0
        "PCModel Format\n"
43
0
        "No comments yet\n";
44
0
    }
45
46
    //Flags() can return be any the following combined by | or be omitted if none apply
47
    // NOTREADABLE  READONEONLY  NOTWRITABLE  WRITEONEONLY
48
    //  virtual unsigned int Flags()
49
    //  {
50
    //    return NOTREADABLE;
51
    //  };
52
53
    const char* SpecificationURL() override
54
0
    { return "http://www.serenasoft.com/"; }  // optional
55
56
    //*** This section identical for most OBMol conversions ***
57
    ////////////////////////////////////////////////////
58
    /// The "API" interface functions
59
    bool ReadMolecule(OBBase* pOb, OBConversion* pConv) override;
60
    bool WriteMolecule(OBBase* pOb, OBConversion* pConv) override;
61
  };
62
  //***
63
64
  //Make an instance of the format class
65
  PCModelFormat thePCModelFormat;
66
67
  /////////////////////////////////////////////////////////////////
68
  bool PCModelFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
69
0
  {
70
71
0
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
72
0
    if (pmol == nullptr)
73
0
      return false;
74
75
    //Define some references so we can use the old parameter names
76
0
    istream &ifs = *pConv->GetInStream();
77
0
    OBMol &mol = *pmol;
78
0
    const char* title = pConv->GetTitle();
79
0
    char buffer[BUFF_SIZE];
80
0
    string temp, temp2;
81
82
0
    OBAtom *atom;
83
0
    vector<string> vs;
84
0
    double x, y, z;
85
0
    unsigned int token;
86
0
    int bondNbr, bondOrder;
87
0
    bool parsingBonds, readingMol = false;
88
0
    bool hasPartialCharges = false;
89
90
0
    ttab.SetFromType("PCM");
91
92
0
    mol.BeginModify();
93
94
0
    while (ifs.getline(buffer,BUFF_SIZE))
95
0
      {
96
0
        if(strncmp(buffer,"{PCM", 4) == 0)
97
0
          {
98
0
            temp = buffer;
99
0
            temp = temp.substr(4, temp.length());
100
0
            mol.SetTitle(temp);
101
0
            readingMol = true;
102
0
          }
103
0
        else if (readingMol && strncmp(buffer,"}", 1) == 0)
104
0
          {
105
0
            readingMol = false;
106
0
            break;
107
0
          }
108
0
        else if (readingMol && strncmp(buffer,"AT ",3) == 0)
109
0
          {
110
0
            tokenize(vs,buffer, "\n\r\t ,:");
111
0
            if (vs.size() < 3)
112
0
              return false;
113
114
0
            atom = mol.NewAtom();
115
0
            temp = vs[2].c_str();
116
0
            ttab.SetToType("INT");
117
0
            ttab.Translate(temp2, temp);
118
0
            atom->SetType(temp2);
119
120
0
            ttab.SetToType("ATN");
121
0
            ttab.Translate(temp2, temp);
122
0
            atom->SetAtomicNum(atoi(temp2.c_str()));
123
0
            x = atof(vs[3].c_str());
124
0
            y = atof(vs[4].c_str());
125
0
            z = atof(vs[5].c_str());
126
0
            atom->SetVector(x,y,z); //set coordinates
127
128
0
            token = 6;
129
0
            parsingBonds = false;
130
0
            while(token < vs.size())
131
0
              {
132
0
                if (vs[token] == "B")
133
0
                  parsingBonds = true;
134
0
                else if (vs[token][0] == 'C')
135
0
                  {
136
0
                    parsingBonds = false;
137
0
                    hasPartialCharges = true;
138
0
                    if (vs[token].size() > 1)
139
0
                      temp = vs[token].substr(1,vs[token].size());
140
0
                    else
141
0
                      {
142
0
                        token++;
143
0
                        temp = vs[token];
144
0
                      }
145
0
                    atom->SetPartialCharge(atof(temp.c_str()));
146
0
                  }
147
148
0
                else if (parsingBonds && token < vs.size() - 1 &&
149
0
                         isdigit(vs[token][0]))
150
0
                  {
151
0
                    bondNbr = atoi(vs[token++].c_str()); // advance to bond order
152
0
                    bondOrder = atoi(vs[token].c_str());
153
0
                    if (bondOrder == 9)
154
0
                      bondOrder = 1;
155
0
                    mol.AddBond(atom->GetIdx(), bondNbr, bondOrder, 0);
156
0
                  }
157
0
                else
158
0
                  parsingBonds = false; // any other token
159
160
0
                token++;
161
0
              } // end atom fields
162
0
          } // end AT line
163
0
      } // end reading
164
165
    // clean out remaining blank lines
166
0
    std::streampos ipos;
167
0
    do
168
0
    {
169
0
      ipos = ifs.tellg();
170
0
      ifs.getline(buffer,BUFF_SIZE);
171
0
    }
172
0
    while(strlen(buffer) == 0 && !ifs.eof() );
173
0
    ifs.seekg(ipos);
174
175
0
    mol.EndModify();
176
0
    if (hasPartialCharges)
177
0
      mol.SetPartialChargesPerceived();
178
0
    mol.SetTitle(title);
179
0
    return(true);
180
0
  }
181
182
  ////////////////////////////////////////////////////////////////
183
184
  bool PCModelFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
185
0
  {
186
0
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
187
0
    if (pmol == nullptr)
188
0
      return false;
189
190
    //Define some references so we can use the old parameter names
191
0
    ostream &ofs = *pConv->GetOutStream();
192
0
    OBMol &mol = *pmol;
193
0
    OBAtom *nbr;
194
0
    vector<OBBond*>::iterator j;
195
0
    string type, temp;
196
0
    int nbrIdx, atomIdx;
197
198
0
    temp = mol.GetTitle();
199
0
    ofs << "{PCM " << temp.substr(0,60) << endl;
200
0
    ofs << "NA " << mol.NumAtoms() << endl;
201
0
    ofs << "ATOMTYPES 1" << endl; // MMX atom types
202
203
0
    ttab.SetFromType("INT");
204
0
    ttab.SetToType("PCM");
205
206
0
    string str,str1;
207
0
    FOR_ATOMS_OF_MOL(atom, mol)
208
0
      {
209
0
        ttab.Translate(type,atom->GetType());
210
0
        atomIdx = atom->GetIdx();
211
212
0
        ofs << "AT " << atom->GetIdx() << "," << type << ":";
213
0
        ofs << atom->GetX() << "," << atom->GetY() << "," << atom->GetZ();
214
215
0
        if (atom->GetExplicitDegree() > 0)
216
0
          {
217
0
            ofs << " B";
218
0
            for (nbr = atom->BeginNbrAtom(j);nbr;nbr = atom->NextNbrAtom(j))
219
0
              {
220
0
                nbrIdx = nbr->GetIdx();
221
0
                ofs << " " << nbrIdx << ","
222
0
                    << (mol.GetBond(nbrIdx, atomIdx))->GetBondOrder();
223
0
              }
224
0
          }
225
226
0
        ofs << " C " << atom->GetPartialCharge();
227
228
0
        ofs << endl;
229
0
      }
230
231
0
    ofs << "}" << endl;
232
233
0
    return(true);
234
0
  }
235
236
} //namespace OpenBabel