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