Atom.h

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

Generated on Sat May 24 08:36:32 2008 for RDCode by  doxygen 1.5.3