       1 package MolecularDescriptors::HydrogenBondsDescriptors;
       2 #
       3 # $RCSfile: HydrogenBondsDescriptors.pm,v $
       4 # $Date: 2015/02/28 20:49:20 $
       5 # $Revision: 1.18 $
       6 #
       7 # Author: Manish Sud <msud@san.rr.com>
       8 #
       9 # Copyright (C) 2015 Manish Sud. All rights reserved.
      10 #
      11 # This file is part of MayaChemTools.
      12 #
      13 # MayaChemTools is free software; you can redistribute it and/or modify it under
      14 # the terms of the GNU Lesser General Public License as published by the Free
      15 # Software Foundation; either version 3 of the License, or (at your option) any
      16 # later version.
      17 #
      18 # MayaChemTools is distributed in the hope that it will be useful, but without
      19 # any warranty; without even the implied warranty of merchantability of fitness
      20 # for a particular purpose.  See the GNU Lesser General Public License for more
      21 # details.
      22 #
      23 # You should have received a copy of the GNU Lesser General Public License
      24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
      25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
      26 # Boston, MA, 02111-1307, USA.
      27 #
      28
      29 use strict;
      30 use Carp;
      31 use Exporter;
      32 use Scalar::Util ();
      33 use TextUtil ();
      34 use Atom;
      35 use Molecule;
      36 use MolecularDescriptors::MolecularDescriptors;
      37
      38 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
      39
      40 @ISA = qw(MolecularDescriptors::MolecularDescriptors Exporter);
      41 @EXPORT = qw();
      42 @EXPORT_OK = qw(GetDescriptorNames);
      43
      44 %EXPORT_TAGS = (all  => [@EXPORT, @EXPORT_OK]);
      45
      46 # Setup class variables...
      47 my($ClassName, @DescriptorNames);
      48 _InitializeClass();
      49
      50 # Overload Perl functions...
      51 use overload '""' => 'StringifyHydrogenBondsDescriptors';
      52
      53 # Class constructor...
      54 sub new {
      55   my($Class, %NamesAndValues) = @_;
      56
      57   # Initialize object...
      58   my $This = $Class->SUPER::new();
      59   bless $This, ref($Class) || $Class;
      60   $This->_InitializeHydrogenBondsDescriptors();
      61
      62   $This->_InitializeHydrogenBondsDescriptorsProperties(%NamesAndValues);
      63
      64   return $This;
      65 }
      66
      67 # Initialize class ...
      68 sub _InitializeClass {
      69   #Class name...
      70   $ClassName = __PACKAGE__;
      71
      72   # Descriptor names...
      73   @DescriptorNames = ('HydrogenBondDonors', 'HydrogenBondAcceptors');
      74
      75 }
      76
      77 # Get descriptor names as an array.
      78 #
      79 # This functionality can be either invoked as a class function or an
      80 # object method.
      81 #
      82 sub GetDescriptorNames {
      83   return @DescriptorNames;
      84 }
      85
      86 # Initialize object data...
      87 #
      88 sub _InitializeHydrogenBondsDescriptors {
      89   my($This) = @_;
      90
      91   # Type of MolecularDescriptor...
      92   $This->{Type} = 'HydrogenBonds';
      93
      94   # The currrent release of MayaChemTools supports identification of two types of
      95   # hydrogen bond donor and acceptor atoms with these names:
      96   #
      97   # HBondsType1 or HydrogenBondsType1
      98   # HBondsType2 or HydrogenBondsType2
      99   #
     100   # The names of these hydrogen bond types are rather arbirary. However, their
     101   # definitions have specific meaning and are as follows:
     102   #
     103   # HydrogenBondsType1 [ Ref 60-61, Ref 65-66 ]:
     104   #   . Donor: NH, NH2, OH - Any N and O with available H
     105   #   . Acceptor: N[!H], O - Any N without available H and any O
     106   #
     107   # HydrogenBondsType2 [ Ref 91 ]:
     108   #   . Donor: NH, NH2, OH - N and O with availabe H
     109   #   . Acceptor: N, O - Add N and O
     110   #
     111   # Note:
     112   #   . HydrogenBondsType2 definition corresponds to Rule of 5.
     113   #
     114   $This->{HydrogenBondsType} = 'HBondsType2';
     115
     116   # Intialize descriptor names and values...
     117   $This->_InitializeDescriptorNamesAndValues(@DescriptorNames);
     118
     119   return $This;
     120 }
     121
     122 # Initialize object properties...
     123 #
     124 sub _InitializeHydrogenBondsDescriptorsProperties {
     125   my($This, %NamesAndValues) = @_;
     126
     127   my($Name, $Value, $MethodName);
     128   while (($Name, $Value) = each  %NamesAndValues) {
     129     $MethodName = "Set${Name}";
     130     $This->$MethodName($Value);
     131   }
     132
     133   return $This;
     134 }
     135
     136 # Set hydrogen bonds type...
     137 #
     138 sub SetHydrogenBondsType {
     139   my($This, $HydrogenBondsType) = @_;
     140
     141   if ($HydrogenBondsType !~ /^(HBondsType1|HBondsType2|HydrogenBondsType1|HydrogenBondsType2)$/i) {
     142     croak "Error: ${ClassName}->SetHydrogenBondsType: Specified hydrogen bonds type, $HydrogenBondsType, is not supported. Valid values: HBondsType1, HBondsType2, HydrogenBondsType1, HydrogenBondsType2 ...\n ";
     143   }
     144
     145   $This->{HydrogenBondsType} = $HydrogenBondsType;
     146
     147   return $This;
     148 }
     149
     150 # Calculate number of hydrogen bond donors and acceptors in a molecule...
     151 #
     152 sub GenerateDescriptors {
     153   my($This) = @_;
     154
     155   # Initialize descriptor values...
     156   $This->_InitializeDescriptorValues();
     157
     158   # Check availability of molecule...
     159   if (!$This->{Molecule}) {
     160     carp "Warning: ${ClassName}->GenerateDescriptors: $This->{Type} molecular descriptors generation didn't succeed: Molecule data is not available: Molecule object hasn't been set...";
     161     return undef;
     162   }
     163
     164   # Calculate descriptor values...
     165   if (!$This->_CalculateDescriptorValues()) {
     166     carp "Warning: ${ClassName}->CalculateDescriptorValues: $This->{Type} molecular descriptors generation didn't succeed: Couldn't calculate number of hydrogen bond donor and accepror values...";
     167     return undef;
     168   }
     169
     170   # Set final descriptor values...
     171   $This->_SetFinalDescriptorValues();
     172
     173 }
     174
     175 # Calculate number of hydrogen bond donors and acceptors...
     176 #
     177 sub _CalculateDescriptorValues {
     178   my($This) = @_;
     179   my($HydrogenBondDonors, $HydrogenBondAcceptors, $Atom);
     180
     181   $HydrogenBondDonors = 0;
     182   $HydrogenBondAcceptors = 0;
     183
     184   for $Atom ($This->{Molecule}->GetAtoms()) {
     185     if ($Atom->IsHydrogenBondDonor($This->{HydrogenBondsType})) {
     186       $HydrogenBondDonors++;
     187     }
     188     if ($Atom->IsHydrogenBondAcceptor($This->{HydrogenBondsType})) {
     189       $HydrogenBondAcceptors++;
     190     }
     191   }
     192
     193   # Track the calculated values...
     194   $This->{HydrogenBondDonors} = $HydrogenBondDonors;
     195   $This->{HydrogenBondAcceptors} = $HydrogenBondAcceptors;
     196
     197   return $This;
     198 }
     199
     200 # Setup final descriptor values...
     201 #
     202 sub _SetFinalDescriptorValues {
     203   my($This) = @_;
     204
     205   $This->{DescriptorsGenerated} = 1;
     206
     207   $This->SetDescriptorValues($This->{HydrogenBondDonors}, $This->{HydrogenBondAcceptors});
     208
     209   return $This;
     210 }
     211
     212 # Return a string containg data for HydrogenBondsDescriptors object...
     213 #
     214 sub StringifyHydrogenBondsDescriptors {
     215   my($This) = @_;
     216   my($HydrogenBondsDescriptorsString);
     217
     218   $HydrogenBondsDescriptorsString = "MolecularDescriptorType: $This->{Type}; HydrogenBondsType: $This->{HydrogenBondsType}; " . $This->_StringifyDescriptorNamesAndValues();
     219
     220   return $HydrogenBondsDescriptorsString;
     221 }
     222
     223 # Is it a HydrogenBondsDescriptors object?
     224 sub _IsHydrogenBondsDescriptors {
     225   my($Object) = @_;
     226
     227   return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0;
     228 }
     229