1 // $Id$ 2 // 3 // Copyright (C) 2001-2006 Rational Discovery LLC 4 // 5 // @@ All Rights Reserved @@ 6 // This file is part of the RDKit. 7 // The contents are covered by the terms of the BSD license 8 // which is included in the file license.txt, found at the root 9 // of the RDKit source tree. 10 // 11 #include "PeriodicTable.h" 12 #include <string> 13 #include <boost/tokenizer.hpp> 14 typedef boost::tokenizer<boost::char_separator<char>> tokenizer; 15 #include <sstream> 16 #include <locale> 17 18 #ifdef RDK_BUILD_THREADSAFE_SSS 19 #include <mutex> 20 #endif 21 22 namespace RDKit { 23 24 class std::unique_ptr<PeriodicTable> PeriodicTable::ds_instance = nullptr; 25 PeriodicTable()26PeriodicTable::PeriodicTable() { 27 // it is assumed that the atomic atomData string constains atoms 28 // in sequence and no atoms are missing in between 29 byanum.clear(); 30 byname.clear(); 31 32 boost::char_separator<char> eolSep("\n"); 33 tokenizer tokens(periodicTableAtomData, eolSep); 34 for (tokenizer::iterator token = tokens.begin(); token != tokens.end(); 35 ++token) { 36 if (*token != " ") { 37 atomicData adata(*token); 38 std::string enam = adata.Symbol(); 39 byname[enam] = adata.AtomicNum(); 40 // there are, for backwards compatibility reasons, some duplicate rows for 41 // atomic numbers in the atomic_data data structure. It's ok to have 42 // multiple symbols map to the same atomic number (above), but we need to 43 // be sure that we only store one entry per atomic number. 44 // Note that this only works because the first atom in the adata list is 45 // the dummy atom (atomic number 0). This was #2784 46 if (rdcast<size_t>(adata.AtomicNum()) == byanum.size()) { 47 byanum.push_back(adata); 48 } 49 } 50 } 51 52 unsigned int lidx = 0; 53 std::istringstream istr; 54 istr.imbue(std::locale("C")); 55 while (isotopesAtomData[lidx] != "" && isotopesAtomData[lidx] != "EOS") { 56 tokenizer lines(isotopesAtomData[lidx++], eolSep); 57 boost::char_separator<char> spaceSep(" \t"); 58 for (tokenizer::iterator line = lines.begin(); line != lines.end(); 59 ++line) { 60 if (*line != " ") { 61 tokenizer tokens(*line, spaceSep); 62 tokenizer::iterator token = tokens.begin(); 63 int anum; 64 istr.clear(); 65 istr.str(*token); 66 istr >> anum; 67 atomicData &adata = byanum[anum]; 68 ++token; 69 if (token == tokens.end()) { 70 continue; 71 } 72 ++token; 73 if (token == tokens.end()) { 74 continue; 75 } 76 unsigned int isotope; 77 istr.clear(); 78 istr.str(*token); 79 istr >> isotope; 80 ++token; 81 if (token == tokens.end()) { 82 continue; 83 } 84 double mass; 85 istr.clear(); 86 istr.str(*token); 87 istr >> mass; 88 ++token; 89 if (token == tokens.end()) { 90 continue; 91 } 92 double abundance; 93 istr.clear(); 94 istr.str(*token); 95 istr >> abundance; 96 adata.d_isotopeInfoMap[isotope] = std::make_pair(mass, abundance); 97 } 98 } 99 } 100 } 101 initInstance()102void PeriodicTable::initInstance() { 103 ds_instance = std::unique_ptr<PeriodicTable>(new PeriodicTable()); 104 } 105 getTable()106PeriodicTable *PeriodicTable::getTable() { 107 #ifdef RDK_BUILD_THREADSAFE_SSS 108 static std::once_flag pt_init_once; 109 std::call_once(pt_init_once, initInstance); 110 #else 111 if (!ds_instance) { 112 initInstance(); 113 } 114 #endif 115 return ds_instance.get(); 116 } 117 118 } // namespace RDKit 119