source: src/Graph/CheckAgainstAdjacencyFile.cpp@ d3abb1

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 d3abb1 was ec87e4, checked in by Frederik Heber <heber@…>, 13 years ago

Rewrite of CheckAgainstAdjacencyFile.

  • we now construct two multimaps -- one from file, the other from World's selected atoms -- and compare these two.
  • added unit test on the class.
  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * CheckAgainstAdjacencyFile.cpp
10 *
11 * Created on: Mar 3, 2011
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include "CodePatterns/MemDebug.hpp"
21
22#include <iostream>
23
24#include "CheckAgainstAdjacencyFile.hpp"
25
26#include "atom.hpp"
27#include "Bond/bond.hpp"
28#include "CodePatterns/Assert.hpp"
29#include "CodePatterns/Log.hpp"
30#include "CodePatterns/Range.hpp"
31#include "Descriptors/AtomIdDescriptor.hpp"
32#include "Helpers/defs.hpp"
33#include "World.hpp"
34
35CheckAgainstAdjacencyFile::CheckAgainstAdjacencyFile(World::AtomSet::const_iterator AtomMapBegin, World::AtomSet::const_iterator AtomMapEnd) :
36 status(true),
37 NonMatchNumber(0)
38{
39 CreateInternalMap(AtomMapBegin, AtomMapEnd);
40}
41
42CheckAgainstAdjacencyFile::~CheckAgainstAdjacencyFile()
43{
44 ExternalAtomBondMap.clear();
45 InternalAtomBondMap.clear();
46}
47
48/** Parses the bond partners of each atom from an external file into \a AtomBondMap.
49 *
50 * @param File file to parse
51 * @return true - everything ok, false - error while parsing
52 */
53bool CheckAgainstAdjacencyFile::ParseInExternalMap(std::istream &File)
54{
55 if (File.fail()) {
56 LOG(1, "STATUS: Adjacency file not found." << endl);
57 return false;
58 }
59
60 ExternalAtomBondMap.clear();
61 char buffer[MAXSTRINGSIZE];
62 int tmp;
63 // Parse the file line by line and count the bonds
64 while (!File.eof()) {
65 File.getline(buffer, MAXSTRINGSIZE);
66 stringstream line;
67 line.str(buffer);
68 int AtomNr = -1;
69 line >> AtomNr;
70 // parse into structure
71 if (AtomNr >= 0) {
72 const atom *Walker = World::getInstance().getAtom(AtomById(AtomNr));
73 ASSERT(Walker != NULL,
74 "CheckAgainstAdjacencyFile::ParseInExternalMap() - there is no atom with id "+toString(AtomNr)+".");
75 if (Walker == NULL)
76 return false;
77 // parse bond partner ids associated to AtomNr
78 while (line >> ws >> tmp) {
79 LOG(3, "INFO: Recognized bond partner " << tmp);
80 ExternalAtomBondMap.insert( std::make_pair(AtomNr, tmp) );
81 }
82 } else {
83 if (AtomNr != -1) {
84 ELOG(2, AtomNr << " is negative.");
85 return false;
86 }
87 }
88 }
89 return true;
90}
91
92/** Fills the InternalAtomBondMap from the atoms given by the two iterators.
93 *
94 * @param AtomMapBegin iterator pointing to begin of map (think of World's SelectionIterator)
95 * @param AtomMapEnd iterator pointing past end of map (think of World's SelectionIterator)
96 */
97void CheckAgainstAdjacencyFile::CreateInternalMap(World::AtomSet::const_iterator &AtomMapBegin, World::AtomSet::const_iterator &AtomMapEnd)
98{
99 InternalAtomBondMap.clear();
100 // go through each atom in the list
101 for (World::AtomSet::const_iterator iter = AtomMapBegin; iter != AtomMapEnd; ++iter) {
102 const atom *Walker = iter->second;
103 const atomId_t WalkerId = Walker->getId();
104 ASSERT(WalkerId != (size_t)-1,
105 "CheckAgainstAdjacencyFile::CreateInternalMap() - Walker has no id.");
106 const BondList& ListOfBonds = Walker->getListOfBonds();
107 // go through each of its bonds
108 for (BondList::const_iterator Runner = ListOfBonds.begin();
109 Runner != ListOfBonds.end();
110 ++Runner) {
111 const atomId_t id = (*Runner)->GetOtherAtom(Walker)->getId();
112 ASSERT(id != (size_t)-1,
113 "CheckAgainstAdjacencyFile::CreateInternalMap() - OtherAtom has not id.");
114 InternalAtomBondMap.insert( std::make_pair(WalkerId, id) );
115 }
116 }
117}
118
119/** Checks contents of adjacency file against bond structure in structure molecule.
120 * \param File file to parser
121 * \return true - structure is equal, false - not equivalence
122 */
123bool CheckAgainstAdjacencyFile::operator()(std::istream &File)
124{
125 LOG(0, "STATUS: Looking at bond structure stored in adjacency file and comparing to present one ... ");
126
127 bool status = true;
128
129 status = status && ParseInExternalMap(File);
130 status = status && CompareInternalExternalMap();
131
132 if (status) { // if equal we parse the KeySetFile
133 LOG(0, "STATUS: Equal.");
134 } else
135 LOG(0, "STATUS: Not equal by " << NonMatchNumber << " atoms.");
136 return status;
137}
138
139template <class T>
140CheckAgainstAdjacencyFile::KeysSet getKeys(const CheckAgainstAdjacencyFile::AtomBondRange &_range)
141{
142 CheckAgainstAdjacencyFile::KeysSet Keys;
143 for (typename T::const_iterator iter = _range.first;
144 iter != _range.second;
145 ++iter) {
146 Keys.insert( iter->first );
147 }
148 return Keys;
149}
150
151template <class T>
152CheckAgainstAdjacencyFile::ValuesSet getValues(const CheckAgainstAdjacencyFile::AtomBondRange&_range)
153{
154 CheckAgainstAdjacencyFile::ValuesSet Values;
155 for (typename T::const_iterator iter = _range.first;
156 iter != _range.second;
157 ++iter) {
158 Values.insert( iter->second );
159 }
160 return Values;
161}
162
163/** Counts the number of mismatching items in each set.
164 *
165 * @param firstset first set
166 * @param secondset second set
167 * @return number of items that don't match between first and second set
168 */
169template <class T>
170size_t getMismatchingItems(const T &firstset, const T &secondset)
171{
172 size_t Mismatch = 0;
173 typename T::const_iterator firstiter = firstset.begin();
174 typename T::const_iterator seconditer = secondset.begin();
175 for (; (firstiter != firstset.end()) && (seconditer != secondset.end());
176 ++firstiter, ++seconditer) {
177 if (*firstiter != *seconditer)
178 ++Mismatch;
179 }
180 return Mismatch;
181}
182
183/** Compares InternalAtomBondMap and ExternalAtomBondMap and sets NonMatchNumber.
184 *
185 * @return true - both maps are the same, false - both maps diverge by NonMatchNumber counts.
186 */
187bool CheckAgainstAdjacencyFile::CompareInternalExternalMap()
188{
189 NonMatchNumber = 0;
190 // check whether sizes match
191 if (ExternalAtomBondMap.size() != InternalAtomBondMap.size()) {
192 NonMatchNumber = abs((int)ExternalAtomBondMap.size() - (int)InternalAtomBondMap.size());
193 LOG(2, "INFO: " << NonMatchNumber << " entries don't match.");
194 return false;
195 }
196 // extract keys and check whether they match
197 const AtomBondRange Intrange(InternalAtomBondMap.begin(), InternalAtomBondMap.end());
198 const AtomBondRange Extrange(ExternalAtomBondMap.begin(), ExternalAtomBondMap.end());
199 KeysSet InternalKeys( getKeys<AtomBondMap>(Intrange) );
200 KeysSet ExternalKeys( getKeys<AtomBondMap>(Extrange) );
201
202// std::cout << "InternalKeys: " << InternalKeys << std::endl;
203// std::cout << "ExternalKeys: " << ExternalKeys << std::endl;
204
205 // check for same amount of keys
206 if (InternalKeys.size() != ExternalKeys.size()) {
207 NonMatchNumber = abs((int)ExternalKeys.size() - (int)InternalKeys.size());
208 LOG(2, "INFO: Number of keys don't match: "
209 << InternalKeys.size() << " != " << ExternalKeys.size());
210 return false;
211 }
212
213 // check items against one another
214 NonMatchNumber = getMismatchingItems(InternalKeys, ExternalKeys);
215
216 if (NonMatchNumber != 0) {
217 LOG(2, "INFO: " << NonMatchNumber << " keys are not the same.");
218 return false;
219 }
220
221 // now check each map per key
222 for (KeysSet::const_iterator keyIter = InternalKeys.begin();
223 keyIter != InternalKeys.end();
224 ++keyIter) {
225// std::cout << "Current key is " << *keyIter << std::endl;
226 const AtomBondRange IntRange( InternalAtomBondMap.equal_range(*keyIter) );
227 const AtomBondRange ExtRange( ExternalAtomBondMap.equal_range(*keyIter) );
228 ValuesSet InternalValues( getValues<AtomBondMap>(IntRange) );
229 ValuesSet ExternalValues( getValues<AtomBondMap>(ExtRange) );
230// std::cout << "InternalValues: " << InternalValues << std::endl;
231// std::cout << "ExternalValues: " << ExternalValues << std::endl;
232 NonMatchNumber += getMismatchingItems(InternalValues, ExternalValues);
233 }
234 if (NonMatchNumber != 0) {
235 LOG(2, "INFO: " << NonMatchNumber << " keys are not the same.");
236 return false;
237 } else {
238 LOG(2, "INFO: All keys are the same.");
239 return true;
240 }
241}
Note: See TracBrowser for help on using the repository browser.