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 explicit degree of the Atom (number of bonded
00123     //!   neighbors in the graph)
00124     /*!
00125       <b>Notes:</b>
00126         - requires an owning molecule
00127     */
00128     unsigned int getDegree() const;
00129 
00130     //! returns the total degree of the Atom (number of bonded
00131     //!   neighbors + number of Hs)
00132     /*!
00133       <b>Notes:</b>
00134         - requires an owning molecule
00135     */
00136     unsigned int getTotalDegree() const;
00137 
00138     //! \brief returns the total number of Hs (implicit and explicit) that
00139     //! this Atom is bound to
00140     /*!
00141       <b>Notes:</b>
00142         - requires an owning molecule
00143     */
00144     unsigned int getTotalNumHs(bool includeNeighbors=false) const;
00145 
00146     //! returns the number of implicit Hs this Atom is bound to
00147     /*!
00148       <b>Notes:</b>
00149         - requires an owning molecule
00150     */
00151     unsigned int getNumImplicitHs() const;
00152 
00153     //! returns the number of explicit Hs this Atom is bound to
00154     int getExplicitValence() const;
00155 
00156     //! returns the implicit valence for this Atom
00157     /*!
00158       <b>Notes:</b>
00159         - requires an owning molecule
00160     */
00161     int getImplicitValence() const;
00162 
00163     //! returns the number of radical electrons for this Atom
00164     /*!
00165       <b>Notes:</b>
00166         - requires an owning molecule
00167     */
00168     unsigned int getNumRadicalElectrons() const { return d_numRadicalElectrons; };
00169     void setNumRadicalElectrons(unsigned int num) { d_numRadicalElectrons=num; };
00170 
00171 
00172     //! returns the formal charge of this atom
00173     const int getFormalCharge() const { return d_formalCharge; };
00174     //! set's the formal charge of this atom
00175     void setFormalCharge(int what) { d_formalCharge = what;} ;
00176 
00177     //! \brief sets our \c noImplicit flag, indicating whether or not
00178     //!  we are allowed to have implicit Hs
00179     void setNoImplicit( bool what ) { df_noImplicit = what; };
00180     //! returns the \c noImplicit flag
00181     bool getNoImplicit() const { return df_noImplicit; };
00182     
00183     //! sets our number of explict Hs
00184     void setNumExplicitHs(unsigned int what) { d_numExplicitHs = what; };
00185     //! returns our number of explict Hs
00186     unsigned int getNumExplicitHs() const { return d_numExplicitHs; };
00187   
00188     //! sets our \c isAromatic flag, indicating whether or not we are aromatic
00189     void setIsAromatic( bool what ) { df_isAromatic = what; };
00190     //! returns our \c isAromatic flag
00191     bool getIsAromatic() const { return df_isAromatic; };
00192 
00193     //! sets our mass (for isotopes)
00194     void setMass( double what) { d_mass = what; };
00195     //! returns our mass
00196     double getMass() const {return d_mass; };
00197 
00198     //! sets our \c dativeFlag
00199     // intended to be used only in construction.
00200     // NOTE: the dative flag is not currently used anywhere
00201     void setDativeFlag(int what) {
00202       d_dativeFlag = what;
00203     };
00204     //! returns our \c dativeFlag
00205     // NOTE: the dative flag is not currently used anywhere
00206     int getDativeFlag() const {
00207       return d_dativeFlag;
00208     };
00209     bool hasDativeFlag(int what) const {
00210       return d_dativeFlag==what;
00211     };
00212     //! clears our \c dativeFlag
00213     // NOTE: the dative flag is not currently used anywhere
00214     void clearDativeFlag(){ d_dativeFlag = 0; };
00215 
00216     //! sets our \c chiralTag
00217     void setChiralTag(ChiralType what) { d_chiralTag = what; };
00218     //! inverts our \c chiralTag
00219     void invertChirality();
00220     //! returns our \c chiralTag
00221     ChiralType getChiralTag() const { return d_chiralTag; };
00222 
00223     //! sets our hybridization
00224     void setHybridization(HybridizationType what) { d_hybrid = what; };
00225     //! returns our hybridization
00226     HybridizationType getHybridization() const { return d_hybrid; };
00227 
00228     // ------------------------------------
00229     // Some words of explanation before getting down into
00230     // the query stuff.
00231     // These query functions are really only here so that they
00232     //  can have real functionality in subclasses (like QueryAtoms).
00233     // Since pretty much it's gonna be a mistake to call any of these
00234     //  (ever), we're saddling them all with a precondition which
00235     //  is guaranteed to fail.  I'd like to have them be pure virtual,
00236     //  but that doesn't work since we need to be able to instantiate
00237     //  Atoms.
00238     // ------------------------------------
00239 
00240     // This method can be used to distinguish query atoms from standard atoms:
00241     virtual bool hasQuery() const { return false; };
00242    
00243     //! NOT CALLABLE
00244     virtual void setQuery(QUERYATOM_QUERY *what);
00245 
00246     //! NOT CALLABLE
00247     virtual QUERYATOM_QUERY *getQuery() const;
00248     //! NOT CALLABLE
00249     virtual void expandQuery(QUERYATOM_QUERY *what,
00250                              Queries::CompositeQueryType how=Queries::COMPOSITE_AND,
00251                              bool maintainOrder=true);
00252 
00253     //! returns whether or not we match the argument
00254     /*!
00255         <b>Notes:</b>
00256           - for Atom objects, "match" means that atomic numbers are the same.
00257     */
00258     virtual bool Match(Atom const *what) const;
00259     //! \overload
00260     virtual bool Match(const ATOM_SPTR what) const;
00261   
00262 
00263     // ------------------------------------
00264     //  Local Property Dict functionality
00265     //  all setProp functions are const because they
00266     //     are not meant to change the atom chemically 
00267     // ------------------------------------
00268     //! returns a list with the names of our \c properties
00269     STR_VECT getPropList() const {
00270       return dp_props->keys();
00271     }
00272 
00273     //! sets a \c property value
00274     /*!
00275        \param key the name under which the \c property should be stored.
00276            If a \c property is already stored under this name, it will be
00277            replaced.
00278        \param val the value to be stored
00279        \param computed (optional) allows the \c property to be flagged
00280            \c computed.
00281      */
00282     template <typename T>
00283     void setProp(const char *key, T val, bool computed=false) const{
00284     
00285       //if(!dp_props) dp_props = new Dict();
00286       std::string what(key);
00287       setProp(what,val, computed);
00288     }
00289 
00290     //! \overload
00291     template <typename T>
00292     void setProp(const std::string key, T val, bool computed=false) const {
00293       if (computed) {
00294         STR_VECT compLst;
00295         if(hasProp("computedProps")) getProp("computedProps", compLst);
00296         if (std::find(compLst.begin(), compLst.end(), key) == compLst.end()) {
00297           compLst.push_back(key);
00298           dp_props->setVal("computedProps", compLst);
00299         }
00300       }
00301       //setProp(key.c_str(),val);
00302       dp_props->setVal(key, val);
00303     }
00304 
00305     //! allows retrieval of a particular property value
00306     /*!
00307 
00308        \param key the name under which the \c property should be stored.
00309            If a \c property is already stored under this name, it will be
00310            replaced.
00311        \param res a reference to the storage location for the value.
00312 
00313        <b>Notes:</b>
00314          - if no \c property with name \c key exists, a KeyErrorException will be thrown.
00315          - the \c boost::lexical_cast machinery is used to attempt type conversions.
00316            If this fails, a \c boost::bad_lexical_cast exception will be thrown.
00317 
00318     */
00319     template <typename T>
00320     void getProp(const char *key,T &res) const {
00321       //PRECONDITION(dp_props,"getProp called on empty property dict");
00322       dp_props->getVal(key,res);
00323     }
00324     //! \overload
00325     template <typename T>
00326     void getProp(const std::string key,T &res) const {
00327       //return getProp(key.c_str(),res);
00328       dp_props->getVal(key,res);
00329     }
00330 
00331     //! returns whether or not we have a \c property with name \c key
00332     bool hasProp(const char *key) const {
00333       if(!dp_props) return false;
00334       return dp_props->hasVal(key);
00335     };
00336     //! \overload
00337     bool hasProp(const std::string key) const {
00338       if(!dp_props) return false;
00339       return dp_props->hasVal(key);
00340     };
00341 
00342     
00343     //! clears the value of a \c property
00344     /*!
00345        <b>Notes:</b>
00346          - if no \c property with name \c key exists, a KeyErrorException
00347            will be thrown.
00348          - if the \c property is marked as \c computed, it will also be removed
00349            from our list of \c computedProperties
00350     */
00351     void clearProp(const char *key) const {
00352       std::string what(key);
00353       clearProp(what);
00354     };
00355     //! \overload
00356     void clearProp(const std::string key) const {
00357       if(hasProp("computedProps")){
00358         STR_VECT compLst;
00359         getProp("computedProps", compLst);
00360         STR_VECT_I svi = std::find(compLst.begin(), compLst.end(), key);
00361         if (svi != compLst.end()) {
00362           compLst.erase(svi);
00363           dp_props->setVal("computedProps", compLst);
00364         }
00365       }    
00366       dp_props->clearVal(key);
00367     };
00368 
00369     //! clears all of our \c computed \c properties
00370     void clearComputedProps() const {
00371       if(!hasProp("computedProps")) return;
00372       STR_VECT compLst;
00373       getProp("computedProps", compLst);
00374       STR_VECT_CI svi;
00375       for (svi = compLst.begin(); svi != compLst.end(); svi++) {
00376         dp_props->clearVal(*svi);
00377       }
00378       compLst.clear();
00379       dp_props->setVal("computedProps", compLst);
00380     }
00381 
00382     //! returns the perturbation order for a list of integers
00383     /*!
00384 
00385       This value is associated with chirality.
00386 
00387       \param probe a list of bond indices.  This must be the same
00388         length as our number of incoming bonds (our degree).
00389       
00390       \return the number of swaps required to convert the ordering
00391         of the probe list to match the order of our incoming bonds:
00392         e.g. if our incoming bond order is: <tt>[0,1,2,3]</tt>
00393         \verbatim
00394         getPerturbationOrder([1,0,2,3]) = 1
00395         getPerturbationOrder([1,2,3,0]) = 3
00396         getPerturbationOrder([1,2,0,3]) = 2
00397         \endverbatim
00398 
00399       See the class documentation for a more detailed description
00400       of our representation of chirality.
00401 
00402       <b>Notes:</b>
00403         - requires an owning molecule
00404       
00405     */
00406     int getPerturbationOrder(INT_LIST probe) const;
00407 
00408     //! calculates any of our lazy \c properties
00409     /*!
00410       <b>Notes:</b>
00411         - requires an owning molecule
00412         - the current lazy \c properties are implicit and explicit valence
00413     */
00414     void updatePropertyCache(bool strict=true);
00415 
00416     //! calculates and returns our explicit valence
00417     /*!
00418       <b>Notes:</b>
00419         - requires an owning molecule
00420     */
00421     int calcExplicitValence(bool strict=true);
00422 
00423     //! calculates and returns our implicit valence
00424     /*!
00425       <b>Notes:</b>
00426         - requires an owning molecule
00427     */
00428     int calcImplicitValence(bool strict=true);
00429 
00430   protected:
00431     //! sets our owning molecule
00432     void setOwningMol(ROMol *other);
00433     //! sets our owning molecule
00434     void setOwningMol(ROMol &other) {setOwningMol(&other);};
00435 
00436     bool df_isAromatic; 
00437     bool df_noImplicit;
00438     int d_dativeFlag;
00439     unsigned int d_numExplicitHs;
00440     int d_formalCharge;
00441     unsigned int d_atomicNum;
00442     unsigned int d_index;
00443     // NOTE that these cannot be signed ints, they are calculated using
00444     // a lazy scheme and are initialized to -1 to indicate that the
00445     // calculation has not yet been done.
00446     int d_implicitValence, d_explicitValence;
00447     unsigned int d_numRadicalElectrons;
00448     ChiralType d_chiralTag;
00449     HybridizationType d_hybrid;
00450     double d_mass;
00451     ROMol *dp_mol;
00452     Dict *dp_props;
00453     void initAtom();
00454   };
00455 
00456 };
00457 //! allows Atom objects to be dumped to streams
00458 std::ostream & operator<<(std::ostream& target, const RDKit::Atom &at);
00459 
00460 #endif

Generated on Tue Oct 7 06:10:10 2008 for RDCode by  doxygen 1.5.5