Coverage Report

Created: 2025-08-24 07:05

/src/openbabel/src/formats/alchemyformat.cpp
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************************
2
Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
3
Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
4
Some portions Copyright (C) 2004 by Chris Morley
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
#include <openbabel/babelconfig.h>
16
17
#include <openbabel/obmolecformat.h>
18
#include <openbabel/mol.h>
19
#include <openbabel/atom.h>
20
#include <openbabel/bond.h>
21
#include <openbabel/elements.h>
22
#include <openbabel/data.h>
23
#include <cstdlib>
24
25
26
using namespace std;
27
namespace OpenBabel
28
{
29
30
  class AlchemyFormat : public OBMoleculeFormat
31
  {
32
  public:
33
    //Register this format type ID
34
    AlchemyFormat()
35
6
    {
36
6
      OBConversion::RegisterFormat("alc",this, "chemical/x-alchemy");
37
6
    }
38
39
    const char* Description() override  // required
40
0
    {
41
0
      return
42
0
        "Alchemy format\n"
43
0
        "No comments yet\n";
44
0
    }
45
46
    const char* SpecificationURL() override
47
0
    { return ""; }  // optional
48
49
    const char* GetMIMEType() override
50
0
    { return "chemical/x-alchemy"; }
51
52
    //Flags() can return be any the following combined by | or be omitted if none apply
53
    // NOTREADABLE  READONEONLY  NOTWRITABLE  WRITEONEONLY
54
    unsigned int Flags() override
55
6
    {
56
6
      return READONEONLY | WRITEONEONLY;
57
6
    }
58
59
    //*** This section identical for most OBMol conversions ***
60
    ////////////////////////////////////////////////////
61
    /// The "API" interface functions
62
    bool ReadMolecule(OBBase* pOb, OBConversion* pConv) override;
63
    bool WriteMolecule(OBBase* pOb, OBConversion* pConv) override;
64
  };
65
  //***
66
67
  //Make an instance of the format class
68
  AlchemyFormat theAlchemyFormat;
69
70
  /////////////////////////////////////////////////////////////////
71
  bool AlchemyFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
72
0
  {
73
74
0
    OBMol* pmol = pOb->CastAndClear<OBMol>();
75
0
    if (pmol == nullptr)
76
0
      return false;
77
78
    //Define some references so we can use the old parameter names
79
0
    istream &ifs = *pConv->GetInStream();
80
0
    OBMol &mol = *pmol;
81
0
    const char* title = pConv->GetTitle();
82
83
0
    int i;
84
0
    int natoms = 0, nbonds = 0;
85
0
    char buffer[BUFF_SIZE];
86
87
0
    ifs.getline(buffer,BUFF_SIZE);
88
0
    sscanf(buffer," %d %*s %d", &natoms, &nbonds);
89
0
    if (!natoms)
90
0
      {
91
0
        ifs.getline(buffer,BUFF_SIZE);
92
0
        sscanf(buffer," %d %*s %d", &natoms, &nbonds);
93
0
        if (!natoms)
94
0
          return(false);
95
0
      }
96
97
0
    mol.ReserveAtoms(natoms);
98
0
    mol.BeginModify();
99
0
    ttab.SetFromType("ALC");
100
101
0
    string str;
102
0
    double x,y,z;
103
0
    OBAtom *atom;
104
0
    vector<string> vs;
105
106
0
    for (i = 1; i <= natoms; i ++)
107
0
      {
108
0
        if (!ifs.getline(buffer,BUFF_SIZE))
109
0
          return(false);
110
0
        tokenize(vs,buffer);
111
0
        if (vs.size() < 5)
112
0
          return(false);
113
0
        atom = mol.NewAtom();
114
0
        x = atof((char*)vs[2].c_str());
115
0
        y = atof((char*)vs[3].c_str());
116
0
        z = atof((char*)vs[4].c_str());
117
0
        atom->SetVector(x,y,z); //set coordinates
118
119
        //set atomic number
120
0
        ttab.SetToType("ATN");
121
0
        ttab.Translate(str,vs[1]);
122
0
        atom->SetAtomicNum(atoi(str.c_str()));
123
        //set type
124
0
        ttab.SetToType("INT");
125
0
        ttab.Translate(str,vs[1]);
126
0
        atom->SetType(str);
127
0
      }
128
129
0
    char bobuf[100];
130
0
    string bostr;
131
0
    int bgn,end,order;
132
133
0
    for (i = 0; i < nbonds; i++)
134
0
      {
135
0
        if (!ifs.getline(buffer,BUFF_SIZE))
136
0
          return(false);
137
0
        sscanf(buffer," %*d%d%d%99s",&bgn,&end,bobuf);
138
0
        bostr = bobuf;
139
0
        order = 1;
140
0
        if      (bostr == "DOUBLE")
141
0
          order = 2;
142
0
        else if (bostr == "TRIPLE")
143
0
          order = 3;
144
0
        else if (bostr == "AROMATIC")
145
0
          order = 5;
146
0
        mol.AddBond(bgn,end,order);
147
0
      }
148
149
    // clean out remaining blank lines
150
0
    std::streampos ipos;
151
0
    do
152
0
    {
153
0
      ipos = ifs.tellg();
154
0
      ifs.getline(buffer,BUFF_SIZE);
155
0
    }
156
0
    while(strlen(buffer) == 0 && !ifs.eof() );
157
0
    ifs.seekg(ipos);
158
159
160
0
    mol.EndModify();
161
0
    mol.SetTitle(title);
162
0
    return(true);
163
0
  }
164
165
  ////////////////////////////////////////////////////////////////
166
167
  bool AlchemyFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
168
0
  {
169
0
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
170
0
    if (pmol == nullptr)
171
0
      return false;
172
173
    //Define some references so we can use the old parameter names
174
0
    ostream &ofs = *pConv->GetOutStream();
175
0
    OBMol &mol = *pmol;
176
177
0
    unsigned int i;
178
0
    char buffer[BUFF_SIZE];
179
0
    char bond_string[10];
180
181
0
    snprintf(buffer, BUFF_SIZE, "%5d ATOMS, %5d BONDS,     0 CHARGES",
182
0
             mol.NumAtoms(),
183
0
             mol.NumBonds());
184
0
    ofs << buffer << endl;
185
186
0
    OBAtom *atom;
187
0
    string str,str1;
188
0
    for(i = 1;i <= mol.NumAtoms(); i++)
189
0
      {
190
0
        atom = mol.GetAtom(i);
191
0
        str = atom->GetType();
192
0
        ttab.SetFromType("INT");
193
0
        ttab.SetToType("ALC");
194
0
        ttab.Translate(str1,str);
195
0
        snprintf(buffer, BUFF_SIZE, "%5d %-6s%8.4f %8.4f %8.4f     0.0000",
196
0
                 i,
197
0
                 (char*)str1.c_str(),
198
0
                 atom->GetX(),
199
0
                 atom->GetY(),
200
0
                 atom->GetZ());
201
0
        ofs << buffer << endl;
202
0
      }
203
204
0
    OBBond *bond;
205
0
    vector<OBBond*>::iterator j;
206
207
0
    for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j))
208
0
      {
209
0
        switch(bond->GetBondOrder())
210
0
          {
211
0
          case 1 :
212
0
            strcpy(bond_string,"SINGLE");
213
0
            break;
214
0
          case 2 :
215
0
            strcpy(bond_string,"DOUBLE");
216
0
            break;
217
0
          case 3 :
218
0
            strcpy(bond_string,"TRIPLE");
219
0
            break;
220
0
          case 5 :
221
0
            strcpy(bond_string,"AROMATIC");
222
0
            break;
223
0
          default :
224
0
            strcpy(bond_string,"SINGLE");
225
0
          }
226
0
        snprintf(buffer, BUFF_SIZE, "%5d  %4d  %4d  %s",
227
0
                 bond->GetIdx()+1,
228
0
                 bond->GetBeginAtomIdx(),
229
0
                 bond->GetEndAtomIdx(),
230
0
                 bond_string);
231
0
        ofs << buffer << endl;
232
0
      }
233
0
    return(true);
234
0
  }
235
236
} //namespace OpenBabel