MayaChemTools

   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