Bond.h

Go to the documentation of this file.
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 #ifndef _RD_BOND_H
00011 #define _RD_BOND_H
00012 
00013 // std stuff
00014 #include <iostream>
00015 
00016 // Ours
00017 // FIX: grn...
00018 #include <Query/QueryObjects.h>
00019 #include <RDGeneral/types.h>
00020 
00021 namespace RDKit{
00022   class ROMol;
00023   class RWMol;
00024   class Atom;
00025   typedef boost::shared_ptr<Atom>    ATOM_SPTR;
00026 
00027   //! class for representing a bond
00028   /*!
00029 
00030     <b>Notes:</b>
00031       - many of the methods of Atom require that the Atom be associated
00032         with a molecule (an ROMol).
00033       - each Bond maintains a Dict of \c properties:  
00034           - Each \c property is keyed by name and can store an
00035             arbitrary type.
00036           - \c Properties can be marked as \c calculated, in which case
00037             they will be cleared when the \c clearComputedProps() method
00038             is called.
00039           - Because they have no impact upon chemistry, all \c property
00040             operations are \c const, this allows extra flexibility for
00041             clients who need to store extra data on Bond objects.
00042 
00043   */
00044   class Bond {
00045     friend class RWMol;
00046     friend class ROMol;
00047   public:
00048     typedef boost::shared_ptr<Bond>    BOND_SPTR;
00049     // FIX: grn...
00050     typedef Queries::Query<int,Bond const *,true> QUERYBOND_QUERY;
00051 
00052     //! the type of Bond
00053     typedef enum {
00054       UNSPECIFIED = 0,
00055       SINGLE,
00056       DOUBLE,
00057       TRIPLE,
00058       QUADRUPLE,
00059       QUINTUPLE,
00060       HEXTUPLE,
00061       ONEANDAHALF,
00062       TWOANDAHALF,
00063       THREEANDAHALF,
00064       FOURANDAHALF,
00065       FIVEANDAHALF,
00066       AROMATIC,
00067       IONIC,
00068       HYDROGEN,
00069       THREECENTER,
00070       DATIVEONE,   //!< one-electron dative (e.g. from a C in a Cp ring to a metal)
00071       DATIVE,      //!< standard two-electron dative
00072       DATIVEL,     //!< standard two-electron dative
00073       DATIVER,     //!< standard two-electron dative
00074       OTHER
00075     } BondType;
00076 
00077     //! the bond's direction (for chirality)
00078     typedef enum {   
00079       NONE=0,         //!< no special style
00080       BEGINWEDGE,     //!< wedged: narrow at begin
00081       BEGINDASH,      //!< dashed: narrow at begin
00082       // FIX: this may not really be adequate
00083       ENDDOWNRIGHT,   //!< for cis/trans
00084       ENDUPRIGHT,     //!<  ditto
00085       EITHERDOUBLE,   //!< a "crossed" double bond 
00086       UNKNOWN,        //!< intentionally unspecified stereochemistry
00087     } BondDir;
00088     
00089     //! the nature of the bond's stereochem (for cis/trans)
00090     typedef enum {   // stereochemistry of double bonds
00091       STEREONONE=0,  // no special style
00092       STEREOANY,     // intentionally unspecified
00093       // -- Put any true specifications about this point so
00094       // that we can do comparisons like if(bond->getStereo()>Bond::STEREOANY) 
00095       STEREOZ,       // Z double bond
00096       STEREOE,       // E double bond
00097     } BondStereo;
00098     
00099     Bond();
00100     //! construct with a particular BondType
00101     explicit Bond(BondType bT);
00102     Bond(const Bond &other);
00103     virtual ~Bond();
00104     Bond &operator=(const Bond &other);
00105 
00106     //! returns a copy
00107     /*!
00108       <b>Note:</b> the caller is responsible for <tt>delete</tt>ing
00109        the returned pointer.
00110     */
00111     virtual Bond *copy() const;
00112 
00113     //! returns our \c bondType
00114     const BondType getBondType() const { return d_bondType; };
00115     //! sets our \c bondType
00116     void setBondType(BondType bT) { d_bondType = bT; };
00117     //! \brief returns our \c bondType as a double
00118     //!   (e.g. SINGLE->1.0, AROMATIC->1.5, etc.)
00119     double getBondTypeAsDouble() const;
00120 
00121     //! returns our contribution to the explicit valence of an Atom
00122     /*!
00123       <b>Notes:</b>
00124         - requires an owning molecule
00125     */
00126     double getValenceContrib(const Atom *at) const;
00127     // \overload
00128     double getValenceContrib(ATOM_SPTR at) const;
00129 
00130     //! sets our \c isAromatic flag
00131     void setIsAromatic( bool what ) { df_isAromatic = what; };
00132     //! returns the status of our \c isAromatic flag
00133     bool getIsAromatic() const { return df_isAromatic; };
00134 
00135     //! sets our \c isConjugated flag
00136     void setIsConjugated(bool what) {df_isConjugated = what;};
00137     //! returns the status of our \c isConjugated flag
00138     bool getIsConjugated() const {return df_isConjugated;};
00139   
00140     //! returns a reference to the ROMol that owns this Bond
00141     ROMol &getOwningMol() const { return *dp_mol; };
00142     //! sets our owning molecule
00143     void setOwningMol(ROMol *other);
00144     //! sets our owning molecule
00145     void setOwningMol(ROMol &other) {setOwningMol(&other);};
00146 
00147     //! returns our index within the ROMol
00148     /*!
00149       <b>Notes:</b>
00150         - this makes no sense if we do not have an owning molecule
00151 
00152     */
00153     unsigned int getIdx() const {return d_index;};
00154     //! sets our index within the ROMol
00155     /*!
00156       <b>Notes:</b>
00157         - this makes no sense if we do not have an owning molecule
00158         - the index should be <tt>< this->getOwningMol()->getNumBonds()</tt>
00159     */
00160     void setIdx(unsigned int index) {d_index=index;};
00161 
00162     //! returns the index of our begin Atom
00163     /*!
00164       <b>Notes:</b>
00165         - this makes no sense if we do not have an owning molecule
00166     */
00167     unsigned int getBeginAtomIdx() const { return d_beginAtomIdx; };
00168 
00169     //! returns the index of our end Atom
00170     /*!
00171       <b>Notes:</b>
00172         - this makes no sense if we do not have an owning molecule
00173     */
00174     unsigned int getEndAtomIdx() const { return d_endAtomIdx; };
00175 
00176     //! given the index of one Atom, returns the index of the other
00177     /*!
00178       <b>Notes:</b>
00179         - this makes no sense if we do not have an owning molecule
00180     */
00181     unsigned int getOtherAtomIdx(unsigned int thisIdx) const;
00182 
00183     //! sets the index of our begin Atom
00184     /*!
00185       <b>Notes:</b>
00186         - requires an owning molecule
00187     */
00188     void setBeginAtomIdx(unsigned int what);
00189     //! sets the index of our end Atom
00190     /*!
00191       <b>Notes:</b>
00192         - requires an owning molecule
00193     */
00194     void setEndAtomIdx(unsigned int what);
00195 
00196     //! sets our begin Atom
00197     /*!
00198       <b>Notes:</b>
00199         - requires an owning molecule
00200     */
00201     void setBeginAtom(Atom *at);
00202     //! \overload
00203     void setBeginAtom(ATOM_SPTR at);
00204     //! sets our end Atom
00205     /*!
00206       <b>Notes:</b>
00207         - requires an owning molecule
00208     */
00209     void setEndAtom(Atom *at);
00210     //! \overload
00211     void setEndAtom(ATOM_SPTR at);
00212 
00213 
00214     //! returns a pointer to our begin Atom
00215     /*!
00216       <b>Notes:</b>
00217         - requires an owning molecule
00218     */
00219     Atom *getBeginAtom() const;
00220     //! returns a pointer to our end Atom
00221     /*!
00222       <b>Notes:</b>
00223         - requires an owning molecule
00224     */
00225     Atom *getEndAtom() const;
00226     //! returns a pointer to the other Atom
00227     /*!
00228       <b>Notes:</b>
00229         - requires an owning molecule
00230     */
00231     Atom *getOtherAtom(Atom const *what) const;
00232 
00233     // ------------------------------------
00234     // Please see the note in Atom.h for some explanation
00235     // of these methods
00236     // ------------------------------------
00237   
00238     // This method can be used to distinguish query bonds from standard bonds
00239     virtual bool hasQuery() const { return false; };
00240 
00241     // FIX: the const crap here is all mucked up.
00242     //! NOT CALLABLE
00243     virtual void setQuery(QUERYBOND_QUERY *what);
00244     //! NOT CALLABLE
00245     virtual QUERYBOND_QUERY *getQuery() const;
00246 
00247     //! NOT CALLABLE
00248     virtual void expandQuery(QUERYBOND_QUERY *what,
00249                              Queries::CompositeQueryType how=Queries::COMPOSITE_AND,
00250                              bool maintainOrder=true);
00251 
00252     //! returns whether or not we match the argument
00253     /*!
00254         <b>Notes:</b>
00255           - for Bond objects, "match" means that either one of the Bonds
00256             has \c bondType Bond::UNSPECIFIED or both Bonds have the
00257             same \c bondType.
00258     */
00259     virtual bool Match(Bond const *what) const;
00260     //! \overload
00261     virtual bool Match(const Bond::BOND_SPTR what) const;
00262   
00263     //! sets our direction
00264     void setBondDir(BondDir what) { d_dirTag = what; };
00265     //! returns our direction
00266     BondDir getBondDir() const { return d_dirTag; };
00267   
00268     //! sets our stereo code
00269     void setStereo(BondStereo what) { d_stereo = what; };
00270     //! returns our stereo code
00271     BondStereo getStereo() const { return d_stereo; };
00272 
00273     //! returns the indices of our stereo atoms
00274     const INT_VECT &getStereoAtoms() const { return d_stereoAtoms; };
00275     //! \overload
00276     INT_VECT &getStereoAtoms() { return d_stereoAtoms; };
00277   
00278     // ------------------------------------
00279     //  Local Property Dict functionality
00280     //  FIX: at some point this stuff should go in a mixin class
00281     // ------------------------------------
00282     //! returns a list with the names of our \c properties
00283     STR_VECT getPropList() const {
00284       return dp_props->keys();
00285     }
00286 
00287     //! sets a \c property value
00288     /*!
00289        \param key the name under which the \c property should be stored.
00290            If a \c property is already stored under this name, it will be
00291            replaced.
00292        \param val the value to be stored
00293        \param computed (optional) allows the \c property to be flagged
00294            \c computed.
00295      */
00296     template <typename T>
00297     void setProp(const char *key,T val, bool computed=false) const{
00298       //if(!dp_props) dp_props = new Dict();
00299       std::string what(key);
00300       setProp(what,val, computed);
00301     }
00302     //! \overload
00303     template <typename T>
00304     void setProp(const std::string key,T val, bool computed=false ) const{
00305       //setProp(key.c_str(),val);
00306       if (computed) {
00307         STR_VECT compLst;
00308         if(hasProp("__computedProps")) getProp("__computedProps", compLst);
00309         if (std::find(compLst.begin(), compLst.end(), key) == compLst.end()) {
00310           compLst.push_back(key);
00311           dp_props->setVal("__computedProps", compLst);
00312         }
00313       }
00314       dp_props->setVal(key,val);
00315     }
00316 
00317     //! allows retrieval of a particular property value
00318     /*!
00319 
00320        \param key the name under which the \c property should be stored.
00321            If a \c property is already stored under this name, it will be
00322            replaced.
00323        \param res a reference to the storage location for the value.
00324 
00325        <b>Notes:</b>
00326          - if no \c property with name \c key exists, a KeyErrorException will be thrown.
00327          - the \c boost::lexical_cast machinery is used to attempt type conversions.
00328            If this fails, a \c boost::bad_lexical_cast exception will be thrown.
00329 
00330     */
00331     template <typename T>
00332     void getProp(const char *key,T &res) const {
00333       PRECONDITION(dp_props,"getProp called on empty property dict");
00334       dp_props->getVal(key,res);
00335     }
00336     //! \overload
00337     template <typename T>
00338     void getProp(const std::string key,T &res) const {
00339       PRECONDITION(dp_props,"getProp called on empty property dict");
00340       dp_props->getVal(key,res);
00341     
00342     }
00343 
00344     //! returns whether or not we have a \c property with name \c key
00345     bool hasProp(const char *key) const {
00346       if(!dp_props) return false;
00347       return dp_props->hasVal(key);
00348     };
00349     //! \overload
00350     bool hasProp(const std::string key) const {
00351       if(!dp_props) return false;
00352       return dp_props->hasVal(key);
00353     };
00354 
00355     //! clears the value of a \c property
00356     /*!
00357        <b>Notes:</b>
00358          - if no \c property with name \c key exists, a KeyErrorException
00359            will be thrown.
00360          - if the \c property is marked as \c computed, it will also be removed
00361            from our list of \c computedProperties
00362     */
00363     void clearProp(const char *key) const {
00364       std::string what(key);
00365       clearProp(what);
00366     };
00367     //! \overload
00368     void clearProp(const std::string key) const {
00369       if(hasProp("__computedProps")){
00370         STR_VECT compLst;
00371         getProp("__computedProps", compLst);
00372         STR_VECT_I svi = std::find(compLst.begin(), compLst.end(), key);
00373         if (svi != compLst.end()) {
00374           compLst.erase(svi);
00375           dp_props->setVal("__computedProps", compLst);
00376         }
00377       }
00378       dp_props->clearVal(key);
00379     };
00380 
00381     //! clears all of our \c computed \c properties
00382     void clearComputedProps() const {
00383       if(!hasProp("__computedProps")) return;
00384       STR_VECT compLst;
00385       getProp("__computedProps", compLst);
00386       STR_VECT_CI svi;
00387       for (svi = compLst.begin(); svi != compLst.end(); svi++) {
00388         dp_props->clearVal(*svi);
00389       }
00390       compLst.clear();
00391       dp_props->setVal("__computedProps", compLst);
00392     }
00393 
00394     //! calculates any of our lazy \c properties
00395     /*!
00396       <b>Notes:</b>
00397         - requires an owning molecule
00398     */
00399     void updatePropertyCache(bool strict=true) {;};
00400 
00401   protected:
00402     //! sets our owning molecule
00403     //void setOwningMol(ROMol *other);
00404     //! sets our owning molecule
00405     //void setOwningMol(ROMol &other) {setOwningMol(&other);};
00406     BondType d_bondType;
00407     ROMol *dp_mol;
00408     bool df_isAromatic;
00409     bool df_isConjugated;
00410     unsigned int d_index;
00411     unsigned int d_beginAtomIdx,d_endAtomIdx;
00412     BondDir d_dirTag;
00413     BondStereo d_stereo;
00414     INT_VECT d_stereoAtoms;
00415     //Atom::ATOM_SPTR dsp_beginAtom,dsp_endAtom;
00416     Dict *dp_props;
00417 
00418     void initBond();
00419   };
00420 
00421 };
00422 
00423 //! allows Bond objects to be dumped to streams
00424 extern std::ostream & operator<<(std::ostream& target, const RDKit::Bond &b);
00425 
00426 #endif