1 package AtomTypes::TPSAAtomTypes; 2 # 3 # File: TPSAAtomTypes.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 Text::ParseWords; 31 use AtomTypes::AtomTypes; 32 use Molecule; 33 34 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 35 36 @ISA = qw(AtomTypes::AtomTypes Exporter); 37 @EXPORT = qw(GetTPSAAtomTypesData GetAllPossibleTPSAAtomTypes); 38 @EXPORT_OK = qw(); 39 40 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 41 42 # Setup class variables... 43 my($ClassName, %TPSAAtomTypesDataMap); 44 _InitializeClass(); 45 46 # Overload Perl functions... 47 use overload '""' => 'StringifyTPSAAtomTypes'; 48 49 # Class constructor... 50 sub new { 51 my($Class, %NamesAndValues) = @_; 52 53 # Initialize object... 54 my $This = $Class->SUPER::new(); 55 bless $This, ref($Class) || $Class; 56 $This->_InitializeTPSAAtomTypes(); 57 58 $This->_InitializeTPSAAtomTypesProperties(%NamesAndValues); 59 60 return $This; 61 } 62 63 # Initialize class ... 64 sub _InitializeClass { 65 #Class name... 66 $ClassName = __PACKAGE__; 67 68 # Initialize the data hash. It'll be loaded on demand later... 69 %TPSAAtomTypesDataMap = (); 70 } 71 72 # Initialize object data... 73 # 74 sub _InitializeTPSAAtomTypes { 75 my($This) = @_; 76 77 # Type of AtomTypes... 78 $This->{Type} = 'TPSA'; 79 80 # Besides polar atoms - N, O, P, S - no TPSA atom types are assigned to any other 81 # atoms. 82 # 83 # By default, TPSA atom types are not assigned to Phosphorus and Sulfur atoms. 84 # 85 $This->{IgnorePhosphorus} = 0; 86 $This->{IgnoreSulfur} = 0; 87 88 return $This; 89 } 90 91 # Initialize object properties... 92 # 93 sub _InitializeTPSAAtomTypesProperties { 94 my($This, %NamesAndValues) = @_; 95 96 my($Name, $Value, $MethodName); 97 while (($Name, $Value) = each %NamesAndValues) { 98 $MethodName = "Set${Name}"; 99 $This->$MethodName($Value); 100 } 101 102 # Make sure molecule object was specified... 103 if (!exists $NamesAndValues{Molecule}) { 104 croak "Error: ${ClassName}->New: Object can't be instantiated without specifying molecule..."; 105 } 106 107 return $This; 108 } 109 110 # Get TPSA atom types and associated data loaded from TPSA data file as 111 # a reference to hash with the following hash data format: 112 # 113 # @{$TPSAAtomTypesDataMap{AtomTypes}} - Array of all possible atom types for all atoms 114 # @{$TPSAAtomTypesDataMap->{ColLabels}} - Array of column labels 115 # %{$TPSAAtomTypesDataMap->{DataCol<Num>}} - Hash keys pair: <DataCol<Num>, AtomType> 116 # 117 # This functionality can be either invoked as a class function or an 118 # object method. 119 # 120 sub GetTPSAAtomTypesData { 121 122 # Make sure data is loaded... 123 _CheckAndLoadTPSAAtomTypesData(); 124 125 return \%TPSAAtomTypesDataMap; 126 } 127 128 # Get all possible TPSA atom types atoms as an array reference... 129 # 130 # This functionality can be either invoked as a class function or an 131 # object method. 132 # 133 sub GetAllPossibleTPSAAtomTypes { 134 return _GetAllPossibleTPSAAtomTypes(); 135 } 136 137 # Are all atoms types successfully assigned? 138 # 139 # Notes: 140 # . Dynamic checking of atom types assignment for atoms eliminates the need 141 # to check and synchronize valid atom types during SetAtomType. 142 # . Base class method is overrided to check atom assignment to nitrogen and 143 # oxygen atom with optional check for phosphorus and sulfur atoms. 144 # 145 sub IsAtomTypesAssignmentSuccessful { 146 my($This) = @_; 147 my($Atom, $AtomType); 148 149 ATOM: for $Atom ($This->{Molecule}->GetAtoms()) { 150 if (!($Atom->IsNitrogen() || $Atom->IsOxygen() || 151 ($Atom->IsPhosphorus() && !$This->{IgnorePhosphorus}) || 152 ($Atom->IsSulfur() && !$This->{IgnoreSulfur}))) { 153 next ATOM; 154 } 155 $AtomType = $This->GetAtomType($Atom); 156 if ($AtomType =~ /^None$/i) { 157 return 0; 158 } 159 } 160 161 return 1; 162 } 163 164 # Get all possible TPSA atom types as an array reference... 165 # 166 sub _GetAllPossibleTPSAAtomTypes { 167 my($TPSAAtomTypesDataRef); 168 169 $TPSAAtomTypesDataRef = GetTPSAAtomTypesData(); 170 171 return \@{$TPSAAtomTypesDataRef->{AtomTypes}}; 172 } 173 174 # Assign Topological Polar Surface Area (TPSA) atom types [ Ref 90-91 ] to Nitrogen and Oxygen 175 # atoms with optional assignment to Phosphorus and Sulfur atoms. 176 # 177 # Notes: 178 # o Number of atom type symbols for: 179 # o N: 27 180 # o O: 7 181 # o P: 5 182 # o S: 8 183 # 184 sub AssignAtomTypes { 185 my($This) = @_; 186 my($Atom, $AtomType); 187 188 ATOM: for $Atom ($This->GetMolecule()->GetAtoms()) { 189 $AtomType = $This->_GetAtomType($Atom); 190 $This->SetAtomType($Atom, $AtomType); 191 } 192 193 return $This; 194 } 195 196 # Get TPSA atom type for atom... 197 # 198 sub _GetAtomType { 199 my($This, $Atom) = @_; 200 my($AtomType); 201 202 $AtomType = 'None'; 203 204 ATOM: { 205 if ($Atom->IsNitrogen()) { 206 $AtomType = $This->_GetAtomTypeForNitrogen($Atom); 207 last ATOM; 208 } 209 210 if ($Atom->IsOxygen()) { 211 $AtomType = $This->_GetAtomTypeForOxygen($Atom); 212 last ATOM; 213 } 214 215 if ($Atom->IsPhosphorus() && !$This->{IgnorePhosphorus}) { 216 $AtomType = $This->_GetAtomTypeForPhosphorus($Atom); 217 last ATOM; 218 } 219 220 if ($Atom->IsSulfur() && !$This->{IgnoreSulfur}) { 221 $AtomType = $This->_GetAtomTypeForSulfur($Atom); 222 last ATOM; 223 } 224 $AtomType = 'None'; 225 } 226 227 return $AtomType; 228 } 229 230 231 # Get TPSA atom type for Nitrogen atom... 232 # 233 # 27 AtomTypeSymbols for element N: 234 # 235 # AtomTypeSymbol - SMARTS - Comments 236 # N1 - '[N](-*)(-*)-*' 237 # N2 - '[N](-*)=*' 238 # N3 - '[N]#*' 239 # N4 - '[N](-*)(=*)=*' - As in nitro group 240 # N5 - '[N](=*)#*' - Middle nitrogen in azide group 241 # N6 - '[N]1(-*)-*-*-1' - Atom in a 3 membered ring 242 # N7 - '[NH](-*)-*' 243 # N8 - '[NH]1-*-*-1' - Atom in a 3 membered ring 244 # N9 - '[NH]=*' 245 # N10 - '[NH2]-*' 246 # N11 - '[N+](-*)(-*)(-*)-*' 247 # N12 - '[N+](-*)(-*)=*' 248 # N13 - '[N+](-*)#*' - Nitrogen in isocyano group 249 # N14 - '[NH+](-*)(-*)-*' 250 # N15 - '[NH+](-*)=*' 251 # N16 - '[NH2+](-*)-*' 252 # N17 - '[NH2+]=*' 253 # N18 - '[NH3+]-*' 254 # N19 - '[n](:*):*' 255 # N20 - '[n](:*)(:*):*' 256 # N21 - '[n](-*)(:*):*' 257 # N22 - '[n](=*)(:*):*' - As in pyridine N-oxide 258 # N23 - '[nH](:*):*' 259 # N24 - '[n+](:*)(:*):*' 260 # N25 - '[n+](-*)(:*):*' 261 # N26 - '[nH+](:*):*' 262 # N - '[#7]' - Any other Nitrogen; Contribution: 30.5 - X*8.2 + H*1.5 or 0.0 for negative value 263 # 264 sub _GetAtomTypeForNitrogen { 265 my($This, $Atom) = @_; 266 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 267 268 $AtomType = 'None'; 269 270 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 271 272 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 273 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 274 275 ATOMTYPE: { 276 277 # Aromatic Nitrogens... 278 if ($Atom->IsAromatic()) { 279 $AtomType = $This->_GetAtomTypeForAromaticNitrogen($Atom); 280 last ATOMTYPE; 281 } 282 283 # Only single bonds... 284 if ($NumOfPiBonds == 0) { 285 $AtomType = $This->_GetAtomTypeForNitrogenWithOnlySigmaBonds($Atom); 286 last ATOMTYPE; 287 } 288 289 # One double bond... 290 if ($NumOfPiBonds == 1) { 291 $AtomType = $This->_GetAtomTypeForNitrogenWithOnePiBond($Atom); 292 last ATOMTYPE; 293 } 294 295 # One triple bond or two double bonds... 296 if ($NumOfPiBonds == 2) { 297 $AtomType = $This->_GetAtomTypeForNitrogenWithTwoPiBonds($Atom); 298 last ATOMTYPE; 299 } 300 301 # One triple bond and a double bond... 302 if ($NumOfPiBonds == 3) { 303 $AtomType = $This->_GetAtomTypeForNitrogenWithThreePiBonds($Atom); 304 last ATOMTYPE; 305 } 306 307 $AtomType = 'N'; 308 } 309 return $AtomType; 310 } 311 312 # Get TPSA atom type for Oxygen atom... 313 # 314 # AtomTypeSymbol - SMARTS - Comments 315 # O1 - '[O](-*)-*' 316 # O2 - '[O]1-*-*-1' - Atom in a 3 membered ring 317 # O3 - '[O]=*' 318 # O4 - '[OH]-*' 319 # O5 - '[O-]-*' 320 # O6 - '[o](:*):*' 321 # O - '[#8]' - Any other Oxygen; Contribution: 28.5 - X*8.6 + H*1.5 or 0.0 for negative value 322 # 323 sub _GetAtomTypeForOxygen { 324 my($This, $Atom) = @_; 325 my($AtomType); 326 327 $AtomType = 'None'; 328 329 ATOMTYPE: { 330 331 # O6 - '[o](:*):*' 332 if ($This->_IsO6Oxygen($Atom)) { 333 $AtomType = 'O6'; 334 last ATOMTYPE; 335 } 336 337 # O3 - '[O]=*' 338 if ($This->_IsO3Oxygen($Atom)) { 339 $AtomType = 'O3'; 340 last ATOMTYPE; 341 } 342 343 # O4 - '[OH]-*' 344 if ($This->_IsO4Oxygen($Atom)) { 345 $AtomType = 'O4'; 346 last ATOMTYPE; 347 } 348 349 # O5 - '[O-]-*' 350 if ($This->_IsO5Oxygen($Atom)) { 351 $AtomType = 'O5'; 352 last ATOMTYPE; 353 } 354 355 # O2 - '[O]1-*-*-1' - Atom in a 3 membered ring 356 if ($This->_IsO2Oxygen($Atom)) { 357 $AtomType = 'O2'; 358 last ATOMTYPE; 359 } 360 361 # O1 - '[O](-*)-*' 362 if ($This->_IsO1Oxygen($Atom)) { 363 $AtomType = 'O1'; 364 last ATOMTYPE; 365 } 366 367 # Any other Oxygen... 368 $AtomType = 'O'; 369 } 370 371 return $AtomType; 372 } 373 374 # Get TPSA atom type for Phosphorus atom... 375 # 376 # 4 AtomTypeSymbols for element P: 377 # 378 # AtomTypeSymbol - SMARTS - Comments 379 # P1 - '[P](-*)(-*)-*' 380 # P2 - '[P](-*)=*' 381 # P3 - '[P](-*)(-*)(-*)=*' 382 # P4 - '[PH](-*)(-*)=*' 383 # P - '[#15]' - Any other Sulfur 384 # 385 sub _GetAtomTypeForPhosphorus { 386 my($This, $Atom) = @_; 387 my($AtomType); 388 389 $AtomType = 'None'; 390 391 ATOMTYPE: { 392 393 # P1 - '[P](-*)(-*)-*' 394 if ($This->_IsP1Phosphorus($Atom)) { 395 $AtomType = 'P1'; 396 last ATOMTYPE; 397 } 398 399 # P2 - '[P](-*)=*' 400 if ($This->_IsP2Phosphorus($Atom)) { 401 $AtomType = 'P2'; 402 last ATOMTYPE; 403 } 404 405 # P3 - '[P](-*)(-*)(-*)=*' 406 if ($This->_IsP3Phosphorus($Atom)) { 407 $AtomType = 'P3'; 408 last ATOMTYPE; 409 } 410 411 # P4 - '[PH](-*)(-*)=*' 412 if ($This->_IsP4Phosphorus($Atom)) { 413 $AtomType = 'P4'; 414 last ATOMTYPE; 415 } 416 417 # Any other Phosphorus... 418 $AtomType = 'P'; 419 } 420 421 return $AtomType; 422 } 423 424 # Get TPSA atom type for Sulfur atom... 425 # 426 # 7 AtomTypeSymbols for element S: 427 # 428 # AtomTypeSymbol - SMARTS - Comments 429 # S1 - '[S](-*)-*' 430 # S2 - '[S]=*' 431 # S3 - '[S](-*)(-*)=*' 432 # S4 - '[S](-*)(-*)(=*)=*' 433 # S5 - '[SH]-*' 434 # S6 - '[s](:*):*' 435 # S - '[#16]' - Any other Phosphorus 436 # 437 sub _GetAtomTypeForSulfur { 438 my($This, $Atom) = @_; 439 my($AtomType); 440 441 $AtomType = 'None'; 442 443 ATOMTYPE: { 444 445 # S6 - '[s](:*):*' 446 if ($This->_IsS6Sulfur($Atom)) { 447 $AtomType = 'S6'; 448 last ATOMTYPE; 449 } 450 451 # S4 - '[S](-*)(-*)(=*)=*' 452 if ($This->_IsS4Sulfur($Atom)) { 453 $AtomType = 'S4'; 454 last ATOMTYPE; 455 } 456 457 # S1 - '[S](-*)-*' 458 if ($This->_IsS1Sulfur($Atom)) { 459 $AtomType = 'S1'; 460 last ATOMTYPE; 461 } 462 463 # S2 - '[S]=*' 464 if ($This->_IsS2Sulfur($Atom)) { 465 $AtomType = 'S2'; 466 last ATOMTYPE; 467 } 468 469 # S3 - '[S](-*)(-*)=*' 470 if ($This->_IsS3Sulfur($Atom)) { 471 $AtomType = 'S3'; 472 last ATOMTYPE; 473 } 474 475 # S5 - '[SH]-*' 476 if ($This->_IsS5Sulfur($Atom)) { 477 $AtomType = 'S5'; 478 last ATOMTYPE; 479 } 480 481 # Any other Sulfur... 482 $AtomType = 'S'; 483 } 484 485 return $AtomType; 486 } 487 488 # Get TPSA atom type for aromatic Nitrogen... 489 # 490 sub _GetAtomTypeForAromaticNitrogen { 491 my($This, $Atom) = @_; 492 my($AtomType); 493 494 $AtomType = 'None'; 495 496 ATOMTYPE: { 497 498 # N19 - '[n](:*):*' 499 if ($This->_IsN19Nitrogen($Atom)) { 500 $AtomType = 'N19'; 501 last ATOMTYPE; 502 } 503 504 # N20 - '[n](:*)(:*):*' 505 if ($This->_IsN20Nitrogen($Atom)) { 506 $AtomType = 'N20'; 507 last ATOMTYPE; 508 } 509 510 # N21 - '[n](-*)(:*):*' 511 if ($This->_IsN21Nitrogen($Atom)) { 512 $AtomType = 'N21'; 513 last ATOMTYPE; 514 } 515 516 # N22 - '[n](=*)(:*):*' - As in pyridine N-oxide 517 if ($This->_IsN22Nitrogen($Atom)) { 518 $AtomType = 'N22'; 519 last ATOMTYPE; 520 } 521 522 # N23 - '[nH](:*):*' 523 if ($This->_IsN23Nitrogen($Atom)) { 524 $AtomType = 'N23'; 525 last ATOMTYPE; 526 } 527 528 # N24 - '[n+](:*)(:*):*' 529 if ($This->_IsN24Nitrogen($Atom)) { 530 $AtomType = 'N24'; 531 last ATOMTYPE; 532 } 533 534 # N25 - '[n+](-*)(:*):*' 535 if ($This->_IsN25Nitrogen($Atom)) { 536 $AtomType = 'N25'; 537 last ATOMTYPE; 538 } 539 540 # N26 - '[nH+](:*):*' 541 if ($This->_IsN26Nitrogen($Atom)) { 542 $AtomType = 'N26'; 543 last ATOMTYPE; 544 } 545 546 $AtomType = 'N'; 547 } 548 549 return $AtomType; 550 } 551 552 # Get TPSA atom type for Nitrogen with only sigma bonds... 553 # 554 sub _GetAtomTypeForNitrogenWithOnlySigmaBonds { 555 my($This, $Atom) = @_; 556 my($AtomType); 557 558 $AtomType = 'None'; 559 560 ATOMTYPE: { 561 562 # N6 - '[N]1(-*)-*-*-1' - Atom in a 3 membered ring 563 if ($This->_IsN6Nitrogen($Atom)) { 564 $AtomType = 'N6'; 565 last ATOMTYPE; 566 } 567 568 # N1 - '[N](-*)(-*)-*' 569 if ($This->_IsN1Nitrogen($Atom)) { 570 $AtomType = 'N1'; 571 last ATOMTYPE; 572 } 573 574 # N8 - '[NH]1-*-*-1' - Atom in a 3 membered ring 575 if ($This->_IsN8Nitrogen($Atom)) { 576 $AtomType = 'N8'; 577 last ATOMTYPE; 578 } 579 580 # N7 - '[NH](-*)-*' 581 if ($This->_IsN7Nitrogen($Atom)) { 582 $AtomType = 'N7'; 583 last ATOMTYPE; 584 } 585 586 # N10 - '[NH2]-*' 587 if ($This->_IsN10Nitrogen($Atom)) { 588 $AtomType = 'N10'; 589 last ATOMTYPE; 590 } 591 592 # N11 - '[N+](-*)(-*)(-*)-*' 593 if ($This->_IsN11Nitrogen($Atom)) { 594 $AtomType = 'N11'; 595 last ATOMTYPE; 596 } 597 598 # N14 - '[NH+](-*)(-*)-*' 599 if ($This->_IsN14Nitrogen($Atom)) { 600 $AtomType = 'N14'; 601 last ATOMTYPE; 602 } 603 604 # N16 - '[NH2+](-*)-*' 605 if ($This->_IsN16Nitrogen($Atom)) { 606 $AtomType = 'N16'; 607 last ATOMTYPE; 608 } 609 610 # N18 - '[NH3+]-*' 611 if ($This->_IsN18Nitrogen($Atom)) { 612 $AtomType = 'N18'; 613 last ATOMTYPE; 614 } 615 616 $AtomType = 'N'; 617 } 618 619 return $AtomType; 620 } 621 622 # Get TPSA atom type for Nitrogen with one pi bonds... 623 # 624 sub _GetAtomTypeForNitrogenWithOnePiBond { 625 my($This, $Atom) = @_; 626 my($AtomType); 627 628 $AtomType = 'None'; 629 630 ATOMTYPE: { 631 632 # N2 - '[N](-*)=*' 633 if ($This->_IsN2Nitrogen($Atom)) { 634 $AtomType = 'N2'; 635 last ATOMTYPE; 636 } 637 638 # N9 - '[NH]=*' 639 if ($This->_IsN9Nitrogen($Atom)) { 640 $AtomType = 'N9'; 641 last ATOMTYPE; 642 } 643 644 # N12 - '[N+](-*)(-*)=*' 645 if ($This->_IsN12Nitrogen($Atom)) { 646 $AtomType = 'N12'; 647 last ATOMTYPE; 648 } 649 650 # N15 - '[NH+](-*)=*' 651 if ($This->_IsN15Nitrogen($Atom)) { 652 $AtomType = 'N15'; 653 last ATOMTYPE; 654 } 655 656 # N17 - '[NH2+]=*' 657 if ($This->_IsN17Nitrogen($Atom)) { 658 $AtomType = 'N17'; 659 last ATOMTYPE; 660 } 661 662 $AtomType = 'N'; 663 } 664 665 return $AtomType; 666 } 667 668 # Get TPSA atom type for Nitrogen with two pi bonds... 669 # 670 sub _GetAtomTypeForNitrogenWithTwoPiBonds { 671 my($This, $Atom) = @_; 672 my($AtomType); 673 674 $AtomType = 'None'; 675 676 ATOMTYPE: { 677 678 # N3 - '[N]#*' 679 if ($This->_IsN3Nitrogen($Atom)) { 680 $AtomType = 'N3'; 681 last ATOMTYPE; 682 } 683 684 # N4 - '[N](-*)(=*)=*' - As in nitro group 685 if ($This->_IsN4Nitrogen($Atom)) { 686 $AtomType = 'N4'; 687 last ATOMTYPE; 688 } 689 690 # N13 - '[N+](-*)#*'- Nitrogen in isocyano group 691 if ($This->_IsN13Nitrogen($Atom)) { 692 $AtomType = 'N13'; 693 last ATOMTYPE; 694 } 695 696 $AtomType = 'N'; 697 } 698 699 return $AtomType; 700 } 701 702 # Get TPSA atom type for Nitrogen with three pi bonds... 703 # 704 sub _GetAtomTypeForNitrogenWithThreePiBonds { 705 my($This, $Atom) = @_; 706 my($AtomType); 707 708 $AtomType = 'None'; 709 710 ATOMTYPE: { 711 712 # N5 - '[N](=*)#*' - Middle nitrogen in azide group 713 if ($This->_IsN5Nitrogen($Atom)) { 714 $AtomType = 'N5'; 715 last ATOMTYPE; 716 } 717 718 $AtomType = 'N'; 719 } 720 721 return $AtomType; 722 } 723 724 # N1 - '[N](-*)(-*)-*' 725 # 726 sub _IsN1Nitrogen { 727 my($This, $Atom) = @_; 728 729 return $Atom->DoesAtomNeighborhoodMatch('N.!RA3.X3.SB3.H0.FC0') ? 1 : 0; 730 } 731 732 # N2 - '[N](-*)=*' 733 # 734 sub _IsN2Nitrogen { 735 my($This, $Atom) = @_; 736 737 return $Atom->DoesAtomNeighborhoodMatch('N.X2.SB1.DB1.H0.FC0') ? 1 : 0; 738 } 739 740 # N3 - '[N]#*' 741 # 742 sub _IsN3Nitrogen { 743 my($This, $Atom) = @_; 744 745 return $Atom->DoesAtomNeighborhoodMatch('N.X1.TB1.H0.FC0') ? 1 : 0; 746 } 747 748 # N4 - '[N](-*)(=*)=*' - As in nitro group 749 # 750 sub _IsN4Nitrogen { 751 my($This, $Atom) = @_; 752 753 return $Atom->DoesAtomNeighborhoodMatch('N.X3.SB1.DB2.H0.FC0') ? 1 : 0; 754 } 755 756 # N5 - '[N](=*)#*' - Middle nitrogen in azide group 757 # 758 sub _IsN5Nitrogen { 759 my($This, $Atom) = @_; 760 761 return $Atom->DoesAtomNeighborhoodMatch('N.X2.DB1.TB1.H0.FC0') ? 1 : 0; 762 } 763 764 # N6 - '[N]1(-*)-*-*-1' - Atom in a 3 membered ring 765 # 766 sub _IsN6Nitrogen { 767 my($This, $Atom) = @_; 768 769 return $Atom->DoesAtomNeighborhoodMatch('N.RA3.X3.SB3.H0.FC0') ? 1 : 0; 770 } 771 772 # N7 - '[NH](-*)-*' 773 # 774 sub _IsN7Nitrogen { 775 my($This, $Atom) = @_; 776 777 return $Atom->DoesAtomNeighborhoodMatch('N.!RA3.X2.SB2.H1.FC0') ? 1 : 0; 778 } 779 780 # N8 - '[NH]1-*-*-1' - Atom in a 3 membered ring 781 # 782 sub _IsN8Nitrogen { 783 my($This, $Atom) = @_; 784 785 return $Atom->DoesAtomNeighborhoodMatch('N.RA3.X2.SB2.H1.FC0') ? 1 : 0; 786 } 787 788 # N9 - '[NH]=*' 789 # 790 sub _IsN9Nitrogen { 791 my($This, $Atom) = @_; 792 793 return $Atom->DoesAtomNeighborhoodMatch('N.X1.DB1.H1.FC0') ? 1 : 0; 794 } 795 796 # N10 - '[NH2]-*' 797 # 798 sub _IsN10Nitrogen { 799 my($This, $Atom) = @_; 800 801 return $Atom->DoesAtomNeighborhoodMatch('N.X1.SB1.H2.FC0') ? 1 : 0; 802 } 803 804 # N11 - '[N+](-*)(-*)(-*)-*' 805 # 806 sub _IsN11Nitrogen { 807 my($This, $Atom) = @_; 808 809 return $Atom->DoesAtomNeighborhoodMatch('N.X4.SB4.H0.FC+1') ? 1 : 0; 810 } 811 812 # N12 - '[N+](-*)(-*)=*' 813 # 814 sub _IsN12Nitrogen { 815 my($This, $Atom) = @_; 816 817 return $Atom->DoesAtomNeighborhoodMatch('N.X3.SB2.DB1.H0.FC+1') ? 1 : 0; 818 } 819 820 # N13 - '[N+](-*)#*'- Nitrogen in isocyano group 821 # 822 sub _IsN13Nitrogen { 823 my($This, $Atom) = @_; 824 825 return $Atom->DoesAtomNeighborhoodMatch('N.X2.SB1.TB1.H0.FC+1') ? 1 : 0; 826 } 827 828 # N14 - '[NH+](-*)(-*)-*' 829 # 830 sub _IsN14Nitrogen { 831 my($This, $Atom) = @_; 832 833 return $Atom->DoesAtomNeighborhoodMatch('N.X3.SB3.H1.FC+1') ? 1 : 0; 834 } 835 836 # N15 - '[NH+](-*)=*' 837 # 838 sub _IsN15Nitrogen { 839 my($This, $Atom) = @_; 840 841 return $Atom->DoesAtomNeighborhoodMatch('N.X2.SB1.DB1.H1.FC+1') ? 1 : 0; 842 } 843 844 # N16 - '[NH2+](-*)-*' 845 # 846 sub _IsN16Nitrogen { 847 my($This, $Atom) = @_; 848 849 return $Atom->DoesAtomNeighborhoodMatch('N.X2.SB2.H2.FC+1') ? 1 : 0; 850 } 851 852 # N17 - '[NH2+]=*' 853 # 854 sub _IsN17Nitrogen { 855 my($This, $Atom) = @_; 856 857 return $Atom->DoesAtomNeighborhoodMatch('N.X1.DB1.H2.FC+1') ? 1 : 0; 858 } 859 860 # N18 - '[NH3+]-*' 861 # 862 sub _IsN18Nitrogen { 863 my($This, $Atom) = @_; 864 865 return $Atom->DoesAtomNeighborhoodMatch('N.X1.SB1.H3.FC+1') ? 1 : 0; 866 } 867 868 # N19 - '[n](:*):*' 869 # 870 sub _IsN19Nitrogen { 871 my($This, $Atom) = @_; 872 873 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.X2.AB2.H0.FC0') ? 1 : 0; 874 } 875 876 # N20 - '[n](:*)(:*):*' 877 # 878 sub _IsN20Nitrogen { 879 my($This, $Atom) = @_; 880 881 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.X3.AB3.H0.FC0') ? 1 : 0; 882 } 883 884 # N21 - '[n](-*)(:*):*' 885 # 886 sub _IsN21Nitrogen { 887 my($This, $Atom) = @_; 888 889 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.X3.AB2.H0.FC0', ['*', '*', '*'], [':', ':', '-']) ? 1 : 0; 890 } 891 892 # N22 - '[n](=*)(:*):*' - As in pyridine N-oxide 893 # 894 sub _IsN22Nitrogen { 895 my($This, $Atom) = @_; 896 897 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.X3.AB2.H0.FC0', ['*', '*', '*'], [':', ':', '=']) ? 1 : 0; 898 } 899 900 # N23 - '[nH](:*):*' 901 # 902 sub _IsN23Nitrogen { 903 my($This, $Atom) = @_; 904 905 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.X2.AB2.H1.FC0') ? 1 : 0; 906 } 907 908 # N24 - '[n+](:*)(:*):*' 909 # 910 sub _IsN24Nitrogen { 911 my($This, $Atom) = @_; 912 913 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.X3.AB3.H0.FC+1') ? 1 : 0; 914 } 915 916 # N25 - '[n+](-*)(:*):*' 917 # 918 sub _IsN25Nitrogen { 919 my($This, $Atom) = @_; 920 921 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.X3.AB2.H0.FC+1', ['*', '*', '*'], [':', ':', '-']) ? 1 : 0; 922 } 923 924 # N26 - '[nH+](:*):*' 925 # 926 sub _IsN26Nitrogen { 927 my($This, $Atom) = @_; 928 929 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.X2.AB2.H1.FC+1') ? 1 : 0; 930 } 931 932 # O1 - '[O](-*)-*' 933 # 934 sub _IsO1Oxygen { 935 my($This, $Atom) = @_; 936 937 return $Atom->DoesAtomNeighborhoodMatch('O.!RA.X2.SB2.H0.FC0') ? 1 : 0; 938 } 939 940 # O2 - '[O]1-*-*-1' - Atom in a 3 membered ring 941 # 942 sub _IsO2Oxygen { 943 my($This, $Atom) = @_; 944 945 return $Atom->DoesAtomNeighborhoodMatch('O.RA3.X2.SB2.H0.FC0') ? 1 : 0; 946 } 947 948 # O3 - '[O]=*' 949 # 950 sub _IsO3Oxygen { 951 my($This, $Atom) = @_; 952 953 return $Atom->DoesAtomNeighborhoodMatch('O.X1.DB1.H0.FC0') ? 1 : 0; 954 } 955 956 # O4 - '[OH]-*' 957 # 958 sub _IsO4Oxygen { 959 my($This, $Atom) = @_; 960 961 return $Atom->DoesAtomNeighborhoodMatch('O.X1.SB1.H1.FC0') ? 1 : 0; 962 } 963 964 # O5 - '[O-]-*' 965 # 966 sub _IsO5Oxygen { 967 my($This, $Atom) = @_; 968 969 return $Atom->DoesAtomNeighborhoodMatch('O.X1.SB1.H0.FC-1') ? 1 : 0; 970 } 971 972 # O6 - '[o](:*):*' 973 # 974 sub _IsO6Oxygen { 975 my($This, $Atom) = @_; 976 977 return $Atom->DoesAtomNeighborhoodMatch('O.Ar.X2.AB2.H0.FC0') ? 1 : 0; 978 } 979 980 # P1 - '[P](-*)(-*)-*' 981 # 982 sub _IsP1Phosphorus { 983 my($This, $Atom) = @_; 984 985 return $Atom->DoesAtomNeighborhoodMatch('P.X3.SB3.H0.FC0') ? 1 : 0; 986 } 987 988 # P2 - '[P](-*)=*' 989 # 990 sub _IsP2Phosphorus { 991 my($This, $Atom) = @_; 992 993 return $Atom->DoesAtomNeighborhoodMatch('P.X2.SB1.DB1.H0.FC0') ? 1 : 0; 994 } 995 996 # P3 - '[P](-*)(-*)(-*)=*' 997 # 998 sub _IsP3Phosphorus { 999 my($This, $Atom) = @_; 1000 1001 return $Atom->DoesAtomNeighborhoodMatch('P.X4.SB3.DB1.H0.FC0') ? 1 : 0; 1002 } 1003 1004 # P4 - '[PH](-*)(-*)=*' 1005 # 1006 sub _IsP4Phosphorus { 1007 my($This, $Atom) = @_; 1008 1009 return $Atom->DoesAtomNeighborhoodMatch('P.X3.SB2.DB1.H1.FC0') ? 1 : 0; 1010 } 1011 1012 # S1 - '[S](-*)-*' 1013 # 1014 sub _IsS1Sulfur { 1015 my($This, $Atom) = @_; 1016 1017 return $Atom->DoesAtomNeighborhoodMatch('S.X2.SB2.H0.FC0') ? 1 : 0; 1018 } 1019 1020 # S2 - '[S]=*' 1021 # 1022 sub _IsS2Sulfur { 1023 my($This, $Atom) = @_; 1024 1025 return $Atom->DoesAtomNeighborhoodMatch('S.X1.DB1.H0.FC0') ? 1 : 0; 1026 } 1027 1028 # S3 - '[S](-*)(-*)=*' 1029 # 1030 sub _IsS3Sulfur { 1031 my($This, $Atom) = @_; 1032 1033 return $Atom->DoesAtomNeighborhoodMatch('S.X3.SB2.DB1.H0.FC0') ? 1 : 0; 1034 } 1035 1036 # S4 - '[S](-*)(-*)(=*)=*' 1037 # 1038 sub _IsS4Sulfur { 1039 my($This, $Atom) = @_; 1040 1041 return $Atom->DoesAtomNeighborhoodMatch('S.X4.SB2.DB2.H0.FC0') ? 1 : 0; 1042 } 1043 1044 # S5 - '[SH]-*' 1045 # 1046 sub _IsS5Sulfur { 1047 my($This, $Atom) = @_; 1048 1049 return $Atom->DoesAtomNeighborhoodMatch('S.X1.SB1.H1.FC0') ? 1 : 0; 1050 } 1051 1052 # S6 - '[s](:*):*' 1053 # 1054 sub _IsS6Sulfur { 1055 my($This, $Atom) = @_; 1056 1057 return $Atom->DoesAtomNeighborhoodMatch('S.Ar.X2.AB2.H0.FC0') ? 1 : 0; 1058 } 1059 1060 # Return a string containg data for TPSAAtomTypes object... 1061 # 1062 sub StringifyTPSAAtomTypes { 1063 my($This) = @_; 1064 my($AtomTypesString); 1065 1066 # Type of AtomTypes... 1067 $AtomTypesString = "AtomTypes: $This->{Type}; IgnorePhosphorus: " . ($This->{IgnorePhosphorus} ? "Yes" : "No") . "; IgnoreSulfur: " . ($This->{IgnoreSulfur} ? "Yes" : "No"); 1068 1069 # Setup atom types information... 1070 my($AtomID, $AtomType, @AtomTypesInfo, %AssignedAtomTypes); 1071 1072 @AtomTypesInfo = (); 1073 %AssignedAtomTypes = $This->GetAtomTypes(); 1074 1075 for $AtomID (sort { $a <=> $b } keys %AssignedAtomTypes) { 1076 $AtomType = $AssignedAtomTypes{$AtomID} ? $AssignedAtomTypes{$AtomID} : 'None'; 1077 push @AtomTypesInfo, "$AtomID:$AtomType"; 1078 } 1079 $AtomTypesString .= "; AtomIDs:AtomTypes: <" . TextUtil::JoinWords(\@AtomTypesInfo, ", ", 0) . ">"; 1080 1081 return $AtomTypesString; 1082 } 1083 1084 # Is it a TPSAAtomTypes object? 1085 sub _IsTPSAAtomTypes { 1086 my($Object) = @_; 1087 1088 return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0; 1089 } 1090 1091 # Check and load TPSA atom types data... 1092 # 1093 sub _CheckAndLoadTPSAAtomTypesData { 1094 1095 # Is it already loaded? 1096 if (exists $TPSAAtomTypesDataMap{AtomTypes}) { 1097 return; 1098 } 1099 1100 _LoadTPSAAtomTypesData(); 1101 } 1102 1103 # Load TPSA atom types data from the file assuming first column to be atom type symbol.. 1104 # 1105 # Format: 1106 # 1107 # "AtomType","SMARTS","TPSAContribution","Comments" 1108 # "N1","[N](-*)(-*)-*","3.24","" 1109 # "N2","[N](-*)=*","12.36","" 1110 # 1111 sub _LoadTPSAAtomTypesData { 1112 my($AtomTypesDataFile, $MayaChemToolsLibDir); 1113 1114 $MayaChemToolsLibDir = FileUtil::GetMayaChemToolsLibDirName(); 1115 1116 $AtomTypesDataFile = "$MayaChemToolsLibDir" . "/data/TPSAAtomTypes.csv"; 1117 if (! -e "$AtomTypesDataFile") { 1118 croak "Error: MayaChemTools package file, $AtomTypesDataFile, is missing: Possible installation problems..."; 1119 } 1120 1121 %TPSAAtomTypesDataMap = (); 1122 AtomTypes::AtomTypes::LoadAtomTypesData($AtomTypesDataFile, \%TPSAAtomTypesDataMap); 1123 } 1124