RDCode: Atom.h Source File

# 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