- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Fragmentation/Fragmentation.cpp
r94d5ac6 r3aa8a5 46 46 #include "Element/periodentafel.hpp" 47 47 #include "Fragmentation/AdaptivityMap.hpp" 48 #include "Fragmentation/AtomMask.hpp" 48 49 #include "Fragmentation/fragmentation_helpers.hpp" 49 50 #include "Fragmentation/Graph.hpp" 51 #include "Fragmentation/helpers.hpp" 50 52 #include "Fragmentation/KeySet.hpp" 51 53 #include "Fragmentation/PowerSetGenerator.hpp" 52 54 #include "Fragmentation/UniqueFragments.hpp" 53 55 #include "Graph/BondGraph.hpp" 54 #include "Graph/CheckAgainstAdjacencyFile.hpp" 56 #include "Graph/AdjacencyList.hpp" 57 #include "Graph/ListOfLocalAtoms.hpp" 55 58 #include "molecule.hpp" 56 #include "MoleculeLeafClass.hpp"57 #include "MoleculeListClass.hpp"58 #include "Parser/FormatParserStorage.hpp"59 59 #include "World.hpp" 60 60 … … 63 63 * 64 64 * \param _mol molecule for internal use (looking up atoms) 65 * \param _FileChecker instance contains adjacency parsed from elsewhere 65 66 * \param _saturation whether to treat hydrogen special and saturate dangling bonds or not 66 67 */ 67 Fragmentation::Fragmentation(molecule *_mol, const enum HydrogenSaturation _saturation) :68 Fragmentation::Fragmentation(molecule *_mol, AdjacencyList &_FileChecker, const enum HydrogenSaturation _saturation) : 68 69 mol(_mol), 69 saturation(_saturation) 70 saturation(_saturation), 71 FileChecker(_FileChecker) 70 72 {} 71 73 … … 89 91 * of vertex indices: Global always means the index in "this" molecule, whereas local refers to the molecule or 90 92 * subgraph in the MoleculeListClass. 93 * \param atomids atomic ids (local to Fragmentation::mol) to fragment, used in AtomMask 91 94 * \param Order up to how many neighbouring bonds a fragment contains in BondOrderScheme::BottumUp scheme 92 95 * \param prefix prefix string for every fragment file name (may include path) … … 94 97 * \return 1 - continue, 2 - stop (no fragmentation occured) 95 98 */ 96 int Fragmentation::FragmentMolecule(int Order, std::string prefix, DepthFirstSearchAnalysis &DFS) 97 { 98 MoleculeListClass *BondFragments = NULL; 99 int FragmentCounter; 100 MoleculeLeafClass *MolecularWalker = NULL; 101 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 102 fstream File; 103 bool FragmentationToDo = true; 99 int Fragmentation::FragmentMolecule(const std::vector<atomId_t> &atomids, int Order, std::string prefix, DepthFirstSearchAnalysis &DFS) 100 { 101 std::fstream File; 104 102 bool CheckOrder = false; 105 Graph **FragmentList = NULL;106 Graph TotalGraph; // graph with all keysets however local numbers107 103 int TotalNumberOfKeySets = 0; 108 atom ***ListOfLocalAtoms = NULL; 109 bool *AtomMask = NULL; 110 111 LOG(0, endl); 104 105 LOG(0, std::endl); 112 106 switch (saturation) { 113 107 case DoSaturate: … … 123 117 124 118 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 119 bool FragmentationToDo = true; 125 120 126 121 // ===== 1. Check whether bond structure is same as stored in files ==== … … 128 123 // === compare it with adjacency file === 129 124 { 130 std::ifstream File; 131 std::string filename; 132 filename = prefix + ADJACENCYFILE; 133 File.open(filename.c_str(), ios::out); 134 LOG(1, "Looking at bond structure stored in adjacency file and comparing to present one ... "); 135 136 CheckAgainstAdjacencyFile FileChecker(World::getInstance().beginAtomSelection(), World::getInstance().endAtomSelection()); 137 FragmentationToDo = FragmentationToDo && FileChecker(File); 138 } 139 140 // === reset bond degree and perform CorrectBondDegree === 141 for(World::MoleculeIterator iter = World::getInstance().getMoleculeIter(); 142 iter != World::getInstance().moleculeEnd(); 143 ++iter) { 144 // correct bond degree 145 World::AtomComposite Set = (*iter)->getAtomSet(); 146 World::getInstance().getBondGraph()->CorrectBondDegree(Set); 147 } 148 149 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs ===== 150 // NOTE: We assume here that DFS has been performed and molecule structure is current. 151 Subgraphs = DFS.getMoleculeStructure(); 125 const std::vector<atomId_t> globalids = getGlobalIdsFromLocalIds(*mol, atomids); 126 AdjacencyList WorldAdjacency(globalids); 127 FragmentationToDo = FragmentationToDo && (FileChecker > WorldAdjacency); 128 } 129 130 // ===== 2. create AtomMask that takes Saturation condition into account 131 AtomMask_t AtomMask(atomids); 132 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) { 133 // remove in hydrogen and we do saturate 134 if ((saturation == DoSaturate) && ((*iter)->getType()->getAtomicNumber() == 1)) // skip hydrogen 135 AtomMask.setFalse((*iter)->getNr()); 136 } 152 137 153 138 // ===== 3. if structure still valid, parse key set file and others ===== … … 156 141 157 142 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 158 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile( prefix);143 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(atomids, prefix); 159 144 160 145 // =================================== Begin of FRAGMENTATION =============================== 161 146 // ===== 6a. assign each keyset to its respective subgraph ===== 162 const int MolCount = World::getInstance().numMolecules(); 163 ListOfLocalAtoms = new atom **[MolCount]; 164 for (int i=0;i<MolCount;i++) 165 ListOfLocalAtoms[i] = NULL; 166 FragmentCounter = 0; 167 Subgraphs->next->AssignKeySetsToFragment(mol, &ParsedFragmentList, ListOfLocalAtoms, FragmentList, FragmentCounter, true); 168 delete[](ListOfLocalAtoms); 147 ListOfLocalAtoms_t ListOfLocalAtoms; 148 Graph FragmentList; 149 AssignKeySetsToFragment(ParsedFragmentList, ListOfLocalAtoms, FragmentList, true); 169 150 170 151 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle 171 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()]; 172 AtomMask = new bool[mol->getAtomCount()+1]; 173 AtomMask[mol->getAtomCount()] = false; 152 KeyStack RootStack; 174 153 FragmentationToDo = false; // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards 175 while ((CheckOrder = CheckOrderAtSite(AtomMask, &ParsedFragmentList, Order, prefix))) { 154 bool LoopDoneAlready = false; 155 while ((CheckOrder = CheckOrderAtSite(AtomMask, ParsedFragmentList, Order, prefix, LoopDoneAlready))) { 176 156 FragmentationToDo = FragmentationToDo || CheckOrder; 177 AtomMask[mol->getAtomCount()]= true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()157 LoopDoneAlready = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 178 158 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 179 Subgraphs->next->FillRootStackForSubgraphs(RootStack, AtomMask, (FragmentCounter = 0), saturation); 180 181 // ===== 7. fill the bond fragment list ===== 182 FragmentCounter = 0; 183 MolecularWalker = Subgraphs; 184 while (MolecularWalker->next != NULL) { 185 MolecularWalker = MolecularWalker->next; 186 LOG(1, "Fragmenting subgraph " << MolecularWalker << "."); 187 if (MolecularWalker->Leaf->hasBondStructure()) { 188 // call BOSSANOVA method 189 LOG(0, endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= "); 190 FragmentBOSSANOVA(MolecularWalker->Leaf, FragmentList[FragmentCounter], RootStack[FragmentCounter]); 191 } else { 192 ELOG(1, "Subgraph " << MolecularWalker << " has no atoms!"); 193 } 194 FragmentCounter++; // next fragment list 195 } 159 FillRootStackForSubgraphs(RootStack, AtomMask); 160 161 // call BOSSANOVA method 162 FragmentBOSSANOVA(mol, FragmentList, RootStack); 196 163 } 197 164 LOG(2, "CheckOrder is " << CheckOrder << "."); 198 delete[](RootStack);199 delete[](AtomMask);200 165 201 166 // ==================================== End of FRAGMENTATION ============================================ 202 167 203 168 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 204 Subgraphs->next->TranslateIndicesToGlobalIDs(FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 205 206 // free subgraph memory again 207 FragmentCounter = 0; 208 while (Subgraphs != NULL) { 209 // remove entry in fragment list 210 // remove subgraph fragment 211 MolecularWalker = Subgraphs->next; 212 Subgraphs->Leaf = NULL; 213 delete(Subgraphs); 214 Subgraphs = MolecularWalker; 215 } 216 // free fragment list 217 for (int i=0; i< FragmentCounter; ++i ) 218 delete(FragmentList[i]); 219 delete[](FragmentList); 220 221 LOG(0, FragmentCounter << " subgraph fragments have been removed."); 222 223 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass ===== 224 //if (FragmentationToDo) { // we should always store the fragments again as coordination might have changed slightly without changing bond structure 225 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 226 BondFragments = new MoleculeListClass(World::getPointer()); 227 int k=0; 228 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) { 229 KeySet test = (*runner).first; 230 LOG(0, "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "."); 231 BondFragments->insert(StoreFragmentFromKeySet(test, World::getInstance().getConfig())); 232 k++; 233 } 234 LOG(0, k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets."); 235 236 // ===== 9. Save fragments' configuration and keyset files et al to disk === 237 if (BondFragments->ListOfMolecules.size() != 0) { 238 // create the SortIndex from BFS labels to order in the config file 239 int *SortIndex = NULL; 240 CreateMappingLabelsToConfigSequence(SortIndex); 241 242 LOG(1, "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs"); 243 bool write_status = true; 244 for (std::vector<std::string>::const_iterator iter = typelist.begin(); 245 iter != typelist.end(); 246 ++iter) { 247 LOG(2, "INFO: Writing bond fragments for type " << (*iter) << "."); 248 write_status = write_status 249 && BondFragments->OutputConfigForListOfFragments( 250 prefix, 251 SortIndex, 252 FormatParserStorage::getInstance().getTypeFromName(*iter)); 253 } 254 if (write_status) 255 LOG(1, "All configs written."); 256 else 257 LOG(1, "Some config writing failed."); 258 259 // store force index reference file 260 BondFragments->StoreForcesFile(prefix, SortIndex); 261 262 // store keysets file 263 TotalGraph.StoreKeySetFile(prefix); 264 265 { 266 // store Adjacency file 267 std::string filename = prefix + ADJACENCYFILE; 268 mol->StoreAdjacencyToFile(filename); 269 } 270 271 // store Hydrogen saturation correction file 272 BondFragments->AddHydrogenCorrection(prefix); 273 274 // store adaptive orders into file 275 StoreOrderAtSiteFile(prefix); 276 277 // restore orbital and Stop values 278 //CalculateOrbitals(*configuration); 279 280 // free memory for bond part 281 LOG(1, "Freeing bond memory"); 282 delete[](SortIndex); 283 } else { 284 LOG(1, "FragmentList is zero on return, splitting failed."); 285 } 286 // remove all create molecules again from the World including their atoms 287 for (MoleculeList::iterator iter = BondFragments->ListOfMolecules.begin(); 288 !BondFragments->ListOfMolecules.empty(); 289 iter = BondFragments->ListOfMolecules.begin()) { 290 // remove copied atoms and molecule again 291 molecule *mol = *iter; 292 mol->removeAtomsinMolecule(); 293 World::getInstance().destroyMolecule(mol); 294 BondFragments->ListOfMolecules.erase(iter); 295 } 296 delete(BondFragments); 169 TranslateIndicesToGlobalIDs(FragmentList, TotalNumberOfKeySets, TotalGraph); 170 171 LOG(1, "STATUS: We have created " << TotalGraph.size() << " fragments."); 172 173 174 // store adaptive orders into file 175 StoreOrderAtSiteFile(prefix); 176 297 177 LOG(0, "End of bond fragmentation."); 298 299 178 return ((int)(!FragmentationToDo)+1); // 1 - continue, 2 - stop (no fragmentation occured) 300 179 }; … … 317 196 * \return pointer to Graph list 318 197 */ 319 void Fragmentation::FragmentBOSSANOVA(molecule *mol, Graph *&FragmentList, KeyStack &RootStack) 320 { 198 void Fragmentation::FragmentBOSSANOVA(molecule *mol, Graph &FragmentList, KeyStack &RootStack) 199 { 200 Info FunctionInfo(__func__); 321 201 Graph ***FragmentLowerOrdersList = NULL; 322 202 int NumLevels = 0; … … 330 210 int RootNr = 0; 331 211 UniqueFragments FragmentSearch; 332 333 LOG(0, "Begin of FragmentBOSSANOVA.");334 212 335 213 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5) … … 420 298 FreeAllOrdersList(FragmentLowerOrdersList, RootStack, mol); 421 299 delete[](NumMoleculesOfOrder); 422 423 LOG(0, "End of FragmentBOSSANOVA.");424 300 }; 425 426 /** Stores a fragment from \a KeySet into \a molecule.427 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete428 * molecule and adds missing hydrogen where bonds were cut.429 * \param *out output stream for debugging messages430 * \param &Leaflet pointer to KeySet structure431 * \param IsAngstroem whether we have Ansgtroem or bohrradius432 * \return pointer to constructed molecule433 */434 molecule * Fragmentation::StoreFragmentFromKeySet(KeySet &Leaflet, bool IsAngstroem)435 {436 Info info(__func__);437 atom **SonList = new atom*[mol->getAtomCount()+1];438 molecule *Leaf = World::getInstance().createMolecule();439 440 for(int i=0;i<=mol->getAtomCount();i++)441 SonList[i] = NULL;442 443 StoreFragmentFromKeySet_Init(mol, Leaf, Leaflet, SonList);444 // create the bonds between all: Make it an induced subgraph and add hydrogen445 // LOG(2, "Creating bonds from father graph (i.e. induced subgraph creation).");446 CreateInducedSubgraphOfFragment(mol, Leaf, SonList, IsAngstroem);447 448 //Leaflet->Leaf->ScanForPeriodicCorrection(out);449 delete[](SonList);450 return Leaf;451 };452 453 301 454 302 /** Estimates by educated guessing (using upper limit) the expected number of fragments. … … 471 319 c = (ListOfBonds.size() > c) ? ListOfBonds.size() : c; 472 320 } 473 FragmentCount = mol->getNoNonHydrogen()*(1 << (c*order));321 FragmentCount = (saturation == DoSaturate ? mol->getNoNonHydrogen() : mol->getAtomCount()) *(1 << (c*order)); 474 322 LOG(1, "Upper limit for this subgraph is " << FragmentCount << " for " 475 323 << mol->getNoNonHydrogen() << " non-H atoms with maximum bond degree of " << c << "."); … … 479 327 480 328 /** Checks whether the OrderAtSite is still below \a Order at some site. 481 * \param *AtomMask defines true/false per global Atom::Nr to mask in/out each nuclear site, used to activate given number of site to increment order adaptively329 * \param AtomMask defines true/false per global Atom::Nr to mask in/out each nuclear site, used to activate given number of site to increment order adaptively 482 330 * \param *GlobalKeySetList list of keysets with global ids (valid in "this" molecule) needed for adaptive increase 483 331 * \param Order desired Order if positive, desired exponent in threshold criteria if negative (0 is single-step) 484 332 * \param path path to ENERGYPERFRAGMENT file (may be NULL if Order is non-negative) 333 * \param LoopDoneAlready indicate whether we have done a fragmentation loop already 485 334 * \return true - needs further fragmentation, false - does not need fragmentation 486 335 */ 487 bool Fragmentation::CheckOrderAtSite( bool *AtomMask, Graph *GlobalKeySetList, int Order, std::string path)336 bool Fragmentation::CheckOrderAtSite(AtomMask_t &AtomMask, const Graph &GlobalKeySetList, int Order, std::string path, bool LoopDoneAlready) 488 337 { 489 338 bool status = false; 490 339 491 // initialize mask list492 for(int i=mol->getAtomCount();i--;)493 AtomMask[i] = false;494 495 340 if (Order < 0) { // adaptive increase of BondOrder per site 496 if ( AtomMask[mol->getAtomCount()] == true) // break after one step341 if (LoopDoneAlready) // break after one step 497 342 return false; 498 343 499 344 // transmorph graph keyset list into indexed KeySetList 500 if (GlobalKeySetList == NULL) { 501 ELOG(1, "Given global key set list (graph) is NULL!"); 502 return false; 503 } 504 AdaptivityMap * IndexKeySetList = GlobalKeySetList->GraphToAdaptivityMap(); 345 AdaptivityMap * IndexKeySetList = GlobalKeySetList.GraphToAdaptivityMap(); 505 346 506 347 // parse the EnergyPerFragment file … … 512 353 if (IndexKeySetList->IsAdaptiveCriteriaListEmpty()) { 513 354 ELOG(2, "Unable to parse file, incrementing all."); 514 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) { 515 if ((saturation == DontSaturate) || ((*iter)->getType()->getAtomicNumber() != 1)) // skip hydrogen 516 { 517 AtomMask[(*iter)->getNr()] = true; // include all (non-hydrogen) atoms 518 status = true; 519 } 520 } 355 status = true; 521 356 } else { 522 IndexKeySetList->MarkUpdateCandidates(AtomMask, Order, mol); 357 // mark as false all sites that are below threshold already 358 status = IndexKeySetList->MarkUpdateCandidates(AtomMask, Order, mol); 523 359 } 524 360 … … 526 362 } else { // global increase of Bond Order 527 363 for(molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) { 528 if ((saturation == DontSaturate) || ((*iter)->getType()->getAtomicNumber() != 1)) // skip hydrogen 529 { 530 AtomMask[(*iter)->getNr()] = true; // include all (non-hydrogen) atoms 531 if ((Order != 0) && ((*iter)->AdaptiveOrder < Order)) // && ((*iter)->AdaptiveOrder < MinimumRingSize[(*iter)->getNr()])) 364 if (AtomMask.isTrue((*iter)->getNr())) { // skip masked out 365 // remove all that have reached desired order 366 if ((Order != 0) && ((*iter)->AdaptiveOrder >= Order)) // && ((*iter)->AdaptiveOrder < MinimumRingSize[(*iter)->getNr()])) 367 AtomMask.setFalse((*iter)->getNr()); 368 else 532 369 status = true; 533 370 } 534 371 } 535 if ((!Order) && (! AtomMask[mol->getAtomCount()])) // single stepping, just check372 if ((!Order) && (!LoopDoneAlready)) // single stepping, just check 536 373 status = true; 537 374 … … 576 413 /** Parses pairs(Atom::Nr, Atom::AdaptiveOrder) from file and stores in molecule's Atom's. 577 414 * Atoms not present in the file get "0". 415 * \param atomids atoms to fragment, used in AtomMask 578 416 * \param &path path to file ORDERATSITEFILEe 579 417 * \return true - file found and scanned, false - file not found 580 418 * \sa ParseKeySetFile() and CheckAdjacencyFileAgainstMolecule() as this is meant to be used in conjunction with the two 581 419 */ 582 bool Fragmentation::ParseOrderAtSiteFromFile(std::string &path) 583 { 584 unsigned char *OrderArray = new unsigned char[mol->getAtomCount()]; 585 bool *MaxArray = new bool[mol->getAtomCount()]; 420 bool Fragmentation::ParseOrderAtSiteFromFile(const std::vector<atomId_t> &atomids, std::string &path) 421 { 422 Info FunctionInfo(__func__); 423 typedef unsigned char order_t; 424 typedef std::map<atomId_t, order_t> OrderArray_t; 425 OrderArray_t OrderArray; 426 AtomMask_t MaxArray(atomids); 586 427 bool status; 587 428 int AtomNr, value; … … 589 430 ifstream file; 590 431 591 for(int i=0;i<mol->getAtomCount();i++) {592 OrderArray[i] = 0;593 MaxArray[i] = false;594 }595 596 LOG(1, "Begin of ParseOrderAtSiteFromFile");597 432 line = path + ORDERATSITEFILE; 598 433 file.open(line.c_str()); … … 605 440 OrderArray[AtomNr] = value; 606 441 file >> value; 607 MaxArray [AtomNr] = value;442 MaxArray.setValue(AtomNr, (bool)value); 608 443 //LOG(2, "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "."); 609 444 } … … 614 449 for(molecule::iterator iter=mol->begin();iter!=mol->end();++iter){ 615 450 (*iter)->AdaptiveOrder = OrderArray[(*iter)->getNr()]; 616 (*iter)->MaxOrder = MaxArray [(*iter)->getNr()];451 (*iter)->MaxOrder = MaxArray.isTrue((*iter)->getNr()); 617 452 } 618 453 //SetAtomValueToIndexedArray( OrderArray, &atom::getNr(), &atom::AdaptiveOrder ); … … 625 460 status = false; 626 461 } 627 delete[](OrderArray); 628 delete[](MaxArray); 629 630 LOG(1, "End of ParseOrderAtSiteFromFile"); 462 631 463 return status; 632 464 }; 633 465 634 /** Create a SortIndex to map from atomic labels to the sequence in which the atoms are given in the config file. 635 * \param *out output stream for debugging 636 * \param *&SortIndex Mapping array of size molecule::AtomCount 637 * \return true - success, false - failure of SortIndex alloc 638 */ 639 bool Fragmentation::CreateMappingLabelsToConfigSequence(int *&SortIndex) 640 { 641 if (SortIndex != NULL) { 642 LOG(1, "SortIndex is " << SortIndex << " and not NULL as expected."); 466 /** Fills the root stack for sites to be used as root in fragmentation depending on order or adaptivity criteria 467 * Again, as in \sa FillBondStructureFromReference steps recursively through each Leaf in this chain list of molecule's. 468 * \param &RootStack stack to be filled 469 * \param AtomMask defines true/false per global Atom::Nr to mask in/out each nuclear site 470 * \return true - stack is non-empty, fragmentation necessary, false - stack is empty, no more sites to update 471 */ 472 void Fragmentation::FillRootStackForSubgraphs(KeyStack &RootStack, const AtomMask_t &AtomMask) 473 { 474 for(molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) { 475 const atom * const Father = (*iter)->GetTrueFather(); 476 if (AtomMask.isTrue(Father->getNr())) // apply mask 477 if ((saturation == DontSaturate) || ((*iter)->getType()->getAtomicNumber() != 1)) // skip hydrogen 478 RootStack.push_front((*iter)->getNr()); 479 } 480 } 481 482 /** The indices per keyset are compared to the respective father's Atom::Nr in each subgraph and thus put into \a **&FragmentList. 483 * \param *KeySetList list with all keysets 484 * \param ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled 485 * \param **&FragmentList list to be allocated and returned 486 * \param FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not 487 * \retuen true - success, false - failure 488 */ 489 bool Fragmentation::AssignKeySetsToFragment(Graph &KeySetList, ListOfLocalAtoms_t &ListOfLocalAtoms, Graph &FragmentList, bool FreeList) 490 { 491 Info FunctionInfo(__func__); 492 bool status = true; 493 size_t KeySetCounter = 0; 494 495 // fill ListOfLocalAtoms if NULL was given 496 if (!mol->FillListOfLocalAtoms(ListOfLocalAtoms, mol->getAtomCount())) { 497 LOG(1, "Filling of ListOfLocalAtoms failed."); 643 498 return false; 644 499 } 645 SortIndex = new int[mol->getAtomCount()+1]; 646 for(int i=mol->getAtomCount()+1;i--;) 647 SortIndex[i] = -1; 648 649 int AtomNo = 0; 650 for(molecule::const_iterator iter=mol->begin();iter!=mol->end();++iter){ 651 ASSERT(SortIndex[(*iter)->getNr()]==-1,"Same SortIndex set twice"); 652 SortIndex[(*iter)->getNr()] = AtomNo++; 653 } 654 655 return true; 656 }; 657 658 659 /** Initializes some value for putting fragment of \a *mol into \a *Leaf. 660 * \param *mol total molecule 661 * \param *Leaf fragment molecule 662 * \param &Leaflet pointer to KeySet structure 663 * \param **SonList calloc'd list which atom of \a *Leaf is a son of which atom in \a *mol 664 * \return number of atoms in fragment 665 */ 666 int Fragmentation::StoreFragmentFromKeySet_Init(molecule *mol, molecule *Leaf, KeySet &Leaflet, atom **SonList) 667 { 668 atom *FatherOfRunner = NULL; 669 670 // first create the minimal set of atoms from the KeySet 671 int size = 0; 672 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) { 673 FatherOfRunner = mol->FindAtom((*runner)); // find the id 674 SonList[FatherOfRunner->getNr()] = Leaf->AddCopyAtom(FatherOfRunner); 675 size++; 676 } 677 return size; 678 }; 679 680 681 /** Creates an induced subgraph out of a fragmental key set, adding bonds and hydrogens (if treated specially). 682 * \param *out output stream for debugging messages 683 * \param *mol total molecule 684 * \param *Leaf fragment molecule 685 * \param IsAngstroem whether we have Ansgtroem or bohrradius 686 * \param **SonList list which atom of \a *Leaf is a son of which atom in \a *mol 687 */ 688 void Fragmentation::CreateInducedSubgraphOfFragment(molecule *mol, molecule *Leaf, atom **SonList, bool IsAngstroem) 689 { 690 bool LonelyFlag = false; 691 atom *OtherFather = NULL; 692 atom *FatherOfRunner = NULL; 693 694 // we increment the iter just before skipping the hydrogen 695 // as we use AddBond, we cannot have a const_iterator here 696 for (molecule::iterator iter = Leaf->begin(); iter != Leaf->end();) { 697 LonelyFlag = true; 698 FatherOfRunner = (*iter)->father; 699 ASSERT(FatherOfRunner,"Atom without father found"); 700 if (SonList[FatherOfRunner->getNr()] != NULL) { // check if this, our father, is present in list 701 // create all bonds 702 const BondList& ListOfBonds = FatherOfRunner->getListOfBonds(); 703 for (BondList::const_iterator BondRunner = ListOfBonds.begin(); 704 BondRunner != ListOfBonds.end(); 705 ++BondRunner) { 706 OtherFather = (*BondRunner)->GetOtherAtom(FatherOfRunner); 707 if (SonList[OtherFather->getNr()] != NULL) { 708 // LOG(2, "INFO: Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->getNr()] 709 // << " is bound to " << *OtherFather << ", whose son is " 710 // << *SonList[OtherFather->getNr()] << "."); 711 if (OtherFather->getNr() > FatherOfRunner->getNr()) { // add bond (Nr check is for adding only one of both variants: ab, ba) 712 std::stringstream output; 713 // output << "ACCEPT: Adding Bond: " 714 output << Leaf->AddBond((*iter), SonList[OtherFather->getNr()], (*BondRunner)->BondDegree); 715 // LOG(3, output.str()); 716 //NumBonds[(*iter)->getNr()]++; 717 } else { 718 // LOG(3, "REJECY: Not adding bond, labels in wrong order."); 719 } 720 LonelyFlag = false; 721 } else { 722 // LOG(2, "INFO: Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->getNr()] 723 // << " is bound to " << *OtherFather << ", who has no son in this fragment molecule."); 724 if (saturation == DoSaturate) { 725 // LOG(3, "ACCEPT: Adding Hydrogen to " << (*iter)->Name << " and a bond in between."); 726 if (!Leaf->AddHydrogenReplacementAtom((*BondRunner), (*iter), FatherOfRunner, OtherFather, IsAngstroem)) 727 exit(1); 728 } 729 //NumBonds[(*iter)->getNr()] += Binder->BondDegree; 730 } 500 501 if (KeySetList.size() != 0) { // if there are some scanned keysets at all 502 // assign scanned keysets 503 KeySet TempSet; 504 for (Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { // key sets contain global numbers! 505 if (ListOfLocalAtoms[mol->FindAtom(*((*runner).first.begin()))->getNr()] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set 506 // translate keyset to local numbers 507 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++) 508 TempSet.insert(ListOfLocalAtoms[mol->FindAtom(*sprinter)->getNr()]->getNr()); 509 // insert into FragmentList 510 FragmentList.insert(GraphPair(TempSet, pair<int, double> (KeySetCounter++, (*runner).second.second))); 731 511 } 732 } else { 733 ELOG(1, "Son " << (*iter)->getName() << " has father " << FatherOfRunner->getName() << " but its entry in SonList is " << SonList[FatherOfRunner->getNr()] << "!"); 734 } 735 if ((LonelyFlag) && (Leaf->getAtomCount() > 1)) { 736 LOG(0, **iter << "has got bonds only to hydrogens!"); 737 } 738 ++iter; 739 if (saturation == DoSaturate) { 740 while ((iter != Leaf->end()) && ((*iter)->getType()->getAtomicNumber() == 1)){ // skip added hydrogen 741 iter++; 742 } 743 } 744 } 745 }; 746 747 /** Sets the desired output types of the fragment configurations. 748 * 749 * @param types vector of desired types. 750 */ 751 void Fragmentation::setOutputTypes(const std::vector<std::string> &types) 752 { 753 typelist = types; 512 TempSet.clear(); 513 } 514 } else 515 LOG(1, "KeySetList is NULL or empty."); 516 517 if (FreeList) { 518 // free the index lookup list 519 ListOfLocalAtoms.clear(); 520 } 521 return status; 754 522 } 523 524 /** Translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 525 * \param &FragmentList Graph with local numbers per fragment 526 * \param &TotalNumberOfKeySets global key set counter 527 * \param &TotalGraph Graph to be filled with global numbers 528 */ 529 void Fragmentation::TranslateIndicesToGlobalIDs(Graph &FragmentList, int &TotalNumberOfKeySets, Graph &TotalGraph) 530 { 531 Info FunctionInfo(__func__); 532 for (Graph::iterator runner = FragmentList.begin(); runner != FragmentList.end(); runner++) { 533 KeySet TempSet; 534 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++) 535 TempSet.insert((mol->FindAtom(*sprinter))->GetTrueFather()->getId()); 536 TotalGraph.insert(GraphPair(TempSet, pair<int, double> (TotalNumberOfKeySets++, (*runner).second.second))); 537 } 538 } 539
Note:
See TracChangeset
for help on using the changeset viewer.