1 package MolecularDescriptors::MolecularDescriptors; 2 # 3 # File: MolecularDescriptors.pm 4 # Author: Manish Sud <msud@san.rr.com> 5 # 6 # Copyright (C) 2024 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 ObjectProperty; 31 use TextUtil (); 32 33 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 34 35 @ISA = qw(ObjectProperty Exporter); 36 @EXPORT = qw(); 37 @EXPORT_OK = qw(); 38 39 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 40 41 # Setup class variables... 42 my($ClassName); 43 _InitializeClass(); 44 45 # Class constructor... 46 sub new { 47 my($Class, %NamesAndValues) = @_; 48 49 # Initialize object... 50 my $This = {}; 51 bless $This, ref($Class) || $Class; 52 $This->_InitializeMolecularDescriptors(); 53 54 $This->_InitializeMolecularDescriptorsProperties(%NamesAndValues); 55 56 return $This; 57 } 58 59 # Initialize object data... 60 # 61 sub _InitializeMolecularDescriptors { 62 my($This) = @_; 63 64 # Molecule object... 65 $This->{Molecule} = ''; 66 67 # Type of molecular descriptors... 68 $This->{Type} = ''; 69 70 # Names and calculated value of molecular descriptors... 71 # 72 # The specific descriptor class, derived from this base class, populate descriptor names and values 73 # arrays... 74 # 75 @{$This->{DescriptorNames}} = (); 76 @{$This->{DescriptorValues}} = (); 77 78 # Marks successful generation of descriptors... 79 $This->{DescriptorsGenerated} = 0; 80 81 } 82 83 # Initialize class ... 84 sub _InitializeClass { 85 #Class name... 86 $ClassName = __PACKAGE__; 87 } 88 89 90 # Initialize object properties.... 91 sub _InitializeMolecularDescriptorsProperties { 92 my($This, %NamesAndValues) = @_; 93 94 my($Name, $Value, $MethodName); 95 while (($Name, $Value) = each %NamesAndValues) { 96 $MethodName = "Set${Name}"; 97 $This->$MethodName($Value); 98 } 99 100 return $This; 101 } 102 103 # Initialize descriptor names and values... 104 # 105 sub _InitializeDescriptorNamesAndValues { 106 my($This, @Names) = @_; 107 108 @{$This->{DescriptorNames}} = @Names; 109 110 $This->_InitializeDescriptorValues(); 111 112 return $This; 113 } 114 115 # Initialize descriptor values... 116 # 117 sub _InitializeDescriptorValues { 118 my($This) = @_; 119 120 $This->{DescriptorsGenerated} = 0; 121 122 @{$This->{DescriptorValues}} = (); 123 124 return $This; 125 } 126 127 # Set molecule object... 128 # 129 sub SetMolecule { 130 my($This, $Molecule) = @_; 131 132 $This->{Molecule} = $Molecule; 133 134 # Weaken the reference to disable increment of reference count... 135 Scalar::Util::weaken($This->{Molecule}); 136 137 return $This; 138 } 139 140 # Set type and make sure it's not already set... 141 # 142 sub SetType { 143 my($This, $Type) = @_; 144 145 if ($This->{Type}) { 146 croak "Error: ${ClassName}->SetType: Can't change MolecularDescriptors type: It's already set..."; 147 } 148 $This->{Type} = $Type; 149 150 return $This; 151 } 152 153 # Get molecular descriptor names as an array... 154 # 155 sub GetDescriptorNames { 156 my($This) = @_; 157 158 return @{$This->{DescriptorNames}}; 159 } 160 161 # Set descriptor names... 162 # 163 sub SetDescriptorNames { 164 my($This, @Names) = @_; 165 166 @{$This->{DescriptorNames}} = @Names; 167 168 return $This; 169 } 170 171 # Add descriptor names... 172 # 173 sub AddDescriptorNames { 174 my($This, @Names) = @_; 175 176 push @{$This->{DescriptorNames}}, @Names; 177 178 return $This; 179 } 180 181 # Set descriptor values... 182 # 183 sub SetDescriptorValues { 184 my($This, @Values) = @_; 185 186 @{$This->{DescriptorValues}} = @Values; 187 188 return $This; 189 } 190 191 # Add descriptor values... 192 # 193 sub AddDescriptorValues { 194 my($This, @Values) = @_; 195 196 push @{$This->{DescriptorValues}}, @Values; 197 198 return $This; 199 } 200 201 # Is descriptors generation successful? 202 # 203 # Notes: 204 # . The specific molecular descriptor class generation class sets the value of 205 # DescriptorsCalculated to 1 after the successful generation of descriptors; 206 # otherwise, it's set to 0. 207 # 208 sub IsDescriptorsGenerationSuccessful { 209 my($This) = @_; 210 211 return $This->{DescriptorsGenerated} ? 1 : 0; 212 } 213 214 # Get all descriptor values as an array... 215 # 216 sub GetDescriptorValues { 217 my($This) = @_; 218 219 if ($This->{DescriptorsGenerated}) { 220 return wantarray ? @{$This->{DescriptorValues}} : scalar @{$This->{DescriptorValues}}; 221 } 222 else { 223 my(@DescriptorValues); 224 225 @DescriptorValues = ('None') x scalar @{$This->{DescriptorNames}}; 226 227 return wantarray ? @DescriptorValues : scalar @DescriptorValues; 228 } 229 } 230 231 # Get descriptor value for a specified descriptor name... 232 # 233 sub GetDescriptorValueByName { 234 my($This, $Name) = @_; 235 my(%NamesAndValues); 236 237 %NamesAndValues = $This->GetDescriptorNamesAndValues(); 238 239 return exists $NamesAndValues{$Name} ? $NamesAndValues{$Name} : 'None'; 240 241 } 242 243 # Get calculated molecular descriptor names sand values as a to a hash with names 244 # and values as key/value pairs... 245 # 246 sub GetDescriptorNamesAndValues { 247 my($This) = @_; 248 my(%NamesAndValues); 249 250 %NamesAndValues = (); 251 @NamesAndValues{ @{$This->{DescriptorNames}} } = $This->GetDescriptorValues(); 252 253 return %NamesAndValues; 254 } 255 256 # Return a string containing descriptor names and values... 257 # 258 sub _StringifyDescriptorNamesAndValues { 259 my($This) = @_; 260 my($NamesAndValuesString, $Name, $Value, @NamesAndValuesInfo, %NamesAndValues); 261 262 @NamesAndValuesInfo = (); 263 %NamesAndValues = $This->GetDescriptorNamesAndValues(); 264 265 for $Name (@{$This->{DescriptorNames}}) { 266 $Value = $NamesAndValues{$Name}; 267 $Value = (TextUtil::IsEmpty($Value) || $Value =~ /^None$/i) ? 'None' : $Value; 268 push @NamesAndValuesInfo, "$Name - $Value"; 269 } 270 if (@NamesAndValuesInfo) { 271 $NamesAndValuesString = "Names - Values: <" . TextUtil::JoinWords(\@NamesAndValuesInfo, ", ", 0) . ">"; 272 } 273 else { 274 $NamesAndValuesString = "Names - Values: < None>"; 275 } 276 return $NamesAndValuesString; 277 } 278