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