00001 // 00002 // Copyright (C) 2001-2010 Greg Landrum and 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 /*! \file Atom.h 00011 00012 \brief Defines the Atom class and associated typedefs 00013 00014 */ 00015 #ifndef _RD_ATOM_H 00016 #define _RD_ATOM_H 00017 00018 // Std stuff 00019 #include <iostream> 00020 #include <boost/foreach.hpp> 00021 00022 // ours 00023 #include <Query/QueryObjects.h> 00024 #include <RDGeneral/types.h> 00025 00026 00027 namespace RDKit{ 00028 class ROMol; 00029 class RWMol; 00030 00031 //! The class for representing atoms 00032 /*! 00033 00034 <b>Notes:</b> 00035 - many of the methods of Atom require that the Atom be associated 00036 with a molecule (an ROMol). 00037 - each Atom maintains a Dict of \c properties: 00038 - Each \c property is keyed by name and can store an 00039 arbitrary type. 00040 - \c Properties can be marked as \c calculated, in which case 00041 they will be cleared when the \c clearComputedProps() method 00042 is called. 00043 - Because they have no impact upon chemistry, all \c property 00044 operations are \c const, this allows extra flexibility for 00045 clients who need to store extra data on Atom objects. 00046 - Atom objects are lazy about computing their explicit and implicit valence 00047 values. These will not be computed until their values are requested. 00048 00049 <b>Chirality:</b> 00050 00051 The chirality of an Atom is determined by two things: 00052 - its \c chiralTag 00053 - the input order of its bonds (see note below for handling of 00054 implicit Hs) 00055 00056 For tetrahedral coordination, the \c chiralTag tells you what 00057 direction you have to rotate to get from bond 2 to bond 3 while looking 00058 down bond 1. This is pretty much identical to the SMILES representation of 00059 chirality. 00060 00061 NOTE: if an atom has an implicit H, the bond to that H is considered to be 00062 at the *end* of the list of other bonds. 00063 00064 */ 00065 class Atom { 00066 friend class MolPickler; //!< the pickler needs access to our privates 00067 friend class ROMol; 00068 friend class RWMol; 00069 public: 00070 00071 typedef boost::shared_ptr<Atom> ATOM_SPTR; 00072 typedef boost::shared_ptr<const Atom> C_ATOM_SPTR; 00073 // FIX: grn... 00074 typedef Queries::Query<int,Atom const *,true> QUERYATOM_QUERY; 00075 00076 //! store hybridization 00077 typedef enum { 00078 UNSPECIFIED=0, //!< hybridization that hasn't been specified 00079 S, 00080 SP, 00081 SP2, 00082 SP3, 00083 SP3D, 00084 SP3D2, 00085 OTHER //!< unrecognized hybridization 00086 } HybridizationType; 00087 00088 //! store type of chirality 00089 typedef enum { 00090 CHI_UNSPECIFIED=0, //!< chirality that hasn't been specified 00091 CHI_TETRAHEDRAL_CW, //!< tetrahedral: clockwise rotation (SMILES @@) 00092 CHI_TETRAHEDRAL_CCW,//!< tetrahedral: counter-clockwise rotation (SMILES @) 00093 CHI_OTHER //!< some unrecognized type of chirality 00094 } ChiralType; 00095 00096 Atom(); 00097 //! construct an Atom with a particular atomic number 00098 explicit Atom(unsigned int num); 00099 //! construct an Atom with a particular symbol (looked up in the PeriodicTable) 00100 explicit Atom(std::string what); 00101 Atom(const Atom & other); 00102 virtual ~Atom(); 00103 00104 //! makes a copy of this Atom and returns a pointer to it. 00105 /*! 00106 <b>Note:</b> the caller is responsible for <tt>delete</tt>ing the result 00107 */ 00108 virtual Atom *copy() const; 00109 00110 //! returns our atomic number 00111 const int getAtomicNum() const { return d_atomicNum; }; 00112 //! sets our atomic number 00113 void setAtomicNum(int newNum) { d_atomicNum = newNum; }; 00114 00115 //! returns our symbol (determined by our atomic number) 00116 std::string getSymbol() const; 00117 00118 //! returns a reference to the ROMol that owns this Atom 00119 ROMol &getOwningMol() const { return *dp_mol; }; 00120 00121 //! returns our index within the ROMol 00122 const unsigned int getIdx() const {return d_index;}; 00123 //! sets our index within the ROMol 00124 /*! 00125 <b>Notes:</b> 00126 - this makes no sense if we do not have an owning molecule 00127 - the index should be <tt>< this->getOwningMol()->getNumAtoms()</tt> 00128 */ 00129 void setIdx(unsigned int index) {d_index=index;}; 00130 00131 //! returns the explicit degree of the Atom (number of bonded 00132 //! neighbors in the graph) 00133 /*! 00134 <b>Notes:</b> 00135 - requires an owning molecule 00136 */ 00137 unsigned int getDegree() const; 00138 00139 //! returns the total degree of the Atom (number of bonded 00140 //! neighbors + number of Hs) 00141 /*! 00142 <b>Notes:</b> 00143 - requires an owning molecule 00144 */ 00145 unsigned int getTotalDegree() const; 00146 00147 //! \brief returns the total number of Hs (implicit and explicit) that 00148 //! this Atom is bound to 00149 /*! 00150 <b>Notes:</b> 00151 - requires an owning molecule 00152 */ 00153 unsigned int getTotalNumHs(bool includeNeighbors=false) const; 00154 00155 //! returns the number of implicit Hs this Atom is bound to 00156 /*! 00157 <b>Notes:</b> 00158 - requires an owning molecule 00159 */ 00160 unsigned int getNumImplicitHs() const; 00161 00162 //! returns the explicit valence (including Hs) of this atom 00163 int getExplicitValence() const; 00164 00165 //! returns the implicit valence for this Atom 00166 /*! 00167 <b>Notes:</b> 00168 - requires an owning molecule 00169 */ 00170 int getImplicitValence() const; 00171 00172 //! returns the number of radical electrons for this Atom 00173 /*! 00174 <b>Notes:</b> 00175 - requires an owning molecule 00176 */ 00177 unsigned int getNumRadicalElectrons() const { return d_numRadicalElectrons; }; 00178 void setNumRadicalElectrons(unsigned int num) { d_numRadicalElectrons=num; }; 00179 00180 00181 //! returns the formal charge of this atom 00182 const int getFormalCharge() const { return d_formalCharge; }; 00183 //! set's the formal charge of this atom 00184 void setFormalCharge(int what) { d_formalCharge = what;} ; 00185 00186 //! \brief sets our \c noImplicit flag, indicating whether or not 00187 //! we are allowed to have implicit Hs 00188 void setNoImplicit( bool what ) { df_noImplicit = what; }; 00189 //! returns the \c noImplicit flag 00190 bool getNoImplicit() const { return df_noImplicit; }; 00191 00192 //! sets our number of explict Hs 00193 void setNumExplicitHs(unsigned int what) { d_numExplicitHs = what; }; 00194 //! returns our number of explict Hs 00195 unsigned int getNumExplicitHs() const { return d_numExplicitHs; }; 00196 00197 //! sets our \c isAromatic flag, indicating whether or not we are aromatic 00198 void setIsAromatic( bool what ) { df_isAromatic = what; }; 00199 //! returns our \c isAromatic flag 00200 bool getIsAromatic() const { return df_isAromatic; }; 00201 00202 //! sets our mass (for isotopes) 00203 void setMass( double what) { d_mass = what; }; 00204 //! returns our mass 00205 double getMass() const {return d_mass; }; 00206 00207 //! sets our \c dativeFlag 00208 // intended to be used only in construction. 00209 // NOTE: the dative flag is not currently used anywhere 00210 void setDativeFlag(int what) { 00211 d_dativeFlag = what; 00212 }; 00213 //! returns our \c dativeFlag 00214 // NOTE: the dative flag is not currently used anywhere 00215 int getDativeFlag() const { 00216 return d_dativeFlag; 00217 }; 00218 bool hasDativeFlag(int what) const { 00219 return d_dativeFlag==what; 00220 }; 00221 //! clears our \c dativeFlag 00222 // NOTE: the dative flag is not currently used anywhere 00223 void clearDativeFlag(){ d_dativeFlag = 0; }; 00224 00225 //! sets our \c chiralTag 00226 void setChiralTag(ChiralType what) { d_chiralTag = what; }; 00227 //! inverts our \c chiralTag 00228 void invertChirality(); 00229 //! returns our \c chiralTag 00230 ChiralType getChiralTag() const { return d_chiralTag; }; 00231 00232 //! sets our hybridization 00233 void setHybridization(HybridizationType what) { d_hybrid = what; }; 00234 //! returns our hybridization 00235 HybridizationType getHybridization() const { return d_hybrid; }; 00236 00237 // ------------------------------------ 00238 // Some words of explanation before getting down into 00239 // the query stuff. 00240 // These query functions are really only here so that they 00241 // can have real functionality in subclasses (like QueryAtoms). 00242 // Since pretty much it's gonna be a mistake to call any of these 00243 // (ever), we're saddling them all with a precondition which 00244 // is guaranteed to fail. I'd like to have them be pure virtual, 00245 // but that doesn't work since we need to be able to instantiate 00246 // Atoms. 00247 // ------------------------------------ 00248 00249 // This method can be used to distinguish query atoms from standard atoms: 00250 virtual bool hasQuery() const { return false; }; 00251 00252 //! NOT CALLABLE 00253 virtual void setQuery(QUERYATOM_QUERY *what); 00254 00255 //! NOT CALLABLE 00256 virtual QUERYATOM_QUERY *getQuery() const; 00257 //! NOT CALLABLE 00258 virtual void expandQuery(QUERYATOM_QUERY *what, 00259 Queries::CompositeQueryType how=Queries::COMPOSITE_AND, 00260 bool maintainOrder=true); 00261 00262 //! returns whether or not we match the argument 00263 /*! 00264 <b>Notes:</b> 00265 - for Atom objects, "match" means that atomic numbers are the same. 00266 */ 00267 virtual bool Match(Atom const *what) const; 00268 //! \overload 00269 virtual bool Match(const ATOM_SPTR what) const; 00270 00271 00272 // ------------------------------------ 00273 // Local Property Dict functionality 00274 // all setProp functions are const because they 00275 // are not meant to change the atom chemically 00276 // ------------------------------------ 00277 //! returns a list with the names of our \c properties 00278 STR_VECT getPropList() const { 00279 return dp_props->keys(); 00280 } 00281 00282 //! sets a \c property value 00283 /*! 00284 \param key the name under which the \c property should be stored. 00285 If a \c property is already stored under this name, it will be 00286 replaced. 00287 \param val the value to be stored 00288 \param computed (optional) allows the \c property to be flagged 00289 \c computed. 00290 */ 00291 template <typename T> 00292 void setProp(const char *key, T val, bool computed=false) const{ 00293 00294 //if(!dp_props) dp_props = new Dict(); 00295 std::string what(key); 00296 setProp(what,val, computed); 00297 } 00298 00299 //! \overload 00300 template <typename T> 00301 void setProp(const std::string key, T val, bool computed=false) const { 00302 if (computed) { 00303 STR_VECT compLst; 00304 if(hasProp("__computedProps")) getProp("__computedProps", compLst); 00305 if (std::find(compLst.begin(), compLst.end(), key) == compLst.end()) { 00306 compLst.push_back(key); 00307 dp_props->setVal("__computedProps", compLst); 00308 } 00309 } 00310 //setProp(key.c_str(),val); 00311 dp_props->setVal(key, val); 00312 } 00313 00314 //! allows retrieval of a particular property value 00315 /*! 00316 00317 \param key the name under which the \c property should be stored. 00318 If a \c property is already stored under this name, it will be 00319 replaced. 00320 \param res a reference to the storage location for the value. 00321 00322 <b>Notes:</b> 00323 - if no \c property with name \c key exists, a KeyErrorException will be thrown. 00324 - the \c boost::lexical_cast machinery is used to attempt type conversions. 00325 If this fails, a \c boost::bad_lexical_cast exception will be thrown. 00326 00327 */ 00328 template <typename T> 00329 void getProp(const char *key,T &res) const { 00330 //PRECONDITION(dp_props,"getProp called on empty property dict"); 00331 dp_props->getVal(key,res); 00332 } 00333 //! \overload 00334 template <typename T> 00335 void getProp(const std::string key,T &res) const { 00336 //return getProp(key.c_str(),res); 00337 dp_props->getVal(key,res); 00338 } 00339 00340 //! returns whether or not we have a \c property with name \c key 00341 bool hasProp(const char *key) const { 00342 if(!dp_props) return false; 00343 return dp_props->hasVal(key); 00344 }; 00345 //! \overload 00346 bool hasProp(const std::string key) const { 00347 if(!dp_props) return false; 00348 return dp_props->hasVal(key); 00349 }; 00350 00351 00352 //! clears the value of a \c property 00353 /*! 00354 <b>Notes:</b> 00355 - if no \c property with name \c key exists, a KeyErrorException 00356 will be thrown. 00357 - if the \c property is marked as \c computed, it will also be removed 00358 from our list of \c computedProperties 00359 */ 00360 void clearProp(const char *key) const { 00361 std::string what(key); 00362 clearProp(what); 00363 }; 00364 //! \overload 00365 void clearProp(const std::string key) const { 00366 if(hasProp("__computedProps")){ 00367 STR_VECT compLst; 00368 getProp("__computedProps", compLst); 00369 STR_VECT_I svi = std::find(compLst.begin(), compLst.end(), key); 00370 if (svi != compLst.end()) { 00371 compLst.erase(svi); 00372 dp_props->setVal("__computedProps", compLst); 00373 } 00374 } 00375 dp_props->clearVal(key); 00376 }; 00377 00378 //! clears all of our \c computed \c properties 00379 void clearComputedProps() const { 00380 if(!hasProp("__computedProps")) return; 00381 STR_VECT compLst; 00382 getProp("__computedProps", compLst); 00383 BOOST_FOREACH(const std::string &sv,compLst){ 00384 dp_props->clearVal(sv); 00385 } 00386 compLst.clear(); 00387 dp_props->setVal("__computedProps", compLst); 00388 } 00389 00390 //! returns the perturbation order for a list of integers 00391 /*! 00392 00393 This value is associated with chirality. 00394 00395 \param probe a list of bond indices. This must be the same 00396 length as our number of incoming bonds (our degree). 00397 00398 \return the number of swaps required to convert the ordering 00399 of the probe list to match the order of our incoming bonds: 00400 e.g. if our incoming bond order is: <tt>[0,1,2,3]</tt> 00401 \verbatim 00402 getPerturbationOrder([1,0,2,3]) = 1 00403 getPerturbationOrder([1,2,3,0]) = 3 00404 getPerturbationOrder([1,2,0,3]) = 2 00405 \endverbatim 00406 00407 See the class documentation for a more detailed description 00408 of our representation of chirality. 00409 00410 <b>Notes:</b> 00411 - requires an owning molecule 00412 00413 */ 00414 int getPerturbationOrder(INT_LIST probe) const; 00415 00416 //! calculates any of our lazy \c properties 00417 /*! 00418 <b>Notes:</b> 00419 - requires an owning molecule 00420 - the current lazy \c properties are implicit and explicit valence 00421 */ 00422 void updatePropertyCache(bool strict=true); 00423 00424 //! calculates and returns our explicit valence 00425 /*! 00426 <b>Notes:</b> 00427 - requires an owning molecule 00428 */ 00429 int calcExplicitValence(bool strict=true); 00430 00431 //! calculates and returns our implicit valence 00432 /*! 00433 <b>Notes:</b> 00434 - requires an owning molecule 00435 */ 00436 int calcImplicitValence(bool strict=true); 00437 00438 protected: 00439 //! sets our owning molecule 00440 void setOwningMol(ROMol *other); 00441 //! sets our owning molecule 00442 void setOwningMol(ROMol &other) {setOwningMol(&other);}; 00443 00444 bool df_isAromatic; 00445 bool df_noImplicit; 00446 int d_dativeFlag; 00447 unsigned int d_numExplicitHs; 00448 int d_formalCharge; 00449 unsigned int d_atomicNum; 00450 unsigned int d_index; 00451 // NOTE that these cannot be signed ints, they are calculated using 00452 // a lazy scheme and are initialized to -1 to indicate that the 00453 // calculation has not yet been done. 00454 int d_implicitValence, d_explicitValence; 00455 unsigned int d_numRadicalElectrons; 00456 ChiralType d_chiralTag; 00457 HybridizationType d_hybrid; 00458 double d_mass; 00459 ROMol *dp_mol; 00460 Dict *dp_props; 00461 void initAtom(); 00462 }; 00463 00464 }; 00465 //! allows Atom objects to be dumped to streams 00466 std::ostream & operator<<(std::ostream& target, const RDKit::Atom &at); 00467 00468 #endif
1.7.1