1 package Fingerprints::Fingerprints; 2 # 3 # $RCSfile: Fingerprints.pm,v $ 4 # $Date: 2015/02/28 20:48:54 $ 5 # $Revision: 1.33 $ 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 ObjectProperty; 34 use MathUtil (); 35 use TextUtil (); 36 use Fingerprints::FingerprintsBitVector; 37 use Fingerprints::FingerprintsVector; 38 39 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 40 41 @ISA = qw(ObjectProperty Exporter); 42 @EXPORT = qw(); 43 @EXPORT_OK = qw(); 44 45 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 46 47 # Setup class variables... 48 my($ClassName); 49 _InitializeClass(); 50 51 # Class constructor... 52 sub new { 53 my($Class, %NamesAndValues) = @_; 54 55 # Initialize object... 56 my $This = {}; 57 bless $This, ref($Class) || $Class; 58 $This->_InitializeFingerprints(); 59 60 $This->_InitializeFingerprintsProperties(%NamesAndValues); 61 62 return $This; 63 } 64 65 # Initialize object data... 66 # 67 sub _InitializeFingerprints { 68 my($This) = @_; 69 70 # Molecule object... 71 $This->{Molecule} = ''; 72 73 # Type of fingerprints... 74 $This->{Type} = ''; 75 76 # Type of fingerprints vector: FingerprintsBitVector or FingerprintsVector... 77 $This->{VectorType} = ''; 78 79 # Marks successful generation of fingerprints... 80 $This->{FingerprintsGenerated} = 0; 81 82 # Initialize values for FingerprintsBitVector... 83 _InitializeClassValuesForFingerprintsBitVector(); 84 85 # Initialize values for FingerprintsVector... 86 _InitializeClassValuesForFingerprintsVector(); 87 } 88 89 # Initialize class ... 90 sub _InitializeClass { 91 #Class name... 92 $ClassName = __PACKAGE__; 93 } 94 95 # Initialize class values specific to FingerprintsBitVector... 96 # 97 sub _InitializeClassValuesForFingerprintsBitVector { 98 my($This) = @_; 99 100 # Size of FingerprintsBitVector... 101 $This->{Size} = ''; 102 103 # Min/Max sizes used for folding FingerprintsBitVector... 104 $This->{MinSize} = ''; 105 $This->{MaxSize} = ''; 106 107 # FingerprintsBitVector... 108 $This->{FingerprintsBitVector} = ''; 109 } 110 111 # Initialize class values specific to FingerprintsVector... 112 # 113 sub _InitializeClassValuesForFingerprintsVector { 114 my($This) = @_; 115 116 # Types of FingerprintsVector values: OrderedNumericalValues, NumericalValues or AlphaNumericalValues. 117 $This->{FingerprintsVectorType} = ''; 118 119 # Fingerprints vector... 120 $This->{FingerprintsVector} = ''; 121 } 122 123 # Initialize object properties.... 124 sub _InitializeFingerprintsProperties { 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 molecule object and make sure it's not already set... 137 # 138 sub SetMolecule { 139 my($This, $Molecule) = @_; 140 141 if ($This->{Molecule}) { 142 croak "Error: ${ClassName}->SetMolecule: Can't change molecule object: It's already set..."; 143 } 144 $This->{Molecule} = $Molecule; 145 146 # Weaken the reference to disable increment of reference count... 147 Scalar::Util::weaken($This->{Molecule}); 148 149 return $This; 150 } 151 152 # Set type and make sure it's not already set... 153 # 154 sub SetType { 155 my($This, $Type) = @_; 156 157 if ($This->{Type}) { 158 croak "Error: ${ClassName}->SetType: Can't change fingerprint type: It's already set..."; 159 } 160 $This->{Type} = $Type; 161 162 return $This; 163 } 164 165 # Is fingerprints generation successful? 166 # 167 # Notes: 168 # . The specific fingerprints generation class sets the value of FingerprinsGenerated 169 # to 1 after the successful generation of fingerprints; otherwise, it's set to 0. 170 # 171 sub IsFingerprintsGenerationSuccessful { 172 my($This) = @_; 173 174 return $This->{FingerprintsGenerated} ? 1 : 0; 175 } 176 177 # Set vector type and make sure it's not already set... 178 # 179 sub SetVectorType { 180 my($This, $VectorType) = @_; 181 182 if ($This->{VectorType}) { 183 croak "Error: ${ClassName}->SetVectorType: Can't change fingerprint vector type: It's already set..."; 184 } 185 if ($VectorType !~ /^(FingerprintsBitVector|FingerprintsVector)$/i) { 186 croak "Error: ${ClassName}->SetVectorType: Specified value, $VectorType, for Type is not vaild. Supported types in current release of MayaChemTools: FingerprintsBitVector and FingerprintsVector..."; 187 } 188 $This->{VectorType} = $VectorType; 189 190 return $This; 191 } 192 193 # 194 # Methods/functions for FingerprintsBitVector... 195 # 196 197 # Initialize fingerprint bit vector... 198 sub _InitializeFingerprintsBitVector { 199 my($This) = @_; 200 201 if ($This->{VectorType} !~ /^FingerprintsBitVector$/i) { 202 croak "Error: ${ClassName}->_InitializeFingerprintsBitVector: Can't initialize fingerprints bit vector: VectorType must be FingerprintsBitVector..."; 203 } 204 205 if ($This->{Size}) { 206 $This->{FingerprintsBitVector} = new Fingerprints::FingerprintsBitVector($This->{Size}); 207 } 208 return $This; 209 } 210 211 # Set size... 212 # 213 sub SetSize { 214 my($This, $Size) = @_; 215 216 if ($This->{MinSize} && $Size < $This->{MinSize}) { 217 croak "Error: ${ClassName}->SetSize: Fingerprint size value, $Size, is not valid : It must be >= $This->{MinSize}..."; 218 } 219 if ($This->{MaxSize} && $Size > $This->{MaxSize}) { 220 croak "Error: ${ClassName}->SetSize: Fingerprint size value, $Size, is not valid: It must be <= $This->{MaxSize}..."; 221 } 222 223 $This->{Size} = $Size; 224 225 return $This; 226 } 227 228 # Set FingerprintsBitVector object and make sure it's not already set... 229 # 230 sub SetFingerprintsBitVector { 231 my($This, $FingerprintsBitVector) = @_; 232 233 if ($This->{FingerprintsBitVector}) { 234 croak "Error: ${ClassName}->SetFingerprintsBitVector: Can't change FingerprintsBitVector object: It's already set..."; 235 } 236 $This->{FingerprintsBitVector} = $FingerprintsBitVector; 237 238 return $This; 239 } 240 241 # Fold fingerprints by recursively reducing its size by half untill bit density is greater than or equal to 242 # specified bit density... 243 # 244 sub FoldFingerprintsByBitDensity { 245 my($This, $BitDensity) = @_; 246 247 if (!($BitDensity >= 0 && $BitDensity <= 1)) { 248 croak "Error: ${ClassName}->FoldFingerprintsByBitDensity: Specified bit density, $BitDensity, is not valid: It must be > 0 && <= 1 ..."; 249 } 250 251 return $This->_FoldFingerprintsBitVector('ByDensity', $BitDensity); 252 } 253 254 # Fold fingerprints by recursively reducing its size by half untill size is less than or equal to 255 # specified size... 256 # 257 sub FoldFingerprintsBySize { 258 my($This, $Size, $CheckSizeValue) = @_; 259 260 if (!defined $CheckSizeValue) { 261 $CheckSizeValue = 1; 262 } 263 264 if ($CheckSizeValue) { 265 if (!TextUtil::IsPositiveInteger($Size)) { 266 croak "Error: ${ClassName}->FoldFingerprintsBySize: Specified size, $Size, is not valid: It must be a positive integer"; 267 } 268 if (!($Size >= $This->{MinSize} && $Size < $This->{Size})) { 269 croak "Error: ${ClassName}->FoldFingerprintsBySize: Specified size, $Size, is not valid: It must be greater than or equal to minimum size of $This->{MinSize} and less than current size of $This->{Size}..."; 270 } 271 if (!TextUtil::IsNumberPowerOfNumber($Size, 2)) { 272 croak "Error: ${ClassName}->FoldFingerprintsBySize: Specified size value, $Size, must be power of 2..."; 273 } 274 } 275 276 return $This->_FoldFingerprintsBitVector('BySize', $Size); 277 } 278 279 # Fold fingerprints bit vector using specified size of bit density... 280 # 281 sub _FoldFingerprintsBitVector { 282 my($This, $Mode, $Value) = @_; 283 284 if (!$This->{FingerprintsBitVector}) { 285 return $This; 286 } 287 my($FingerprintsBitVector, $FoldedFingerprintsBitVector); 288 289 $FoldedFingerprintsBitVector = ''; 290 $FingerprintsBitVector = $This->{FingerprintsBitVector}; 291 MODE: { 292 if ($Mode =~ /^BySize$/i) { $FoldedFingerprintsBitVector = $FingerprintsBitVector->FoldFingerprintsBitVectorBySize($Value); last MODE; } 293 if ($Mode =~ /^ByDensity$/i) { $FoldedFingerprintsBitVector = $FingerprintsBitVector->FoldFingerprintsBitVectorByDensity($Value); last MODE; } 294 $FoldedFingerprintsBitVector = ''; 295 } 296 if ($FoldedFingerprintsBitVector) { 297 $This->{FingerprintsBitVector} = $FoldedFingerprintsBitVector; 298 $This->{Size} = $FoldedFingerprintsBitVector->GetSize(); 299 } 300 return $This; 301 } 302 303 # Get fingerprints as a binary ascii string containing 0s and 1s... 304 # 305 sub GetFingerprintBitsAsBinaryString { 306 my($This, $BitOrder) = @_; 307 308 return $This->_GetFingerprintBitsAsString('Binary', $BitOrder); 309 } 310 311 # Get fingerprints as a hexadecimal string... 312 # 313 sub GetFingerprintBitsAsHexadecimalString { 314 my($This, $BitOrder) = @_; 315 316 return $This->_GetFingerprintBitsAsString('Hexadecimal', $BitOrder); 317 } 318 319 # Get fingerprints as a raw binary string containing packed bit values for each 320 # byte... 321 # 322 sub GetFingerprintBitsAsRawBinaryString { 323 my($This, $BitOrder) = @_; 324 325 return $This->_GetFingerprintBitsAsString('RawBinary', $BitOrder); 326 } 327 328 # Get fingerprint bits as a string... 329 # 330 sub _GetFingerprintBitsAsString { 331 my($This, $Format) = @_; 332 333 if (!$This->{FingerprintsBitVector}) { 334 return undef; 335 } 336 FORMAT : { 337 if ($Format =~ /^(Binary|Bin|BinaryString)$/i) { return $This->{FingerprintsBitVector}->GetBitsAsBinaryString(); last FORMAT; } 338 if ($Format =~ /^(Hexadecimal|Hex|HexadecimalString)$/i) { return $This->{FingerprintsBitVector}->GetBitsAsHexadecimalString(); last FORMAT; } 339 if ($Format =~ /^(RawBinary|RawBin|RawBinaryString)$/i) { return $This->{FingerprintsBitVector}->GetBitsAsRawBinaryString(); last FORMAT; } 340 croak "Error: ${ClassName}->_GetFingerprintBitsAsString: Specified bit vector string format, $Format, is not supported. Value values: Binary, Bin, BinaryString, Hexdecimal, Hex, HexadecimalString, RawBinary, RawBin, RawBinaryString..."; 341 } 342 return undef; 343 } 344 345 # 346 # Methods/functions for FingerprintsVector... 347 # 348 349 # Initialize fingerprint vector... 350 sub _InitializeFingerprintsVector { 351 my($This) = @_; 352 353 if ($This->{VectorType} !~ /^FingerprintsVector$/i) { 354 croak "Error: ${ClassName}->_InitializeFingerprintsVector: Can't initialize fingerprints vector: VectorType must be FingerprintsVector..."; 355 } 356 357 if ($This->{FingerprintsVectorType}) { 358 $This->{FingerprintsVector} = new Fingerprints::FingerprintsVector('Type' => $This->{FingerprintsVectorType}); 359 } 360 return $This; 361 } 362 363 # Set FingerprintsVector object and make sure it's not already set... 364 # 365 sub SetFingerprintsVector { 366 my($This, $FingerprintsVector) = @_; 367 368 if ($This->{FingerprintsVector}) { 369 croak "Error: ${ClassName}->SetFingerprintsVector: Can't change FingerprintsVector object: It's already set..."; 370 } 371 $This->{FingerprintsVector} = $FingerprintsVector; 372 373 return $This; 374 } 375 376 # Types of FingerprintsVector values: OrderedNumericalValues, NumericalValues or AlphaNumericalValues. 377 # 378 sub SetFingerprintsVectorType { 379 my($This, $FingerprintsVectorType) = @_; 380 381 if ($This->{FingerprintsVectorType}) { 382 croak "Error: ${ClassName}->SetFingerprintsVector: Can't change FingerprintsVectorType: It's already set..."; 383 } 384 if ($FingerprintsVectorType !~ /^(OrderedNumericalValues|NumericalValues|AlphaNumericalValues)$/i) { 385 croak "Error: ${ClassName}->SetFingerprintsVectorType: Specified value, $FingerprintsVectorType, for Type is not vaild. Supported types in current release of MayaChemTools: OrderedNumericalValues, NumericalValues or AlphaNumericalValues"; 386 } 387 $This->{FingerprintsVectorType} = $FingerprintsVectorType; 388 389 return $This; 390 } 391 392 # Get fingerprints vector values as an array or reference to an array... 393 # 394 sub GetFingerprintsVectorValues { 395 my($This) = @_; 396 397 if (!$This->{FingerprintsVector}) { 398 return undef; 399 } 400 return $This->{FingerprintsVector}->GetValues(); 401 } 402 403 # Get fingerprints vector value IDs as an array or reference to an array... 404 # 405 sub GetFingerprintsVectorValueIDs { 406 my($This) = @_; 407 408 if (!$This->{FingerprintsVector}) { 409 return undef; 410 } 411 return $This->{FingerprintsVector}->GetValueIDs(); 412 } 413