MayaChemTools

   1 package MolecularDescriptors::SLogPAndSMRDescriptors;
   2 #
   3 # $RCSfile: SLogPAndSMRDescriptors.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 MathUtil ();
  35 use Atom;
  36 use Molecule;
  37 use MolecularDescriptors::MolecularDescriptors;
  38 use AtomTypes::SLogPAtomTypes;
  39 
  40 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  41 
  42 @ISA = qw(MolecularDescriptors::MolecularDescriptors Exporter);
  43 @EXPORT = qw();
  44 @EXPORT_OK = qw(GetDescriptorNames);
  45 
  46 %EXPORT_TAGS = (all  => [@EXPORT, @EXPORT_OK]);
  47 
  48 # Setup class variables...
  49 my($ClassName, @DescriptorNames);
  50 _InitializeClass();
  51 
  52 # Overload Perl functions...
  53 use overload '""' => 'StringifySLogPAndSMRDescriptors';
  54 
  55 # Class constructor...
  56 sub new {
  57   my($Class, %NamesAndValues) = @_;
  58 
  59   # Initialize object...
  60   my $This = $Class->SUPER::new();
  61   bless $This, ref($Class) || $Class;
  62   $This->_InitializeSLogPAndSMRDescriptors();
  63 
  64   $This->_InitializeSLogPAndSMRDescriptorsProperties(%NamesAndValues);
  65 
  66   return $This;
  67 }
  68 
  69 # Initialize class ...
  70 sub _InitializeClass {
  71   #Class name...
  72   $ClassName = __PACKAGE__;
  73 
  74   # Descriptor names...
  75   @DescriptorNames = ('SLogP', 'SMR');
  76 }
  77 
  78 # Get descriptor names as an array.
  79 #
  80 # This functionality can be either invoked as a class function or an
  81 # object method.
  82 #
  83 sub GetDescriptorNames {
  84   return @DescriptorNames;
  85 }
  86 
  87 # Initialize object data...
  88 #
  89 sub _InitializeSLogPAndSMRDescriptors {
  90   my($This) = @_;
  91 
  92   # Type of MolecularDescriptor...
  93   $This->{Type} = 'SLogPAndSMR';
  94 
  95   # SLogPAndSMR atom types assigned to hydrogen and non-hydrogen atoms...
  96   %{$This->{AtomTypes}} = ();
  97 
  98   # Intialize descriptor names and values...
  99   $This->_InitializeDescriptorNamesAndValues(@DescriptorNames);
 100 
 101   return $This;
 102 }
 103 
 104 # Initialize object properties...
 105 #
 106 sub _InitializeSLogPAndSMRDescriptorsProperties {
 107   my($This, %NamesAndValues) = @_;
 108 
 109   my($Name, $Value, $MethodName);
 110   while (($Name, $Value) = each  %NamesAndValues) {
 111     $MethodName = "Set${Name}";
 112     $This->$MethodName($Value);
 113   }
 114 
 115   return $This;
 116 }
 117 
 118 
 119 # Calculate SLogPAndSMR value [ Ref 89 ] for a molecule...
 120 #
 121 # Methodology:
 122 #   . Assign SLogP atom types to all atoms.
 123 #   . Calculate SLogP and SMR value by adding contribution of each atom type.
 124 #
 125 # Caveats:
 126 #   . All hydrogens must be added to molecule before calling GenerateDescriptors.
 127 #
 128 sub GenerateDescriptors {
 129   my($This) = @_;
 130 
 131   # Initialize descriptor values...
 132   $This->_InitializeDescriptorValues();
 133 
 134   # Check availability of molecule...
 135   if (!$This->{Molecule}) {
 136     carp "Warning: ${ClassName}->GenerateDescriptors: $This->{Type} molecular descriptors generation didn't succeed: Molecule data is not available: Molecule object hasn't been set...";
 137     return undef;
 138   }
 139 
 140   # Cache appropriate molecule data...
 141   $This->_SetupMoleculeDataCache();
 142 
 143   # Assign SLogP atom types...
 144   if (!$This->_AssignAtomTypes()) {
 145     carp "Warning: ${ClassName}->GenerateDescriptors: $This->{Type} molecular descriptors generation didn't succeed: Couldn't assign valid SLogPAndSMR atom types to all atoms...";
 146     return undef;
 147   }
 148 
 149   # Calculate descriptor values...
 150   if (!$This->_CalculateDescriptorValues()) {
 151     carp "Warning: ${ClassName}->GenerateDescriptors: $This->{Type} molecular description generation didn't succeed: Couldn't calculate SLogPAndSMR values corresponding to assigned SLogP atom types...";
 152     return undef;
 153   }
 154 
 155   # Set final descriptor values...
 156   $This->_SetFinalDescriptorValues();
 157 
 158   # Clear cached molecule data...
 159   $This->_ClearMoleculeDataCache();
 160 
 161   return $This;
 162 }
 163 
 164 # Assign SLogPAndSMR atom types..
 165 #
 166 sub _AssignAtomTypes {
 167   my($This) = @_;
 168   my($SLogPAtomTypes, $Atom, $AtomID);
 169 
 170   %{$This->{AtomTypes}} = ();
 171 
 172   # Assign atom types...
 173   $SLogPAtomTypes = new AtomTypes::SLogPAtomTypes('Molecule' => $This->{Molecule}, 'IgnoreHydrogens' => 0);
 174   $SLogPAtomTypes->AssignAtomTypes();
 175 
 176   # Make sure SLogP atom types assignment is successful...
 177   if (!$SLogPAtomTypes->IsAtomTypesAssignmentSuccessful()) {
 178     return undef;
 179   }
 180 
 181   # Collect assigned atom types...
 182   for $Atom (@{$This->{Atoms}}) {
 183     $AtomID = $Atom->GetID();
 184     $This->{AtomTypes}{$AtomID} = $SLogPAtomTypes->GetAtomType($Atom);
 185   }
 186 
 187   return $This;
 188 }
 189 
 190 # Calculate SLogP and SMR values...
 191 #
 192 sub _CalculateDescriptorValues {
 193   my($This) = @_;
 194   my($SLogP, $SMR, $AtomID, $SLogPAndSMRDataRef, $AtomType);
 195 
 196   $SLogP = 0; $SMR = 0;
 197 
 198   # Get SLogP and SMR atom types data...
 199   $SLogPAndSMRDataRef = AtomTypes::SLogPAtomTypes::GetSLogPAtomTypesData();
 200 
 201   for $AtomID (keys %{$This->{AtomTypes}}) {
 202     $AtomType = $This->{AtomTypes}{$AtomID};
 203 
 204     # Makes sure data for SLogp and SMR contribution exists for atom type...
 205     if (!(exists($SLogPAndSMRDataRef->{DataCol4}{$AtomType}) && exists($SLogPAndSMRDataRef->{DataCol5}{$AtomType}))) {
 206       return undef;
 207     }
 208 
 209     # Data for SLogP contribution is in column number 4...
 210     $SLogP += $SLogPAndSMRDataRef->{DataCol4}{$AtomType};
 211 
 212     # Data for SMR contribution is in column number 5...
 213     $SMR += $SLogPAndSMRDataRef->{DataCol5}{$AtomType};
 214   }
 215 
 216   # Track the calculated values...
 217   $This->{SLogP} = MathUtil::round($SLogP, 2);
 218   $This->{SMR} = MathUtil::round($SMR, 2);
 219 
 220   return $This;
 221 }
 222 
 223 # Setup final descriptor values...
 224 #
 225 sub _SetFinalDescriptorValues {
 226   my($This) = @_;
 227 
 228   $This->{DescriptorsGenerated} = 1;
 229 
 230   $This->SetDescriptorValues($This->{SLogP}, $This->{SMR});
 231 
 232   return $This;
 233 }
 234 
 235 # Cache  appropriate molecule data...
 236 #
 237 sub _SetupMoleculeDataCache {
 238   my($This) = @_;
 239 
 240   @{$This->{Atoms}} = $This->GetMolecule()->GetAtoms();
 241 
 242   return $This;
 243 }
 244 
 245 # Clear cached molecule data...
 246 #
 247 sub _ClearMoleculeDataCache {
 248   my($This) = @_;
 249 
 250   @{$This->{Atoms}} = ();
 251 
 252   return $This;
 253 }
 254 
 255 # Return a string containg data for SLogPAndSMRDescriptors object...
 256 #
 257 sub StringifySLogPAndSMRDescriptors {
 258   my($This) = @_;
 259   my($SLogPAndSMRDescriptorsString);
 260 
 261   $SLogPAndSMRDescriptorsString = "MolecularDescriptorType: $This->{Type}; "  . $This->_StringifyDescriptorNamesAndValues();
 262 
 263   return $SLogPAndSMRDescriptorsString;
 264 }
 265 
 266 # Is it a SLogPAndSMRDescriptors object?
 267 sub _IsSLogPAndSMRDescriptors {
 268   my($Object) = @_;
 269 
 270   return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0;
 271 }
 272