/src/openbabel/src/ops/readconformers.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************** |
2 | | read-conformers.cpp - A OBOp for combining conformers during conversion. |
3 | | |
4 | | Copyright (C) 2010 by Chris Morley |
5 | | |
6 | | This file is part of the Open Babel project. |
7 | | For more information, see <http://openbabel.org/> |
8 | | |
9 | | This program is free software; you can redistribute it and/or modify |
10 | | it under the terms of the GNU General Public License as published by |
11 | | the Free Software Foundation version 2 of the License. |
12 | | |
13 | | This program is distributed in the hope that it will be useful, |
14 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | GNU General Public License for more details. |
17 | | ***********************************************************************/ |
18 | | #include <openbabel/babelconfig.h> |
19 | | #include <openbabel/op.h> |
20 | | #include <openbabel/mol.h> |
21 | | #include <openbabel/obconversion.h> |
22 | | #include "deferred.h" |
23 | | #include <algorithm> |
24 | | |
25 | | namespace OpenBabel |
26 | | { |
27 | | |
28 | | class OpReadConformers : public OBOp |
29 | | { |
30 | | public: |
31 | 6 | OpReadConformers(const char* ID) : OBOp(ID, false){}; |
32 | 0 | const char* Description() override { return |
33 | 0 | "Adjacent conformers combined into a single molecule\n" |
34 | 0 | "If a molecule has the same structure as the preceding molecule, as determined\n" |
35 | 0 | "from its SMILES, it is not output but its coordinates are added to the\n" |
36 | 0 | "preceding molecule as an additional conformer. There can be multiple groups\n" |
37 | 0 | "of conformers, but the molecules in each group must be adjacent.\n" |
38 | 0 | ; } |
39 | | |
40 | 0 | bool WorksWith(OBBase* pOb) const override { return dynamic_cast<OBMol*>(pOb) != nullptr; } |
41 | | bool Do(OBBase* pOb, const char* OptionText=nullptr, OpMap* pOptions=nullptr, OBConversion* pConv=nullptr) override; |
42 | | bool ProcessVec(std::vector<OBBase*>& vec) override; |
43 | | }; |
44 | | |
45 | | ///////////////////////////////////////////////////////////////// |
46 | | OpReadConformers theOpReadConformers("readconformer"); //Global instance |
47 | | |
48 | | ///////////////////////////////////////////////////////////////// |
49 | | bool OpReadConformers::Do(OBBase* pOb, const char* OptionText, OpMap* pOptions, OBConversion* pConv) |
50 | 0 | { |
51 | | //Make a deferred format and divert the output to it |
52 | 0 | if(pConv && pConv->IsFirstInput()) |
53 | 0 | new DeferredFormat(pConv, this); //it will delete itself |
54 | |
|
55 | 0 | return true; |
56 | 0 | } |
57 | | |
58 | | bool OpReadConformers::ProcessVec(std::vector<OBBase*>& vec) |
59 | 0 | { |
60 | | // DeferredFormat collects all the molecules, they are processed here, and Deferred Format outputs them |
61 | 0 | OBConversion smconv; |
62 | 0 | smconv.AddOption("n"); |
63 | 0 | if(!smconv.SetOutFormat("smi")) |
64 | 0 | { |
65 | 0 | obErrorLog.ThrowError(__FUNCTION__, "SmilesFormat is not loaded" , obError, onceOnly); |
66 | 0 | return false; |
67 | 0 | } |
68 | | |
69 | 0 | std::string smiles, stored_smiles; |
70 | 0 | OBMol* stored_pmol=nullptr; |
71 | 0 | std::vector<OBBase*>::iterator iter; |
72 | 0 | for(iter= vec.begin();iter!=vec.end();++iter) |
73 | 0 | { |
74 | 0 | OBMol* pmol = dynamic_cast<OBMol*>(*iter); |
75 | 0 | if(!pmol) |
76 | 0 | continue; |
77 | 0 | smiles = smconv.WriteString(pmol); |
78 | 0 | Trim(smiles); |
79 | |
|
80 | 0 | if(stored_smiles==smiles) |
81 | 0 | { |
82 | | //add the coordinates of the current mol to the stored one as a conformer, and delete current mol |
83 | 0 | double *confCoord = new double [pmol->NumAtoms() * 3]; |
84 | 0 | memcpy((char*)confCoord,(char*)pmol->GetCoordinates(),sizeof(double)*3*pmol->NumAtoms()); |
85 | 0 | stored_pmol->AddConformer(confCoord); |
86 | 0 | delete pmol; |
87 | 0 | *iter = nullptr; |
88 | 0 | } |
89 | 0 | else |
90 | 0 | { |
91 | 0 | stored_pmol = pmol; |
92 | 0 | stored_smiles = smiles; |
93 | 0 | } |
94 | 0 | } |
95 | | |
96 | | //erase the NULLS |
97 | 0 | vec.erase(std::remove(vec.begin(), vec.end(), nullptr), vec.end()); |
98 | 0 | return true; |
99 | 0 | } |
100 | | |
101 | | } //namespace |
102 | | |
103 | | /* |
104 | | To use with OBConversion::Read(), etc. |
105 | | OBMol mol; |
106 | | vector<OBBase*> vec; |
107 | | while(pConv->Read(&mol)) |
108 | | vec.push_back(&mol); |
109 | | OBOp* pOp = OBOp::FindType("readconformers"); |
110 | | if(!pOp) |
111 | | pOp->ProcessVec(vec); |
112 | | vec now contains one or more molecules with multiple conformers |
113 | | */ |