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