source: src/Graph/CheckAgainstAdjacencyFile.cpp@ b4f72c

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since b4f72c was 06f41f3, checked in by Frederik Heber <heber@…>, 12 years ago

CheckAgainstAdjacencyFile now works on given vector of atomids.

  • added helper function getGlobalIdsFromLocalIds() as we have to translate molecule's internal ids to global atomId_t to check against those in file.
  • TESTFIX: Adapted CheckAgainstAdjacencyFileUnitTest to the changes, also added another test case to operatorTest().
  • Property mode set to 100644
File size: 8.7 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder 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, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder 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 General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * CheckAgainstAdjacencyFile.cpp
25 *
26 * Created on: Mar 3, 2011
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include "CodePatterns/MemDebug.hpp"
36
37#include <iostream>
38#include <map>
39#include <set>
40#include <utility>
41
42#include "CheckAgainstAdjacencyFile.hpp"
43
44#include "Atom/atom.hpp"
45#include "Bond/bond.hpp"
46#include "CodePatterns/Assert.hpp"
47#include "CodePatterns/Log.hpp"
48#include "CodePatterns/Range.hpp"
49#include "Descriptors/AtomIdDescriptor.hpp"
50#include "Helpers/defs.hpp"
51#include "World.hpp"
52
53/** Constructor of class CheckAgainstAdjacencyFile.
54 *
55 * \param File file to parser
56 */
57CheckAgainstAdjacencyFile::CheckAgainstAdjacencyFile(std::istream &File) :
58 NonMatchNumber(0)
59{
60 bool status = ParseInInternalMap(File);
61 if (!status) // remove map if failed to parse
62 InternalAtomBondMap.clear();
63}
64
65CheckAgainstAdjacencyFile::~CheckAgainstAdjacencyFile()
66{}
67
68/** Parses the bond partners of each atom from an external file into \a AtomBondMap.
69 *
70 * @param File file to parse
71 * @return true - everything ok, false - error while parsing
72 */
73bool CheckAgainstAdjacencyFile::ParseInInternalMap(std::istream &File)
74{
75 if (File.fail()) {
76 LOG(1, "STATUS: Adjacency file not found." << endl);
77 return false;
78 }
79
80 InternalAtomBondMap.clear();
81 char buffer[MAXSTRINGSIZE];
82 int tmp;
83 // Parse the file line by line and count the bonds
84 while (!File.eof()) {
85 File.getline(buffer, MAXSTRINGSIZE);
86 stringstream line;
87 line.str(buffer);
88 int AtomNr = -1;
89 line >> AtomNr;
90 // parse into structure
91 if (AtomNr > 0) {
92 const atom *Walker = World::getInstance().getAtom(AtomById(AtomNr-1));
93 if (Walker == NULL)
94 return false;
95 const atomId_t WalkerId = Walker->getId();
96 // parse bond partner ids associated to AtomNr
97 while (line >> ws >> tmp) {
98 LOG(3, "INFO: Recognized bond partner " << tmp-1 << " for " << WalkerId << ".");
99 InternalAtomBondMap.insert( std::make_pair(WalkerId, tmp-1) );
100 }
101 } else {
102 if (AtomNr != -1) {
103 ELOG(2, AtomNr << " is negative.");
104 return false;
105 }
106 }
107 }
108 return true;
109}
110
111/** Fills the InternalAtomBondMap from the atoms given by the two iterators.
112 *
113 * @param atomids set of atomic ids to check (must be global ids, i.e. from atom::getId())
114 */
115void CheckAgainstAdjacencyFile::CreateExternalMap(const atomids_t &atomids)
116{
117 ExternalAtomBondMap.clear();
118 // go through each atom in the list
119 for (atomids_t::const_iterator iter = atomids.begin(); iter != atomids.end(); ++iter) {
120 const atomId_t WalkerId = *iter;
121 ASSERT(WalkerId != (size_t)-1,
122 "CheckAgainstAdjacencyFile::CreateExternalMap() - Walker has no id.");
123 const atom *Walker = World::getInstance().getAtom(AtomById(WalkerId));
124 ASSERT( Walker != NULL,
125 "CheckAgainstAdjacencyFile::CreateExternalMap() - Walker id "+toString(*iter)
126 +" is not associated to any of World's atoms.");
127 const BondList& ListOfBonds = Walker->getListOfBonds();
128 // go through each of its bonds
129 for (BondList::const_iterator Runner = ListOfBonds.begin();
130 Runner != ListOfBonds.end();
131 ++Runner) {
132 const atomId_t id = (*Runner)->GetOtherAtom(Walker)->getId();
133 ASSERT(id != (size_t)-1,
134 "CheckAgainstAdjacencyFile::CreateExternalMap() - OtherAtom has not id.");
135 ExternalAtomBondMap.insert( std::make_pair(WalkerId, id) );
136 }
137 }
138}
139
140/** Checks contents of adjacency file against bond structure in structure molecule.
141 * \return true - structure is equal, false - not equivalence
142 */
143bool CheckAgainstAdjacencyFile::operator()(const atomids_t &atomids)
144{
145 LOG(0, "STATUS: Looking at bond structure of given ids and comparing against stored in adjacency file... ");
146
147 // parse in external map
148 CreateExternalMap(atomids);
149
150 bool status = CompareInternalExternalMap();
151 if (status) { // if equal we parse the KeySetFile
152 LOG(0, "STATUS: Equal.");
153 } else
154 LOG(0, "STATUS: Not equal by " << NonMatchNumber << " atoms.");
155 return status;
156}
157
158CheckAgainstAdjacencyFile::KeysSet CheckAgainstAdjacencyFile::getKeys(const CheckAgainstAdjacencyFile::AtomBondRange &_range) const
159{
160 KeysSet Keys;
161 for (AtomBondMap::const_iterator iter = _range.first;
162 iter != _range.second;
163 ++iter) {
164 Keys.insert( iter->first );
165 }
166 return Keys;
167}
168
169CheckAgainstAdjacencyFile::ValuesSet CheckAgainstAdjacencyFile::getValues(const CheckAgainstAdjacencyFile::AtomBondRange&_range) const
170{
171 ValuesSet Values;
172 for (AtomBondMap::const_iterator iter = _range.first;
173 iter != _range.second;
174 ++iter) {
175 Values.insert( iter->second );
176 }
177 return Values;
178}
179
180/** Counts the number of items in the second set not present in the first set.
181 *
182 * \note We assume that the sets are sorted.
183 *
184 * @param firstset check set
185 * @param secondset reference set
186 * @return number of items in the first set that are missing in the second
187 */
188template <class T>
189size_t getMissingItems(const T &firstset, const T &secondset)
190{
191 size_t Mismatch = 0;
192 typename T::const_iterator firstiter = firstset.begin();
193 typename T::const_iterator seconditer = secondset.begin();
194 for (; (firstiter != firstset.end()) && (seconditer != secondset.end());) {
195 if (*firstiter > *seconditer)
196 ++seconditer;
197 else {
198 if (*firstiter < *seconditer)
199 ++Mismatch;
200 ++firstiter;
201 }
202 }
203 return Mismatch;
204}
205
206/** Compares InternalAtomBondMap and ExternalAtomBondMap and sets NonMatchNumber.
207 *
208 * @return true - both maps are the same, false - both maps diverge by NonMatchNumber counts.
209 */
210bool CheckAgainstAdjacencyFile::CompareInternalExternalMap()
211{
212 NonMatchNumber = 0;
213 // extract keys and check whether they match
214 const AtomBondRange Intrange(InternalAtomBondMap.begin(), InternalAtomBondMap.end());
215 const AtomBondRange Extrange(ExternalAtomBondMap.begin(), ExternalAtomBondMap.end());
216 KeysSet InternalKeys( getKeys(Intrange) );
217 KeysSet ExternalKeys( getKeys(Extrange) );
218
219// std::cout << "InternalKeys: " << InternalKeys << std::endl;
220// std::cout << "ExternalKeys: " << ExternalKeys << std::endl;
221
222 // check for same amount of keys
223 if (ExternalKeys.size() > InternalKeys.size()) {
224 NonMatchNumber = (int)ExternalKeys.size() - (int)InternalKeys.size();
225 LOG(2, "INFO: Number of external keys exceeds internal one by " << NonMatchNumber << ".");
226 return false;
227 }
228
229 // check which keys are missing in the internal set
230 NonMatchNumber = getMissingItems(ExternalKeys, InternalKeys);
231
232 if (NonMatchNumber != 0) {
233 LOG(2, "INFO: " << NonMatchNumber << " keys are not the same.");
234 return false;
235 }
236
237 // now check each map per key
238 for (KeysSet::const_iterator keyIter = ExternalKeys.begin();
239 keyIter != ExternalKeys.end();
240 ++keyIter) {
241// std::cout << "Current key is " << *keyIter << std::endl;
242 const AtomBondRange IntRange( InternalAtomBondMap.equal_range(*keyIter) );
243 const AtomBondRange ExtRange( ExternalAtomBondMap.equal_range(*keyIter) );
244 ValuesSet InternalValues( getValues(IntRange) );
245 ValuesSet ExternalValues( getValues(ExtRange) );
246 // throw out all values not present in ExternalKeys
247 ValuesSet ExternalValues_temp( ExternalValues );
248 for(KeysSet::const_iterator iter = ExternalKeys.begin();
249 iter != ExternalKeys.end(); ++iter)
250 ExternalValues_temp.erase(*iter);
251 // all remaining values must be masked out
252 for (ValuesSet::const_iterator iter = ExternalValues_temp.begin();
253 iter != ExternalValues_temp.end(); ++iter)
254 ExternalValues.erase(*iter);
255// std::cout << "InternalValues: " << InternalValues << std::endl;
256// std::cout << "ExternalValues: " << ExternalValues << std::endl;
257 NonMatchNumber += getMissingItems(ExternalValues, InternalValues);
258 }
259 if (NonMatchNumber != 0) {
260 LOG(2, "INFO: " << NonMatchNumber << " keys are not the same.");
261 return false;
262 } else {
263 LOG(2, "INFO: All keys are the same.");
264 return true;
265 }
266}
Note: See TracBrowser for help on using the repository browser.