1 package MolecularDescriptors::MolecularComplexityDescriptors; 2 # 3 # $RCSfile: MolecularComplexityDescriptors.pm,v $ 4 # $Date: 2015/02/28 20:49:20 $ 5 # $Revision: 1.15 $ 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::AtomicInvariantsAtomTypes; 39 use AtomTypes::FunctionalClassAtomTypes; 40 use Fingerprints::AtomTypesFingerprints; 41 use Fingerprints::ExtendedConnectivityFingerprints; 42 use Fingerprints::MACCSKeys; 43 use Fingerprints::PathLengthFingerprints; 44 use Fingerprints::TopologicalAtomPairsFingerprints; 45 use Fingerprints::TopologicalAtomTripletsFingerprints; 46 use Fingerprints::TopologicalAtomTorsionsFingerprints; 47 use Fingerprints::TopologicalPharmacophoreAtomPairsFingerprints; 48 use Fingerprints::TopologicalPharmacophoreAtomTripletsFingerprints; 49 50 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 51 52 @ISA = qw(MolecularDescriptors::MolecularDescriptors Exporter); 53 @EXPORT = qw(); 54 @EXPORT_OK = qw(GetDescriptorNames GetMolecularComplexityTypeAbbreviation); 55 56 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 57 58 # Setup class variables... 59 my($ClassName, @DescriptorNames); 60 _InitializeClass(); 61 62 # Overload Perl functions... 63 use overload '""' => 'StringifyMolecularComplexityDescriptors'; 64 65 # Class constructor... 66 sub new { 67 my($Class, %NamesAndValues) = @_; 68 69 # Initialize object... 70 my $This = $Class->SUPER::new(); 71 bless $This, ref($Class) || $Class; 72 $This->_InitializeMolecularComplexityDescriptors(); 73 74 $This->_InitializeMolecularComplexityDescriptorsProperties(%NamesAndValues); 75 76 return $This; 77 } 78 79 # Initialize class ... 80 sub _InitializeClass { 81 #Class name... 82 $ClassName = __PACKAGE__; 83 84 # Descriptor names... 85 @DescriptorNames = ('MolecularComplexity'); 86 87 } 88 89 # Get descriptor names as an array. 90 # 91 # This functionality can be either invoked as a class function or an 92 # object method. 93 # 94 sub GetDescriptorNames { 95 return @DescriptorNames; 96 } 97 98 # Initialize object data... 99 # 100 sub _InitializeMolecularComplexityDescriptors { 101 my($This) = @_; 102 103 # Type of MolecularDescriptor... 104 $This->{Type} = 'MolecularComplexity'; 105 106 # 107 # The current release of MayaChemTools supports calculation of molecular complexity 108 # corresponding to number of bits-set or unique keys [ Ref 117-119 ] in molecular 109 # fingerprints. The following types of fingerprints based molecular complexity measures 110 # are supported: 111 # 112 # AtomTypesFingerprints 113 # ExtendedConnectivityFingerprints 114 # MACCSKeys 115 # PathLengthFingerprints 116 # TopologicalAtomPairsFingerprints 117 # TopologicalAtomTripletsFingerprints 118 # TopologicalAtomTorsionsFingerprints 119 # TopologicalPharmacophoreAtomPairsFingerprints 120 # TopologicalPharmacophoreAtomTripletsFingerprints 121 # 122 # Default: MACCSKeys 123 # 124 $This->{MolecularComplexityType} = ''; 125 126 # Atom types to use for generating fingerprints... 127 # 128 # Currently supported values are: AtomicInvariantsAtomTypes, DREIDINGAtomTypes, 129 # EStateAtomTypes, FunctionalClassAtomTypes, MMFF94AtomTypes, SLogPAtomTypes, 130 # SYBYLAtomTypes, TPSAAtomTypes, UFFAtomTypes 131 # 132 # Notes: 133 # . AtomicInvariantsAtomTypes for all supported MolecularComplexityType except for 134 # TopologicalPharmacophoreAtomPairsFingerprints and TopologicalPharmacophoreAtomTripletsFingerprints 135 # . This value is not used for MACCSKeys 136 # . FunctionalClassAtomTypes is the only valid value during topological pharmacophore fingerprints. 137 # 138 # . Default values for AtomicInvariantsToUse and FunctionalClassesToUse are set appropriately 139 # for different types of fingerprints as shown below. 140 # 141 # MolecularComplexityType AtomicInvariantsToUse 142 # 143 # AtomTypesFingerprints AS, X, BO, H, FC 144 # TopologicalAtomPairsFingerprints AS, X, BO, H, FC 145 # TopologicalAtomTripletsFingerprints AS, X, BO, H, FC 146 # TopologicalAtomTorsionsFingerprints AS, X, BO, H, FC 147 # 148 # ExtendedConnectivityFingerprints AS, X, BO, H, FC, MN 149 # PathLengthFingerprints AS 150 # 151 # Default for FunctionalClassesToUse for all fingerprints is set to: 152 # 153 # HBD, HBA, PI, NI, Ar, Hal 154 # 155 # except for the following two MolecularComplexityType fingerprints: 156 # 157 # TopologicalPharmacophoreAtomPairsFingerprints HBD, HBA, PI, NI, H 158 # TopologicalPharmacophoreAtomTripletsFingerprints HBD, HBA, PI, NI, H, Ar 159 # 160 $This->{AtomIdentifierType} = ''; 161 162 # Size of MACCS key set: 166 or 322... 163 # 164 $This->{MACCSKeysSize} = 166; 165 166 # Atomic neighborhoods radius for extended connectivity fingerprints... 167 $This->{NeighborhoodRadius} = 2; 168 169 # Minimum and maximum path lengths to use for path length fingerprints... 170 $This->{MinPathLength} = 1; 171 $This->{MaxPathLength} = 8; 172 173 # By default bond symbols are included in atom path strings used to generate path length 174 # fingerprints... ... 175 $This->{UseBondSymbols} = 1; 176 177 # Minimum and maximum bond distance between atom pairs during topological 178 # atom pairs/triplets fingerprints... 179 $This->{MinDistance} = 1; 180 $This->{MaxDistance} = 10; 181 182 # Determines whether to apply triangle inequality to distance triplets... 183 # 184 # Default for TopologicalAtomTripletsFingerprints: 0 185 # Default for TopologicalPharmacophoreAtomTripletsFingerprints: 1 186 # 187 $This->{UseTriangleInequality} = ''; 188 189 # Distance bin size used for binning distances during generation of 190 # topological pharmacophore atom triplets fingerprints... 191 # 192 $This->{DistanceBinSize} = 2; 193 194 # Normalization methodology to use for scaling the number of bits-set or unique keys 195 # for: 196 # 197 # ExtendedConnectivityFingerprints 198 # TopologicalPharmacophoreAtomPairsFingerprints 199 # TopologicalPharmacophoreAtomTripletsFingerprints 200 # 201 # This option is gnored for all other types of fingerprints. 202 # 203 # Possible values during extended connectivity fingerprints: None or ByHeavyAtomsCount. Default: 204 # None. 205 # 206 # Possible values during topological pharmacophore atom pairs and tripletes fingerprints: None, 207 # or ByPossibleKeysCount. Default: None. ByPossibleKeysCount corresponds to total number of 208 # possible topological pharmacophore atom pairs or triplets in a molecule. 209 # 210 # 211 $This->{NormalizationMethodology} = 'None'; 212 213 # Intialize descriptor names and values... 214 $This->_InitializeDescriptorNamesAndValues(@DescriptorNames); 215 216 return $This; 217 } 218 219 # Initialize object properties... 220 # 221 sub _InitializeMolecularComplexityDescriptorsProperties { 222 my($This, %NamesAndValues) = @_; 223 224 my($Name, $Value, $MethodName); 225 while (($Name, $Value) = each %NamesAndValues) { 226 $MethodName = "Set${Name}"; 227 $This->$MethodName($Value); 228 } 229 230 # Make sure MolecularComplexityType is set... 231 if (!exists $NamesAndValues{MolecularComplexityType}) { 232 $This->{MolecularComplexityType} = 'MACCSKeys'; 233 } 234 235 # Make sure AtomIdentifierType is set... 236 if ($This->{MolecularComplexityType} !~ /^MACCSKeys$/i) { 237 if (!exists $NamesAndValues{AtomIdentifierType}) { 238 $This->_InitializeAtomIdentifierType(); 239 } 240 } 241 242 # Make sure UseTriangleInequality is set... 243 if ($This->{MolecularComplexityType} =~ /^(TopologicalAtomTripletsFingerprints|TopologicalPharmacophoreAtomTripletsFingerprints)$/i) { 244 if (!exists $NamesAndValues{UseTriangleInequality}) { 245 $This->{UseTriangleInequality} = ($This->{MolecularComplexityType} =~ /^TopologicalPharmacophoreAtomTripletsFingerprints$/i) ? 1 : 0; 246 } 247 } 248 249 return $This; 250 } 251 252 # Initialize atom identifer type... 253 # 254 sub _InitializeAtomIdentifierType { 255 my($This) = @_; 256 my($AtomIdentifierType); 257 258 if ($This->{MolecularComplexityType} =~ /^MACCSKeys$/i) { 259 return $This; 260 } 261 262 $AtomIdentifierType = ($This->{MolecularComplexityType} =~ /^(TopologicalPharmacophoreAtomPairsFingerprints|TopologicalPharmacophoreAtomTripletsFingerprints)$/i) ? 'FunctionalClassAtomTypes' : 'AtomicInvariantsAtomTypes'; 263 264 $This->SetAtomIdentifierType($AtomIdentifierType); 265 266 return $This; 267 } 268 269 # Get abbreviation for specified molecular complexity type or using descriptors object... 270 # 271 # This functionality can be either invoked as a class function or an 272 # object method. 273 # 274 sub GetMolecularComplexityTypeAbbreviation { 275 my($FirstParameter) = @_; 276 my($This, $ComplexityType, %ComplexityTypeToAbbrev); 277 278 if (_IsMolecularComplexityDescriptors($FirstParameter)) { 279 $This = $FirstParameter; 280 $ComplexityType = $This->{MolecularComplexityType}; 281 } 282 else { 283 $ComplexityType = $FirstParameter; 284 } 285 286 %ComplexityTypeToAbbrev = (lc 'AtomTypesFingerprints' => 'ATFP', lc 'ExtendedConnectivityFingerprints' => 'ECFP', 287 lc 'MACCSKeys' => 'MACCSKeys', lc 'PathLengthFingerprints' => 'PLFP', 288 lc 'TopologicalAtomPairsFingerprints' => 'TAPFP', lc 'TopologicalAtomTripletsFingerprints' => 'TATFP', 289 lc 'TopologicalAtomTorsionsFingerprints' => 'TATFP', 290 lc 'TopologicalPharmacophoreAtomPairsFingerprints' => 'TPAPFP', 291 lc 'TopologicalPharmacophoreAtomTripletsFingerprints' => 'TPATFP'); 292 293 return exists $ComplexityTypeToAbbrev{lc $ComplexityType} ? $ComplexityTypeToAbbrev{lc $ComplexityType} : ''; 294 } 295 296 # Set MACCS key set size... 297 # 298 sub SetMACCSKeysSize { 299 my($This, $Value) = @_; 300 301 if (!TextUtil::IsPositiveInteger($Value)) { 302 croak "Error: ${ClassName}->SetMACCSKeysSize: Size value, $Value, is not valid: It must be a positive integer..."; 303 } 304 if ($Value !~ /^(166|322)/i) { 305 croak "Error: ${ClassName}->SetMACCSKeysSize: The current release of MayaChemTools doesn't support MDL MACCS $Value keys..."; 306 } 307 $This->{MACCSKeysSize} = $Value; 308 309 return $This; 310 } 311 312 # Set minimum path length... 313 # 314 sub SetMinPathLength { 315 my($This, $Value) = @_; 316 317 if (!TextUtil::IsPositiveInteger($Value)) { 318 croak "Error: ${ClassName}->SetMinPathLength: MinPathLength value, $Value, is not valid: It must be a positive integer..."; 319 } 320 $This->{MinPathLength} = $Value; 321 322 return $This; 323 } 324 325 # Set maximum path length... 326 # 327 sub SetMaxPathLength { 328 my($This, $Value) = @_; 329 330 if (!TextUtil::IsPositiveInteger($Value)) { 331 croak "Error: ${ClassName}->SetMaxPathLength: MaxPathLength value, $Value, is not valid: It must be a positive integer..."; 332 } 333 $This->{MaxPathLength} = $Value; 334 335 return $This; 336 } 337 338 # Set minimum bond distance between atom pairs during topological and topological 339 # pharmacophore atom pairs/triplets fingerprints... 340 # 341 sub SetMinDistance { 342 my($This, $Value) = @_; 343 344 if (!TextUtil::IsPositiveInteger($Value)) { 345 croak "Error: ${ClassName}->SetMinDistance: MinDistance value, $Value, is not valid: It must be a positive integer..."; 346 } 347 $This->{MinDistance} = $Value; 348 349 return $This; 350 } 351 352 # Set maximum bond distance between atom pairs during topological and topological 353 # pharmacophore atom pairs/triplets fingerprints... 354 # 355 sub SetMaxDistance { 356 my($This, $Value) = @_; 357 358 if (!TextUtil::IsPositiveInteger($Value)) { 359 croak "Error: ${ClassName}->SetMaxDistance: MaxDistance value, $Value, is not valid: It must be a positive integer..."; 360 } 361 $This->{MaxDistance} = $Value; 362 363 return $This; 364 } 365 366 # Set atom neighborhood radius... 367 # 368 sub SetNeighborhoodRadius { 369 my($This, $Value) = @_; 370 371 if (!TextUtil::IsInteger($Value)) { 372 croak "Error: ${ClassName}->SetNeighborhoodRadius: NeighborhoodRadius value, $Value, is not valid: It must be an integer..."; 373 } 374 375 if ($Value < 0 ) { 376 croak "Error: ${ClassName}->SetNeighborhoodRadius: NeighborhoodRadius value, $Value, is not valid: It must be >= 0..."; 377 } 378 $This->{NeighborhoodRadius} = $Value; 379 380 return $This; 381 } 382 383 # Set molecular complexity type... 384 # 385 sub SetMolecularComplexityType { 386 my($This, $Value) = @_; 387 388 if ($Value !~ /^(AtomTypesFingerprints|ExtendedConnectivityFingerprints|MACCSKeys|PathLengthFingerprints|TopologicalAtomPairsFingerprints|TopologicalAtomTripletsFingerprints|TopologicalAtomTorsionsFingerprints|TopologicalPharmacophoreAtomPairsFingerprints|TopologicalPharmacophoreAtomTripletsFingerprints)$/i) { 389 croak "Error: ${ClassName}->SetMolecularComplexityType: MolecularComplexityType value, $Value, is not valid. Supported values: AtomTypesFingerprints, ExtendedConnectivityFingerprints, MACCSKeys, PathLengthFingerprints, TopologicalAtomPairsFingerprints, TopologicalAtomTripletsFingerprints, TopologicalAtomTorsionsFingerprints, TopologicalPharmacophoreAtomPairsFingerprints, or TopologicalPharmacophoreAtomTripletsFingerprints..."; 390 } 391 392 $This->{MolecularComplexityType} = $Value; 393 394 return $This; 395 } 396 397 # Set distance bin size for binning pharmacophore atom pair distances in atom triplets... 398 # 399 sub SetDistanceBinSize { 400 my($This, $Value) = @_; 401 402 if (!TextUtil::IsPositiveInteger($Value)) { 403 croak "Error: ${ClassName}->SetDistanceBinSize: DistanceBinSize value, $Value, is not valid: It must be a positive integer..."; 404 } 405 $This->{DistanceBinSize} = $Value; 406 407 return $This; 408 } 409 410 # Set normalization methodology to use for scaling the number of bits-set or unique keys 411 # in fingerprints... 412 # 413 sub SetNormalizationMethodology { 414 my($This, $Value) = @_; 415 416 if ($Value !~ /^(ByHeavyAtomsCount|ByPossibleKeysCount|None)$/i) { 417 croak "Error: ${ClassName}->SetNormalizationMethodology: NormalizationMethodology value, $Value, is not valid. Supported values: None, ByHeavyAtomsCount or ByPossibleKeysCount..."; 418 } 419 420 if ($This->{MolecularComplexityType}) { 421 if ($This->{MolecularComplexityType} !~ /^(ExtendedConnectivityFingerprints|TopologicalPharmacophoreAtomPairsFingerprints|TopologicalPharmacophoreAtomTripletsFingerprints)$/i) { 422 croak "Error: ${ClassName}->SetNormalizationMethodology: Normalization is not supported for MolecularComplexityType: $This->{MolecularComplexityType}. Valid MolecularComplexityType values: ExtendedConnectivityFingerprints, TopologicalPharmacophoreAtomPairsFingerprints, or TopologicalPharmacophoreAtomTripletsFingerprints...\n"; 423 } 424 425 if ($This->{MolecularComplexityType} =~ /^ExtendedConnectivityFingerprints$/i && $Value !~ /^(ByHeavyAtomsCount|None)$/i) { 426 croak "Error: ${ClassName}->SetNormalizationMethodology: NormalizationMethodology value, $Value, is not valid for MolecularComplexityType: $This->{MolecularComplexityType}. Supported values: None or ByHeavyAtomsCount..."; 427 } 428 429 if ($This->{MolecularComplexityType} =~ /^(TopologicalPharmacophoreAtomPairsFingerprints|TopologicalPharmacophoreAtomTripletsFingerprints)$/i && $Value !~ /^(ByPossibleKeysCount|None)$/i) { 430 croak "Error: ${ClassName}->SetNormalizationMethodology: NormalizationMethodology value, $Value, is not valid for MolecularComplexityType: $This->{MolecularComplexityType}. Supported values: None or ByPossibleKeysCount..."; 431 } 432 } 433 434 $This->{NormalizationMethodology} = $Value; 435 436 return $This; 437 } 438 439 # Set intial atom identifier type.. 440 # 441 sub SetAtomIdentifierType { 442 my($This, $IdentifierType) = @_; 443 444 if ($IdentifierType !~ /^(AtomicInvariantsAtomTypes|FunctionalClassAtomTypes|DREIDINGAtomTypes|EStateAtomTypes|MMFF94AtomTypes|SLogPAtomTypes|SYBYLAtomTypes|TPSAAtomTypes|UFFAtomTypes)$/i) { 445 croak "Error: ${ClassName}->SetAtomIdentifierType: Specified value, $IdentifierType, for AtomIdentifierType is not vaild. Supported types in current release of MayaChemTools: AtomicInvariantsAtomTypes, FunctionalClassAtomTypes, DREIDINGAtomTypes, EStateAtomTypes, MMFF94AtomTypes, SLogPAtomTypes, SYBYLAtomTypes, TPSAAtomTypes and UFFAtomTypes."; 446 } 447 448 # FunctionalClassAtomTypes is the only valid atom identifier type for pharmacophore fingerprints... 449 if ($This->{MolecularComplexityType} =~ /^(TopologicalPharmacophoreAtomPairsFingerprints|TopologicalPharmacophoreAtomTripletsFingerprints)$/i) { 450 if ($IdentifierType !~ /^FunctionalClassAtomTypes$/i) { 451 croak "Error: ${ClassName}->SetAtomIdentifierType: Specified value, $IdentifierType, for AtomIdentifierType is not vaild. Supported type for $This->{MolecularComplexityType} complexity type: FunctionalClassAtomTypes."; 452 } 453 } 454 455 if ($This->{AtomIdentifierType}) { 456 croak "Error: ${ClassName}->SetAtomIdentifierType: Can't change intial atom identifier type: It's already set..."; 457 } 458 459 $This->{AtomIdentifierType} = $IdentifierType; 460 461 # Initialize identifier type information... 462 $This->_InitializeAtomIdentifierTypeInformation(); 463 464 return $This; 465 } 466 467 # Calculate molecular complexity [ Ref 117-119 ] of a molecule using its fingerprints. 468 # 469 # The current release of MayaChemTools supports calculation of molecular complexity 470 # corresponding to the number of bits-set or unique keys in molecular fingerprints. The 471 # following types of fingerprints based molecular complexity measures are supported: 472 # 473 # AtomTypesFingerprints 474 # ExtendedConnectivityFingerprints 475 # MACCSKeys 476 # PathLengthFingerprints 477 # TopologicalAtomPairsFingerprints 478 # TopologicalAtomTripletsFingerprints 479 # TopologicalAtomTorsionsFingerprints 480 # TopologicalPharmacophoreAtomPairsFingerprints 481 # TopologicalPharmacophoreAtomTripletsFingerprints 482 # 483 # After the molecular complexity value has been calculated, it can also be normalized by 484 # by scaling the number of bits-set or unique keys for following types of fingerprints: 485 # 486 # ExtendedConnectivityFingerprints 487 # TopologicalPharmacophoreAtomPairsFingerprints 488 # TopologicalPharmacophoreAtomTripletsFingerprints 489 # 490 # Two types of normalization methodologies are supported: by heavy atoms count for 491 # extended connectivity fingerprints; by possible keys count for topological pharmacophore 492 # atom pairs and triplets fingerprints. 493 # 494 sub GenerateDescriptors { 495 my($This) = @_; 496 497 # Initialize descriptor values... 498 $This->_InitializeDescriptorValues(); 499 500 # Check availability of molecule... 501 if (!$This->{Molecule}) { 502 carp "Warning: ${ClassName}->GenerateDescriptors: $This->{Type} molecular descriptors generation didn't succeed: Molecule data is not available: Molecule object hasn't been set..."; 503 return undef; 504 } 505 506 # Calculate descriptor values... 507 if (!$This->_CalculateDescriptorValues()) { 508 carp "Warning: ${ClassName}->GenerateDescriptors: $This->{Type} molecular descriptors generation didn't succeed: Couldn't calculate MolecularComplexity values corresponding to assigned MolecularComplexity atom types..."; 509 return undef; 510 } 511 512 # Set final descriptor values... 513 $This->_SetFinalDescriptorValues(); 514 515 return $This; 516 } 517 518 # Calculate molecular complexity value... 519 # 520 sub _CalculateDescriptorValues { 521 my($This) = @_; 522 my($FingerprintsObject, $MethodName); 523 524 # Setup fingerprints object and generate fingerprints... 525 $MethodName = "_Setup" . $This->{MolecularComplexityType}; 526 $FingerprintsObject = $This->$MethodName(); 527 528 $FingerprintsObject->GenerateFingerprints(); 529 530 # Make sure atom types fingerprints generation is successful... 531 if (!$FingerprintsObject->IsFingerprintsGenerationSuccessful()) { 532 return undef; 533 } 534 535 if (!$This->_CalculateMolecularComplexity($FingerprintsObject)) { 536 return undef; 537 } 538 539 # Normalize molecular complexity... 540 if ($This->{NormalizationMethodology} !~ /^None$/i) { 541 if (!$This->_NormalizeMolecularComplexity($FingerprintsObject)) { 542 return undef; 543 } 544 } 545 546 return $This; 547 } 548 549 # Setup atom types fingerprints... 550 # 551 sub _SetupAtomTypesFingerprints { 552 my($This) = @_; 553 my($FingerprintsObject); 554 555 $FingerprintsObject = new Fingerprints::AtomTypesFingerprints('Molecule' => $This->{Molecule}, 'Type' => 'AtomTypesCount', 'AtomIdentifierType' => $This->{AtomIdentifierType}, 'IgnoreHydrogens' => 1); 556 $This->_SetAtomIdentifierTypeValuesToUse($FingerprintsObject); 557 558 return $FingerprintsObject; 559 } 560 561 # Setup extended connectivity fingerprints... 562 # 563 sub _SetupExtendedConnectivityFingerprints { 564 my($This) = @_; 565 my($FingerprintsObject); 566 567 $FingerprintsObject = new Fingerprints::ExtendedConnectivityFingerprints('Molecule' => $This->{Molecule}, 'Type' => 'ExtendedConnectivity', 'NeighborhoodRadius' => $This->{NeighborhoodRadius}, 'AtomIdentifierType' => $This->{AtomIdentifierType}); 568 $This->_SetAtomIdentifierTypeValuesToUse($FingerprintsObject); 569 570 return $FingerprintsObject; 571 } 572 573 # Setup MACCS keys... 574 # 575 sub _SetupMACCSKeys { 576 my($This) = @_; 577 my($FingerprintsObject); 578 579 $FingerprintsObject = new Fingerprints::MACCSKeys('Molecule' => $This->{Molecule}, 'Type' => 'MACCSKeyBits', 'Size' => $This->{MACCSKeysSize}); 580 581 return $FingerprintsObject; 582 } 583 584 # Set up path length fingerprints... 585 # 586 sub _SetupPathLengthFingerprints { 587 my($This) = @_; 588 my($FingerprintsObject); 589 590 $FingerprintsObject = new Fingerprints::PathLengthFingerprints('Molecule' => $This->{Molecule}, 'Type' => 'PathLengthCount', 'AtomIdentifierType' => $This->{AtomIdentifierType}, 'MinLength' => $This->{MinPathLength}, 'MaxLength' => $This->{MaxPathLength}, 'AllowRings' => 1, 'AllowSharedBonds' => 1, 'UseBondSymbols' => $This->{UseBondSymbols}, 'UseUniquePaths' => 1); 591 $This->_SetAtomIdentifierTypeValuesToUse($FingerprintsObject); 592 593 return $FingerprintsObject; 594 } 595 596 # Setup topological atom pairs fingerprints... 597 # 598 sub _SetupTopologicalAtomPairsFingerprints { 599 my($This) = @_; 600 my($FingerprintsObject); 601 602 $FingerprintsObject = new Fingerprints::TopologicalAtomPairsFingerprints('Molecule' => $This->{Molecule}, 'MinDistance' => $This->{MinDistance}, 'MaxDistance' => $This->{MaxDistance}, 'AtomIdentifierType' => $This->{AtomIdentifierType}); 603 $This->_SetAtomIdentifierTypeValuesToUse($FingerprintsObject); 604 605 return $FingerprintsObject; 606 } 607 608 # Setup topological atom triplets fingerprints... 609 # 610 sub _SetupTopologicalAtomTripletsFingerprints { 611 my($This) = @_; 612 my($FingerprintsObject); 613 614 $FingerprintsObject = new Fingerprints::TopologicalAtomTripletsFingerprints('Molecule' => $This->{Molecule}, 'MinDistance' => $This->{MinDistance}, 'MaxDistance' => $This->{MaxDistance}, 'UseTriangleInequality' => $This->{UseTriangleInequality}, 'AtomIdentifierType' => $This->{AtomIdentifierType}); 615 $This->_SetAtomIdentifierTypeValuesToUse($FingerprintsObject); 616 617 return $FingerprintsObject; 618 } 619 620 # Setup topological atom torsions fingerprints... 621 # 622 sub _SetupTopologicalAtomTorsionsFingerprints { 623 my($This) = @_; 624 my($FingerprintsObject); 625 626 $FingerprintsObject = new Fingerprints::TopologicalAtomTorsionsFingerprints('Molecule' => $This->{Molecule}, 'AtomIdentifierType' => $This->{AtomIdentifierType}); 627 628 $This->_SetAtomIdentifierTypeValuesToUse($FingerprintsObject); 629 630 return $FingerprintsObject; 631 } 632 633 # Setup TopologicalPharmacophoreAtomPairsFingerprints... 634 # 635 sub _SetupTopologicalPharmacophoreAtomPairsFingerprints { 636 my($This) = @_; 637 my($FingerprintsObject, $AtomPairsSetSizeToUse); 638 639 # Use fixed size to get total number of possible keys for normalization... 640 $AtomPairsSetSizeToUse = ($This->{NormalizationMethodology} =~ /^ByPossibleKeysCount$/i) ? 'FixedSize' : 'ArbitrarySize'; 641 642 $FingerprintsObject = new Fingerprints::TopologicalPharmacophoreAtomPairsFingerprints('Molecule' => $This->{Molecule}, 'AtomPairsSetSizeToUse' => $AtomPairsSetSizeToUse, 'MinDistance' => $This->{MinDistance}, 'MaxDistance' => $This->{MaxDistance}, 'AtomTypesToUse' => \@{$This->{FunctionalClassesToUse}}, 'NormalizationMethodology' => 'None', 'ValuesPrecision' => 2); 643 644 return $FingerprintsObject; 645 } 646 647 # Setup TopologicalPharmacophoreAtomTripletsFingerprints... 648 # 649 sub _SetupTopologicalPharmacophoreAtomTripletsFingerprints { 650 my($This) = @_; 651 my($FingerprintsObject, $AtomTripletsSetSizeToUse); 652 653 # Use fixed size to get total number of possible keys for normalization... 654 $AtomTripletsSetSizeToUse = ($This->{NormalizationMethodology} =~ /^ByPossibleKeysCount$/i) ? 'FixedSize' : 'ArbitrarySize'; 655 656 $FingerprintsObject = new Fingerprints::TopologicalPharmacophoreAtomTripletsFingerprints('Molecule' => $This->{Molecule}, 'AtomTripletsSetSizeToUse' => $AtomTripletsSetSizeToUse, 'MinDistance' => $This->{MinDistance}, 'MaxDistance' => $This->{MaxDistance}, 'DistanceBinSize' => $This->{DistanceBinSize}, 'UseTriangleInequality' => $This->{UseTriangleInequality}, 'AtomTypesToUse' => \@{$This->{FunctionalClassesToUse}}); 657 658 return $FingerprintsObject; 659 } 660 661 # Normalize molecular complexity value... 662 # 663 sub _NormalizeMolecularComplexity { 664 my($This, $FingerprintsObject) = @_; 665 666 if ($This->{MolecularComplexityType} =~ /^ExtendedConnectivityFingerprints$/i && $This->{NormalizationMethodology} =~ /^ByHeavyAtomsCount$/i) { 667 return $This->_NormalizeMolecularComplexityByHeavyAtomsCount($FingerprintsObject); 668 } 669 elsif ($This->{MolecularComplexityType} =~ /^(TopologicalPharmacophoreAtomPairsFingerprints|TopologicalPharmacophoreAtomTripletsFingerprints)$/i && $This->{NormalizationMethodology} =~ /^ByPossibleKeysCount$/i) { 670 return $This->_NormalizeMolecularComplexityByPossibleKeysCount($FingerprintsObject); 671 } 672 else { 673 warn "Warning: ${ClassName}->_NormalizeMolecularComplexity: NormalizationMethodology value, $This->{NormalizationMethodology}, is not valid. Supported values: ByHeavyAtomsCount or ByPossibleKeysCount..."; 674 } 675 return undef; 676 } 677 678 # Normalize molecular complexity value by heavy atom count... 679 # 680 sub _NormalizeMolecularComplexityByHeavyAtomsCount { 681 my($This, $FingerprintsObject) = @_; 682 my($NumOfHeavyAtoms, $NormalizedComplexity); 683 684 $NumOfHeavyAtoms = $This->{Molecule}->GetNumOfHeavyAtoms(); 685 if (!$NumOfHeavyAtoms) { 686 return $This; 687 } 688 689 $NormalizedComplexity = $This->{MolecularComplexity} / $NumOfHeavyAtoms; 690 $This->{MolecularComplexity} = MathUtil::round($NormalizedComplexity, 2) + 0; 691 692 return $This; 693 } 694 695 # Normalize molecular complexity value by possible keys count... 696 # 697 sub _NormalizeMolecularComplexityByPossibleKeysCount { 698 my($This, $FingerprintsObject) = @_; 699 my($NumOfPossibleKeys, $NormalizedComplexity); 700 701 $NumOfPossibleKeys = $FingerprintsObject->GetFingerprintsVector()->GetNumOfValues(); 702 if (!$NumOfPossibleKeys) { 703 return $This; 704 } 705 706 $NormalizedComplexity = $This->{MolecularComplexity} / $NumOfPossibleKeys; 707 $This->{MolecularComplexity} = MathUtil::round($NormalizedComplexity, 2) + 0; 708 709 return $This; 710 } 711 712 # Calculate molecular complexity value using fingerprints objects... 713 # 714 sub _CalculateMolecularComplexity { 715 my($This, $FingerprintsObject) = @_; 716 717 if ($FingerprintsObject->GetVectorType() =~ /^FingerprintsBitVector$/i) { 718 return $This->_CalculateMolecularComplexityUsingFingerprintsBitVector($FingerprintsObject->GetFingerprintsBitVector()); 719 } 720 elsif ($FingerprintsObject->GetVectorType() =~ /^FingerprintsVector$/i) { 721 return $This->_CalculateMolecularComplexityUsingFingerprintsVector($FingerprintsObject->GetFingerprintsVector()); 722 } 723 else { 724 warn "Warning: ${ClassName}->_CalculateMolecularComplexity: Fingerprints vector type is not valid. Supported values: FingerprintsBitVector or FingerprintsVector..."; 725 } 726 727 return undef; 728 } 729 730 # Calculate molecular complexity value using fingerprints vector... 731 # 732 sub _CalculateMolecularComplexityUsingFingerprintsVector { 733 my($This, $FingerprintsVector) = @_; 734 735 $This->{MolecularComplexity} = ($FingerprintsVector->GetType() =~ /^(OrderedNumericalValues|NumericalValues)$/i) ? $FingerprintsVector->GetNumOfNonZeroValues() : $FingerprintsVector->GetNumOfValues(); 736 737 return $This; 738 } 739 740 # Calculate molecular complexity value using fingerprints vector... 741 # 742 sub _CalculateMolecularComplexityUsingFingerprintsBitVector { 743 my($This, $FingerprintsBitVector) = @_; 744 745 $This->{MolecularComplexity} = $FingerprintsBitVector->GetNumOfSetBits(); 746 747 return $This; 748 } 749 750 # Setup final descriptor values... 751 # 752 sub _SetFinalDescriptorValues { 753 my($This) = @_; 754 755 $This->{DescriptorsGenerated} = 1; 756 757 $This->SetDescriptorValues($This->{MolecularComplexity}); 758 759 return $This; 760 } 761 762 # Set atom identifier type to use for generating fingerprints... 763 # 764 sub _SetAtomIdentifierTypeValuesToUse { 765 my($This, $FingerprintsObject) = @_; 766 767 if ($This->{AtomIdentifierType} =~ /^AtomicInvariantsAtomTypes$/i) { 768 $FingerprintsObject->SetAtomicInvariantsToUse(\@{$This->{AtomicInvariantsToUse}}); 769 } 770 elsif ($This->{AtomIdentifierType} =~ /^FunctionalClassAtomTypes$/i) { 771 $FingerprintsObject->SetFunctionalClassesToUse(\@{$This->{FunctionalClassesToUse}}); 772 } 773 elsif ($This->{AtomIdentifierType} =~ /^(DREIDINGAtomTypes|EStateAtomTypes|MMFF94AtomTypes|SLogPAtomTypes|SYBYLAtomTypes|TPSAAtomTypes|UFFAtomTypes)$/i) { 774 # Nothing to do for now... 775 } 776 else { 777 croak "Error: The value specified, $This->{AtomIdentifierType}, for option \"-a, --AtomIdentifierType\" is not valid. Supported atom identifier types in current release of MayaChemTools: AtomicInvariantsAtomTypes, DREIDINGAtomTypes, EStateAtomTypes, FunctionalClassAtomTypes, MMFF94AtomTypes, SLogPAtomTypes, SYBYLAtomTypes, TPSAAtomTypes, UFFAtomTypes\n"; 778 } 779 } 780 781 # Initialize atom indentifier type information... 782 # 783 # Current supported values: 784 # 785 # AtomicInvariantsAtomTypes, FunctionalClassAtomTypes, DREIDINGAtomTypes, EStateAtomTypes, 786 # MMFF94AtomTypes, SLogPAtomTypes, SYBYLAtomTypes, TPSAAtomTypes, UFFAtomTypes 787 # 788 sub _InitializeAtomIdentifierTypeInformation { 789 my($This) = @_; 790 791 IDENTIFIERTYPE: { 792 if ($This->{AtomIdentifierType} =~ /^AtomicInvariantsAtomTypes$/i) { 793 $This->_InitializeAtomicInvariantsAtomTypesInformation(); 794 last IDENTIFIERTYPE; 795 } 796 if ($This->{AtomIdentifierType} =~ /^FunctionalClassAtomTypes$/i) { 797 $This->_InitializeFunctionalClassAtomTypesInformation(); 798 last IDENTIFIERTYPE; 799 } 800 if ($This->{AtomIdentifierType} =~ /^(DREIDINGAtomTypes|EStateAtomTypes|MMFF94AtomTypes|SLogPAtomTypes|SYBYLAtomTypes|TPSAAtomTypes|UFFAtomTypes)$/i) { 801 # Nothing to do for now... 802 last IDENTIFIERTYPE; 803 } 804 carp "Warning: ${ClassName}->_InitializeAtomIdentifierTypeInformation: Unknown atom indentifier type $This->{AtomIdentifierType}..."; 805 } 806 return $This; 807 } 808 809 # Initialize atomic invariants atom types, generated by AtomTypes::AtomicInvariantsAtomTypes 810 # class, to use for generating initial atom identifiers... 811 # 812 # Let: 813 # AS = Atom symbol corresponding to element symbol 814 # 815 # X<n> = Number of non-hydrogen atom neighbors or heavy atoms attached to atom 816 # BO<n> = Sum of bond orders to non-hydrogen atom neighbors or heavy atoms attached to atom 817 # LBO<n> = Largest bond order of non-hydrogen atom neighbors or heavy atoms attached to atom 818 # SB<n> = Number of single bonds to non-hydrogen atom neighbors or heavy atoms attached to atom 819 # DB<n> = Number of double bonds to non-hydrogen atom neighbors or heavy atoms attached to atom 820 # TB<n> = Number of triple bonds to non-hydrogen atom neighbors or heavy atoms attached to atom 821 # H<n> = Number of implicit and explicit hydrogens for atom 822 # Ar = Aromatic annotation indicating whether atom is aromatic 823 # RA = Ring atom annotation indicating whether atom is a ring 824 # FC<+n/-n> = Formal charge assigned to atom 825 # MN<n> = Mass number indicating isotope other than most abundant isotope 826 # SM<n> = Spin multiplicity of atom. Possible values: 1 (singlet), 2 (doublet) or 3 (triplet) 827 # 828 # Then: 829 # 830 # Atom type generated by AtomTypes::AtomicInvariantsAtomTypes class corresponds to: 831 # 832 # AS.X<n>.BO<n>.LBO<n>.<SB><n>.<DB><n>.<TB><n>.H<n>.Ar.RA.FC<+n/-n>.MN<n>.SM<n> 833 # 834 # Except for AS which is a required atomic invariant in atom types, all other atomic invariants are 835 # optional. 836 # 837 # Default atomic invariants used for generating inital atom identifiers are [ Ref 24 ]: 838 # 839 # AS, X<n>, BO<n>, H<n>, FC<+n/-n>, MN<n> 840 # 841 # In addition to usage of abbreviations for specifying atomic invariants, the following descriptive words 842 # are also allowed: 843 # 844 # X : NumOfNonHydrogenAtomNeighbors or NumOfHeavyAtomNeighbors 845 # BO : SumOfBondOrdersToNonHydrogenAtoms or SumOfBondOrdersToHeavyAtoms 846 # LBO : LargestBondOrderToNonHydrogenAtoms or LargestBondOrderToHeavyAtoms 847 # SB : NumOfSingleBondsToNonHydrogenAtoms or NumOfSingleBondsToHeavyAtoms 848 # DB : NumOfDoubleBondsToNonHydrogenAtoms or NumOfDoubleBondsToHeavyAtoms 849 # TB : NumOfTripleBondsToNonHydrogenAtoms or NumOfTripleBondsToHeavyAtoms 850 # H : NumOfImplicitAndExplicitHydrogens 851 # Ar : Aromatic 852 # RA : RingAtom 853 # FC : FormalCharge 854 # MN : MassNumber 855 # SM : SpinMultiplicity 856 # 857 sub _InitializeAtomicInvariantsAtomTypesInformation { 858 my($This) = @_; 859 860 @{$This->{AtomicInvariantsToUse}} = (); 861 862 if ($This->{MolecularComplexityType} =~ /^(AtomTypesFingerprints|TopologicalAtomPairsFingerprints|TopologicalAtomTripletsFingerprints|TopologicalAtomTorsionsFingerprints)$/i) { 863 @{$This->{AtomicInvariantsToUse}} = ('AS', 'X', 'BO', 'H', 'FC'); 864 } 865 elsif ($This->{MolecularComplexityType} =~ /^ExtendedConnectivityFingerprints$/i) { 866 @{$This->{AtomicInvariantsToUse}} = ('AS', 'X', 'BO', 'H', 'FC', 'MN'); 867 } 868 elsif ($This->{MolecularComplexityType} =~ /^PathLengthFingerprints$/i) { 869 @{$This->{AtomicInvariantsToUse}} = ('AS'); 870 } 871 872 return $This; 873 } 874 875 # Initialize functional class atom types, generated by AtomTypes::FunctionalClassAtomTypes 876 # class, to use for generating initial atom identifiers... 877 # 878 # Let: 879 # HBD: HydrogenBondDonor 880 # HBA: HydrogenBondAcceptor 881 # PI : PositivelyIonizable 882 # NI : NegativelyIonizable 883 # Ar : Aromatic 884 # Hal : Halogen 885 # H : Hydrophobic 886 # RA : RingAtom 887 # CA : ChainAtom 888 # 889 # Then: 890 # 891 # Functiononal class atom type specification for an atom corresponds to: 892 # 893 # Ar.CA.H.HBA.HBD.Hal.NI.PI.RA 894 # 895 # Default functional classes used are: HBD, HBA, PI, NI, Ar, Hal 896 # 897 # FunctionalAtomTypes are assigned using the following definitions [ Ref 60-61, Ref 65-66 ]: 898 # 899 # HydrogenBondDonor: NH, NH2, OH 900 # HydrogenBondAcceptor: N[!H], O 901 # PositivelyIonizable: +, NH2 902 # NegativelyIonizable: -, C(=O)OH, S(=O)OH, P(=O)OH 903 # 904 sub _InitializeFunctionalClassAtomTypesInformation { 905 my($This) = @_; 906 907 @{$This->{FunctionalClassesToUse}} = (); 908 909 if ($This->{MolecularComplexityType} =~ /^(AtomTypesFingerprints|ExtendedConnectivityFingerprints|PathLengthFingerprints|TopologicalAtomPairsFingerprints|TopologicalAtomTripletsFingerprints|TopologicalAtomTorsionsFingerprints)$/i) { 910 @{$This->{FunctionalClassesToUse}} = ('HBD', 'HBA', 'PI', 'NI', 'Ar', 'Hal'); 911 } 912 elsif ($This->{MolecularComplexityType} =~ /^TopologicalPharmacophoreAtomPairsFingerprints$/i) { 913 @{$This->{FunctionalClassesToUse}} = ('HBD', 'HBA', 'PI', 'NI', 'H'); 914 } 915 elsif ($This->{MolecularComplexityType} =~ /^TopologicalPharmacophoreAtomTripletsFingerprints$/i) { 916 @{$This->{FunctionalClassesToUse}} = ('HBD', 'HBA', 'PI', 'NI', 'H', 'Ar'); 917 } 918 919 return $This; 920 } 921 922 # Set atomic invariants to use for generation of intial atom indentifiers... 923 # 924 sub SetAtomicInvariantsToUse { 925 my($This, @Values) = @_; 926 my($FirstValue, $TypeOfFirstValue, $AtomicInvariant, $SpecifiedAtomicInvariant, @SpecifiedAtomicInvariants, @AtomicInvariantsToUse); 927 928 if (!@Values) { 929 carp "Warning: ${ClassName}->SetAtomicInvariantsToUse: No values specified..."; 930 return; 931 } 932 933 if ($This->{AtomIdentifierType} !~ /^AtomicInvariantsAtomTypes$/i) { 934 carp "Warning: ${ClassName}->SetAtomicInvariantsToUse: AtomicInvariantsToUse can't be set for InitialAtomIdentifierType of $This->{AtomIdentifierType}..."; 935 return; 936 } 937 938 $FirstValue = $Values[0]; 939 $TypeOfFirstValue = ref $FirstValue; 940 941 @SpecifiedAtomicInvariants = (); 942 @AtomicInvariantsToUse = (); 943 944 if ($TypeOfFirstValue =~ /^ARRAY/) { 945 push @SpecifiedAtomicInvariants, @{$FirstValue}; 946 } 947 else { 948 push @SpecifiedAtomicInvariants, @Values; 949 } 950 951 # Make sure specified AtomicInvariants are valid... 952 for $SpecifiedAtomicInvariant (@SpecifiedAtomicInvariants) { 953 if (!AtomTypes::AtomicInvariantsAtomTypes::IsAtomicInvariantAvailable($SpecifiedAtomicInvariant)) { 954 croak "Error: ${ClassName}->SetAtomicInvariantsToUse: Specified atomic invariant, $SpecifiedAtomicInvariant, is not supported...\n "; 955 } 956 $AtomicInvariant = $SpecifiedAtomicInvariant; 957 push @AtomicInvariantsToUse, $AtomicInvariant; 958 } 959 960 # Set atomic invariants to use... 961 @{$This->{AtomicInvariantsToUse}} = (); 962 push @{$This->{AtomicInvariantsToUse}}, @AtomicInvariantsToUse; 963 964 return $This; 965 } 966 967 # Set functional classes to use for generation of intial atom indentifiers... 968 # 969 sub SetFunctionalClassesToUse { 970 my($This, @Values) = @_; 971 my($FirstValue, $TypeOfFirstValue, $FunctionalClass, $SpecifiedFunctionalClass, @SpecifiedFunctionalClasses, @FunctionalClassesToUse); 972 973 if (!@Values) { 974 carp "Warning: ${ClassName}->SetFunctionalClassesToUse: No values specified..."; 975 return; 976 } 977 978 if ($This->{AtomIdentifierType} !~ /^FunctionalClassAtomTypes$/i) { 979 carp "Warning: ${ClassName}->SetFunctionalClassesToUse: FunctionalClassesToUse can't be set for InitialAtomIdentifierType of $This->{AtomIdentifierType}..."; 980 return; 981 } 982 983 $FirstValue = $Values[0]; 984 $TypeOfFirstValue = ref $FirstValue; 985 986 @SpecifiedFunctionalClasses = (); 987 @FunctionalClassesToUse = (); 988 989 if ($TypeOfFirstValue =~ /^ARRAY/) { 990 push @SpecifiedFunctionalClasses, @{$FirstValue}; 991 } 992 else { 993 push @SpecifiedFunctionalClasses, @Values; 994 } 995 996 # Make sure specified FunctionalClasses are valid... 997 for $SpecifiedFunctionalClass (@SpecifiedFunctionalClasses) { 998 if (!AtomTypes::FunctionalClassAtomTypes::IsFunctionalClassAvailable($SpecifiedFunctionalClass)) { 999 croak "Error: ${ClassName}->SetFunctionalClassesToUse: Specified functional class, $SpecifiedFunctionalClass, is not supported...\n "; 1000 } 1001 push @FunctionalClassesToUse, $SpecifiedFunctionalClass; 1002 } 1003 1004 # Set functional classes to use... 1005 @{$This->{FunctionalClassesToUse}} = (); 1006 push @{$This->{FunctionalClassesToUse}}, @FunctionalClassesToUse; 1007 1008 return $This; 1009 } 1010 1011 # Return a string containg data for MolecularComplexityDescriptors object... 1012 # 1013 sub StringifyMolecularComplexityDescriptors { 1014 my($This) = @_; 1015 my($ComplexityDescriptorsString, $Nothing); 1016 1017 $ComplexityDescriptorsString = "MolecularDescriptorType: $This->{Type}; MolecularComplexityType: $This->{MolecularComplexityType}; " . $This->_StringifyDescriptorNamesAndValues(); 1018 1019 # Setup fingerprints specific information... 1020 if ($This->{MolecularComplexityType} =~ /^MACCSKeys$/i) { 1021 $ComplexityDescriptorsString .= "; MACCSKeysSize = $This->{MACCSKeysSize}"; 1022 } 1023 elsif ($This->{MolecularComplexityType} =~ /^ExtendedConnectivityFingerprints$/i) { 1024 $ComplexityDescriptorsString .= "; NeighborhoodRadius = $This->{NeighborhoodRadius}; NormalizationMethodology = $This->{NormalizationMethodology}"; 1025 } 1026 elsif ($This->{MolecularComplexityType} =~ /^PathLengthFingerprints$/i) { 1027 $ComplexityDescriptorsString .= "; MinPathLength = $This->{MinPathLength}; MaxPathLength = $This->{MaxPathLength}; UseBondSymbols: " . ($This->{UseBondSymbols} ? "Yes" : "No"); 1028 } 1029 elsif ($This->{MolecularComplexityType} =~ /^TopologicalAtomPairsFingerprints$/i) { 1030 $ComplexityDescriptorsString .= "; MinDistance = $This->{MinDistance}; MaxDistance = $This->{MaxDistance}"; 1031 } 1032 elsif ($This->{MolecularComplexityType} =~ /^TopologicalAtomTripletsFingerprints$/i) { 1033 $ComplexityDescriptorsString .= "; MinDistance = $This->{MinDistance}; MaxDistance = $This->{MaxDistance}; UseTriangleInequality: " . ($This->{UseTriangleInequality} ? "Yes" : "No"); 1034 } 1035 elsif ($This->{MolecularComplexityType} =~ /^TopologicalAtomTorsionsFingerprints$/i) { 1036 $ComplexityDescriptorsString .= "; MinDistance = $This->{MinDistance}; MaxDistance = $This->{MaxDistance}"; 1037 } 1038 elsif ($This->{MolecularComplexityType} =~ /^TopologicalPharmacophoreAtomPairsFingerprints$/i) { 1039 $ComplexityDescriptorsString .= "; MinDistance = $This->{MinDistance}; MaxDistance = $This->{MaxDistance}; NormalizationMethodology = $This->{NormalizationMethodology}"; 1040 } 1041 elsif ($This->{MolecularComplexityType} =~ /^TopologicalPharmacophoreAtomTripletsFingerprints$/i) { 1042 $ComplexityDescriptorsString .= "; MinDistance = $This->{MinDistance}; MaxDistance = $This->{MaxDistance}; NormalizationMethodology = $This->{NormalizationMethodology}; DistanceBinSize: $This->{DistanceBinSize}; UseTriangleInequality: " . ($This->{UseTriangleInequality} ? "Yes" : "No"); 1043 } 1044 1045 # Setup atom identifier information... 1046 if ($This->{MolecularComplexityType} =~ /^(AtomTypesFingerprints|ExtendedConnectivityFingerprints|PathLengthFingerprints|TopologicalAtomPairsFingerprints|TopologicalAtomTripletsFingerprints|TopologicalAtomTorsionsFingerprints|TopologicalPharmacophoreAtomPairsFingerprints|TopologicalPharmacophoreAtomTripletsFingerprints)$/i) { 1047 $ComplexityDescriptorsString .= "; AtomIdentifierType = $This->{AtomIdentifierType}"; 1048 1049 if ($This->{AtomIdentifierType} =~ /^AtomicInvariantsAtomTypes$/i) { 1050 my($AtomicInvariant, @AtomicInvariants, @AtomicInvariantsOrder, %AvailableAtomicInvariants); 1051 1052 @AtomicInvariantsOrder = AtomTypes::AtomicInvariantsAtomTypes::GetAtomicInvariantsOrder(); 1053 %AvailableAtomicInvariants = AtomTypes::AtomicInvariantsAtomTypes::GetAvailableAtomicInvariants(); 1054 1055 for $AtomicInvariant (@AtomicInvariantsOrder) { 1056 push @AtomicInvariants, "$AtomicInvariant: $AvailableAtomicInvariants{$AtomicInvariant}"; 1057 } 1058 1059 $ComplexityDescriptorsString .= "; AtomicInvariantsToUse: <" . TextUtil::JoinWords(\@{$This->{AtomicInvariantsToUse}}, ", ", 0) . ">"; 1060 $ComplexityDescriptorsString .= "; AtomicInvariantsOrder: <" . TextUtil::JoinWords(\@AtomicInvariantsOrder, ", ", 0) . ">"; 1061 $ComplexityDescriptorsString .= "; AvailableAtomicInvariants: <" . TextUtil::JoinWords(\@AtomicInvariants, ", ", 0) . ">"; 1062 } 1063 elsif ($This->{AtomIdentifierType} =~ /^FunctionalClassAtomTypes$/i) { 1064 my($FunctionalClass, @FunctionalClasses, @FunctionalClassesOrder, %AvailableFunctionalClasses); 1065 1066 @FunctionalClassesOrder = AtomTypes::FunctionalClassAtomTypes::GetFunctionalClassesOrder(); 1067 %AvailableFunctionalClasses = AtomTypes::FunctionalClassAtomTypes::GetAvailableFunctionalClasses(); 1068 1069 for $FunctionalClass (@FunctionalClassesOrder) { 1070 push @FunctionalClasses, "$FunctionalClass: $AvailableFunctionalClasses{$FunctionalClass}"; 1071 } 1072 1073 $ComplexityDescriptorsString .= "; FunctionalClassesToUse: <" . TextUtil::JoinWords(\@{$This->{FunctionalClassesToUse}}, ", ", 0) . ">"; 1074 $ComplexityDescriptorsString .= "; FunctionalClassesOrder: <" . TextUtil::JoinWords(\@FunctionalClassesOrder, ", ", 0) . ">"; 1075 $ComplexityDescriptorsString .= "; AvailableFunctionalClasses: <" . TextUtil::JoinWords(\@FunctionalClasses, ", ", 0) . ">"; 1076 } 1077 } 1078 return $ComplexityDescriptorsString; 1079 } 1080 1081 # Is it a MolecularComplexityDescriptors object? 1082 sub _IsMolecularComplexityDescriptors { 1083 my($Object) = @_; 1084 1085 return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0; 1086 } 1087