Mercurial > repos > deepakjadmin > mayatool3_test2
diff lib/Bond.pm @ 0:4816e4a8ae95 draft default tip
Uploaded
author | deepakjadmin |
---|---|
date | Wed, 20 Jan 2016 09:23:18 -0500 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Bond.pm Wed Jan 20 09:23:18 2016 -0500 @@ -0,0 +1,1512 @@ +package Bond; +# +# $RCSfile: Bond.pm,v $ +# $Date: 2015/02/28 20:47:02 $ +# $Revision: 1.40 $ +# +# Author: Manish Sud <msud@san.rr.com> +# +# Copyright (C) 2015 Manish Sud. All rights reserved. +# +# This file is part of MayaChemTools. +# +# MayaChemTools is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. +# +# MayaChemTools is distributed in the hope that it will be useful, but without +# any warranty; without even the implied warranty of merchantability of fitness +# for a particular purpose. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or +# write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, +# Boston, MA, 02111-1307, USA. +# + +use strict; +use Carp; +use Exporter; +use Storable (); +use Scalar::Util (); +use ObjectProperty; + +use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); + +@ISA = qw(ObjectProperty Exporter); +@EXPORT = qw(); +@EXPORT_OK = qw(); + +%EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); + +# Setup class variables... +my($ClassName, $ObjectID); +_InitializeClass(); + +# Overload Perl functions... +use overload '""' => 'StringifyBond'; + +# Class constructor... +sub new { + my($Class, %NamesAndValues) = @_; + + # Initialize object... + my $This = {}; + bless $This, ref($Class) || $Class; + $This->_InitializeBond(); + + $This->_InitializeBondProperties(%NamesAndValues); + + return $This; +} + +# Initialize object data... +# +sub _InitializeBond { + my($This) = @_; + my($ObjectID) = _GetNewObjectID(); + + # All other property names and values along with all Set/Get<PropertyName> methods + # are implemented on-demand using ObjectProperty class. + $This->{ID} = $ObjectID; + + # Bond from and to atoms indicate begining and ending bond atoms... + $This->{BondFromAtom} = undef; + $This->{BondToAtom} = undef; + + $This->{BondOrder} = ''; + $This->{BondType} = ''; + $This->{BondStereochemistry} = ''; +} + +# Initialize class ... +sub _InitializeClass { + #Class name... + $ClassName = __PACKAGE__; + + # ID to keep track of objects... + $ObjectID = 0; +} + +# Initialize bond properties... +sub _InitializeBondProperties { + my($This, %NamesAndValues) = @_; + + my($Name, $Value, $MethodName); + while (($Name, $Value) = each %NamesAndValues) { + $MethodName = "Set${Name}"; + $This->$MethodName($Value); + } + + if (!exists $NamesAndValues{'Atoms'}) { + carp "Warning: ${ClassName}->new: Bond object instantiated without specifying atoms list..."; + } + if (!exists $NamesAndValues{'BondOrder'}) { + carp "Warning: ${ClassName}->new: Bond object instantiated without setting bond order..."; + } + return $This; +} + +# Setup an explicit SetID method to block setting of ID by AUTOLOAD function... +sub SetID { + my($This, $Value) = @_; + + carp "Warning: ${ClassName}->SetID: Object ID can't be changed: it's used for internal tracking..."; + + return $This; +} + +# Setup an explicit SetMolecule method to block setting of ID by AUTOLOAD function... +sub SetMolecule { + my($This, $Value) = @_; + + carp "Warning: ${ClassName}->SetMolecule: Molecule property can't be changed: it's used for internal tracking..."; + + return $This; +} + +# Assign bond to molecule... +sub _SetMolecule { + my($This, $Molecule) = @_; + + $This->{Molecule} = $Molecule; + + # Weaken the reference to disable increment of reference count; otherwise, + # it it becomes a circular reference and destruction of Molecule object doesn't + # get initiated which in turn disables destruction of bond object. + # + Scalar::Util::weaken($This->{Molecule}); + + return $This; +} + +# Set bond atoms... +sub SetAtoms { + my($This, @Values) = @_; + + if (!@Values) { + croak "Error: ${ClassName}->SetAtoms: No atoms specified..."; + } + + my($FirstValue, $TypeOfFirstValue, $Atom1, $Atom2, $AtomID1, $AtomID2); + $FirstValue = $Values[0]; + $TypeOfFirstValue = ref $FirstValue; + + if ($TypeOfFirstValue =~ /^ARRAY/) { + # Initialize using array refernce... + if (@{$FirstValue} != 2) { + croak "Warning: ${ClassName}->SetAtoms: Number of atoms specified in bond object is not equal to 2..."; + } + ($Atom1, $Atom2) = @{$FirstValue}; + } + else { + # It's a list of values... + if (@Values != 2) { + croak "Warning: ${ClassName}->SetAtoms: Number of atoms specified in bond object is not equal to 2..."; + } + ($Atom1, $Atom2) = @Values; + } + + $AtomID1 = $Atom1->GetID(); $AtomID2 = $Atom2->GetID(); + if ($AtomID1 == $AtomID2) { + croak "Warning: ${ClassName}->SetAtoms: Can't specify same atoms to create a bond..."; + } + + $This->{BondFromAtom} = $Atom1; + $This->{BondToAtom} = $Atom2; + + return $This; +} + +# Get bond atoms as array. In scalar context, return number of atoms involved in +# bond... +# +sub GetAtoms { + my($This) = @_; + + return wantarray ? ($This->{BondFromAtom}, $This->{BondToAtom}) : 2; +} + +# Get atom bonded to specified atom... +sub GetBondedAtom { + my($This, $Atom) = @_; + my($Atom1, $Atom2, $AtomID1, $AtomID2, $AtomID); + + ($Atom1, $Atom2) = $This->GetAtoms(); + $AtomID1 = $Atom1->GetID(); $AtomID2 = $Atom2->GetID(); $AtomID = $Atom->GetID(); + + return ($AtomID1 == $AtomID) ? $Atom2 : (($AtomID2 == $AtomID) ? $Atom1 : undef) ; +} + +# Get common atom between two bonds... +sub GetCommonAtom { + my($This, $Other) = @_; + my($Atom1, $Atom2, $AtomID1, $AtomID2, $OtherAtom1, $OtherAtom2, $OtherAtomID1, $OtherAtomID2); + + ($Atom1, $Atom2) = $This->GetAtoms(); + $AtomID1 = $Atom1->GetID(); $AtomID2 = $Atom2->GetID(); + + ($OtherAtom1, $OtherAtom2) = $Other->GetAtoms(); + $OtherAtomID1 = $OtherAtom1->GetID(); $OtherAtomID2 = $OtherAtom2->GetID(); + + return ($AtomID1 == $OtherAtomID1 || $AtomID1 == $OtherAtomID2) ? $Atom1 : (($AtomID2 == $OtherAtomID1 || $AtomID2 == $OtherAtomID2) ? $Atom2 : undef) ; +} + +# Get bond from atom indicating begining atom of a bond... +sub GetBondFromAtom { + my($This) = @_; + + return $This->{BondFromAtom}; +} + +# Get begin bond atom... +sub GetBondBeginAtom { + my($This) = @_; + + return $This->GetBondFromAtom(); +} + +# Get bond to atom indicating ending atom of a bond... +sub GetBondToAtom { + my($This) = @_; + + return $This->{BondToAtom}; +} + +# Get begin bond atom... +sub GetBondEndAtom { + my($This) = @_; + + return $This->GetBondToAtom(); +} + +# Switch bond from and to atoms... +sub SwitchBondFromAndToAtoms { + my($This) = @_; + my($FromAtom, $ToAtom); + + ($FromAtom, $ToAtom) = $This->GetAtoms(); + + $This->{BondFromAtom} = $ToAtom; + $This->{BondToAtom} = $FromAtom; + + return $This; +} + +# Set bond order... +# +# Possible BondOrder are: 0 = None, 1 = Single, 1.5 = Aromatic, 2 = Double, 3 = Triple, 4 = Quadruple, +# 5 = Quintuple, 6 = Sextuple, 7 = Septuple +# +# Possible BondType for different BondOrders are: +# +# 0 : None, Ionic, Unspecified +# 1 : Single, Dative, Coordinate, SingleOrDouble, SingleOrAromatic, Tautomeric +# 1.5 : Aromatic, Resonance, SingleOrAromatic, DoubleOrAromatic +# 2 : Double, Tautomeric, SingleOrDouble, DoubleOrAromatic +# 3 : Triple +# 4 : Quadruple +# 5 : Quintuple +# 6 : Sextuple +# 7 : Septuple +# +# Note: BondType Any is valid for all BondOrders. +# +# Possible BondStereochemistry values for different BondOrders are: +# +# 0 : None, Unspecified +# 1 : Wedge, Up, Hash, Down, Wavy, WedgeOrHash, UpOrDown, Upward, Downward, None, Unspecified +# 2 : Cis, Trans, Z, E, DoubleCross, CisOrTrans, None, Unspecified +# +# Notes: +# . BondType property is automatically assigned using default BondType values for +# specified BondOrder. +# . BondType values can also be explicit set. +# . To make bonds aromatic in a ring, explicitly set "Aromatic" property for bond/atoms and make sure +# appropriate BondOrder values are assigned. +# . Dative or coordinate bond types are treated as single bond types with explicit formal charge +# of + and - on first and second bond atoms. +# +sub SetBondOrder { + my($This, $BondOrder) = @_; + + if ($BondOrder !~ /^(0|1|1.5|2|3|4|5|6|7)$/) { + croak "Error: ${ClassName}->SetBondOrder: BondOrder value $BondOrder is not valid. Supported values: 0, 1, 1.5, 2, 3, 4, 5, 6, 7"; + } + + # Set bond order and type... + my($BondType); + + BONDORDER: { + if ($BondOrder == 1) {$BondType = 'Single'; last BONDORDER; } + if ($BondOrder == 1.5) {$BondType = 'Aromatic'; last BONDORDER; } + if ($BondOrder == 2) {$BondType = 'Double'; last BONDORDER; } + if ($BondOrder == 3) {$BondType = 'Triple'; last BONDORDER; } + if ($BondOrder == 4) {$BondType = 'Quadruple'; last BONDORDER; } + if ($BondOrder == 5) {$BondType = 'Quintuple'; last BONDORDER; } + if ($BondOrder == 6) {$BondType = 'Sextuple'; last BONDORDER; } + if ($BondOrder == 7) {$BondType = 'Septuple'; last BONDORDER; } + $BondType = ''; + $BondOrder = 0; + } + $This->{BondType} = $BondType; + $This->{BondOrder} = $BondOrder; + + return $This; + +} + +# Set bond type for a specific bond... +# +sub SetBondType { + my($This, $BondType) = @_; + + if ($BondType !~ /^(None|Ionic|Unspecified|Single|Dative|Coordinate|SingleOrDouble|SingleOrAromatic|Aromatic|Tautomeric|Resonance|DoubleOrAromatic|Double|Triple|Quadruple|Any)$/i) { + croak "Error: ${ClassName}->SetBondType: BondType value $BondType is not valid. Supported values: None, Ionic, Unspecified, Single, Dative, Coordinate, SingleOrDouble, SingleOrAromatic, Aromatic, Tautomeric, Resonance, DoubleOrAromatic, Double, Triple, Quadruple, Any..."; + } + + # Make sure its a valid BondType value for BondOrder... + my($BondOrder, $ValidBondType); + + $ValidBondType = 0; + $BondOrder = $This->{BondOrder}; + + BONDORDER: { + if ($BondOrder == 0 && $BondType =~ /^(None|Ionic|Unspecified|Any)$/i) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 1 && $BondType =~ /^(Single|Dative|Coordinate|SingleOrDouble|SingleOrAromatic|Tautomeric|Any)$/i) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 1.5 && $BondType =~ /^(Aromatic|Resonance|SingleOrAromatic|DoubleOrAromatic|Any)$/i) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 2 && $BondType =~ /^(Double|SingleOrDouble|DoubleOrAromatic|Tautomeric|Any)$/i ) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 3 && $BondType =~ /^(Triple|Any)$/i) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 4 && $BondType =~ /^(Quadruple|Any)$/i) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 5 && $BondType =~ /^(Quintuple|Any)$/i) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 6 && $BondType =~ /^(Sextuple|Any)$/i) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 7 && $BondType =~ /^(Septuple|Any)$/i) {$ValidBondType = 1; last BONDORDER; } + $ValidBondType = 0; + } + + if (!$ValidBondType) { + carp "Warning: ${ClassName}->SetBondType: Assigning invalid BondType value, $BondType, for BondOrder $BondOrder..."; + } + + $This->{BondType} = $BondType; + + # Set explicit formal charge for atoms involved in Dative or coordinate bonds... + if ($BondType =~ /^(Dative|Coordinate)$/i) { + my($Atom1, $Atom2) = $This->GetAtoms(); + $Atom1->SetFormalCharge('1'); + $Atom2->SetFormalCharge('-1'); + } + + return $This; +} + +# Set bond stereochemistry... +# +# Single bond stereochemistry: +# +# None, Unspecified: Not a stereo bond or unspecified +# +# Wedge, Up : Wedge end pointing up +# Hash, Down: Wedge end pointing down +# Wavy, WedgeOrHash, UpOrDown: Wedge end up or down +# +# Note: Wedge starts at begin atom of bond making wedge pointed end always at this +# atom. +# +# Upward: Single bond around cis/trans double bonds pointing upward +# Downward: Single bond around cis/trans double bonds pointing upward +# +# Note: Upward/downward bonds start at atoms involved in cis/trans double bond. +# +# Double bond stereochemistry: +# +# None, Unspecified: Not a stereo bond or unspecified +# +# Z, cis: Similar groups on same side of double bond +# E, trans: Similar groups on different side of double bond +# +# CisOrTrans, DoubleCross: cis or trans +# +sub SetBondStereochemistry { + my($This, $BondStereochemistry) = @_; + + if ($BondStereochemistry !~ /^(None|Unspecified|Wedge|Hash|Up|Down|Wavy|WedgeOrHash|UpOrDown|Upward|Downward|Cis|Trans|Z|E|DoubleCross|CisOrTrans)$/i) { + croak "Error: ${ClassName}->SetBondStereochemistry: BondStereochemistry value $BondStereochemistry is not valid. Supported values: None, Unspecified, Wedge, Hash, Up, Down, Wavy, WedgeOrHash, UpOrDown, Upward, Downward, Cis, Trans, Z, E, DoubleCross, CisOrTrans..."; + } + + # Make sure its a valid BondStereochemistry value for BondOrder... + my($BondOrder, $ValidBondType); + + $ValidBondType = 0; + $BondOrder = $This->{BondOrder}; + + BONDORDER: { + if ($BondOrder == 0 && $BondStereochemistry =~ /^(None|Unspecified)$/i) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 1 && $BondStereochemistry =~ /^(Wedge|Hash|Up|Down|Wavy|WedgeOrHash|UpOrDown|Upward|Downward|None|Unspecified)$/i) {$ValidBondType = 1; last BONDORDER; } + if ($BondOrder == 2 && $BondStereochemistry =~ /^(Cis|Trans|Z|E|DoubleCross|CisOrTrans|None|Unspecified)$/i ) {$ValidBondType = 1; last BONDORDER; } + $ValidBondType = 0; + } + + if (!$ValidBondType) { + carp "Warning: ${ClassName}->SetBondStereochemistry: Assigning invalid BondStereochemistry value, $BondStereochemistry, for BondOrder $BondOrder..."; + } + + $This->{BondStereochemistry} = $BondStereochemistry; + + return $This; +} + +# Is it a single bond? +sub IsSingle { + my($This) = @_; + + return ($This->{BondOrder} == 1) ? 1 : 0; +} + +# Is it a double bond? +sub IsDouble { + my($This) = @_; + + return ($This->{BondOrder} == 2) ? 1 : 0; +} + +# Is it a triple bond? +sub IsTriple { + my($This) = @_; + + return ($This->{BondOrder} == 3) ? 1 : 0; +} + +# Is it a quadruple bond? +sub IsQuadruple { + my($This) = @_; + + return ($This->{BondOrder} == 4) ? 1 : 0; +} + +# Is aromatic property set for the bond? +sub IsAromatic { + my($This) = @_; + my($Aromatic); + + $Aromatic = $This->GetAromatic(); + + return ((defined($Aromatic) && $Aromatic) || $This->{BondOrder} == 1.5) ? 1 : 0; +} + +# Is it a quintuple bond? +sub IsQuintuple { + my($This) = @_; + + return ($This->{BondOrder} == 5) ? 1 : 0; +} + +# Is it a sextuple bond? +sub IsSextuple { + my($This) = @_; + + return ($This->{BondOrder} == 6) ? 1 : 0; +} + +# Is bond type specified? +sub IsBondTypeSpecified { + my($This) = @_; + + return ($This->{BondType} && $This->{BondType} !~ /^(None|Unspecified)$/i) ? 1 : 0; +} + +# Is it a dative or coordinate bond? +sub IsDative { + my($This) = @_; + + return ($This->{BondType} =~ /^(Dative|Coordinate)$/i) ? 1 : 0; +} + +# Is it a dative or coordinate bond? +sub IsCoordinate { + my($This) = @_; + + return $This->IsDative(); +} + +# Is it a ionic bond? +sub IsIonic { + my($This) = @_; + + return ($This->{BondType} =~ /^Ionic$/i) ? 1 : 0; +} + +# Is it a tautomeric bond? +sub IsTautomeric { + my($This) = @_; + + return ($This->{BondType} =~ /^Tautomeric$/i) ? 1 : 0; +} + +# Is bond stereochemistry specified? +sub IsBondStereochemistrySpecified { + my($This) = @_; + + return ($This->{BondStereochemistry} && $This->{BondStereochemistry} !~ /^(None|Unspecified)$/i) ? 1 : 0; +} + +# Is it a Wedge or Up single bond? +sub IsWedge { + my($This) = @_; + + return $This->IsUp(); +} + +# Is it a Wedge or Up single bond? +sub IsUp { + my($This) = @_; + + return ($This->{BondStereochemistry} =~ /^(Wedge|Up)$/i) ? 1 : 0; +} + +# Is it a Hash or Down single bond? +sub IsHash { + my($This) = @_; + + return $This->IsDown(); +} + +# Is it a Hash or Down single bond? +sub IsDown { + my($This) = @_; + + return ($This->{BondStereochemistry} =~ /^(Hash|Down)$/i) ? 1 : 0; +} + +# Is it a Wavy, WedgeOrHash or UpOrDown single bond? +sub IsWedgeOrHash { + my($This) = @_; + + return $This->IsUpOrDown(); +} + +# Is it a Wavy, WedgeOrHash or UpOrDown single bond? +sub IsUpOrDown { + my($This) = @_; + + return ($This->{BondStereochemistry} =~ /^(Wavy|WedgeOrHash|UpOrDown)$/i) ? 1 : 0; +} + +# Is it a upward single bond? +sub IsUpward { + my($This) = @_; + + return ($This->{BondStereochemistry} =~ /^Upward$/i) ? 1 : 0; +} + +# Is it a Downward single bond? +sub IsDownward { + my($This) = @_; + + return ($This->{BondStereochemistry} =~ /^Downward$/i) ? 1 : 0; +} +# Is it a cis or Z double bond? +sub IsCis { + my($This) = @_; + + return ($This->{BondStereochemistry} =~ /^(Cis|Z)$/i) ? 1 : 0; +} + +# Is it a trans or E double bond? +sub IsTrans { + my($This) = @_; + + return ($This->{BondStereochemistry} =~ /^(Trans|E)$/i) ? 1 : 0; +} + +# Is it a cis or trans double bond? +sub IsCisOrTrans { + my($This) = @_; + + return ($This->{BondStereochemistry} =~ /^(CisOrTrans|DoubleCross)$/i) ? 1 : 0; +} + +# Delete bond... +sub DeleteBond { + my($This) = @_; + + # Is this atom in a molecule? + if (!$This->HasProperty('Molecule')) { + # Nothing to do... + return $This; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + $Molecule->DeleteBond($This); + + return $This; +} + +# Copy bond and all its associated data... +sub Copy { + my($This) = @_; + my($Bond); + + $Bond = Storable::dclone($This); + + return $Bond; +} + +# Is bond in a ring? +# +sub IsInRing { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_IsBondInRing($This); +} + +# Is bond not in a ring? +# +sub IsNotInRing { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_IsBondNotInRing($This); +} + +# Is bond only in one ring? +# +sub IsOnlyInOneRing { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_IsBondInOnlyOneRing($This); +} + +# Is bond in a ring of specific size? +# +sub IsInRingOfSize { + my($This, $RingSize) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_IsBondInRingOfSize($This, $RingSize); +} + +# Get size of smallest ring containing the bond... +# +sub GetSizeOfSmallestRing { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetSizeOfSmallestBondRing($This); +} + +# Get size of largest ring containing the bond... +# +sub GetSizeOfLargestRing { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetSizeOfLargestBondRing($This); +} + +# Get number of rings containing the bond... +# +sub GetNumOfRings { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetNumOfBondRings($This); +} + +# Get number of rings with odd size containing the bond... +# +sub GetNumOfRingsWithOddSize { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetNumOfBondRingsWithOddSize($This); +} + +# Get number of rings with even size containing the bond... +# +sub GetNumOfRingsWithEvenSize { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetNumOfBondRingsWithEvenSize($This); +} + +# Get number of rings with specified size containing the bond... +# +sub GetNumOfRingsWithSize { + my($This, $RingSize) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetNumOfBondRingsWithSize($This, $RingSize); +} + +# Get number of rings with size less than specified containing the bond... +# +sub GetNumOfRingsWithSizeLessThan { + my($This, $RingSize) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetNumOfBondRingsWithSizeLessThan($This, $RingSize); +} + +# Get number of rings with size greater than specified size containing the bond... +# +sub GetNumOfRingsWithSizeGreaterThan { + my($This, $RingSize) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetNumOfBondRingsWithSizeGreaterThan($This, $RingSize); +} + +# Get all rings as an array of references to arrays containing ring atoms... +# +sub GetRings { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetBondRings($This); +} + +# Get smallest ring as an array containing ring atoms... +# +sub GetSmallestRing { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetSmallestBondRing($This); +} + +# Get largest ring as an array containing ring atoms... +# +sub GetLargestRing { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetLargestBondRing($This); +} + +# Get odd size rings an array of references to arrays containing ring atoms... +# +sub GetRingsWithOddSize { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetBondRingsWithOddSize($This); +} + +# Get even size rings an array of references to arrays containing ring atoms... +# +sub GetRingsWithEvenSize { + my($This) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetBondRingsWithEvenSize($This); +} + +# Get rings with specified size an array of references to arrays containing ring atoms... +# +sub GetRingsWithSize { + my($This, $RingSize) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetBondRingsWithSize($This, $RingSize); +} + +# Get rings with size less than specfied size as an array of references to arrays containing ring atoms... +# +sub GetRingsWithSizeLessThan { + my($This, $RingSize) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetBondRingsWithSizeLessThan($This, $RingSize); +} + +# Get rings with size greater than specfied size as an array of references to arrays containing ring atoms... +# +sub GetRingsWithSizeGreaterThan { + my($This, $RingSize) = @_; + + # Is this bond in a molecule? + if (!$This->HasProperty('Molecule')) { + return undef; + } + my($Molecule); + $Molecule = $This->GetProperty('Molecule'); + + return $Molecule->_GetBondRingsWithSizeGreaterThan($This, $RingSize); +} + +# Get next object ID... +sub _GetNewObjectID { + $ObjectID++; + return $ObjectID; +} + +# Return a string containing bond and other properties... +sub StringifyBond { + my($This) = @_; + my($BondString, $ID, $BondOrder, $BondType, $Stereochemistry, $AtomsString, $RingBond, $AromaticBond, $NumOfRings, $Atom1, $Atom2); + + $ID = $This->GetID(); + $BondOrder = $This->GetBondOrder(); + if (!defined $BondOrder) { + $BondOrder = "undefined"; + } + $BondType = $This->GetBondType(); + if (!defined $BondOrder) { + $BondType = "undefined"; + } + if (defined($BondOrder) && $BondOrder == 2) { + $Stereochemistry = $This->GetStereochemistry(); + if (!defined $Stereochemistry) { + $Stereochemistry = "undefined"; + } + } + $RingBond = $This->IsInRing(); + if (defined $RingBond) { + $RingBond = $RingBond ? 'Yes' : 'No'; + $NumOfRings = $This->GetNumOfRings(); + } + else { + $RingBond = 'undefined'; + $NumOfRings = 'undefined'; + } + + $AromaticBond = $This->GetAromatic(); + if (defined $AromaticBond) { + $AromaticBond = $AromaticBond ? 'Yes' : 'No'; + } + else { + $AromaticBond = 'undefined'; + } + + ($Atom1, $Atom2) = $This->GetAtoms(); + $AtomsString = "Atoms: undefined"; + if (defined($Atom1) && defined($Atom2)) { + my($Atom, $AtomID, $AtomCount, $AtomName, $AtomSymbol, $AtomicNumber, @BondAtoms); + @BondAtoms = (); + push @BondAtoms, ($Atom1, $Atom2); + $AtomCount = 0; + $AtomsString = ""; + for $Atom (@BondAtoms) { + $AtomCount++; + $AtomID = $Atom->GetID(); + $AtomName = $Atom->GetName(); + $AtomSymbol = $Atom->GetAtomSymbol(); + $AtomicNumber = $Atom->GetAtomicNumber(); + if ($AtomCount == 1) { + $AtomsString .= "FirstAtom:"; + } + else { + $AtomsString .= "; SecondAtom:"; + } + $AtomsString .= " [ ID: $AtomID; Name: \"$AtomName\"; AtomSymbol: \"$AtomSymbol\"; AtomicNumber: $AtomicNumber ]"; + } + } + $BondString = "Bond: ID: $ID; BondOrder: $BondOrder; BondType: $BondType; RingBond: $RingBond; NumOfBondRings: $NumOfRings; AromaticBond: $AromaticBond;"; + if (defined($BondOrder) && $BondOrder == 2) { + $BondString .= " Stereochemistry: $Stereochemistry;"; + } + $BondString .= " $AtomsString"; + + return $BondString; +} + +1; + +__END__ + +=head1 NAME + +Bond + +=head1 SYNOPSIS + +use Bond; + +use Bond qw(:all); + +=head1 DESCRIPTION + +B<Bond> class provides the following methods: + +new, Copy, DeleteBond, GetAtoms, GetBondBeginAtom, GetBondEndAtom, +GetBondFromAtom, GetBondToAtom, GetBondedAtom, GetCommonAtom, GetLargestRing, +GetNumOfRings, GetNumOfRingsWithEvenSize, GetNumOfRingsWithOddSize, +GetNumOfRingsWithSize, GetNumOfRingsWithSizeGreaterThan, +GetNumOfRingsWithSizeLessThan, GetRings, GetRingsWithEvenSize, +GetRingsWithOddSize, GetRingsWithSize, GetRingsWithSizeGreaterThan, +GetRingsWithSizeLessThan, GetSizeOfLargestRing, GetSizeOfSmallestRing, +GetSmallestRing, IsAromatic, IsBondStereochemistrySpecified, IsBondTypeSpecified, +IsCis, IsCisOrTrans, IsCoordinate, IsDative, IsDouble, IsDown, IsDownward, IsHash, +IsInRing, IsInRingOfSize, IsIonic, IsNotInRing, IsOnlyInOneRing, IsQuadruple, +IsQuintuple, IsSextuple, IsSingle, IsTautomeric, IsTrans, IsTriple, IsUp, +IsUpOrDown, IsUpward, IsWedge, IsWedgeOrHash, SetAtoms, SetBondOrder, +SetBondStereochemistry, SetBondType, StringifyBond, SwitchBondFromAndToAtoms + +B<Bond> class is derived from B<ObjectProperty> base class which provides methods not explicitly +defined in B<Atom> or B<ObjectProperty> class using Perl's AUTOLOAD functionality. These methods +are generated on-the-fly for a specified object property: + + Set<PropertyName>(<PropertyValue>); + $PropertyValue = Get<PropertyName>(); + Delete<PropertyName>(); + +=head2 METHODS + +=over 4 + +=item B<new> + + $NewBond = new Bond([%PropertyNameAndValues]); + +Using specified I<Bond> property names and values hash, B<new> method creates a new object +and returns a reference to newly created B<Bond> object. By default, following properties are +initialized: + + ID = SequentialObjectID + @Atoms = (); + BondType = "" + BondOrder = "" + +Except for I<ID> property, all other default properties and other additional properties can +be set during invocation of this method. + +Examples: + + $Bond = new Bond(); + $DoubleBond = new Bond('Atoms' => [$Atom2, $Atom1], + 'BondOrder' => 2); + +=item B<Copy> + + $BondCopy = $Bond->Copy(); + +Copy I<Bond> and its associated data using B<Storable::dclone> and return a new +B<Bond> object. + +=item B<DeleteBond> + + $Bond->DeleteBond(); + +Delete I<Bond> between atoms in from a molecule. + +=item B<GetAtoms> + + @BondedAtoms = $Bond->GetAtoms(); + +Returns an array containing I<Atoms> invoved in I<Bond>. + +=item B<GetBondedAtom> + + $BondedAtom = $Bond->GetBondedAtom($Atom); + +Returns B<BondedAtom> bonded to I<Atom> in I<Bond>. + +=item B<GetBondBeginAtom> + + $BeginAtom = $Bond->GetBondBeginAtom(); + +Returns B<BeginAtom> corresponding to bond starting atom in I<Bond>. + +=item B<GetBondEndAtom> + + $EndAtom = $Bond->GetBondEndAtom(); + +Returns B<EndAtom> corresponding to bond ending atom in I<Bond>. + +=item B<GetBondFromAtom> + + $FromAtom = $Bond->GetBondFromAtom(); + +Returns B<FromAtom> corresponding to bond starting atom in I<Bond>. + +=item B<GetBondToAtom> + + $ToAotm = $Bond->GetBondToAtom(); + +Returns B<ToAtom> corresponding to bond ending atom in I<Bond>. + +=item B<GetCommonAtom> + + $CommonAtom = $Bond->GetCommonAtom($OtherBond); + +Returns B<Atom> common to both I<Bond> and I<$OtherBond>. + +=item B<GetLargestRing> + + @RingAtoms = $Bond->GetLargestRing(); + +Returns an array of ring I<Atoms> corresponding to the largest ring containing I<Bond>. +in a molecule + +=item B<GetNumOfRings> + + $NumOfRings = $Bond->GetNumOfRings(); + +Returns number of rings containing I<Bond> in a molecule. + +=item B<GetNumOfRingsWithEvenSize> + + $NumOfRings = $Bond->GetNumOfRingsWithEvenSize(); + +Returns number of rings with even size containing I<Bond> in a molecule. + +=item B<GetNumOfRingsWithOddSize> + + $NumOfRings = $Bond->GetNumOfRingsWithOddSize(); + +Returns number of rings with odd size containing I<Bond> in a molecule. + +=item B<GetNumOfRingsWithSize> + + $NumOfRings = $Bond->GetNumOfRingsWithSize($RingSize); + +Returns number of rings with specific I<RingSize> containing I<Bond> in a molecule. + +=item B<GetNumOfRingsWithSizeGreaterThan> + + $NumOfRings = $Bond->GetNumOfRingsWithSizeGreaterThan($RingSize); + +Returns number of rings with size greater than specific I<RingSize> containing +I<Bond> in a molecule. + +=item B<GetNumOfRingsWithSizeLessThan> + + $NumOfRings = $Bond->GetNumOfRingsWithSizeLessThan($RingSize); + +Returns number of rings with size less than specific I<RingSize> containing I<Bond> +in a molecule. + +=item B<GetRings> + + @Rings = $Bond->GetRings(); + +Returns an array of references to arrays containing ring atoms corressponding +to all rings containing I<Bond> in a molecule. + +=item B<GetRingsWithEvenSize> + + @Rings = $Bond->GetRingsWithEvenSize(); + +Returns an array of references to arrays containing ring atoms corressponding to all rings with even size +containing I<Bond> in a molecule. + +=item B<GetRingsWithOddSize> + + @Rings = $Bond->GetRingsWithOddSize(); + +Returns an array of references to arrays containing ring atoms corressponding to all rings with odd size +containing I<Bond> in a molecule. + +=item B<GetRingsWithSize> + + @Rings = $Bond->GetRingsWithSize($RingSize); + +Returns an array of references to arrays containing ring atoms corressponding to all rings with specific +I<RingSize >containing I<Bond> in a molecule. + +=item B<GetRingsWithSizeGreaterThan> + + @Rings = $Bond->GetRingsWithSizeGreaterThan($RingSize); + +Returns an array of references to arrays containing ring atoms corressponding to all rings with size +greater than specific I<RingSize >containing I<Bond> in a molecule. + +=item B<GetRingsWithSizeLessThan> + + @Rings = $Bond->GetRingsWithSizeLessThan($RingSize); + +Returns an array of references to arrays containing ring atoms corressponding to all rings with size +less than specific I<RingSize >containing I<Bond> in a molecule. + +=item B<GetSizeOfLargestRing> + + $Size = $Bond->GetSizeOfLargestRing(); + +Returns size of the largest ring containing I<Bond> in a molecule. + +=item B<GetSizeOfSmallestRing> + + $Size = $Bond->GetSizeOfSmallestRing(); + +Returns size of the smallest ring containing I<Bond> in a molecule. + +=item B<GetSmallestRing> + + @RingAtoms = $Bond->GetSmallestRing(); + +Returns an array of ring I<Atoms> corresponding to the largest ring containing I<Bond> +in a molecule. + +=item B<IsAromatic> + + $Status = $Bond->IsAromatic(); + +Returns 1 or 0 based on whether it's an aromatic I<Bond>. + +=item B<IsBondStereochemistrySpecified> + + $Status = $Bond->IsBondStereochemistrySpecified(); + +Returns 1 or 0 based on whether I<Bond>'s sterochemistry is specified. + +=item B<IsBondTypeSpecified> + + $Status = $Bond->IsBondTypeSpecified(); + +Returns 1 or 0 based on whether I<Bond>'s type is specified. + +=item B<IsCis> + + $Status = $Bond->IsCis(); + +Returns 1 or 0 based on whether it's a cis I<Bond>. + +=item B<IsCisOrTrans> + + $Status = $Bond->IsCisOrTrans(); + +Returns 1 or 0 based on whether it's a cis or trans I<Bond>. + +=item B<IsCoordinate> + + $Status = $Bond->IsCoordinate(); + +Returns 1 or 0 based on whether it's a coordinate or dative I<Bond>. + +=item B<IsDative> + + $Status = $Bond->IsDative(); + +Returns 1 or 0 based on whether it's a coordinate or dative I<Bond>. + +=item B<IsDouble> + + $Status =$Bond->IsDouble(); + +Returns 1 or 0 based on whether it's a double I<Bond>. + +=item B<IsDown> + + $Status = $Bond->IsDown(); + +Returns 1 or 0 based on whether it's a hash or down single I<Bond>. + +=item B<IsDownward> + + $Return = $Bond->IsDownward(); + +Returns 1 or 0 based on whether it's a downward I<Bond>. + +=item B<IsHash> + + $Status = $Bond->IsHash(); + +Returns 1 or 0 based on whether it's a hash or down single I<Bond>. + +=item B<IsInRing> + + $Status = $Bond->IsInRing(); + +Returns 1 or 0 based on whether I<Bond> is present in a ring. + +=item B<IsInRingOfSize> + + $Status = $Bond->IsInRingOfSize($Size); + +Returns 1 or 0 based on whether I<Bond> is present in a ring of specific I<Size>. + +=item B<IsIonic> + + $Status = $Bond->IsIonic(); + +Returns 1 or 0 based on whether it's an ionic I<Bond>. + +=item B<IsNotInRing> + + $Status = $Bond->IsNotInRing(); + +Returns 1 or 0 based on whether I<Bond> is not present in a ring. + +=item B<IsOnlyInOneRing> + + $Status = $Bond->IsOnlyInOneRing(); + +Returns 1 or 0 based on whether I<Bond> is only present in one ring. + +=item B<IsQuadruple> + + $Status = $Bond->IsQuadruple(); + +Returns 1 or 0 based on whether it's a quadruple I<Bond>. + +=item B<IsQuintuple> + + $Status = $Bond->IsQuintuple(); + +Returns 1 or 0 based on whether it's a quintuple I<Bond>. + +=item B<IsSextuple> + + $Status = $Bond->IsSextuple(); + +Returns 1 or 0 based on whether it's a sextuple I<Bond>. + +=item B<IsSingle> + + $Status =$Bond->IsSingle(); + +Returns 1 or 0 based on whether it's a single I<Bond>. + +=item B<IsTriple> + + $Status =$Bond->IsTriple(); + +Returns 1 or 0 based on whether it's a triple I<Bond>. + +=item B<IsTautomeric> + + $Status = $Bond->IsTautomeric(); + +Returns 1 or 0 based on whether it's a I<Bond>. + +=item B<IsTrans> + + $Status = $Bond->IsTrans(); + +Returns 1 or 0 based on whether it's a trans I<Bond>. + +=item B<IsUp> + + $Status = $Bond->IsUp(); + +Returns 1 or 0 based on whether it's a up I<Bond>. + +=item B<IsUpOrDown> + + $Status = $Bond->IsUpOrDown(); + +Returns 1 or 0 based on whether it's an up or down I<Bond>. + +=item B<IsUpward> + + $Status = $Bond->IsUpward(); + +Returns 1 or 0 based on whether it's an upward I<Bond>. + +=item B<IsWedge> + + $Status = $Bond->IsWedge(); + +Returns 1 or 0 based on whether it's a wedge I<Bond>. + +=item B<IsWedgeOrHash> + + $Status = $Bond->IsWedgeOrHash(); + +Returns 1 or 0 based on whether it's a wedge or hash I<Bond>. + +=item B<SetAtoms> + + $Bond->SetAtoms($AtomsRef); + $Bond->SetAtoms(@Atoms); + +Set atoms of I<Bond> to atoms in I<Atoms> array or in a reference to an array of atoms +and return I<Bond>. + +=item B<SetBondOrder> + + $Bond->SetBondOrder($BondOrder); + +Sets bond order of I<Bond> to specified I<BondOrder> and returns I<Bond>. Possible bond order +values: 1 = Single, 1.5 = Aromatic, 2 = Double, 3 = Triple, 4 = Quadruple, 5 = Quintuple, +6 = Sextuple, 7 = Septuple + +Notes: + + . BondType property is automatically assigned using default BondType + values for specified BondOrder. + . BondType values can also be explicit set. + . To make bonds aromatic in a ring, explicitly set "Aromatic" + property for bond/atoms and make sure appropriate BondOrder + values are assigned. + . Dative or coordinate bond types are treated as single bond types with + explicit formal charge of + and - on first and second bond atoms. + +=item B<SetBondType> + + $Bond->SetBondType($BondType); + +Sets bond type for I<Bond> to specified I<BondType> and returns I<Bond>. Possible bond type +values for different bond orders are: + + 0: None, Ionic, Unspecified + 1 : Single, Dative, Coordinate, SingleOrDouble, SingleOrAromatic, Tautomeric + 2 : Double, SingleOrDouble, DoubleOrAromatic, Tautomeric + 3 : Triple + 4 : Quadruple + 5 : Quintuple + 6 : Sextuple + 7 : Septuple + 1.5 : Aromatic, Resonance, SingleOrAromatic, DoubleOrAromatic + +Notes: + + o BondType Any is valid for all BondOrders. + o BondOrder property is automatically assigned using default BondOrder + values for specified BondType. + +Possible bond stereochemistry values for different bond orders are: + + 0 : None, Unspecified + 1 : Wedge, Up, Hash, Down, Wavy, WedgeOrHash, UpOrDown, Upward, Downward, + None, Unspecified + 2 : Cis, Trans, Z, E, DoubleCross, CisOrTrans, None, Unspecified + +=item B<SetBondStereochemistry> + + $Bond = $Bond->SetBondStereochemistry($BondStereochemistry); + +Sets bond stereochemistry of I<Bond> to specified I<BondStereochemistry> and +returns I<Bond>. Possible I<BondStereoChemistry> values for different bond orders +are: + +BondOrder: 1 + + None, Unspecified: Not a stereo bond or unspecified + + Wedge, Up : Wedge end pointing up + Hash, Down: Wedge end pointing down + Wavy, WedgeOrHash, UpOrDown: Wedge end up or down + + Upward: Single bond around cis/trans double bonds pointing upward + Downward: Single bond around cis/trans double bonds pointing upward + +Notes: + + o Wedge starts at begin atom of a bond making wedge pointed end always + at this atom. + o Upward/downward bonds start at atoms involved in cis/trans double bonds. + +BondOrder: 2 + + None, Unspecified: Not a stereo bond or unspecified + + Z, cis: Similar groups on same side of double bond + E, trans: Similar groups on different side of double bond + + CisOrTrans, DoubleCross: cis or trans + +=item B<StringifyBond> + + $BondString = $Bond->StringifyBond(); + +Returns a string containing information about I<bond> object. + +=item B<SwitchBondFromAndToAtoms> + + $Bond = $Bond->SwitchBondFromAndToAtoms(); + +Swaps bond from and to atoms in I<Bond> and returns I<Bond>. + +=back + +=head1 AUTHOR + +Manish Sud <msud@san.rr.com> + +=head1 SEE ALSO + +Atom.pm, Molecule.pm + +=head1 COPYRIGHT + +Copyright (C) 2015 Manish Sud. All rights reserved. + +This file is part of MayaChemTools. + +MayaChemTools is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free +Software Foundation; either version 3 of the License, or (at your option) +any later version. + +=cut