PeriodicTable.h

Go to the documentation of this file.
00001 //
00002 //  Copyright (C) 2001-2011 Rational Discovery LLC
00003 //
00004 //   @@ All Rights Reserved @@
00005 //  This file is part of the RDKit.
00006 //  The contents are covered by the terms of the BSD license
00007 //  which is included in the file license.txt, found at the root
00008 //  of the RDKit source tree.
00009 //
00010 #ifndef _RD_PERIODIC_TABLE_H
00011 #define _RD_PERIODIC_TABLE_H
00012 
00013 #include <map>
00014 #include <vector>
00015 #include <RDGeneral/types.h>
00016 #include "atomic_data.h"
00017 
00018 namespace RDKit {
00019 
00020   //! singleton class for retrieving information about atoms
00021   /*!
00022     Use the singleton like this:
00023       
00024     \verbatim
00025     const PeriodicTable *tbl = PeriodicTable::getTable();
00026     tbl->getAtomicWeight(6); // get atomic weight for Carbon
00027     tbl->getAtomicWeight("C"); // get atomic weight for Carbon
00028     \endverbatim
00029       
00030   */
00031   class PeriodicTable {
00032 
00033   public:
00034 
00035     //! returns a pointer to the singleton PeriodicTable
00036     /*
00037         \return a pointer to the singleton ParamCollection
00038 
00039         <b>Notes:</b>
00040           - do <b>not</b> delete the pointer returned here
00041           - if the singleton PeriodicTable has already been instantiated and
00042             the singleton will be returned, otherwise the singleton will
00043             be constructed.
00044 
00045      */
00046     static PeriodicTable *getTable(); 
00047         
00048     ~PeriodicTable() {
00049       byanum.clear();
00050       byname.clear();
00051     };
00052 
00053     
00054     //! returns the atomic weight
00055     double getAtomicWeight( UINT atomicNumber ) const {
00056       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00057       double mass = byanum[atomicNumber].Mass();
00058       return mass;
00059     }
00060     //! \overload
00061     double getAtomicWeight( const std::string &elementSymbol) const {
00062       PRECONDITION(byname.count(elementSymbol),"Element not found");
00063       int anum = byname.find(elementSymbol)->second;
00064       double mass = byanum[anum].Mass();
00065       return mass;
00066     }
00067     //! \overload
00068     double getAtomicWeight( char * elementSymbol ) const {
00069       return getAtomicWeight(std::string(elementSymbol));
00070     }
00071 
00072     //! returns the atomic number
00073     int getAtomicNumber( char *elementSymbol ) const {
00074       std::string symb(elementSymbol);
00075       
00076       return getAtomicNumber(symb);
00077     }
00078     //! overload
00079     int getAtomicNumber( const std::string &elementSymbol ) const {
00080       // this little optimization actually makes a measurable difference
00081       // in molecule-construction time
00082       int anum=-1;
00083       if(elementSymbol=="C") anum=6;
00084       else if(elementSymbol=="N") anum=7;
00085       else if(elementSymbol=="O") anum=8;
00086       else anum = byname.find(elementSymbol)->second;
00087       POSTCONDITION(anum>-1,"Element '" + elementSymbol +"' not found");
00088       return anum;
00089     }
00090 
00091     //! returns the atomic symbol
00092     std::string getElementSymbol(UINT atomicNumber) const {
00093       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00094       return byanum[atomicNumber].Symbol();
00095     }
00096 
00097     //! returns the atom's van der Waals radius
00098     double getRvdw(UINT atomicNumber) const {
00099       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00100       return byanum[atomicNumber].Rvdw();
00101     }
00102     //! \overload
00103     double getRvdw(const std::string &elementSymbol ) const {
00104       PRECONDITION(byname.count(elementSymbol),"Element '" + elementSymbol +"' not found");
00105       return getRvdw(byname.find(elementSymbol)->second);
00106     }
00107     //! \overload
00108     double getRvdw(char *elementSymbol ) const {
00109       return getRvdw(std::string(elementSymbol));
00110     }
00111 
00112     //! returns the atom's covalent radius
00113     double getRcovalent(UINT atomicNumber) const {
00114       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00115       return byanum[atomicNumber].Rcov();
00116     }
00117     //! \overload
00118     double getRcovalent(const std::string &elementSymbol) const {
00119       PRECONDITION(byname.count(elementSymbol),"Element '" + elementSymbol +"' not found");
00120       return getRcovalent(byname.find(elementSymbol)->second);
00121     }
00122     //! \overload
00123     double getRcovalent(char *elementSymbol ) const {
00124       return getRcovalent(std::string(elementSymbol));
00125     }
00126 
00127     //! returns the atom's bond radius
00128     double getRb0(UINT atomicNumber) const {
00129       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00130       return byanum[atomicNumber].Rb0();
00131     }
00132     //! \overload
00133     double getRb0(const std::string &elementSymbol) const {
00134       PRECONDITION(byname.count(elementSymbol),"Element '" + elementSymbol +"' not found");
00135       return getRb0(byname.find(elementSymbol)->second);
00136     }
00137     //! \overload
00138     double getRb0(char *elementSymbol ) const {
00139       return getRb0(std::string(elementSymbol));
00140     }
00141 
00142     //! returns the atom's default valence 
00143     int getDefaultValence(UINT atomicNumber) const {
00144       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00145       return byanum[atomicNumber].DefaultValence();
00146     }
00147     //! \overload
00148     int getDefaultValence(const std::string &elementSymbol) const {
00149       PRECONDITION(byname.count(elementSymbol),"Element '" + elementSymbol +"' not found");
00150       return getDefaultValence(byname.find(elementSymbol)->second);
00151     }
00152     //! \overload
00153     int getDefaultValence(char *elementSymbol ) const {
00154       return getDefaultValence(std::string(elementSymbol));
00155     }
00156 
00157     //! returns a vector of all stable valences. For atoms where
00158     //! we really don't have any idea what a reasonable maximum
00159     //! valence is (like transition metals), the vector ends with -1
00160     const INT_VECT &getValenceList( UINT atomicNumber ) const {
00161       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00162       return byanum[atomicNumber].ValenceList();
00163     }
00164     //! \overload
00165     const INT_VECT &getValenceList( const std::string &elementSymbol) const {
00166       PRECONDITION(byname.count(elementSymbol),"Element '" + elementSymbol +"' not found");
00167       return getValenceList(byname.find(elementSymbol)->second);
00168     }
00169     //! \overload
00170     const INT_VECT &getValenceList(char *elementSymbol ) const {
00171       return getValenceList(std::string(elementSymbol));
00172     }
00173 
00174     //! returns the number of outer shell electrons
00175     int getNouterElecs( UINT atomicNumber ) const {
00176       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00177       return byanum[atomicNumber].NumOuterShellElec();
00178     }
00179     //! \overload
00180     int getNouterElecs( const std::string &elementSymbol) const {
00181       PRECONDITION(byname.count(elementSymbol),"Element '" + elementSymbol +"' not found");
00182       return getNouterElecs(byname.find(elementSymbol)->second);
00183     }
00184     //! \overload
00185     int getNouterElecs(char *elementSymbol ) const {
00186       return getNouterElecs(std::string(elementSymbol));
00187     }
00188 
00189     //! returns the number of the most common isotope
00190     int getMostCommonIsotope( UINT atomicNumber ) const {
00191       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00192       return byanum[atomicNumber].MostCommonIsotope();
00193     }
00194     //! \overload
00195     int getMostCommonIsotope( const std::string &elementSymbol) const {
00196       PRECONDITION(byname.count(elementSymbol),"Element '" + elementSymbol +"' not found");
00197       return getMostCommonIsotope(byname.find(elementSymbol)->second);
00198     }
00199     //! \overload
00200     int getMostCommonIsotope(char *elementSymbol ) const {
00201       return getMostCommonIsotope(std::string(elementSymbol));
00202     }
00203 
00204     //! returns the mass of the most common isotope
00205     double getMostCommonIsotopeMass( UINT atomicNumber ) const {
00206       PRECONDITION(atomicNumber<byanum.size(),"Atomic number not found");
00207       return byanum[atomicNumber].MostCommonIsotopeMass();
00208     }
00209     //! \overload
00210     double getMostCommonIsotopeMass( const std::string &elementSymbol) const {
00211       PRECONDITION(byname.count(elementSymbol),"Element '" + elementSymbol +"' not found");
00212       return getMostCommonIsotopeMass(byname.find(elementSymbol)->second);
00213     }
00214     //! \overload
00215     double getMostCommonIsotopeMass(char *elementSymbol ) const {
00216       return getMostCommonIsotopeMass(std::string(elementSymbol));
00217     }
00218 
00219     
00220     //! convenience function to determine which atom is more electronegative
00221     /*!
00222 
00223        check if atom with atomic number \c anum1 is more 
00224        electronegative than the one with \c anum2
00225        this is rather lame but here is how we do it
00226          - the atom with the higher number of outer shell electrons
00227            is considered more electronegative
00228          - if the # of outer shell elecs are the same
00229            the atom with the lower atomic weight is more electronegative
00230 
00231     */
00232     bool moreElectroNegative(UINT anum1, UINT anum2) const {
00233       PRECONDITION(anum1<byanum.size(),"Atomic number not found");
00234       PRECONDITION(anum2<byanum.size(),"Atomic number not found");
00235       // FIX: the atomic_data needs to have real electronegativity values
00236       UINT ne1 = getNouterElecs(anum1);
00237       UINT ne2 = getNouterElecs(anum2);
00238       if (ne1 > ne2) {
00239         return true;
00240       }
00241       if (ne1 == ne2) {
00242         if (anum1 < anum2) {
00243           return true;
00244         }
00245       }
00246       return false;
00247     }
00248 
00249 
00250   private:
00251 
00252     PeriodicTable();
00253     PeriodicTable &operator =( const PeriodicTable & );
00254 
00255     static class PeriodicTable *ds_instance;
00256 
00257     std::vector<atomicData> byanum;
00258     STR_UINT_MAP byname;
00259   };
00260 
00261 };
00262 
00263 #endif