1 package AtomTypes::MMFF94AtomTypes; 2 # 3 # File: MMFF94AtomTypes.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(GetMMFF94AtomTypesData GetAllPossibleMMFF94AtomTypes GetAllPossibleMMFF94NonHydrogenAtomTypes); 38 @EXPORT_OK = qw(); 39 40 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 41 42 # Setup class variables... 43 my($ClassName, %MMFF94AtomTypesDataMap); 44 _InitializeClass(); 45 46 # Overload Perl functions... 47 use overload '""' => 'StringifyMMFF94AtomTypes'; 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->_InitializeMMFF94AtomTypes(); 57 58 $This->_InitializeMMFF94AtomTypesProperties(%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 %MMFF94AtomTypesDataMap = (); 70 } 71 72 73 # Initialize object data... 74 # 75 sub _InitializeMMFF94AtomTypes { 76 my($This) = @_; 77 78 # Type of AtomTypes... 79 $This->{Type} = 'MMFF94'; 80 81 # By default, MMFF94 atom types are also assigned to hydrogens... 82 $This->{IgnoreHydrogens} = 0; 83 84 return $This; 85 } 86 87 # Initialize object properties... 88 # 89 sub _InitializeMMFF94AtomTypesProperties { 90 my($This, %NamesAndValues) = @_; 91 92 my($Name, $Value, $MethodName); 93 while (($Name, $Value) = each %NamesAndValues) { 94 $MethodName = "Set${Name}"; 95 $This->$MethodName($Value); 96 } 97 98 # Make sure molecule object was specified... 99 if (!exists $NamesAndValues{Molecule}) { 100 croak "Error: ${ClassName}->New: Object can't be instantiated without specifying molecule..."; 101 } 102 103 return $This; 104 } 105 106 # Get MMFF94 atom types and associated data loaded from MMFF94 data file as 107 # a reference to hash with the following hash data format: 108 # 109 # @{$MMFF94AtomTypesDataMap{AtomTypes}} - Array of all possible atom types for all atoms 110 # @{$MMFF94AtomTypesDataMap{NonHydrogenAtomTypes}} - Array of all possible atom types for non-hydrogen atoms 111 # @{$MMFF94AtomTypesDataMap->{ColLabels}} - Array of column labels 112 # %{$MMFF94AtomTypesDataMap->{DataCol<Num>}} - Hash keys pair: <DataCol<Num>, AtomType> 113 # 114 # This functionality can be either invoked as a class function or an 115 # object method. 116 # 117 sub GetMMFF94AtomTypesData { 118 119 # Make sure data is loaded... 120 _CheckAndLoadMMFF94AtomTypesData(); 121 122 return \%MMFF94AtomTypesDataMap; 123 } 124 125 # Get all possible MMFF94 atom types corresponding to hydrogen and non-hydrogen 126 # atoms as an array reference... 127 # 128 # This functionality can be either invoked as a class function or an 129 # object method. 130 # 131 sub GetAllPossibleMMFF94AtomTypes { 132 return _GetAllPossibleMMFF94AtomTypes(); 133 } 134 135 # Get all possible MMFF94 atom types corresponding to non-hydrogen atoms 136 # as an array reference... 137 # 138 # This functionality can be either invoked as a class function or an 139 # object method. 140 # 141 sub GetAllPossibleMMFF94NonHydrogenAtomTypes { 142 my($NonHydrogensOnly); 143 144 $NonHydrogensOnly = 1; 145 return _GetAllPossibleMMFF94AtomTypes($NonHydrogensOnly); 146 } 147 148 # Get all possible MMFF94 atom types as an array reference... 149 # 150 sub _GetAllPossibleMMFF94AtomTypes { 151 my($NonHydrogensOnly) = @_; 152 my($MMFF94AtomTypesDataRef); 153 154 $NonHydrogensOnly = defined $NonHydrogensOnly ? $NonHydrogensOnly : 0; 155 156 $MMFF94AtomTypesDataRef = GetMMFF94AtomTypesData(); 157 158 return $NonHydrogensOnly ? \@{$MMFF94AtomTypesDataRef->{NonHydrogenAtomTypes}}: \@{$MMFF94AtomTypesDataRef->{AtomTypes}}; 159 } 160 161 # Assign MMFF94 [ Ref 83-87 ] atom types to all atoms... 162 # 163 # Notes: 164 # o 212 MMFF94 atom type symbols are listed 165 # o 95 MMFF94 atom type numbers are listed 166 # o Atom type numbers from 83 to 86 are not used 167 # o Number of atom type symbols for: 168 # o C: 34 169 # o N: 47 170 # o O: 45 171 # o P: 7 172 # o S: 18 173 # o F, Br: 2 174 # o Cl: 3 175 # o I: 1 176 # o H: 41 177 # o Fe,Cu, Zn: 2 178 # o Li, Na, L, K, Mg, Si, : 1 179 # 180 sub AssignAtomTypes { 181 my($This) = @_; 182 183 $This->_AssignAtomTypesToNonHydrogenAtoms(); 184 185 if (!$This->{IgnoreHydrogens}) { 186 $This->_AssignAtomTypesToHydrogenAtoms(); 187 } 188 189 return $This; 190 } 191 192 # Assign atom types to all non-Hydrogen atoms.. 193 # 194 sub _AssignAtomTypesToNonHydrogenAtoms { 195 my($This) = @_; 196 my($Atom, $AtomType); 197 198 ATOM: for $Atom ($This->GetMolecule()->GetAtoms()) { 199 if ($Atom->IsHydrogen()) { 200 next ATOM; 201 } 202 $AtomType = $This->_GetAtomType($Atom); 203 $This->SetAtomType($Atom, $AtomType); 204 } 205 return $This; 206 } 207 208 # Assign atom types to Hydrogen atoms.. 209 # 210 sub _AssignAtomTypesToHydrogenAtoms { 211 my($This) = @_; 212 my($Atom, $AtomType); 213 214 if ($This->{IgnoreHydrogens}) { 215 return $This; 216 } 217 218 ATOM: for $Atom ($This->GetMolecule()->GetAtoms()) { 219 if (!$Atom->IsHydrogen()) { 220 next ATOM; 221 } 222 $AtomType = $This->_GetAtomTypeForHydrogen($Atom); 223 $This->SetAtomType($Atom, $AtomType); 224 } 225 return $This; 226 } 227 228 # Get MMFF94 atom type for atom... 229 # 230 sub _GetAtomType { 231 my($This, $Atom) = @_; 232 my($AtomType); 233 234 $AtomType = ''; 235 236 ATOM: { 237 if ($Atom->IsCarbon()) { 238 $AtomType = $This->_GetAtomTypeForCarbon($Atom); 239 last ATOM; 240 } 241 if ($Atom->IsNitrogen()) { 242 $AtomType = $This->_GetAtomTypeForNitrogen($Atom); 243 last ATOM; 244 } 245 if ($Atom->IsOxygen()) { 246 $AtomType = $This->_GetAtomTypeForOxygen($Atom); 247 last ATOM; 248 } 249 if ($Atom->IsPhosphorus()) { 250 $AtomType = $This->_GetAtomTypeForPhosphorus($Atom); 251 last ATOM; 252 } 253 if ($Atom->IsSulfur()) { 254 $AtomType = $This->_GetAtomTypeForSulfur($Atom); 255 last ATOM; 256 } 257 if ($Atom->IsHydrogen()) { 258 $AtomType = $This->_GetAtomTypeForHydrogen($Atom); 259 last ATOM; 260 } 261 $AtomType = $This->_GetAtomTypeForOtherAtoms($Atom); 262 } 263 264 return $AtomType; 265 } 266 267 # Get MMFF94 atom type for Carbon atom... 268 # 269 # 34 AtomTypeSymbols for element C: 270 # 271 # AtomTypeSymbol AtomTypeNum AtomTypeDefinition 272 # CR 1 ALKYL CARBON, SP3 273 # C=C 2 VINYLIC CARBON, SP2 274 # CSP2 2 GENERIC SP2 CARBON 275 # C=O 3 GENERAL CARBONYL CARBON 276 # C=N 3 SP2 CARBON IN C=N 277 # CGD 3 GUANIDINE CARBON, DOUBLY BONDED TO N 278 # C=OR 3 KETONE OR ALDEHYDE CARBONYL CARBON 279 # C=ON 3 AMIDE CARBONYL CARBON 280 # CONN 3 UREA CARBONYL CARBON 281 # COO 3 CARBOXYLIC ACID OR ESTER CARBONYL CARBON 282 # COON 3 CARBAMATE CARBONYL CARBON 283 # COOO 3 CARBONIC ACID OR ESTER CARBONYL CARBON 284 # C=OS 3 THIOESTER CARBONYL CARBON, DOUBLE BONDED TO O 285 # C=S 3 THIOESTER CARBON, DOUBLY BONDED TO S 286 # C=SN 3 THIOAMIDE, CARBON, DOUBLY BONDED TO S 287 # CSO2 3 CARBON IN >C=SO2 288 # CS=O 3 CARBON IN >C=S=O (SULFINYL GROUP) 289 # CSS 3 THIOCARBOXYLIC ACID OR ESTER CARBONYL CARBON 290 # C=P 3 CARBON DOUBLE BONDED TO PHOSPHOROUS 291 # CSP 4 ACETYLENIC CARBON 292 # =C= 4 ALLENIC CARBON 293 # CR4R 20 CARBON IN 4-MEMBERED RINGS 294 # CR3R 22 CARBON IN A 3-MEMBERED RING 295 # CE4R 30 OLEFINIC CARBON IN 4-MEMBERED RINGS 296 # CB 37 CARBON AS IN BENZENE, PYRROLE 297 # CO2M 41 CARBOXYLATE ANION CARBON 298 # CS2M 41 CARBON IN THIOCARBOXYLATE ANION 299 # CGD+ 57 GUANIDINIUM CARBON 300 # CNN+ 57 C IN +N=C-N RESONANCE STRUCTURES 301 # C% 60 ISONITRILE CARBON 302 # C5A 63 ALPHA CARBON IN 5-MEMBERED HETEROAROMATIC RING 303 # C5B 64 BETA CARBON IN 5-MEMBERED HETEROAROMATIC RING 304 # C5 78 GENERAL CARBON IN 5-MEMBERED HETEROAROMATIC RING 305 # CIM+ 80 C IN N-C-N IN IMIDAZOLIUM ION 306 # 307 # Notes: 308 # . During atom type assignments, matches are performed starting from specific to generic. 309 # 310 sub _GetAtomTypeForCarbon { 311 my($This, $Atom) = @_; 312 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 313 314 $AtomType = 'None'; 315 316 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 317 318 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 319 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 320 321 ATOMTYPE: { 322 323 # Only single bonds... 324 if ($NumOfPiBonds == 0) { 325 $AtomType = $This->_GetAtomTypeForCarbonWithOnlySigmaBonds($Atom); 326 last ATOMTYPE; 327 } 328 329 # One double bond... 330 if ($NumOfPiBonds == 1) { 331 $AtomType = $This->_GetAtomTypeForCarbonWithOnePiBond($Atom); 332 last ATOMTYPE; 333 } 334 335 # One triple bond or two double bonds... 336 if ($NumOfPiBonds == 2) { 337 $AtomType = $This->_GetAtomTypeForCarbonWithTwoPiBonds($Atom); 338 last ATOMTYPE; 339 } 340 341 $AtomType = 'None'; 342 carp "Warning: ${ClassName}->_GetAtomTypeForCarbon: MMFF94 atom type for Carbon cann't be assigned..."; 343 } 344 return $AtomType; 345 } 346 347 # Get MMFF94 atom type for Nitrogen atom... 348 # 349 # 47 AtomTypeSymbols for element N: 350 # 351 # AtomTypeSymbol AtomTypeNum AtomTypeDefinition 352 # NR 8 NITROGEN IN ALIPHATIC AMINES 353 # N=C 9 NITROGEN IN IMINES 354 # N=N 9 NITROGEN IN AZO COMPOUNDS 355 # NC=O 10 NITROGEN IN AMIDES 356 # NC=S 10 NITROGEN IN N-C=S, THIOAMIDE 357 # NN=C 10 NITROGEN IN N-N=C 358 # NN=N 10 NITROGEN IN N-N=N 359 # NR+ 34 QUATERNARY NITROGEN, SP3, POSITIVELY CHARGED 360 # NPYD 38 NITROGEN, AS IN PYRIDINE 361 # NPYL 39 NITROGEN, AS IN PYRROLE 362 # NC=C 40 NITROGEN ON N-C=C 363 # NC=N 40 NITROGEN IN N-C=N 364 # NC=P 40 NITROGEN IN N-C=P 365 # NC%C 40 NITROGEN ATTACHED TO C-C TRIPLE BOND 366 # NSP 42 NITROGEN, TRIPLE BONDED 367 # NSO2 43 NITROGEN IN SULFONAMIDES 368 # NSO3 43 NITROGEN IN SULFONAMIDES, THREE Os ON S 369 # NPO2 43 NITROGEN IN PHOSPHONAMIDES 370 # NPO3 43 NITROGEN IN PHOSPHONAMIDES, THREE Os ON P 371 # NC%N 43 NITROGEN ATTACHED TO CYANO GROUP 372 # NO2 45 NITRO GROUP NITROGEN 373 # NO3 45 NITRATE GROUP NITROGEN 374 # N=O 46 NITROSO NITROGEN 375 # NAZT 47 TERMINAL NITROGEN IN AZIDO OR DIAZO GROUP 376 # NSO 48 DIVALENT NITROGEN REPLACING MONOVALENT O IN SO2 GROUP 377 # =N= 53 NITROGEN IN C=N=N OR -N=N=N 378 # N+=C 54 POSITIVELY CHARGED IMINIUM NITROGEN 379 # N+=N 54 POSITIVELY CHARGED NITROGEN DOUBLE-BONDED TO N 380 # NCN+ 55 N IN +N=C-N RESONANCE STRUCTURES - FORMAL CHARGE=1/2 381 # NGD+ 56 GUANIDINIUM-TYPE NITROGEN - FORMAL CHARGE=1/3 382 # NPD+ 58 PYRIDINIUM-TYPE NITROGEN - FORMAL CHARGE=1 383 # NR% 61 ISONITRILE NITROGEN [FC = 0] OR DIAZO NITROGEN [FC = 1] 384 # NM 62 DEPROTONATED SULFONAMIDE N-; FORMAL CHARGE=-1 385 # N5A 65 ALPHA AROM HETEROCYCLIC 5-RING NITROGEN 386 # N5B 66 BETA AROM HETEROCYCLIC 5-RING NITROGEN 387 # N2OX 67 SP2-HYDRIDIZED N-OXIDE NITROGEN 388 # N3OX 68 SP3-HYDRIDIZED N-OXIDE NITROGEN 389 # NPOX 69 PYRIDINE N-OXIDE NITROGEN 390 # N5M 76 NEGATIVELY CHARGED N IN, E.G, TRI- OR TETRAZOLE ANION 391 # N5 79 GENERAL NITROGEN IN 5-MEMBERED HETEROCYCLIC RING 392 # NIM+ 81 IMIDAZOLIUM-TYPE NITROGEN - FORMAL CHARGE=1/2 393 # N5A+ 81 POSITIVE N5A NITROGEN - FORMAL CHARGE=1 394 # N5B+ 81 POSITIVE N5B NITROGEN - FORMAL CHARGE=1 395 # N5+ 81 POSITIVE N5 NITROGEN - FORMAL CHARGE=1 396 # N5AX 82 N-OXIDE NITROGEN IN 5-RING ALPHA POSITION 397 # N5BX 82 N-OXIDE NITROGEN IN 5-RING BETA POSITION 398 # N5OX 82 N-OXIDE NITROGEN IN GENERAL 5-RING POSITION 399 # 400 # Notes: 401 # . The current release of MayaChemTools assigns "None" to Oxygens in the following environment 402 # as no generic or specific MMFF94 atom types exists to handle them: 403 # 404 # . Terminal Nitrogens attched to Sulfur in >S=N 405 # 406 sub _GetAtomTypeForNitrogen { 407 my($This, $Atom) = @_; 408 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 409 410 $AtomType = 'None'; 411 412 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 413 414 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 415 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 416 417 ATOMTYPE: { 418 419 # Nitrogens in five membered rings... 420 if ($Atom->IsInRingOfSize(5)) { 421 $AtomType = $This->_GetAtomTypeForFiveMemberedRingNitrogen($Atom); 422 last ATOMTYPE; 423 } 424 425 # -N(-)-, -N+(-)(-)-, -(N-1)(-) 426 if ($NumOfPiBonds == 0) { 427 $AtomType = $This->_GetAtomTypeForNitrogenWithOnlySigmaBonds($Atom); 428 last ATOMTYPE; 429 } 430 431 # -N=, and -N+(=)- 432 if ($NumOfPiBonds == 1) { 433 $AtomType = $This->_GetAtomTypeForNitrogenWithOnePiBond($Atom); 434 last ATOMTYPE; 435 } 436 437 # #N, #N+-, and =N+= 438 if ($NumOfPiBonds == 2) { 439 $AtomType = $This->_GetAtomTypeForNitrogenWithTwoPiBonds($Atom); 440 last ATOMTYPE; 441 } 442 443 $AtomType = 'None'; 444 carp "Warning: ${ClassName}->_GetAtomTypeForNitrogen: MMFF94 atom type for Nitrogen cann't be assigned..."; 445 } 446 return $AtomType; 447 } 448 449 # Get MMFF94 atom type for Oxygen atom... 450 # 451 # 45 AtomTypeSymbols for element O: 452 # 453 # AtomTypeSymbol AtomTypeNum AtomTypeDefinition 454 # OR 6 ALCOHOL OR ETHER OXYGEN 455 # OC=O 6 ESTER OR CARBOXYLIC ACID -O- 456 # OC=C 6 ENOLIC OR PHENOLIC OXYGEN 457 # OC=N 6 DIVALENT OXYGEN 458 # OC=S 6 THIOESTER OR THIOACID -O- 459 # ONO2 6 DIVALENT NITRATE ETHER OXYGEN 460 # ON=O 6 DIVALENT NITRITE ETHER OXYGEN 461 # OSO3 6 DIVALENT OXYGEN ATTACHED TO SULFUR 462 # OSO2 6 DIVALENT OXYGEN ATTACHED TO SULFUR 463 # OSO 6 DIVALENT OXYGEN ATTACHED TO SULFUR 464 # OS=O 6 DIVALENT OXYGEN ATTACHED TO SULFOXIDE SULFUR 465 # -OS 6 GENERAL DIVALENT OXYGEN ATTACHED TO S 466 # OPO3 6 DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 467 # OPO2 6 DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 468 # OPO 6 DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 469 # -OP 6 DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 470 # -O- 6 GENERAL DIVALENT O 471 # O=C 7 GENERAL C=O 472 # O=CN 7 CARBONYL OXYGEN, AMIDES 473 # O=CR 7 CARBONYL OXYGEN, ALDEHYDES AND KETONES 474 # O=CO 7 CARBONYL OXYGEN, CARBOXYLIC ACIDS AND ESTERS 475 # O=N 7 NITROSO OXYGEN 476 # O=S 7 O=S IN SULFOXIDES 477 # O=S= 7 O=S ON SULFUR DOUBLY BONDED TO, E.G., CARBON 478 # O2CM 32 OXYGEN IN CARBOXYLATE ANION 479 # OXN 32 N-OXIDE OXYGEN 480 # O2N 32 NITRO OXYGEN 481 # O2NO 32 NITRO-GROUP OXYGEN IN NITRATE 482 # O3N 32 NITRATE ANION OXYGEN 483 # O-S 32 SINGLE TERMINAL OXYGEN ON TETRACOORD SULFUR 484 # O2S 32 TERMINAL O-S IN SULFONES AND SULFONAMIDES 485 # O3S 32 TERMINAL O IN SULFONATES 486 # O4S 32 TERMINAL O IN SO4(-3) 487 # OSMS 32 TERM O IN THIOSULFINATE ANION - FORMAL CHARGE=-0.5 488 # OP 32 TERMINAL O IN PHOSPHOXIDES 489 # O2P 32 TERMINAL O IN PHOSPHINATES 490 # O3P 32 TERMINAL OXYGEN IN PHOSPHONATES 491 # O4P 32 TERMINAL OXYGEN IN PHOSPHATES AND PHOSPHODIESTERS 492 # O4CL 32 OXYGEN IN CLO4(-) ANION - FORMAL CHARGE=-0.25 493 # OM 35 ALKOXIDE OXYGEN, NEGATIVELY CHARGED 494 # OM2 35 OXIDE OXYGEN ON SP2 CARBON, NEGATIVELY CHARGED 495 # O+ 49 POSITIVELY CHARGED OXONIUM (TRICOORDINATE) OXYGEN 496 # O=+ 51 POSITIVELY CHARGED OXENIUM (DICOORDINATE) OXYGEN 497 # OFUR 59 AROMATIC OXYGEN AS IN FURAN 498 # OH2 70 OXYGEN ON WATER 499 # 500 # Notes: 501 # . The current release of MayaChemTools assigns "None" to Oxygens in the following environment 502 # as no generic or specific MMFF94 atom types exists to handle them: 503 # 504 # . Terminal anion Oxygen corresponding to divalent Oxygen attached to Sulfoxide Sulfur in 505 # OS=O and divalent Oxygen attached to Sulfur in -OS 506 # . Terminal Oxygens attched to Sulfur in =SO2 507 # . Terminal anion Oxygen attched to Sulfur in SO2M which is same as OS=O 508 # 509 sub _GetAtomTypeForOxygen { 510 my($This, $Atom) = @_; 511 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds, $OxygenAttachedToSulfur, $OxygenAttachedToPhosphorus); 512 513 $AtomType = 'None'; 514 515 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 516 517 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 518 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 519 520 $OxygenAttachedToSulfur = $Atom->GetNeighborsUsingAtomSpecification('S'); 521 $OxygenAttachedToPhosphorus = $Atom->GetNeighborsUsingAtomSpecification('P'); 522 523 ATOMTYPE: { 524 525 # Divalent or terminal Oxygen attached to Sulfur... 526 if ($OxygenAttachedToSulfur) { 527 $AtomType = $This->_GetAtomTypeForOxygenAttachedToSulfur($Atom); 528 last ATOMTYPE; 529 } 530 531 # Divalent or terminal Oxygen attached to Phosphorous... 532 if ($OxygenAttachedToPhosphorus) { 533 $AtomType = $This->_GetAtomTypeForOxygenAttachedToPhosphorus($Atom); 534 last ATOMTYPE; 535 } 536 537 # Only single bonds... 538 if ($NumOfPiBonds == 0) { 539 $AtomType = $This->_GetAtomTypeForOxygenWithOnlySigmaBonds($Atom); 540 last ATOMTYPE; 541 } 542 543 # One double bond... 544 if ($NumOfPiBonds == 1) { 545 $AtomType = $This->_GetAtomTypeForOxygenWithOnePiBond($Atom); 546 last ATOMTYPE; 547 } 548 549 $AtomType = 'None'; 550 carp "Warning: ${ClassName}->_GetAtomTypeForOxygen: MMFF94 atom type for Oxygen cann't be assigned..."; 551 } 552 return $AtomType; 553 } 554 555 # Get MMFF94 atom type for Phosphorus atom... 556 # 557 # 7 AtomTypeSymbols for element P: 558 # 559 # AtomTypeSymbol AtomTypeNum AtomTypeDefinition 560 # PO4 25 PHOSPHOROUS IN PHOSPHATES AND PHOSPHODIESTERS 561 # PO3 25 TETRACOORDINATE P WITH THREE ATTACHED OXYGENS 562 # PO2 25 TETRACOORDINATE P WITH TWO ATTACHED OXYGENS 563 # PO 25 TETRACOORDINATE P WITH ONE ATTACHED OXYGEN 564 # PTET 25 GENERAL TETRACOORDINATE PHOSPHORUS 565 # P 26 TRICOORDINATE P, AS IN PHOSPHINES 566 # -P=C 75 PHOSPHOROUS DOUBLY BONDED TO CARBON 567 # 568 sub _GetAtomTypeForPhosphorus { 569 my($This, $Atom) = @_; 570 my($AtomType); 571 572 $AtomType = 'None'; 573 574 ATOMTYPE: { 575 576 # PO4 : PHOSPHOROUS IN PHOSPHATES AND PHOSPHODIESTERS 577 if ($This->_IsPhosphateOrPhosphodiesterPhosphorus($Atom)) { 578 $AtomType = 'PO4'; 579 last ATOMTYPE; 580 } 581 582 # PO3 : TETRACOORDINATE P WITH THREE ATTACHED OXYGENS 583 if ($This->_IsPhosphonatePhosphorus($Atom)) { 584 $AtomType = 'PO3'; 585 last ATOMTYPE; 586 } 587 588 # PO2 : TETRACOORDINATE P WITH TWO ATTACHED OXYGENS 589 if ($This->_IsPhosphinatePhosphorus($Atom)) { 590 $AtomType = 'PO2'; 591 last ATOMTYPE; 592 } 593 594 # PO : TETRACOORDINATE P WITH ONE ATTACHED OXYGEN 595 if ($This->_IsPhosphoxidePhosphorus($Atom)) { 596 $AtomType = 'PO'; 597 last ATOMTYPE; 598 } 599 600 # -P=C : PHOSPHOROUS DOUBLY BONDED TO CARBON 601 if ($This->_IsDoublyBondedToCarbonPhosphorous($Atom)) { 602 $AtomType = '-P=C'; 603 last ATOMTYPE; 604 } 605 606 # PTET : GENERAL TETRACOORDINATE PHOSPHORUS 607 if ($This->_IsTetraCoordinatedPhosphorus($Atom)) { 608 $AtomType = 'PTET'; 609 last ATOMTYPE; 610 } 611 612 # P : TRICOORDINATE P, AS IN PHOSPHINES 613 if ($This->_IsTriCoordinatedPhosphorus($Atom)) { 614 $AtomType = 'P'; 615 last ATOMTYPE; 616 } 617 618 $AtomType = 'None'; 619 carp "Warning: ${ClassName}->_GetAtomTypeForPhosphorus: MMFF94 atom type for Phosphorous cann't be assigned..."; 620 } 621 622 return $AtomType; 623 } 624 625 # Get MMFF94 atom type for Sulfur atom... 626 # 627 # 18 AtomTypeSymbols for element S: 628 # 629 # AtomTypeSymbol AtomTypeNum AtomTypeDefinition 630 # S 15 SULFUR IN THIOETHERS AND MERCAPTANS 631 # S=C 16 TERMINAL SULFUR DOUBLY BONDED TO CARBON 632 # S=O 17 SULFUR IN SULFOXIDES 633 # >S=N 17 SULFUR, TRICOORD, DOUBLY BONDED TO N 634 # SO2 18 SULFUR IN SULFONES 635 # SO2N 18 SULFUR IN SULFONAMIDES 636 # SO3 18 SULFONATE SULFUR 637 # SO4 18 SULFATE SULFUR 638 # =SO2 18 SULFONE SULPHER DOUBLY BONDED TO CARBON 639 # SNO 18 SULFUR IN NITROGEN ANALOG OF A SULFONE 640 # STHI 44 SULFUR AS IN THIOPHENE 641 # S-P 72 TERMINAL SULFUR BONDED TO PHOSPHORUS 642 # S2CM 72 TERMINAL SULFUR IN THIOCARBOXYLATE ANION 643 # SM 72 TERMINAL SULFUR - FORMAL CHARGE=-1 644 # SSMO 72 TERMINAL SULFUR IN THIOSULFINATE GROUP 645 # SO2M 73 SULFUR IN NEGATIVELY CHARGED SULFINATE GROUP 646 # SSOM 73 TRICOORD SULFUR IN THIOSULFINATE GROUP 647 # =S=O 74 SULFINYL SULFUR, EG. IN C=S=O 648 # 649 sub _GetAtomTypeForSulfur { 650 my($This, $Atom) = @_; 651 my($AtomType); 652 653 $AtomType = 'None'; 654 655 ATOMTYPE: { 656 657 # SO4 : SULFATE SULFUR 658 if ($This->_IsSulfateSulfur($Atom)) { 659 $AtomType = 'SO4'; 660 last ATOMTYPE; 661 } 662 663 # SO3 : SULFONATE SULFUR 664 if ($This->_IsSulfonateSulfur($Atom)) { 665 $AtomType = 'SO3'; 666 last ATOMTYPE; 667 } 668 669 # SO2N : SULFUR IN SULFONAMIDES 670 if ($This->_IsSulfonamideSulfur($Atom)) { 671 $AtomType = 'SO2N'; 672 last ATOMTYPE; 673 } 674 675 # SO2 : SULFUR IN SULFONES 676 if ($This->_IsSulfoneSulfur($Atom)) { 677 $AtomType = 'SO2'; 678 last ATOMTYPE; 679 } 680 681 # =SO2: SULFONE SULPHER DOUBLY BONDED TO CARBON 682 if ($This->_IsDoublyBondedToCarbonSulfoneSulfur($Atom)) { 683 $AtomType = '=SO2'; 684 last ATOMTYPE; 685 } 686 687 # SO2M: SULFUR IN NEGATIVELY CHARGED SULFINATE GROUP 688 if ($This->_IsNegativelyChargedSulfinateSulfur($Atom)) { 689 $AtomType = 'SO2M'; 690 last ATOMTYPE; 691 } 692 693 # SNO : SULFUR IN NITROGEN ANALOG OF A SULFONE 694 if ($This->_IsNitrogenAnalogOfSulfoneSulfur($Atom)) { 695 $AtomType = 'SNO'; 696 last ATOMTYPE; 697 } 698 699 # S=O : SULFUR IN SULFOXIDES 700 if ($This->_IsSulfoxideSulfur($Atom)) { 701 $AtomType = 'S=O'; 702 last ATOMTYPE; 703 } 704 705 # >S=N : SULFUR, TRICOORD, DOUBLY BONDED TO N 706 if ($This->_IsSNTricoordinatedSulfur($Atom)) { 707 $AtomType = '>S=N'; 708 last ATOMTYPE; 709 } 710 711 # STHI : SULFUR AS IN THIOPHENE 712 if ($This->_IsSTHISulfur($Atom)) { 713 $AtomType = 'STHI'; 714 last ATOMTYPE; 715 } 716 717 # S2CM : TERMINAL SULFUR IN THIOCARBOXYLATE ANION 718 if ($This->_IsThioCarboxylateAnionTerminalSulfur($Atom)) { 719 $AtomType = 'S2CM'; 720 last ATOMTYPE; 721 } 722 723 # SSMO : TERMINAL SULFUR IN THIOSULFINATE GROUP 724 if ($This->_IsThioSulfinateTerminalSulfur($Atom)) { 725 $AtomType = 'SSMO'; 726 last ATOMTYPE; 727 } 728 729 # SSOM : TRICOORD SULFUR IN THIOSULFINATE GROUP 730 if ($This->_IsTriCoordinatedThioSulfinateSulfur($Atom)) { 731 $AtomType = 'SSOM'; 732 last ATOMTYPE; 733 } 734 735 # =S=O: SULFINYL SULFUR, EG. IN C=S=O 736 if ($This->_IsSulfinylSulfur($Atom)) { 737 $AtomType = '=S=O'; 738 last ATOMTYPE; 739 } 740 741 # S-P : TERMINAL SULFUR BONDED TO PHOSPHORUS 742 if ($This->_IsSPTerminalSulfur($Atom)) { 743 $AtomType = 'S-P'; 744 last ATOMTYPE; 745 } 746 747 # S=C : TERMINAL SULFUR DOUBLY BONDED TO CARBON 748 if ($This->_IsSCTerminalSulfur($Atom)) { 749 $AtomType = 'S=C'; 750 last ATOMTYPE; 751 } 752 753 # SM : TERMINAL SULFUR - FORMAL CHARGE=-1 754 if ($This->_IsNegativelyChargedTerminalSulfur($Atom)) { 755 $AtomType = 'SM'; 756 last ATOMTYPE; 757 } 758 759 # S : SULFUR IN THIOETHERS AND MERCAPTANS 760 if ($This->_IsThioEthersOrMercaptansSulfur($Atom)) { 761 $AtomType = 'S'; 762 last ATOMTYPE; 763 } 764 765 $AtomType = 'None'; 766 carp "Warning: ${ClassName}->_GetAtomTypeForSulfur: MMFF94 atom type for Sulfur cann't be assigned..."; 767 } 768 return $AtomType; 769 } 770 771 # Get MMFF94 atom type for Hydrogen atom... 772 # 773 # 41 AtomTypeSymbols for element H: 774 # 775 # AtomTypeSymbol AtomTypeNum AtomTypeDefinition 776 # HC 5 H ATTACHED TO C 777 # HSI 5 H ATTACHED TO SI 778 # HOR 21 HYDROGEN IN ALCOHOLS 779 # HO 21 GENERAL H ON OXYGEN 780 # HOM 21 HYDROGEN IN HYDROXIDE ANION 781 # HNR 23 H-N(SP3) 782 # H3N 23 H-N(SP3), AMMONIA 783 # HPYL 23 H-N IN PYRROLE 784 # HNOX 23 H-N IN IN A N-OXIDE 785 # HNM 23 H ON DICOORD, NEGATIVELY CHARGED NITROGEN 786 # HN 23 GENERAL H ON NITROGEN 787 # HOCO 24 H-O IN CARBOXYLIC ACIDS 788 # HOP 24 HYDROGEN ON OXYGEN ATTACHED TO PHOSPHOROUS 789 # HN=N 27 AZO HYDROGEN 790 # HN=C 27 IMINE HYDROGEN 791 # HNCO 28 AMIDE HYDROGEN 792 # HNCS 28 THIOAMIDE HYDROGEN 793 # HNCC 28 H-N IN ENAMINES 794 # HNCN 28 H-N IN H-N-C=N 795 # HNNC 28 H-N IN H-N-N=C 796 # HNNN 28 H-N IN H-N-N=N 797 # HNSO 28 H-N IN SULFONAMIDE 798 # HNPO 28 H-N IN PHOSPHONAMIDE 799 # HNC% 28 HYDROGEN ON N ATTACHED TO TRIPLY BONDED CARBON 800 # HSP2 28 GENERAL H ON SP2 NITROGEN 801 # HOCC 29 H-O IN ENOLS AND PHENOLS 802 # HOCN 29 H-O IN HO-C=N 803 # HOH 31 HYDROGEN IN H2O 804 # HOS 33 H ON OXYGEN ATTACHED TO SULFUR 805 # HNR+ 36 H ON QUATERNARY NITROGEN 806 # HIM+ 36 H ON IMIDAZOLIUM-TYPE NITROGEN 807 # HPD+ 36 H ON PROTONATED PYRIDINE NITROGEN 808 # HNN+ 36 H ON AMIDINIUM-TYPE NITROGEN 809 # HNC+ 36 H ON PROTONATED IMINE NITROGEN 810 # HGD+ 36 H ON GUANIDINIUM-TYPE NITROGEN 811 # HN5+ 36 H ON N5+, N5A+ OR N5B+ 812 # HO+ 50 HYDROGEN ON O+ OXYGEN 813 # HO=+ 52 HYDROGEN ON OXENIUM OXYGEN 814 # HS 71 H ATTACHED TO DIVALENT, DICOORDINATE S 815 # HS=N 71 H ATTACHED TO TETRAVALENT, TRICOODR S DBL BONDED TO N 816 # HP 71 H ATTACHED TO TRI- OR TETRACOORDINATE PHOSPHORUS 817 # 818 sub _GetAtomTypeForHydrogen { 819 my($This, $Atom) = @_; 820 my($AtomType, $AtomNeighbor); 821 822 $AtomType = 'None'; 823 824 # Get non-hydrogen atom neighbor... 825 $AtomNeighbor = $Atom->GetNonHydrogenNeighborOfHydrogenAtom(); 826 if (!$AtomNeighbor) { 827 return $AtomType; 828 } 829 830 ATOMNEIGHBOR: { 831 if ($AtomNeighbor->IsCarbon()) { 832 $AtomType = $This->_GetAtomTypeForHydrogenAttachedToCarbon($AtomNeighbor); 833 last ATOMNEIGHBOR; 834 } 835 if ($AtomNeighbor->IsNitrogen()) { 836 $AtomType = $This->_GetAtomTypeForHydrogenAttachedToNitrogen($AtomNeighbor); 837 last ATOMNEIGHBOR; 838 } 839 if ($AtomNeighbor->IsOxygen()) { 840 $AtomType = $This->_GetAtomTypeForHydrogenAttachedToOxygen($AtomNeighbor); 841 last ATOMNEIGHBOR; 842 } 843 if ($AtomNeighbor->IsPhosphorus()) { 844 $AtomType = $This->_GetAtomTypeForHydrogenAttachedToPhosphorus($AtomNeighbor); 845 last ATOMNEIGHBOR; 846 } 847 if ($AtomNeighbor->IsSulfur()) { 848 $AtomType = $This->_GetAtomTypeForHydrogenAttachedToSulfur($AtomNeighbor); 849 last ATOMNEIGHBOR; 850 } 851 if ($AtomNeighbor->IsSilicon()) { 852 $AtomType = $This->_GetAtomTypeForHydrogenAttachedToSilicon($AtomNeighbor); 853 last ATOMNEIGHBOR; 854 } 855 $AtomType = "None"; 856 carp "Warning: ${ClassName}->_GetAtomTypeForHydrogen: MMFF94 atom type for Hydrogen cann't be assigned..."; 857 } 858 return $AtomType; 859 } 860 861 # Get MMFF94 atom type for atoms other than Carbon, Nitrogen, Oxygen, Phosporus, 862 # Sulfur and Hydrogen... 863 # 864 # AtomTypeSymbol AtomTypeNum AtomTypeDefinition 865 # LI+ 92 LITHIUM CATION 866 # F 11 FLUORINE 867 # F- 89 FLUORIDE ANION 868 # NA+ 93 SODIUM CATION 869 # MG+2 99 DIPOSITIVE MAGNESIUM CATION 870 # SI 19 SILICON 871 # CL 12 CHLORINE 872 # CLO4 77 CHLORINE IN PERCHLORATE ANION, CLO4(-) 873 # CL- 90 CHLORIDE ANION 874 # K+ 94 POTASSIUM CATION 875 # CA+2 96 DIPOSITIVE CALCIUM 876 # FE+2 87 IRON +2 CATION 877 # FE+3 88 IROM +3 CATION 878 # CU+1 97 MONOPOSITIVE COPPER 879 # CU+2 98 DIPOSITIVE COPPER 880 # ZINC 95 DIPOSITIVE ZINC 881 # ZN+2 95 DIPOSITIVE ZINC 882 # BR 13 BROMINE 883 # BR- 91 BROMIDE ANION 884 # I 14 IODINE 885 # 886 # 887 sub _GetAtomTypeForOtherAtoms { 888 my($This, $Atom) = @_; 889 my($AtomType, $AtomSymbol, $FormalCharge, $CallingMethod, @AllowedFormalCharges); 890 891 $AtomType = 'None'; 892 893 $AtomSymbol = $Atom->GetAtomSymbol(); 894 $FormalCharge = $Atom->GetFormalCharge(); 895 896 $CallingMethod = "_GetAtomTypeForOtherAtoms"; 897 @AllowedFormalCharges = (); 898 899 ATOMSYMBOL: { 900 # FLUORINE 901 if ($AtomSymbol =~ /^F$/i) { 902 # F : FLUORINE; F- : FLUORIDE ANION 903 $AtomType = ($FormalCharge == -1) ? 'F-' : 'F'; 904 @AllowedFormalCharges = ('0', '-1'); 905 last ATOMSYMBOL; 906 } 907 # CHLORINE 908 if ($AtomSymbol =~ /^Cl$/i) { 909 # CL : CHLORINE; CLO4 : CHLORINE IN PERCHLORATE ANION, CLO4(-); 910 # CL- : CHLORIDE ANION 911 $AtomType = $This->_IsPerChlorateAnionChlorine($Atom) ? 'CLO4' : (($FormalCharge == -1) ? 'CL-' : 'CL'); 912 @AllowedFormalCharges = ('0', '-1'); 913 last ATOMSYMBOL; 914 } 915 # BROMINE 916 if ($AtomSymbol =~ /^Br$/i) { 917 # BR : BROMINE; BR- : BROMIDE ANION 918 $AtomType = ($FormalCharge == -1) ? 'BR-' : 'BR'; 919 @AllowedFormalCharges = ('0', '-1'); 920 last ATOMSYMBOL; 921 } 922 # IODINE 923 if ($AtomSymbol =~ /^I$/i) { 924 $AtomType = 'I'; 925 @AllowedFormalCharges = ('0'); 926 last ATOMSYMBOL; 927 } 928 # LI+ : LITHIUM CATION 929 if ($AtomSymbol =~ /^Li$/i) { 930 $AtomType = 'LI+'; 931 @AllowedFormalCharges = ('+1'); 932 last ATOMSYMBOL; 933 } 934 # NA+ : SODIUM CATION 935 if ($AtomSymbol =~ /^Na$/i) { 936 $AtomType = 'NA+'; 937 @AllowedFormalCharges = ('+1'); 938 last ATOMSYMBOL; 939 } 940 # MG+2 : DIPOSITIVE MAGNESIUM CATION 941 if ($AtomSymbol =~ /^Mg$/i) { 942 $AtomType = 'MG+2'; 943 @AllowedFormalCharges = ('+2'); 944 last ATOMSYMBOL; 945 } 946 # SI : SILICON 947 if ($AtomSymbol =~ /^Si$/i) { 948 $AtomType = 'SI'; 949 @AllowedFormalCharges = ('0'); 950 last ATOMSYMBOL; 951 } 952 # K+ : POTASSIUM CATION 953 if ($AtomSymbol =~ /^K$/i) { 954 $AtomType = 'K+'; 955 @AllowedFormalCharges = ('+1'); 956 last ATOMSYMBOL; 957 } 958 # CA+2 : DIPOSITIVE CALCIUM 959 if ($AtomSymbol =~ /^Ca$/i) { 960 $AtomType = 'CA+2'; 961 @AllowedFormalCharges = ('+2'); 962 last ATOMSYMBOL; 963 } 964 # IRON 965 if ($AtomSymbol =~ /^Fe$/i) { 966 # FE+2 : IRON +2 CATION; FE+3 : IROM +3 CATION 967 $AtomType = ($FormalCharge == 3) ? 'FE+3' : 'FE+2'; 968 @AllowedFormalCharges = ('+2', '+3'); 969 last ATOMSYMBOL; 970 } 971 # COPPER 972 if ($AtomSymbol =~ /^Cu$/i) { 973 # CU+1 : MONOPOSITIVE COPPER; CU+2 : DIPOSITIVE COPPER 974 $AtomType = ($FormalCharge == 1) ? 'CU+1' : 'CU+2'; 975 @AllowedFormalCharges = ('+1', '+2'); 976 last ATOMSYMBOL; 977 } 978 # ZINC 979 if ($AtomSymbol =~ /^Zn$/i) { 980 # ZN+2 : DIPOSITIVE ZINC 981 $AtomType = 'Zn+2'; 982 @AllowedFormalCharges = ('+2'); 983 last ATOMSYMBOL; 984 } 985 $AtomType = 'None'; 986 carp "Warning: ${ClassName}->_GetAtomTypeForOtherAtoms: MMFF94 atom type for $AtomSymbol cann't be assigned..."; 987 } 988 if (@AllowedFormalCharges) { 989 $This->_CheckFormalChargeMismatch($CallingMethod, $AtomSymbol, $AtomType, $FormalCharge, \@AllowedFormalCharges); 990 } 991 return $AtomType; 992 } 993 994 # Check any formal charge mismatches... 995 # 996 sub _CheckFormalChargeMismatch { 997 my($This, $CallingMethod, $AtomSymbol, $AssignedAtomType, $FormalCharge, $AllowedFormalChargesRef) = @_; 998 my($AllowedFormalCharge, $FormalChargeMismatch); 999 1000 $FormalChargeMismatch = 1; 1001 1002 FORMALCHARGE: for $AllowedFormalCharge (@{$AllowedFormalChargesRef}) { 1003 if ($AllowedFormalCharge == $FormalCharge) { 1004 $FormalChargeMismatch = 0; 1005 last FORMALCHARGE; 1006 } 1007 } 1008 if ($FormalChargeMismatch) { 1009 my($AllowedFormalCharges); 1010 $AllowedFormalCharges = TextUtil::JoinWords($AllowedFormalChargesRef, ",", 0); 1011 1012 carp "\nWarning: ${ClassName}->${CallingMethod}:_CheckFormalChargeMismatch: MMFF94 atom for $AtomSymbol with formal charge, $FormalCharge, cann't be assigned: Formal charge, $FormalCharge, is different from allowed formal charge(s): $AllowedFormalCharges. Default UFF atom type, $AssignedAtomType, has been assigned..."; 1013 } 1014 1015 return $This; 1016 } 1017 1018 # Get MMFF94 atom type for Carbon with only sigma bonds... 1019 # 1020 sub _GetAtomTypeForCarbonWithOnlySigmaBonds { 1021 my($This, $Atom) = @_; 1022 my($AtomType); 1023 1024 $AtomType = 'None'; 1025 1026 ATOMTYPE: { 1027 # CR4R : CARBON IN 4-MEMBERED RINGS 1028 if ($This->_IsFourMemberedRingCarbon($Atom)) { 1029 $AtomType = 'CR4R'; 1030 last ATOMTYPE; 1031 } 1032 1033 # CR3R : CARBON IN A 3-MEMBERED RING 1034 if ($This->_IsThreeMemberedRingCarbon($Atom)) { 1035 $AtomType = 'CR3R'; 1036 last ATOMTYPE; 1037 } 1038 1039 # CR : ALKYL CARBON, SP3 1040 if ($This->_IsAlkylCarbon($Atom)) { 1041 $AtomType = 'CR'; 1042 last ATOMTYPE; 1043 } 1044 1045 # As far as I can tell, MMFF94 doesn't have a generic atom type for SP3 carbon. So the current 1046 # release of MayaChemTools package used CR as defaul SP3 carbon. 1047 # 1048 $AtomType = 'CR'; 1049 } 1050 1051 return $AtomType; 1052 } 1053 1054 # Get MMFF94 atom type for Carbon with one pi bond... 1055 # 1056 sub _GetAtomTypeForCarbonWithOnePiBond { 1057 my($This, $Atom) = @_; 1058 my($AtomType); 1059 1060 $AtomType = 'None'; 1061 1062 ATOMTYPE: { 1063 # CR3R : CARBON IN 3-MEMBERED RINGS 1064 if ($This->_IsThreeMemberedRingOlefinicCarbon($Atom)) { 1065 $AtomType = 'CR3R'; 1066 last ATOMTYPE; 1067 } 1068 1069 # CE4R : OLEFINIC CARBON IN 4-MEMBERED RINGS 1070 if ($This->_IsFourMemberedRingOlefinicCarbon($Atom)) { 1071 $AtomType = 'CE4R'; 1072 last ATOMTYPE; 1073 } 1074 1075 # CIM+ : C IN N-C-N IN IMIDAZOLIUM ION 1076 if ($This->_IsImidazoliumCarbon($Atom)) { 1077 $AtomType = 'CIM+'; 1078 last ATOMTYPE; 1079 } 1080 1081 # C5A : ALPHA CARBON IN 5-MEMBERED HETEROAROMATIC RING 1082 if ($This->_IsFiveMemberedHeteroAromaticRingAlphaCarbon($Atom)) { 1083 $AtomType = 'C5A'; 1084 last ATOMTYPE; 1085 } 1086 1087 # C5B : BETA CARBON IN 5-MEMBERED HETEROAROMATIC RING 1088 if ($This->_IsFiveMemberedHeteroAromaticRingBetaCarbon($Atom)) { 1089 $AtomType = 'C5B'; 1090 last ATOMTYPE; 1091 } 1092 1093 # C5 : GENERAL CARBON IN 5-MEMBERED HETEROAROMATIC RING 1094 if ($This->_IsFiveMemberedHeteroAromaticRingCarbon($Atom)) { 1095 $AtomType = 'C5'; 1096 last ATOMTYPE; 1097 } 1098 1099 # CB : CARBON AS IN BENZENE, PYRROLE 1100 if ($This->_IsRingAromaticCarbon($Atom)) { 1101 $AtomType = 'CB'; 1102 last ATOMTYPE; 1103 } 1104 1105 # C=C : VINYLIC CARBON, SP2 1106 if ($This->_IsVinylicCarbon($Atom)) { 1107 $AtomType = 'C=C'; 1108 last ATOMTYPE; 1109 } 1110 1111 # C=OR : KETONE OR ALDEHYDE CARBONYL CARBON 1112 if ($This->_IsKetoneOrAldehydeCarbonylCarbon($Atom)) { 1113 $AtomType = 'C=OR'; 1114 last ATOMTYPE; 1115 } 1116 1117 # C=ON : AMIDE CARBONYL CARBON 1118 if ($This->_IsAmideCarbonylCarbon($Atom)) { 1119 $AtomType = 'C=ON'; 1120 last ATOMTYPE; 1121 } 1122 1123 # CONN : UREA CARBONYL CARBON 1124 if ($This->_IsUreaCarbonylCarbon($Atom)) { 1125 $AtomType = 'CONN'; 1126 last ATOMTYPE; 1127 } 1128 1129 # COO : CARBOXYLIC ACID OR ESTER CARBONYL CARBON 1130 if ($This->_IsCarboxylicAcidOrEsterCarbonylCarbon($Atom)) { 1131 $AtomType = 'COO'; 1132 last ATOMTYPE; 1133 } 1134 1135 # CO2M : CARBOXYLATE ANION CARBON 1136 if ($This->_IsCarboxylateAnionCarbon($Atom)) { 1137 $AtomType = 'CO2M'; 1138 last ATOMTYPE; 1139 } 1140 1141 # COON: CARBAMATE CARBONYL CARBON 1142 if ($This->_IsCarbamateCarbonylCarbon($Atom)) { 1143 $AtomType = 'COON'; 1144 last ATOMTYPE; 1145 } 1146 1147 # COOO: CARBONIC ACID OR ESTER CARBONYL CARBON 1148 if ($This->_IsCarbonicAcidOrEsterCarbonylCarbon($Atom)) { 1149 $AtomType = 'COOO'; 1150 last ATOMTYPE; 1151 } 1152 1153 # C=OS : THIOESTER CARBONYL CARBON, DOUBLE BONDED TO O 1154 if ($This->_IsThioEsterCarbonylCarbon($Atom)) { 1155 $AtomType = 'C=OS'; 1156 last ATOMTYPE; 1157 } 1158 1159 # C=O : GENERAL CARBONYL CARBON 1160 if ($This->_IsGeneralCarbonylCarbon($Atom)) { 1161 $AtomType = 'C=O'; 1162 last ATOMTYPE; 1163 } 1164 1165 # C=SN : THIOAMIDE, CARBON, DOUBLY BONDED TO S 1166 if ($This->_IsThioAmideCarbon($Atom)) { 1167 $AtomType = 'C=SN'; 1168 last ATOMTYPE; 1169 } 1170 1171 # CSO2 : CARBON IN >C=SO2 1172 if ($This->_IsSulfonylCarbon($Atom)) { 1173 $AtomType = 'CSO2'; 1174 last ATOMTYPE; 1175 } 1176 1177 # CS=O : CARBON IN >C=S=O (SULFINYL GROUP) 1178 if ($This->_IsSulfinylCarbon($Atom)) { 1179 $AtomType = 'CS=O'; 1180 last ATOMTYPE; 1181 } 1182 1183 # CSS : THIOCARBOXYLIC ACID OR ESTER CARBONYL CARBON 1184 if ($This->_IsThioCarboxylicAcidOrEsterCarbonylCarbon($Atom)) { 1185 $AtomType = 'CSS'; 1186 last ATOMTYPE; 1187 } 1188 1189 # CS2M : CARBON IN THIOCARBOXYLATE ANION 1190 if ($This->_IsThioCarboxylateAnionCarbon($Atom)) { 1191 $AtomType = 'CS2M'; 1192 last ATOMTYPE; 1193 } 1194 1195 # C=S : THIOESTER CARBON, DOUBLY BONDED TO S 1196 if ($This->_IsThioEsterCarbon($Atom)) { 1197 $AtomType = 'C=S'; 1198 last ATOMTYPE; 1199 } 1200 1201 # C=P : CARBON DOUBLE BONDED TO PHOSPHOROUS 1202 if ($This->_IsDoublyBondedToPhosphorousCarbon($Atom)) { 1203 $AtomType = 'C=P'; 1204 last ATOMTYPE; 1205 } 1206 1207 # CGD : GUANIDINE CARBON, DOUBLY BONDED TO N 1208 if ($This->_IsGuandineCarbon($Atom)) { 1209 $AtomType = 'CGD'; 1210 last ATOMTYPE; 1211 } 1212 1213 # CGD+ : GUANIDINIUM CARBON 1214 if ($This->_IsGuandiniumCarbon($Atom)) { 1215 $AtomType = 'CGD+'; 1216 last ATOMTYPE; 1217 } 1218 1219 #CNN+ : C IN +N=C-N RESONANCE STRUCTURES 1220 if ($This->_IsNCNResonaceStructuresCarbon($Atom)) { 1221 $AtomType = 'CNN+'; 1222 last ATOMTYPE; 1223 } 1224 1225 # C=N : SP2 CARBON IN C=N 1226 if ($This->_IsDoublyBondedToNitrogenSP2Carbon($Atom)) { 1227 $AtomType = 'C=N'; 1228 last ATOMTYPE; 1229 } 1230 1231 # CSP2 : GENERIC SP2 CARBON 1232 if ($This->_IsGenericSP2Carbon($Atom)) { 1233 $AtomType = 'CSP2'; 1234 last ATOMTYPE; 1235 } 1236 1237 $AtomType = 'CSP2'; 1238 carp "Warning: ${ClassName}->_GetAtomTypeForCarbonWithOnePiBond: MMFF94 atom type for Carbon cann't be assigned; Default MMFF94 atom type, $AtomType, has been assigned...\n"; 1239 } 1240 1241 return $AtomType; 1242 } 1243 1244 # Get MMFF94 atom type for Carbon with two pi bonds... 1245 # 1246 sub _GetAtomTypeForCarbonWithTwoPiBonds { 1247 my($This, $Atom) = @_; 1248 my($AtomType); 1249 1250 $AtomType = 'None'; 1251 1252 ATOMTYPE: { 1253 # =C= : ALLENIC CARBON 1254 if ($This->_IsAllenicCarbon($Atom)) { 1255 $AtomType = '=C='; 1256 last ATOMTYPE; 1257 } 1258 1259 # C% : ISONITRILE CARBON ( R-N+#C- ) 1260 if ($This->_IsIsoNitrileCarbon($Atom)) { 1261 $AtomType = 'C%'; 1262 last ATOMTYPE; 1263 } 1264 1265 # CSP : ACETYLENIC CARBON 1266 if ($This->_IsAcetylenicCarbon($Atom)) { 1267 $AtomType = 'CSP'; 1268 last ATOMTYPE; 1269 } 1270 1271 $AtomType = 'CSP'; 1272 carp "Warning: ${ClassName}->_GetAtomTypeForCarbonWithTwoPiBonds: MMFF94 atom type for Carbon cann't be assigned; Default MMFF94 atom type, $AtomType, has been assigned...\n"; 1273 } 1274 1275 return $AtomType; 1276 } 1277 1278 1279 # CR4R : CARBON IN 4-MEMBERED RINGS 1280 # 1281 sub _IsFourMemberedRingCarbon { 1282 my($This, $Atom) = @_; 1283 1284 return $Atom->DoesAtomNeighborhoodMatch('C.RA4.T4.TSB4') ? 1 : 0; 1285 } 1286 1287 # CR4R : CARBON IN 3-MEMBERED RINGS 1288 # 1289 sub _IsThreeMemberedRingCarbon { 1290 my($This, $Atom) = @_; 1291 1292 return $Atom->DoesAtomNeighborhoodMatch('C.RA3.T4.TSB4') ? 1 : 0; 1293 } 1294 1295 # CR : ALKYL CARBON, SP3 1296 # 1297 sub _IsAlkylCarbon { 1298 my($This, $Atom) = @_; 1299 1300 return $Atom->DoesAtomNeighborhoodMatch('C.T4.TSB4', ['C,H', 'C,H', 'C,H', 'C,H'], ['-', '-', '-', '-']) ? 1 : 0; 1301 } 1302 1303 # C5A : ALPHA CARBON IN 5-MEMBERED HETEROAROMATIC RING 1304 # 1305 sub _IsFiveMemberedHeteroAromaticRingAlphaCarbon { 1306 my($This, $Atom) = @_; 1307 1308 # Is it an aromatic atom in a five membered ring? 1309 if (!$Atom->DoesAtomNeighborhoodMatch('C.Ar.RA5')) { 1310 return 0; 1311 } 1312 1313 # Is it part of a five membered ring containing hetero atom at alpha position? 1314 my($RingAtomsRef); 1315 1316 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 1317 if ($This->_IsAtomPositionAlphaInHeteroAromaticRing($Atom, $RingAtomsRef)) { 1318 return 1; 1319 } 1320 } 1321 return 0; 1322 } 1323 1324 # C5B : BETA CARBON IN 5-MEMBERED HETEROAROMATIC RING 1325 # 1326 sub _IsFiveMemberedHeteroAromaticRingBetaCarbon { 1327 my($This, $Atom) = @_; 1328 1329 # Is it an aromatic atom in a five membered ring? 1330 if (!$Atom->DoesAtomNeighborhoodMatch('C.Ar.RA5')) { 1331 return 0; 1332 } 1333 1334 # Is it part of five membered rings containing hetero atom at beta position? 1335 my($RingAtomsRef); 1336 1337 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 1338 if ($This->_IsAtomPositionBetaInHeteroAromaticRing($Atom, $RingAtomsRef)) { 1339 return 1; 1340 } 1341 } 1342 return 0; 1343 } 1344 1345 1346 # C5 : GENERAL CARBON IN 5-MEMBERED HETEROAROMATIC RING 1347 # 1348 sub _IsFiveMemberedHeteroAromaticRingCarbon { 1349 my($This, $Atom) = @_; 1350 1351 # Is it an aromatic atom in a five membered ring? 1352 if (!$Atom->DoesAtomNeighborhoodMatch('C.Ar.RA5')) { 1353 return 0; 1354 } 1355 1356 # Is it part of five membered rings containing at least one hetero atom? 1357 my($RingAtomsRef, $RingIsAromatic, $NumOfHeteroAtoms); 1358 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 1359 ($RingIsAromatic, $NumOfHeteroAtoms) = $This->_GetHeteroAtomsInformationInRing($RingAtomsRef); 1360 if ($RingIsAromatic && $NumOfHeteroAtoms >= 1) { 1361 return 1; 1362 } 1363 } 1364 return 0; 1365 } 1366 1367 # CR3R : OLEFINIC CARBON IN 3-MEMBERED RINGS 1368 # 1369 # Notes: 1370 # . MMFF94 atom type for olefinic Carbon in 3-membered rings is same as SP3 Carbon. 1371 # 1372 sub _IsThreeMemberedRingOlefinicCarbon { 1373 my($This, $Atom) = @_; 1374 1375 return $Atom->DoesAtomNeighborhoodMatch('C.RA3.T3.DB1', ['*', '*', '*'], ['=', '-', '-']) ? 1 : 0; 1376 } 1377 1378 # CE4R : OLEFINIC CARBON IN 4-MEMBERED RINGS 1379 # 1380 sub _IsFourMemberedRingOlefinicCarbon { 1381 my($This, $Atom) = @_; 1382 1383 return $Atom->DoesAtomNeighborhoodMatch('C.RA4.T3.DB1', ['*', '*', '*'], ['=', '-', '-']) ? 1 : 0; 1384 } 1385 1386 # CB : CARBON AS IN BENZENE, PYRROLE 1387 # 1388 # Notes: 1389 # . MayaChemTools assigns all aromatic carbons, other than five membered 1390 # hetero aromatic ring Carbons, as CB. 1391 # 1392 sub _IsRingAromaticCarbon { 1393 my($This, $Atom) = @_; 1394 1395 return ($Atom->DoesAtomNeighborhoodMatch('C.Ar.RA')) ? 1 : 0; 1396 } 1397 1398 # C=C : VINYLIC CARBON, SP2 1399 # 1400 sub _IsVinylicCarbon { 1401 my($This, $Atom) = @_; 1402 1403 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['C', '*', '*'], ['=', '-', '-'], ['C,H', 'C,H', 'C,H']) ? 1 : 0; 1404 } 1405 1406 # C=OR : KETONE OR ALDEHYDE CARBONYL CARBON 1407 # 1408 sub _IsKetoneOrAldehydeCarbonylCarbon { 1409 my($This, $Atom) = @_; 1410 1411 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['O', 'C,H', 'C,H'], ['=', '-', '-']) ? 1 : 0; 1412 } 1413 1414 # C=ON : AMIDE CARBONYL CARBON 1415 # 1416 sub _IsAmideCarbonylCarbon { 1417 my($This, $Atom) = @_; 1418 1419 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['O', 'N', 'C,H'], ['=', '-', '-']) ? 1 : 0; 1420 } 1421 1422 # CONN : UREA CARBONYL CARBON : R-(R'-)N-C(=O)-N(-R")-R''' 1423 # 1424 sub _IsUreaCarbonylCarbon { 1425 my($This, $Atom) = @_; 1426 1427 return $Atom->DoesAtomNeighborhoodMatch('C.X3.DB1', ['O', 'N', 'N'], ['=', '-', '-']) ? 1 : 0; 1428 } 1429 1430 # COO : CARBOXYLIC ACID OR ESTER CARBONYL CARBON 1431 # 1432 sub _IsCarboxylicAcidOrEsterCarbonylCarbon { 1433 my($This, $Atom) = @_; 1434 1435 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['O', 'O.X1.FC0,O.X2', 'C,H'], ['=', '-', '-'], ['C', 'C,H', 'C,H']) ? 1 : 0; 1436 } 1437 1438 # CO2M : CARBOXYLATE ANION CARBON 1439 # 1440 sub _IsCarboxylateAnionCarbon { 1441 my($This, $Atom) = @_; 1442 1443 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['O', 'O.X1.FC-1', 'C,H'], ['=', '-', '-'], ['C', 'C,H', 'C,H']) ? 1 : 0; 1444 } 1445 1446 # COON: CARBAMATE CARBONYL CARBON : R-O-C(=O)-N(-R')-R" 1447 # 1448 sub _IsCarbamateCarbonylCarbon { 1449 my($This, $Atom) = @_; 1450 1451 return $Atom->DoesAtomNeighborhoodMatch('C.X3.DB1', ['O', 'O', 'N'], ['=', '-', '-']) ? 1 : 0; 1452 } 1453 1454 # COOO: CARBONIC ACID OR ESTER CARBONYL CARBON: R-O-C(=O)-O-R' 1455 # 1456 sub _IsCarbonicAcidOrEsterCarbonylCarbon { 1457 my($This, $Atom) = @_; 1458 1459 return $Atom->DoesAtomNeighborhoodMatch('C.X3.DB1', ['O', 'O', 'O'], ['=', '-', '-']) ? 1 : 0; 1460 } 1461 1462 # C=OS : THIOESTER CARBONYL CARBON, DOUBLE BONDED TO O 1463 # 1464 sub _IsThioEsterCarbonylCarbon { 1465 my($This, $Atom) = @_; 1466 1467 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['O', 'S', 'C,H'], ['=', '-', '-']) ? 1 : 0; 1468 } 1469 1470 # C=O : GENERAL CARBONYL CARBON 1471 # 1472 sub _IsGeneralCarbonylCarbon { 1473 my($This, $Atom) = @_; 1474 1475 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['O', '*', '*'], ['=', '-', '-']) ? 1 : 0; 1476 } 1477 1478 # C=SN : THIOAMIDE, CARBON, DOUBLY BONDED TO S 1479 # 1480 sub _IsThioAmideCarbon { 1481 my($This, $Atom) = @_; 1482 1483 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['S', 'N', 'C,H'], ['=', '-', '-']) ? 1 : 0; 1484 } 1485 1486 # CSO2 : CARBON IN >C=SO2 1487 # 1488 sub _IsSulfonylCarbon { 1489 my($This, $Atom) = @_; 1490 my($AtomNeighbor); 1491 1492 # Is it connected to a sulfone Sulfur? 1493 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S')) { 1494 if ($This->_IsDoublyBondedToCarbonSulfoneSulfur($AtomNeighbor)) { 1495 return 1; 1496 } 1497 } 1498 return 0; 1499 } 1500 1501 1502 # CS=O : CARBON IN >C=S=O (SULFINYL GROUP) 1503 # 1504 sub _IsSulfinylCarbon { 1505 my($This, $Atom) = @_; 1506 my($AtomNeighbor); 1507 1508 # Is it connected to a sulfinyl Sulfur? 1509 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S')) { 1510 if ($This->_IsSulfinylSulfur($AtomNeighbor)) { 1511 return 1; 1512 } 1513 } 1514 return 0; 1515 } 1516 1517 # CSS : THIOCARBOXYLIC ACID OR ESTER CARBONYL CARBON 1518 # 1519 sub _IsThioCarboxylicAcidOrEsterCarbonylCarbon { 1520 my($This, $Atom) = @_; 1521 1522 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['S', 'S.X1.FC0,S.X2', 'C,H'], ['=', '-', '-'], ['C', 'C,H', 'C,H']) ? 1 : 0; 1523 } 1524 1525 # CS2M : CARBON IN THIOCARBOXYLATE ANION 1526 # 1527 sub _IsThioCarboxylateAnionCarbon { 1528 my($This, $Atom) = @_; 1529 1530 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['S', 'S.X1.FC-1', 'C,H'], ['=', '-', '-'], ['C', 'C,H', 'C,H']) ? 1 : 0; 1531 } 1532 1533 # C=S : THIOESTER CARBON, DOUBLY BONDED TO S 1534 # 1535 sub _IsThioEsterCarbon { 1536 my($This, $Atom) = @_; 1537 1538 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['S.X1', '*', '*'], ['=', '-', '-']) ? 1 : 0; 1539 } 1540 1541 # C=P : CARBON DOUBLE BONDED TO PHOSPHOROUS 1542 # 1543 sub _IsDoublyBondedToPhosphorousCarbon { 1544 my($This, $Atom) = @_; 1545 1546 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['P.X1', '*', '*'], ['=', '-', '-']) ? 1 : 0; 1547 } 1548 1549 # CIM+ : C IN N-C-N IN IMIDAZOLIUM ION 1550 # 1551 # Notes: 1552 # . Imidazole is five membered ring contain C*=C-N-C=N* (* - Ring bond) 1553 # . Imidazolium ion is where N in C=N has a formal charge of +1 and has an extra substituent 1554 # 1555 sub _IsImidazoliumCarbon { 1556 my($This, $Atom) = @_; 1557 1558 # Is it in a 5 membered aromatic ring surrounded by two aromatic Nitrogens? 1559 # 1560 if (!($Atom->DoesAtomNeighborhoodMatch('C.Ar.RA5.TR1', ['N.Ar.RA5.TR1.FC0', 'N.Ar.RA5.TR1.FC+1'], ['-', '=']) || 1561 $Atom->DoesAtomNeighborhoodMatch('C.Ar.RA5.TR1', ['N.Ar.RA5.TR1.!FC0', 'N.Ar.RA5.TR1.!FC0'], ['-', '=']))) { 1562 return 0; 1563 } 1564 1565 # Check to make sure ring contains only two Nitrogen hetero atom... 1566 my($RingAtomsRef, $RingIsAromatic, $NumOfHeteroAtoms, $HeteroAtomSymbolsRef); 1567 1568 ($RingAtomsRef) = $Atom->GetRingsWithSize(5); 1569 ($RingIsAromatic, $NumOfHeteroAtoms, $HeteroAtomSymbolsRef) = $This->_GetHeteroAtomsInformationInRing($RingAtomsRef); 1570 1571 if ($NumOfHeteroAtoms != 2) { 1572 return 0; 1573 } 1574 1575 return (exists($HeteroAtomSymbolsRef->{N}) && ($HeteroAtomSymbolsRef->{N} == 2)) ? 1 : 0; 1576 } 1577 1578 # CNN+ : C IN +N=C-N RESONANCE STRUCTURES 1579 # 1580 sub _IsNCNResonaceStructuresCarbon { 1581 my($This, $Atom) = @_; 1582 1583 # Match +1 formal charge on Nitrogen... 1584 if ($Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['N.FC+1', 'N.FC0'], ['=', '-'])) { 1585 return 1; 1586 } 1587 1588 # Match non-zero (+1/2) formal charge on Nitrogen with single, double or resonnace bonds... 1589 if ($Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['N.!FC0', 'N.!FC0'], ['-,=,:', '-,=,:'])) { 1590 return 1; 1591 } 1592 1593 return 0; 1594 } 1595 1596 # CGD : GUANIDINE CARBON, DOUBLY BONDED TO N 1597 # 1598 sub _IsGuandineCarbon { 1599 my($This, $Atom) = @_; 1600 1601 return $Atom->DoesAtomNeighborhoodMatch('C.X3.DB1', ['N.FC0', 'N.FC0', 'N.FC0'], ['=', '-', '-']) ? 1 : 0; 1602 } 1603 1604 # CGD+ : GUANIDINIUM CARBON 1605 # 1606 sub _IsGuandiniumCarbon { 1607 my($This, $Atom) = @_; 1608 1609 # Match +1 formal charge on a Nitrogen with explicitly single and double bonds... 1610 if ($Atom->DoesAtomNeighborhoodMatch('C.X3.DB1', ['N.FC+1', 'N.FC0', 'N.FC0'], ['=', '-', '-'])) { 1611 return 1; 1612 } 1613 1614 # Match +1/3 formal charge on each Nitrogen with single, double or resonance bonds... 1615 if ($Atom->DoesAtomNeighborhoodMatch('C.X3.DB1', ['N.!FC0', 'N.!FC0', 'N.!FC0'], ['-,=,:', '-,=,:', '-,=,:'])) { 1616 return 1; 1617 } 1618 1619 return 0; 1620 } 1621 1622 # C=N : SP2 CARBON IN C=N 1623 # 1624 sub _IsDoublyBondedToNitrogenSP2Carbon { 1625 my($This, $Atom) = @_; 1626 1627 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['N', '*', '*'], ['=', '-', '-']) ? 1 : 0; 1628 } 1629 1630 # CSP2 : GENERIC SP2 CARBON 1631 # 1632 sub _IsGenericSP2Carbon { 1633 my($This, $Atom) = @_; 1634 1635 return $Atom->DoesAtomNeighborhoodMatch('C.T3.DB1', ['*', '*', '*'], ['=', '-', '-']) ? 1 : 0; 1636 } 1637 1638 # =C= : ALLENIC CARBON 1639 # 1640 sub _IsAllenicCarbon { 1641 my($This, $Atom) = @_; 1642 1643 return $Atom->DoesAtomNeighborhoodMatch('C.X2.DB2', ['*', '*'], ['=', '=']) ? 1 : 0; 1644 } 1645 1646 # C% : ISONITRILE CARBON ( R-N+#C- ) 1647 # 1648 sub _IsIsoNitrileCarbon { 1649 my($This, $Atom) = @_; 1650 1651 return $Atom->DoesAtomNeighborhoodMatch('C.X1.TB1.FC-1', ['N.T2.TB1.FC+1'], ['#'], ['C,H']) ? 1 : 0; 1652 } 1653 1654 # CSP : ACETYLENIC CARBON 1655 # 1656 sub _IsAcetylenicCarbon { 1657 my($This, $Atom) = @_; 1658 1659 return $Atom->DoesAtomNeighborhoodMatch('C.T2.TB1', ['*', '*'], ['#', '-']) ? 1 : 0; 1660 } 1661 1662 # Get MMFF94 atom type Nitrogen in five membered ring... 1663 # 1664 # Note: 1665 # . The method handles both SP3 and SP2 five membered ring Nitrogens. 1666 # 1667 sub _GetAtomTypeForFiveMemberedRingNitrogen { 1668 my($This, $Atom) = @_; 1669 my($AtomType); 1670 1671 $AtomType = 'None'; 1672 1673 ATOMTYPE: { 1674 1675 # NIM+ : IMIDAZOLIUM-TYPE NITROGEN - FORMAL CHARGE=1/2 1676 if ($This->_IsImidazoliumNitrogen($Atom)) { 1677 $AtomType = 'NIM+'; 1678 last ATOMTYPE; 1679 } 1680 1681 # N5A+ : POSITIVE N5A NITROGEN - FORMAL CHARGE=1 1682 if ($This->_IsPositivelyChargedFiveMemberedHeteroAromaticRingAlphaNitrogen($Atom)) { 1683 $AtomType = 'N5A+'; 1684 last ATOMTYPE; 1685 } 1686 1687 # N5A : ALPHA AROM HETEROCYCLIC 5-RING NITROGEN 1688 if ($This->_IsFiveMemberedHeteroAromaticRingAlphaNitrogen($Atom)) { 1689 $AtomType = 'N5A'; 1690 last ATOMTYPE; 1691 } 1692 1693 # N5B+ : POSITIVE N5B NITROGEN - FORMAL CHARGE=1 1694 if ($This->_IsPositivelyChargedFiveMemberedHeteroAromaticRingBetaNitrogen($Atom)) { 1695 $AtomType = 'N5B+'; 1696 last ATOMTYPE; 1697 } 1698 1699 # N5B : BETA AROM HETEROCYCLIC 5-RING NITROGEN 1700 if ($This->_IsFiveMemberedHeteroAromaticRingBetaNitrogen($Atom)) { 1701 $AtomType = 'N5B'; 1702 last ATOMTYPE; 1703 } 1704 1705 # N5AX : N-OXIDE NITROGEN IN 5-RING ALPHA POSITION 1706 if ($This->_IsNOxideFiveMemberedHeteroCyclicRingAlphaNitrogen($Atom)) { 1707 $AtomType = 'N5AX'; 1708 last ATOMTYPE; 1709 } 1710 1711 # N5BX : N-OXIDE NITROGEN IN 5-RING BETA POSITION 1712 if ($This->_IsNOxideFiveMemberedHeteroCyclicRingBetaNitrogen($Atom)) { 1713 $AtomType = 'N5BX'; 1714 last ATOMTYPE; 1715 } 1716 1717 # N5OX : N-OXIDE NITROGEN IN GENERAL 5-RING POSITION 1718 if ($This->_IsNOxideFiveMemberedHeteroCyclicRingNitrogen($Atom)) { 1719 $AtomType = 'N5OX'; 1720 last ATOMTYPE; 1721 } 1722 1723 # N5M : NEGATIVELY CHARGED N IN, E.G, TRI- OR TETRAZOLE ANION 1724 if ($This->_IsNegativelyChargedFiveMemberedHeteroCyclicRingNitrogen($Atom)) { 1725 $AtomType = 'N5M'; 1726 last ATOMTYPE; 1727 } 1728 1729 # N5+ : POSITIVE N5 NITROGEN - FORMAL CHARGE=1 1730 if ($This->_IsPositivelyChargedFiveMemberedHeteroCyclicRingNitrogen($Atom)) { 1731 $AtomType = 'N5+'; 1732 last ATOMTYPE; 1733 } 1734 1735 # N5 : GENERAL NITROGEN IN 5-MEMBERED HETEROCYCLIC RING 1736 if ($This->_IsFiveMemberedHeteroCyclicRingNitrogen($Atom)) { 1737 $AtomType = 'N5'; 1738 last ATOMTYPE; 1739 } 1740 1741 $AtomType = 'N5'; 1742 } 1743 1744 return $AtomType; 1745 } 1746 1747 # Get MMFF94 atom type for Nitrogen with only sigma bonds... 1748 # 1749 sub _GetAtomTypeForNitrogenWithOnlySigmaBonds { 1750 my($This, $Atom) = @_; 1751 my($AtomType); 1752 1753 $AtomType = 'None'; 1754 1755 ATOMTYPE: { 1756 1757 # NPYL : NITROGEN, AS IN PYRROLE 1758 if ($This->_IsPyrroleNitrogen($Atom)) { 1759 $AtomType = 'NPYL'; 1760 last ATOMTYPE; 1761 } 1762 1763 # NC=O : NITROGEN IN AMIDES 1764 if ($This->_IsAmideNitrogen($Atom)) { 1765 $AtomType = 'NC=O'; 1766 last ATOMTYPE; 1767 } 1768 1769 # NC=S : NITROGEN IN N-C=S, THIOAMIDE 1770 if ($This->_IsThioAmideNitrogen($Atom)) { 1771 $AtomType = 'NC=S'; 1772 last ATOMTYPE; 1773 } 1774 1775 # NN=C : NITROGEN IN N-N=C 1776 if ($This->_IsNNCNitrogen($Atom)) { 1777 $AtomType = 'NN=C'; 1778 last ATOMTYPE; 1779 } 1780 1781 # NGD+ : GUANIDINIUM-TYPE NITROGEN - FORMAL CHARGE=1/3 1782 if ($This->_IsGuanidiniumNitrogen($Atom)) { 1783 $AtomType = 'NGD+'; 1784 last ATOMTYPE; 1785 } 1786 1787 # NCN+ : N IN +N=C-N RESONANCE STRUCTURES - FORMAL CHARGE=1/2 1788 if ($This->_IsNCNResonaceStructuresNitrogen($Atom)) { 1789 $AtomType = 'NCN+'; 1790 last ATOMTYPE; 1791 } 1792 1793 # NN=N : NITROGEN IN N-N=N 1794 if ($This->_IsNNNNitrogen($Atom)) { 1795 $AtomType = 'NN=N'; 1796 last ATOMTYPE; 1797 } 1798 1799 # NC=C : NITROGEN ON N-C=C 1800 if ($This->_IsNCCNitrogen($Atom)) { 1801 $AtomType = 'NC=C'; 1802 last ATOMTYPE; 1803 } 1804 1805 # NC=N : NITROGEN IN N-C=N 1806 if ($This->_IsNCNNitrogen($Atom)) { 1807 $AtomType = 'NC=N'; 1808 last ATOMTYPE; 1809 } 1810 1811 # NC=P : NITROGEN IN N-C=P 1812 if ($This->_IsNCPNitrogen($Atom)) { 1813 $AtomType = 'NC=P'; 1814 last ATOMTYPE; 1815 } 1816 1817 # NM : DEPROTONATED SULFONAMIDE N-; FORMAL CHARGE=-1 1818 if ($This->_IsDeprotonatedSulfonamideNitrogen($Atom)) { 1819 $AtomType = 'NM'; 1820 last ATOMTYPE; 1821 } 1822 1823 # NSO2 : NITROGEN IN SULFONAMIDES 1824 if ($This->_IsNSO2SulfonamideNitrogen($Atom)) { 1825 $AtomType = 'NSO2'; 1826 last ATOMTYPE; 1827 } 1828 1829 # NSO3 : NITROGEN IN SULFONAMIDES, THREE Os ON S 1830 if ($This->_IsNSO3SulfonamideNitrogen($Atom)) { 1831 $AtomType = 'NSO3'; 1832 last ATOMTYPE; 1833 } 1834 1835 # NPO2 : NITROGEN IN PHOSPHONAMIDES 1836 if ($This->_IsNPO2PhosphonamideNitrogen($Atom)) { 1837 $AtomType = 'NPO2'; 1838 last ATOMTYPE; 1839 } 1840 1841 # NPO3 : NITROGEN IN PHOSPHONAMIDES, THREE Os ON P 1842 if ($This->_IsNPO3PhosphonamideNitrogen($Atom)) { 1843 $AtomType = 'NPO3'; 1844 last ATOMTYPE; 1845 } 1846 1847 # NC%N : NITROGEN ATTACHED TO CYANO GROUP 1848 if ($This->_IsAttachedToCyanoNitrogen($Atom)) { 1849 $AtomType = 'NC%N'; 1850 last ATOMTYPE; 1851 } 1852 1853 # N3OX : SP3-HYDRIDIZED N-OXIDE NITROGEN 1854 if ($This->_IsSP3NOxideNitrogen($Atom)) { 1855 $AtomType = 'N3OX'; 1856 last ATOMTYPE; 1857 } 1858 1859 # NC%C : NITROGEN ATTACHED TO C-C TRIPLE BOND 1860 if ($This->_IsAttchedToCCTripleBondNitrogen($Atom)) { 1861 $AtomType = 'NC%C'; 1862 last ATOMTYPE; 1863 } 1864 1865 # NR : NITROGEN IN ALIPHATIC AMINES 1866 if ($This->_IsAliphaticAmineNitrogen($Atom)) { 1867 $AtomType = 'NR'; 1868 last ATOMTYPE; 1869 } 1870 1871 # NR+ : QUATERNARY NITROGEN, SP3, POSITIVELY CHARGED 1872 if ($This->_IsAliphaticAmineQuaternaryNitrogen($Atom)) { 1873 $AtomType = 'NR+'; 1874 last ATOMTYPE; 1875 } 1876 1877 $AtomType = 'NR'; 1878 } 1879 1880 return $AtomType; 1881 } 1882 1883 # Get MMFF94 atom type for Nitrogen with one pi bond... 1884 # 1885 sub _GetAtomTypeForNitrogenWithOnePiBond { 1886 my($This, $Atom) = @_; 1887 my($AtomType); 1888 1889 $AtomType = 'None'; 1890 1891 ATOMTYPE: { 1892 1893 # NPOX : PYRIDINE N-OXIDE NITROGEN 1894 if ($This->_IsPyridineNOxideNitrogen($Atom)) { 1895 $AtomType = 'NPOX'; 1896 last ATOMTYPE; 1897 } 1898 1899 # NPD+ : PYRIDINIUM-TYPE NITROGEN - FORMAL CHARGE=1 1900 if ($This->_IsPyridiniumNitrogen($Atom)) { 1901 $AtomType = 'NPD+'; 1902 last ATOMTYPE; 1903 } 1904 1905 # NPYD : NITROGEN, AS IN PYRIDINE 1906 if ($This->_IsPyridineNitrogen($Atom)) { 1907 $AtomType = 'NPYD'; 1908 last ATOMTYPE; 1909 } 1910 1911 # N2OX : SP2-HYDRIDIZED N-OXIDE NITROGEN 1912 if ($This->_IsSP2NOxideNitrogen($Atom)) { 1913 $AtomType = 'N2OX'; 1914 last ATOMTYPE; 1915 } 1916 1917 # NAZT : TERMINAL NITROGEN IN AZIDO OR DIAZO GROUP 1918 if ($This->_IsNAZTNitrogen($Atom)) { 1919 $AtomType = 'NAZT'; 1920 last ATOMTYPE; 1921 } 1922 1923 # NR% : ISONITRILE NITROGEN [FC = 0] OR DIAZO NITROGEN [FC = 1] 1924 if ($This->_IsIsoNitrileOrDiAzoNitrogen($Atom)) { 1925 $AtomType = 'NR%'; 1926 last ATOMTYPE; 1927 } 1928 1929 # NGD+ : GUANIDINIUM-TYPE NITROGEN - FORMAL CHARGE=1/3 1930 if ($This->_IsGuanidiniumNitrogen($Atom)) { 1931 $AtomType = 'NGD+'; 1932 last ATOMTYPE; 1933 } 1934 1935 # NCN+ : N IN +N=C-N RESONANCE STRUCTURES - FORMAL CHARGE=1/2 1936 if ($This->_IsNCNResonaceStructuresNitrogen($Atom)) { 1937 $AtomType = 'NCN+'; 1938 last ATOMTYPE; 1939 } 1940 1941 # N=C : NITROGEN IN IMINES 1942 if ($This->_IsImineNitrogen($Atom)) { 1943 $AtomType = 'N=C'; 1944 last ATOMTYPE; 1945 } 1946 1947 # N+=C : POSITIVELY CHARGED IMINIUM NITROGEN 1948 if ($This->_IsPositivelyChargedIminiumNitrogen($Atom)) { 1949 $AtomType = 'N+=C'; 1950 last ATOMTYPE; 1951 } 1952 1953 # N=N : NITROGEN IN AZO COMPOUNDS 1954 if ($This->_IsAzoNitrogen($Atom)) { 1955 $AtomType = 'N=N'; 1956 last ATOMTYPE; 1957 } 1958 1959 # N+=N : POSITIVELY CHARGED NITROGEN DOUBLE-BONDED TO N 1960 if ($This->_IsPositivelyChargedAzoNitrogen($Atom)) { 1961 $AtomType = 'N+=N'; 1962 last ATOMTYPE; 1963 } 1964 1965 # NO2 : NITRO GROUP NITROGEN 1966 if ($This->_IsNitroNitrogen($Atom)) { 1967 $AtomType = 'NO2'; 1968 last ATOMTYPE; 1969 } 1970 1971 # NO3 : NITRATE GROUP NITROGEN 1972 if ($This->_IsNitrateNitrogen($Atom)) { 1973 $AtomType = 'NO3'; 1974 last ATOMTYPE; 1975 } 1976 1977 # N=O : NITROSO NITROGEN 1978 if ($This->_IsNitrosoNitrogen($Atom)) { 1979 $AtomType = 'N=O'; 1980 last ATOMTYPE; 1981 } 1982 1983 # NSO : DIVALENT NITROGEN REPLACING MONOVALENT O IN SO2 GROUP 1984 if ($This->_IsNSONitrogen($Atom)) { 1985 $AtomType = 'NSO'; 1986 last ATOMTYPE; 1987 } 1988 1989 $AtomType = 'None'; 1990 carp "Warning: ${ClassName}->_GetAtomTypeForNitrogenWithOnePiBond: MMFF94 atom type for Nitrogen cann't be assigned; Default MMFF94 atom type, $AtomType, has been assigned...\n"; 1991 } 1992 1993 return $AtomType; 1994 } 1995 1996 # Get MMFF94 atom type for Nitrogen with two pi bonds... 1997 # 1998 sub _GetAtomTypeForNitrogenWithTwoPiBonds { 1999 my($This, $Atom) = @_; 2000 my($AtomType); 2001 2002 $AtomType = 'None'; 2003 2004 ATOMTYPE: { 2005 2006 # NAZT : TERMINAL NITROGEN IN AZIDO OR DIAZO GROUP 2007 if ($This->_IsNAZTNitrogen($Atom)) { 2008 $AtomType = 'NAZT'; 2009 last ATOMTYPE; 2010 } 2011 2012 # NR% : ISONITRILE NITROGEN [FC = 0] OR DIAZO NITROGEN [FC = 1] 2013 if ($This->_IsIsoNitrileOrDiAzoNitrogen($Atom)) { 2014 $AtomType = 'NR%'; 2015 last ATOMTYPE; 2016 } 2017 2018 # =N= : NITROGEN IN C=N=N OR -N=N=N 2019 if ($This->_IsTwoDoublyBondedNitrogen($Atom)) { 2020 $AtomType = '=N='; 2021 last ATOMTYPE; 2022 } 2023 2024 # NSP : NITROGEN, TRIPLE BONDED 2025 if ($This->_IsTriplyBondedSPNitrogen($Atom)) { 2026 $AtomType = 'NSP'; 2027 last ATOMTYPE; 2028 } 2029 2030 $AtomType = 'NSP'; 2031 } 2032 2033 return $AtomType; 2034 } 2035 2036 # NR : NITROGEN IN ALIPHATIC AMINES 2037 # 2038 sub _IsAliphaticAmineNitrogen { 2039 my($This, $Atom) = @_; 2040 2041 return $Atom->DoesAtomNeighborhoodMatch('N.T3', ['C,H', 'C,H', 'C,H'], ['-', '-','-']) ? 1 : 0; 2042 } 2043 2044 # NR+ : QUATERNARY NITROGEN, SP3, POSITIVELY CHARGED 2045 # 2046 sub _IsAliphaticAmineQuaternaryNitrogen { 2047 my($This, $Atom) = @_; 2048 2049 return $Atom->DoesAtomNeighborhoodMatch('N.T4.FC+1', ['C,H', 'C,H', 'C,H', 'C,H'], ['-', '-','-','-']) ? 1 : 0; 2050 } 2051 2052 # NC=O : NITROGEN IN AMIDES 2053 # 2054 sub _IsAmideNitrogen { 2055 my($This, $Atom) = @_; 2056 my($AtomNeighbor); 2057 2058 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2059 return 0; 2060 } 2061 2062 # Is it attached to amide carbonyl Carbon? 2063 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.T3.DB1')) { 2064 if ($This->_IsAmideCarbonylCarbon($AtomNeighbor)) { 2065 return 1; 2066 } 2067 } 2068 return 0; 2069 } 2070 2071 # NC=S : NITROGEN IN N-C=S, THIOAMIDE 2072 # 2073 sub _IsThioAmideNitrogen { 2074 my($This, $Atom) = @_; 2075 my($AtomNeighbor); 2076 2077 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2078 return 0; 2079 } 2080 2081 # Is it attached to thioamide Carbon? 2082 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.T3.DB1')) { 2083 if ($This->_IsThioAmideCarbon($AtomNeighbor)) { 2084 return 1; 2085 } 2086 } 2087 return 0; 2088 } 2089 2090 # NN=C : NITROGEN IN N-N=C 2091 # 2092 sub _IsNNCNitrogen { 2093 my($This, $Atom) = @_; 2094 my($AtomNeighbor); 2095 2096 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2097 return 0; 2098 } 2099 2100 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('N.DB1')) { 2101 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('N.T2.DB1', ['C.T3', 'N.T3'], ['=', '-'])) { 2102 return 1; 2103 } 2104 } 2105 return 0; 2106 } 2107 2108 # NN=N : NITROGEN IN N-N=N 2109 # 2110 sub _IsNNNNitrogen { 2111 my($This, $Atom) = @_; 2112 my($AtomNeighbor); 2113 2114 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2115 return 0; 2116 } 2117 2118 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('N.DB1')) { 2119 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('N.T2.DB1', ['N.T2', 'N.T3'], ['=', '-'])) { 2120 return 1; 2121 } 2122 } 2123 return 0; 2124 } 2125 2126 # NPYD : NITROGEN, AS IN PYRIDINE 2127 # 2128 sub _IsPyridineNitrogen { 2129 my($This, $Atom) = @_; 2130 2131 # Is it an aromatic Nitrogen in only one six membered ring? 2132 if (!$Atom->DoesAtomNeighborhoodMatch('N.Ar.RA6.TR1')) { 2133 return 0; 2134 } 2135 2136 # Is it part of six membered ring containing only one hetero atom? 2137 my($RingAtomsRef, $RingIsAromatic, $NumOfHeteroAtoms); 2138 for $RingAtomsRef ($Atom->GetRingsWithSize(6)) { 2139 ($RingIsAromatic, $NumOfHeteroAtoms) = $This->_GetHeteroAtomsInformationInRing($RingAtomsRef); 2140 if ($RingIsAromatic && $NumOfHeteroAtoms == 1) { 2141 return 1; 2142 } 2143 } 2144 return 0; 2145 } 2146 2147 # NPYL : NITROGEN, AS IN PYRROLE 2148 # 2149 sub _IsPyrroleNitrogen { 2150 my($This, $Atom) = @_; 2151 2152 # Is it an aromatic Nitrogen in only one five membered ring? 2153 if (!$Atom->DoesAtomNeighborhoodMatch('N.Ar.RA5.TR1')) { 2154 return 0; 2155 } 2156 2157 # Is it part of five membered ring containing only one hetero atom? 2158 my($RingAtomsRef, $RingIsAromatic, $NumOfHeteroAtoms); 2159 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 2160 ($RingIsAromatic, $NumOfHeteroAtoms) = $This->_GetHeteroAtomsInformationInRing($RingAtomsRef); 2161 if ($RingIsAromatic && $NumOfHeteroAtoms == 1) { 2162 return 1; 2163 } 2164 } 2165 return 0; 2166 } 2167 2168 # NC=C : NITROGEN ON N-C=C 2169 # 2170 sub _IsNCCNitrogen { 2171 my($This, $Atom) = @_; 2172 my($AtomNeighbor); 2173 2174 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2175 return 0; 2176 } 2177 2178 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 2179 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.T3.DB1', ['C.T3', 'N.T3', '*'], ['=', '-','-'])) { 2180 return 1; 2181 } 2182 } 2183 return 0; 2184 } 2185 2186 # NC=N : NITROGEN IN N-C=N 2187 # 2188 sub _IsNCNNitrogen { 2189 my($This, $Atom) = @_; 2190 my($AtomNeighbor); 2191 2192 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2193 return 0; 2194 } 2195 2196 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 2197 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.T3.DB1', ['N.T2', 'N.T3', '*'], ['=', '-','-'])) { 2198 return 1; 2199 } 2200 } 2201 return 0; 2202 } 2203 2204 # NC=P : NITROGEN IN N-C=P 2205 # 2206 sub _IsNCPNitrogen { 2207 my($This, $Atom) = @_; 2208 my($AtomNeighbor); 2209 2210 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2211 return 0; 2212 } 2213 2214 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 2215 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.T3.DB1', ['P.X1', 'N.T3', '*'], ['=', '-', '-'])) { 2216 return 1; 2217 } 2218 } 2219 return 0; 2220 } 2221 2222 # NC%C : NITROGEN ATTACHED TO C-C TRIPLE BOND 2223 # 2224 sub _IsAttchedToCCTripleBondNitrogen { 2225 my($This, $Atom) = @_; 2226 my($AtomNeighbor); 2227 2228 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2229 return 0; 2230 } 2231 2232 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.TB1')) { 2233 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.X2.TB1', ['C.T2', 'N.T3'], ['#', '-'])) { 2234 return 1; 2235 } 2236 } 2237 return 0; 2238 } 2239 2240 # NSO2 : NITROGEN IN SULFONAMIDES 2241 # 2242 sub _IsNSO2SulfonamideNitrogen { 2243 my($This, $Atom) = @_; 2244 my($AtomNeighbor); 2245 2246 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2247 return 0; 2248 } 2249 2250 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T4.DB2')) { 2251 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('S.T4.DB2', ['N', 'O', 'O', '!O'], ['-', '=', '=', '-'])) { 2252 return 1; 2253 } 2254 } 2255 return 0; 2256 } 2257 2258 # NSO3 : NITROGEN IN SULFONAMIDES, THREE Os ON S 2259 # 2260 sub _IsNSO3SulfonamideNitrogen { 2261 my($This, $Atom) = @_; 2262 my($AtomNeighbor); 2263 2264 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2265 return 0; 2266 } 2267 2268 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T4.DB2')) { 2269 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('S.X4.DB2', ['N', 'O', 'O', 'O'], ['-', '=', '=', '-'])) { 2270 return 1; 2271 } 2272 } 2273 return 0; 2274 } 2275 2276 # NPO2 : NITROGEN IN PHOSPHONAMIDES 2277 # 2278 sub _IsNPO2PhosphonamideNitrogen { 2279 my($This, $Atom) = @_; 2280 my($AtomNeighbor); 2281 2282 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2283 return 0; 2284 } 2285 2286 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P.DB1')) { 2287 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('P.T4.DB1', ['N', 'O', 'O', '!O'], ['-', '=', '-', '-'])) { 2288 return 1; 2289 } 2290 } 2291 return 0; 2292 } 2293 2294 # NPO3 : NITROGEN IN PHOSPHONAMIDES, THREE Os ON P 2295 # 2296 sub _IsNPO3PhosphonamideNitrogen { 2297 my($This, $Atom) = @_; 2298 my($AtomNeighbor); 2299 2300 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2301 return 0; 2302 } 2303 2304 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P.DB1')) { 2305 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('P.X4.DB1', ['N', 'O', 'O', 'O'], ['-', '=', '-', '-'])) { 2306 return 1; 2307 } 2308 } 2309 return 0; 2310 } 2311 2312 # NC%N : NITROGEN ATTACHED TO CYANO GROUP 2313 # 2314 sub _IsAttachedToCyanoNitrogen { 2315 my($This, $Atom) = @_; 2316 my($AtomNeighbor); 2317 2318 if (!$Atom->DoesAtomNeighborhoodMatch('N.T3.TSB3')) { 2319 return 0; 2320 } 2321 2322 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.TB1')) { 2323 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.T2.TB1', ['N', 'N'], ['-', '#'])) { 2324 return 1; 2325 } 2326 } 2327 return 0; 2328 } 2329 2330 # NM : DEPROTONATED SULFONAMIDE N-; FORMAL CHARGE=-1 2331 # 2332 sub _IsDeprotonatedSulfonamideNitrogen { 2333 my($This, $Atom) = @_; 2334 my($AtomNeighbor); 2335 2336 if (!$Atom->DoesAtomNeighborhoodMatch('N.T2.FC-1.TSB2')) { 2337 return 0; 2338 } 2339 2340 # Is it attached to sulfonamide Sulfur? 2341 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T4.DB2')) { 2342 if ($This->_IsSulfonamideSulfur($AtomNeighbor)) { 2343 return 1; 2344 } 2345 } 2346 return 0; 2347 } 2348 2349 # N=C : NITROGEN IN IMINES 2350 # 2351 sub _IsImineNitrogen { 2352 my($This, $Atom) = @_; 2353 2354 return $Atom->DoesAtomNeighborhoodMatch('N.T2.DB1', ['C', '*'], ['=', '-']) ? 1 : 0; 2355 } 2356 2357 # N+=C : POSITIVELY CHARGED IMINIUM NITROGEN 2358 # 2359 sub _IsPositivelyChargedIminiumNitrogen { 2360 my($This, $Atom) = @_; 2361 2362 return $Atom->DoesAtomNeighborhoodMatch('N.DB1.FC+1', ['C', '*', '*'], ['=', '-', '-']) ? 1 : 0; 2363 } 2364 2365 # N=N : NITROGEN IN AZO COMPOUNDS 2366 # 2367 sub _IsAzoNitrogen { 2368 my($This, $Atom) = @_; 2369 2370 return $Atom->DoesAtomNeighborhoodMatch('N.T2.DB1', ['N', '*'], ['=', '-']) ? 1 : 0; 2371 } 2372 2373 # N+=N : POSITIVELY CHARGED NITROGEN DOUBLE-BONDED TO N 2374 # 2375 sub _IsPositivelyChargedAzoNitrogen { 2376 my($This, $Atom) = @_; 2377 2378 return $Atom->DoesAtomNeighborhoodMatch('N.DB1.FC+1', ['N', '*', '*'], ['=', '-', '-']) ? 1 : 0; 2379 } 2380 2381 # NO2 : NITRO GROUP NITROGEN 2382 # 2383 sub _IsNitroNitrogen { 2384 my($This, $Atom) = @_; 2385 2386 # R-N+(=O)-(O-) 2387 return $Atom->DoesAtomNeighborhoodMatch('N.T3.DB1.FC+1', ['O', 'O.FC-1', '!O'], ['=', '-', '-']) ? 1 : 0; 2388 } 2389 2390 # NO3 : NITRATE GROUP NITROGEN 2391 # 2392 sub _IsNitrateNitrogen { 2393 my($This, $Atom) = @_; 2394 2395 # (O-)-N+(=O)-(O-) or R-O-N+(=O)-(O-) 2396 # 2397 return $Atom->DoesAtomNeighborhoodMatch('N.T3.DB1.FC+1', ['O', 'O.FC-1', 'O.T2.FC0'], ['=', '-', '-']) ? 1 : 0; 2398 } 2399 2400 # N=O : NITROSO NITROGEN 2401 # 2402 sub _IsNitrosoNitrogen { 2403 my($This, $Atom) = @_; 2404 2405 # R-N=O 2406 return $Atom->DoesAtomNeighborhoodMatch('N.T2.DB1', ['O'], ['=']) ? 1 : 0; 2407 } 2408 2409 # NAZT : TERMINAL NITROGEN IN AZIDO OR DIAZO GROUP 2410 # 2411 sub _IsNAZTNitrogen { 2412 my($This, $Atom) = @_; 2413 2414 return ($This->_IsAzidoTerminalNitrogen($Atom) || $This->_IsDiazoTerminalNitrogen($Atom)) ? 1 : 0; 2415 } 2416 2417 # TERMINAL NITROGEN IN AZIDO GROUP 2418 # 2419 sub _IsAzidoTerminalNitrogen { 2420 my($This, $Atom) = @_; 2421 my($AtomNeighbor); 2422 2423 if (!$Atom->DoesAtomNeighborhoodMatch('N.X1.DB1')) { 2424 return 0; 2425 } 2426 2427 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('N.DB2')) { 2428 if ($This->_IsAzidoGroupMiddleNitrogen($AtomNeighbor)) { 2429 return 1; 2430 } 2431 } 2432 return 0; 2433 } 2434 2435 # TERMINAL NITROGEN IN DIAZO GROUP 2436 # 2437 sub _IsDiazoTerminalNitrogen { 2438 my($This, $Atom) = @_; 2439 my($AtomNeighbor); 2440 2441 if (!$Atom->DoesAtomNeighborhoodMatch('N.X1.TB1,N.X1.DB1')) { 2442 return 0; 2443 } 2444 2445 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('N.DB2,N.TB1')) { 2446 if ($This->_IsDiazoGroupMiddleNitrogen($AtomNeighbor)) { 2447 return 1; 2448 } 2449 } 2450 return 0; 2451 } 2452 2453 # Azido group: R-N=N+=N- 2454 # 2455 sub _IsAzidoGroupMiddleNitrogen { 2456 my($This, $Atom) = @_; 2457 2458 return $Atom->DoesAtomNeighborhoodMatch('N.X2.DB2.FC+1', ['N.X1.FC-1', 'N.T2.FC0'], ['=', '=']) ? 1 : 0; 2459 } 2460 2461 # Diazo group: R'-(C-)(-R")-(N+)#N or R'-C(-R")=(N+)=(N-) 2462 # 2463 sub _IsDiazoGroupMiddleNitrogen { 2464 my($This, $Atom) = @_; 2465 2466 # Diazo group: R'-C(-R")=(N+)=(N-) 2467 if ($Atom->DoesAtomNeighborhoodMatch('N.X2.DB2.FC+1', ['C.T3.FC0', 'N.X1.FC-1'], ['=', '='])) { 2468 return 1; 2469 } 2470 2471 # Diazo group: R'-(C-)(-R")-(N+)#N 2472 if ($Atom->DoesAtomNeighborhoodMatch('N.X2.TB1.FC+1', ['C.T3.FC-1', 'N.X1.FC0'], ['-', '#'])) { 2473 return 1; 2474 } 2475 2476 return 0; 2477 } 2478 2479 # NSO : DIVALENT NITROGEN REPLACING MONOVALENT O IN SO2 GROUP 2480 # 2481 sub _IsNSONitrogen { 2482 my($This, $Atom) = @_; 2483 my($AtomNeighbor); 2484 2485 if (!$Atom->DoesAtomNeighborhoodMatch('N.T2.DB1')) { 2486 return 0; 2487 } 2488 2489 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.DB2')) { 2490 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('S.DB2', ['N', 'O'], ['=', '='])) { 2491 return 1; 2492 } 2493 } 2494 return 0; 2495 } 2496 2497 # NCN+ : N IN +N=C-N RESONANCE STRUCTURES - FORMAL CHARGE=1/2 2498 # 2499 # Notes: 2500 # . This method is called invoked for both SP and SP2 Nitrogens to check and assign 2501 # NCN+ to both Nitrogens. 2502 # 2503 sub _IsNCNResonaceStructuresNitrogen { 2504 my($This, $Atom) = @_; 2505 my($AtomNeighbor); 2506 2507 if (!$Atom->DoesAtomNeighborhoodMatch('N')) { 2508 return 0; 2509 } 2510 2511 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 2512 if ($This->_IsNCNResonaceStructuresCarbon($AtomNeighbor)) { 2513 return 1; 2514 } 2515 } 2516 return 0; 2517 } 2518 2519 # NGD+ : GUANIDINIUM-TYPE NITROGEN - FORMAL CHARGE=1/3 2520 # 2521 # Notes: 2522 # . This method is called invoked for both SP and SP2 Nitrogens to check and assign 2523 # NGD+ to all three Guanidinium Nitrogens. 2524 # 2525 sub _IsGuanidiniumNitrogen { 2526 my($This, $Atom) = @_; 2527 my($AtomNeighbor); 2528 2529 if (!$Atom->DoesAtomNeighborhoodMatch('N')) { 2530 return 0; 2531 } 2532 2533 # Is it attached to Guandinium Carbon? 2534 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 2535 if ($This->_IsGuandiniumCarbon($AtomNeighbor)) { 2536 return 1; 2537 } 2538 } 2539 return 0; 2540 } 2541 2542 # NPD+ : PYRIDINIUM-TYPE NITROGEN - FORMAL CHARGE=1 2543 # 2544 sub _IsPyridiniumNitrogen { 2545 my($This, $Atom) = @_; 2546 2547 return ($This->_IsPyridineNitrogen($Atom) && $Atom->DoesAtomNeighborhoodMatch('N.FC+1')) ? 1 : 0; 2548 } 2549 2550 # NR% : ISONITRILE NITROGEN [FC = 0] OR DIAZO NITROGEN [FC = 1] 2551 # 2552 # Notes: 2553 # . This method is called invoked for both SP and SP2 Nitrogens to check and assign 2554 # NR%. 2555 # 2556 sub _IsIsoNitrileOrDiAzoNitrogen { 2557 my($This, $Atom) = @_; 2558 2559 return ($This->_IsIsoNitrileNitrogen($Atom) || $This->_IsDiAzoNitrogen($Atom)) ? 1 : 0; 2560 } 2561 2562 # Isonitrile nitrogen: R-N+#C- 2563 # 2564 # Notes: 2565 # . MayaChemTools assumes isonitrile Nitrogen to have a formal charge of +1; otherwise 2566 # it won't be an isonitrile group. It's not clear why it would be zero as indicated in 2567 # MMFF documentation. 2568 # 2569 sub _IsIsoNitrileNitrogen { 2570 my($This, $Atom) = @_; 2571 my($AtomNeighbor); 2572 2573 if (!$Atom->DoesAtomNeighborhoodMatch('N.FC+1.TB1')) { 2574 return 0; 2575 } 2576 2577 # Is it attached to isonitrile Carbon? 2578 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.TB1')) { 2579 if ($This->_IsIsoNitrileCarbon($AtomNeighbor)) { 2580 return 1; 2581 } 2582 } 2583 return 0; 2584 } 2585 2586 # Diazo group: R1-(C-)(-R2)-(N+)#N or R1-C(-R2)=(N+)=(N-) 2587 # 2588 sub _IsDiAzoNitrogen { 2589 my($This, $Atom) = @_; 2590 my($AtomNeighbor); 2591 2592 return $This->_IsDiazoGroupMiddleNitrogen($Atom) ? 1 : 0; 2593 } 2594 2595 # N5A : ALPHA AROM HETEROCYCLIC 5-RING NITROGEN 2596 # 2597 sub _IsFiveMemberedHeteroAromaticRingAlphaNitrogen { 2598 my($This, $Atom) = @_; 2599 2600 # Is it an aromatic atom in a five membered ring? 2601 if (!$Atom->DoesAtomNeighborhoodMatch('N.Ar.RA5.FC0')) { 2602 return 0; 2603 } 2604 2605 # Is it part of five membered rings containing hetero atom at alpha position? 2606 my($RingAtomsRef); 2607 2608 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 2609 if ($This->_IsAtomPositionAlphaInHeteroAromaticRing($Atom, $RingAtomsRef)) { 2610 return 1; 2611 } 2612 } 2613 return 0; 2614 } 2615 2616 # N5B : BETA AROM HETEROCYCLIC 5-RING NITROGEN 2617 # 2618 sub _IsFiveMemberedHeteroAromaticRingBetaNitrogen { 2619 my($This, $Atom) = @_; 2620 2621 # Is it an aromatic atom in a five membered ring? 2622 if (!$Atom->DoesAtomNeighborhoodMatch('N.Ar.RA5.FC0')) { 2623 return 0; 2624 } 2625 2626 # Is it part of five membered rings containing hetero atom at beta position? 2627 my($RingAtomsRef); 2628 2629 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 2630 if ($This->_IsAtomPositionBetaInHeteroAromaticRing($Atom, $RingAtomsRef)) { 2631 return 1; 2632 } 2633 } 2634 return 0; 2635 } 2636 2637 # N5A+ : POSITIVE N5A NITROGEN - FORMAL CHARGE=1 2638 # 2639 sub _IsPositivelyChargedFiveMemberedHeteroAromaticRingAlphaNitrogen { 2640 my($This, $Atom) = @_; 2641 2642 # Is it an aromatic atom in a five membered ring? 2643 if (!$Atom->DoesAtomNeighborhoodMatch('N.Ar.RA5.FC+1')) { 2644 return 0; 2645 } 2646 2647 # Is it part of five membered rings containing hetero atom at alpha position? 2648 my($RingAtomsRef); 2649 2650 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 2651 if ($This->_IsAtomPositionAlphaInHeteroAromaticRing($Atom, $RingAtomsRef)) { 2652 return 1; 2653 } 2654 } 2655 return 0; 2656 } 2657 2658 # N5B+ : POSITIVE N5B NITROGEN - FORMAL CHARGE=1 2659 # 2660 sub _IsPositivelyChargedFiveMemberedHeteroAromaticRingBetaNitrogen { 2661 my($This, $Atom) = @_; 2662 2663 # Is it an aromatic atom in a five membered ring? 2664 if (!$Atom->DoesAtomNeighborhoodMatch('N.Ar.RA5.FC+1')) { 2665 return 0; 2666 } 2667 2668 # Is it part of five membered rings containing hetero atom at beta position? 2669 my($RingAtomsRef); 2670 2671 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 2672 if ($This->_IsAtomPositionBetaInHeteroAromaticRing($Atom, $RingAtomsRef)) { 2673 return 1; 2674 } 2675 } 2676 return 0; 2677 } 2678 2679 # N2OX : SP2-HYDRIDIZED N-OXIDE NITROGEN 2680 # 2681 sub _IsSP2NOxideNitrogen { 2682 my($This, $Atom) = @_; 2683 2684 # R=(R'-)(N+)-(O-) 2685 # 2686 return $Atom->DoesAtomNeighborhoodMatch('N.FC+1.DB1.T3', ['O.X1.FC-1', 'C', '*'], ['-', '=', '-']) ? 1 : 0; 2687 } 2688 2689 # N3OX : SP3-HYDRIDIZED N-OXIDE NITROGEN 2690 # 2691 sub _IsSP3NOxideNitrogen { 2692 my($This, $Atom) = @_; 2693 2694 # R-(R'-)(R"-)(N+)-(O-) 2695 # 2696 return $Atom->DoesAtomNeighborhoodMatch('N.FC+1.T4', ['O.X1.FC-1', '*', '*', '*'], ['-', '-', '-', '-']) ? 1 : 0; 2697 } 2698 2699 # NPOX : PYRIDINE N-OXIDE NITROGEN 2700 # 2701 sub _IsPyridineNOxideNitrogen { 2702 my($This, $Atom) = @_; 2703 2704 return ($This->_IsPyridineNitrogen($Atom) && $This->_IsSP2NOxideNitrogen($Atom)) ? 1 : 0; 2705 } 2706 2707 # N5M : NEGATIVELY CHARGED N IN, E.G, TRI- OR TETRAZOLE ANION 2708 # 2709 sub _IsNegativelyChargedFiveMemberedHeteroCyclicRingNitrogen { 2710 my($This, $Atom) = @_; 2711 2712 return $Atom->DoesAtomNeighborhoodMatch('N.RA5.FC-1') ? 1 : 0; 2713 } 2714 2715 # N5 : GENERAL NITROGEN IN 5-MEMBERED HETEROCYCLIC RING 2716 # 2717 sub _IsFiveMemberedHeteroCyclicRingNitrogen { 2718 my($This, $Atom) = @_; 2719 2720 return $Atom->DoesAtomNeighborhoodMatch('N.RA5') ? 1 : 0; 2721 } 2722 2723 # N5+ : POSITIVE N5 NITROGEN - FORMAL CHARGE=1 2724 # 2725 sub _IsPositivelyChargedFiveMemberedHeteroCyclicRingNitrogen { 2726 my($This, $Atom) = @_; 2727 2728 return $Atom->DoesAtomNeighborhoodMatch('N.RA5.FC+1') ? 1 : 0; 2729 } 2730 2731 # N5AX : N-OXIDE NITROGEN IN 5-RING ALPHA POSITION 2732 # 2733 sub _IsNOxideFiveMemberedHeteroCyclicRingAlphaNitrogen { 2734 my($This, $Atom) = @_; 2735 2736 # Is it a N-oxide Nitrogen atom in a five membered ring? 2737 if (!$Atom->DoesAtomNeighborhoodMatch('N.RA5.FC+1', ['O.X1.FC-1.!RA'], ['-'])) { 2738 return 0; 2739 } 2740 2741 # Is it part of five membered rings containing hetero atom at alpha position? 2742 my($RingAtomsRef); 2743 2744 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 2745 if ($This->_IsAtomPositionAlphaInHeteroRing($Atom, $RingAtomsRef)) { 2746 return 1; 2747 } 2748 } 2749 return 0; 2750 } 2751 2752 # N5BX : N-OXIDE NITROGEN IN 5-RING BETA POSITION 2753 # 2754 sub _IsNOxideFiveMemberedHeteroCyclicRingBetaNitrogen { 2755 my($This, $Atom) = @_; 2756 2757 # Is it a N-oxide Nitrogen atom in a five membered ring? 2758 if (!$Atom->DoesAtomNeighborhoodMatch('N.RA5.FC+1', ['O.X1.FC-1.!RA'], ['-'])) { 2759 return 0; 2760 } 2761 2762 # Is it part of five membered rings containing hetero atom at alpha position? 2763 my($RingAtomsRef); 2764 2765 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 2766 if ($This->_IsAtomPositionBetaInHeteroRing($Atom, $RingAtomsRef)) { 2767 return 1; 2768 } 2769 } 2770 return 0; 2771 } 2772 2773 # N5OX : N-OXIDE NITROGEN IN GENERAL 5-RING POSITION 2774 # 2775 sub _IsNOxideFiveMemberedHeteroCyclicRingNitrogen { 2776 my($This, $Atom) = @_; 2777 2778 return $Atom->DoesAtomNeighborhoodMatch('N.FC+1.RA5', ['O.X1.FC-1.!RA'], ['-']) ? 1 : 0; 2779 } 2780 2781 # NIM+ : IMIDAZOLIUM-TYPE NITROGEN - FORMAL CHARGE=1/2 2782 # 2783 # Notes: 2784 # . MayaChemTools assigns NIM+ to both the Nitrogens around Imidazolium Carbon. 2785 # 2786 sub _IsImidazoliumNitrogen { 2787 my($This, $Atom) = @_; 2788 my($AtomNeighbor); 2789 2790 # Is it an aromatic Nitrogen in only one five membered ring? 2791 if (!$Atom->DoesAtomNeighborhoodMatch('N.Ar.RA5.TR1')) { 2792 return 0; 2793 } 2794 2795 # Is it attached to Imidazolium Carbon? 2796 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.RA5')) { 2797 if ($This->_IsImidazoliumCarbon($AtomNeighbor)) { 2798 return 1; 2799 } 2800 } 2801 return 0; 2802 } 2803 2804 # =N= : NITROGEN IN C=N=N OR -N=N=N 2805 # 2806 # Notes: 2807 # . MayaChemTools assign =N= to all doubly bonded Nitrogen atoms 2808 # irrespective of whether it has explcit formal charge of +1. 2809 # 2810 sub _IsTwoDoublyBondedNitrogen { 2811 my($This, $Atom) = @_; 2812 2813 if ($Atom->DoesAtomNeighborhoodMatch('N.DB2', ['N', 'N'], ['=', '='])) { 2814 return 1; 2815 } 2816 if ($Atom->DoesAtomNeighborhoodMatch('N.DB2', ['C', 'N'], ['=', '='])) { 2817 return 1; 2818 } 2819 return 0; 2820 } 2821 2822 # NSP : NITROGEN, TRIPLE BONDED 2823 # 2824 sub _IsTriplyBondedSPNitrogen { 2825 my($This, $Atom) = @_; 2826 2827 return $Atom->DoesAtomNeighborhoodMatch('N.TB1') ? 1 : 0; 2828 } 2829 2830 2831 # Get MMFF94 atom type for divalent or terminal Oxygen attached to Sulfur... 2832 # 2833 sub _GetAtomTypeForOxygenAttachedToSulfur { 2834 my($This, $Atom) = @_; 2835 my($AtomType); 2836 2837 $AtomType = 'None'; 2838 2839 ATOMTYPE: { 2840 2841 # OSMS : TERM O IN THIOSULFINATE ANION - FORMAL CHARGE=-0.5 2842 if ($This->_IsThioSulfinateTerminalOxygen($Atom)) { 2843 $AtomType = 'OSMS'; 2844 last ATOMTYPE; 2845 } 2846 2847 # OSO3 : DIVALENT OXYGEN ATTACHED TO SULFUR 2848 if ($This->_IsOSO3DivalentOxygen($Atom)) { 2849 $AtomType = 'OSO3'; 2850 last ATOMTYPE; 2851 } 2852 2853 # OSO2 : DIVALENT OXYGEN ATTACHED TO SULFUR 2854 if ($This->_IsOSO2DivalentOxygen($Atom)) { 2855 $AtomType = 'OSO2'; 2856 last ATOMTYPE; 2857 } 2858 2859 # OSO : DIVALENT OXYGEN ATTACHED TO SULFUR 2860 if ($This->_IsOSODivalentOxygen($Atom)) { 2861 $AtomType = 'OSO'; 2862 last ATOMTYPE; 2863 } 2864 2865 # OS=O : DIVALENT OXYGEN ATTACHED TO SULFOXIDE SULFUR 2866 if ($This->_IsSulfoxideDivalentOxygen($Atom)) { 2867 $AtomType = 'OS=O'; 2868 last ATOMTYPE; 2869 } 2870 2871 # -OS : GENERAL DIVALENT OXYGEN ATTACHED TO S 2872 if ($This->_IsOSDivalentOxygen($Atom)) { 2873 $AtomType = ' -OS'; 2874 last ATOMTYPE; 2875 } 2876 2877 # O4S : TERMINAL O IN SO4(-3) 2878 if ($This->_IsSulfateTerminalOxygen($Atom)) { 2879 $AtomType = 'O4S'; 2880 last ATOMTYPE; 2881 } 2882 2883 # O3S : TERMINAL O IN SULFONATES 2884 if ($This->_IsSulfonateTerminalOxygen($Atom)) { 2885 $AtomType = 'O3S'; 2886 last ATOMTYPE; 2887 } 2888 2889 # O2S : TERMINAL O-S IN SULFONES AND SULFONAMIDES 2890 if ($This->_IsSulfoneOrSulfonamideTerminalOxygen($Atom)) { 2891 $AtomType = 'O2S'; 2892 last ATOMTYPE; 2893 } 2894 2895 # O=S : O=S IN SULFOXIDES 2896 if ($This->_IsSulfoxideOxygen($Atom)) { 2897 $AtomType = 'O=S'; 2898 last ATOMTYPE; 2899 } 2900 2901 # O=S= : O=S ON SULFUR DOUBLY BONDED TO, E.G., CARBON 2902 if ($This->_IsDoublyBondedOSOxygen($Atom)) { 2903 $AtomType = 'O=S='; 2904 last ATOMTYPE; 2905 } 2906 2907 # O-S : SINGLE TERMINAL OXYGEN ON TETRACOORD SULFUR 2908 if ($This->_IsOSTerminalOxygen($Atom)) { 2909 $AtomType = 'O-S'; 2910 last ATOMTYPE; 2911 } 2912 2913 $AtomType = 'None'; 2914 carp "Warning: ${ClassName}->_GetAtomTypeForOxygenAttachedToSulfur: MMFF94 atom type for Oxygen cann't be assigned..."; 2915 } 2916 2917 return $AtomType; 2918 } 2919 2920 # Get MMFF94 atom type for divalent or terminal Oxygen attached to Phosphorus... 2921 # 2922 sub _GetAtomTypeForOxygenAttachedToPhosphorus { 2923 my($This, $Atom) = @_; 2924 my($AtomType); 2925 2926 $AtomType = 'None'; 2927 2928 ATOMTYPE: { 2929 2930 # OPO3 : DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 2931 if ($This->_IsOPO3DivalentOxygen($Atom)) { 2932 $AtomType = 'OPO3'; 2933 last ATOMTYPE; 2934 } 2935 2936 # OPO2 : DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 2937 if ($This->_IsOPO2DivalentOxygen($Atom)) { 2938 $AtomType = 'OPO2'; 2939 last ATOMTYPE; 2940 } 2941 2942 # OPO : DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 2943 if ($This->_IsOPODivalentOxygen($Atom)) { 2944 $AtomType = 'OPO'; 2945 last ATOMTYPE; 2946 } 2947 2948 # -OP : DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 2949 if ($This->_IsOPDivalentOxygen($Atom)) { 2950 $AtomType = '-OP'; 2951 last ATOMTYPE; 2952 } 2953 2954 # O4P : TERMINAL OXYGEN IN PHOSPHATES AND PHOSPHODIESTERS 2955 if ($This->_IsPhosphateOrPhosphodiesterTerminalOxygen($Atom)) { 2956 $AtomType = 'O4P'; 2957 last ATOMTYPE; 2958 } 2959 2960 # O3P : TERMINAL OXYGEN IN PHOSPHONATES 2961 if ($This->_IsPhosphonateTerminalOxygen($Atom)) { 2962 $AtomType = 'O3P'; 2963 last ATOMTYPE; 2964 } 2965 2966 # O2P : TERMINAL O IN PHOSPHINATES 2967 if ($This->_IsPhosphinateTerminalOxygen($Atom)) { 2968 $AtomType = 'O2P'; 2969 last ATOMTYPE; 2970 } 2971 2972 # OP : TERMINAL O IN PHOSPHOXIDES 2973 if ($This->_IsPhosphoxideTerminalOxygen($Atom)) { 2974 $AtomType = 'OP'; 2975 last ATOMTYPE; 2976 } 2977 2978 $AtomType = 'None'; 2979 carp "Warning: ${ClassName}->_GetAtomTypeForOxygenAttachedToPhosphorus: MMFF94 atom type for Oxygen cann't be assigned..."; 2980 } 2981 2982 return $AtomType; 2983 } 2984 2985 # Get MMFF94 atom type for Oxygen with only sigma bonds... 2986 # 2987 sub _GetAtomTypeForOxygenWithOnlySigmaBonds { 2988 my($This, $Atom) = @_; 2989 my($AtomType); 2990 2991 $AtomType = 'None'; 2992 2993 ATOMTYPE: { 2994 2995 # OFUR : AROMATIC OXYGEN AS IN FURAN 2996 if ($This->_IsAromaticOxygen($Atom)) { 2997 $AtomType = 'OFUR'; 2998 last ATOMTYPE; 2999 } 3000 3001 # OC=O : ESTER OR CARBOXYLIC ACID -O- 3002 if ($This->_IsEsterOrCarboxylicAcidOxygen($Atom)) { 3003 $AtomType = 'OC=O'; 3004 last ATOMTYPE; 3005 } 3006 3007 # O2CM : OXYGEN IN CARBOXYLATE ANION 3008 if ($This->_IsCarboxylateAnionOxygen($Atom)) { 3009 $AtomType = 'O2CM'; 3010 last ATOMTYPE; 3011 } 3012 3013 # OC=C : ENOLIC OR PHENOLIC OXYGEN 3014 if ($This->_IsEnolicOrPhenolicOxygen($Atom)) { 3015 $AtomType = 'OC=C '; 3016 last ATOMTYPE; 3017 } 3018 3019 # OC=N : DIVALENT OXYGEN 3020 if ($This->_IsOCNDivalentOxygen($Atom)) { 3021 $AtomType = 'OC=N'; 3022 last ATOMTYPE; 3023 } 3024 3025 # OC=S : THIOESTER OR THIOACID -O- 3026 if ($This->_IsThioEsterOrThioAcidOxygen($Atom)) { 3027 $AtomType = 'OC=S'; 3028 last ATOMTYPE; 3029 } 3030 3031 # ON=O : DIVALENT NITRITE ETHER OXYGEN 3032 if ($This->_IsDivalentNitriteEtherOxygen($Atom)) { 3033 $AtomType = 'ON=O'; 3034 last ATOMTYPE; 3035 } 3036 3037 # ONO2 : DIVALENT NITRATE ETHER OXYGEN 3038 if ($This->_IsDivalentNitrateEtherOxygen($Atom)) { 3039 $AtomType = 'ONO2'; 3040 last ATOMTYPE; 3041 } 3042 3043 # O3N : NITRATE ANION OXYGEN 3044 if ($This->_IsNitrateAnionOxygen($Atom)) { 3045 $AtomType = 'O3N'; 3046 last ATOMTYPE; 3047 } 3048 3049 # O2N : NITRO OXYGEN 3050 if ($This->_IsNitroOxygen($Atom)) { 3051 $AtomType = 'O2N'; 3052 last ATOMTYPE; 3053 } 3054 3055 # OXN : N-OXIDE OXYGEN 3056 if ($This->_IsNOxideOxygen($Atom)) { 3057 $AtomType = 'OXN'; 3058 last ATOMTYPE; 3059 } 3060 3061 # OM2 : OXIDE OXYGEN ON SP2 CARBON, NEGATIVELY CHARGED 3062 if ($This->_IsNegativelyChargedSP2OxideOxygen($Atom)) { 3063 $AtomType = 'OM2'; 3064 last ATOMTYPE; 3065 } 3066 3067 # OM : ALKOXIDE OXYGEN, NEGATIVELY CHARGED 3068 if ($This->_IsNegativelyChargedAlkoxideOxygen($Atom)) { 3069 $AtomType = 'OM'; 3070 last ATOMTYPE; 3071 } 3072 3073 # O4CL : OXYGEN IN CLO4(-) ANION - FORMAL CHARGE=-0.25 3074 if ($This->_IsPerChlorateAnionOxygen($Atom)) { 3075 $AtomType = 'O4CL'; 3076 last ATOMTYPE; 3077 } 3078 3079 # O+ : POSITIVELY CHARGED OXONIUM (TRICOORDINATE) OXYGEN 3080 if ($This->_IsPositivelyChargedOxoniumOxygen($Atom)) { 3081 $AtomType = 'O+'; 3082 last ATOMTYPE; 3083 } 3084 3085 # OH2 : OXYGEN ON WATER 3086 if ($This->_IsWaterOxygen($Atom)) { 3087 $AtomType = 'OH2'; 3088 last ATOMTYPE; 3089 } 3090 3091 # OR : ALCOHOL OR ETHER OXYGEN 3092 if ($This->_IsAlcoholOrEtherOxygen($Atom)) { 3093 $AtomType = 'OR'; 3094 last ATOMTYPE; 3095 } 3096 3097 # GENERAL DIVALENT O 3098 if ($This->_IsDivalentOxygen($Atom)) { 3099 $AtomType = '-O-'; 3100 last ATOMTYPE; 3101 } 3102 3103 $AtomType = 'None'; 3104 carp "Warning: ${ClassName}->_GetAtomTypeForOxygenWithOnlySigmaBonds: MMFF94 atom type for Oxygen cann't be assigned..."; 3105 } 3106 3107 return $AtomType; 3108 } 3109 3110 # Get MMFF94 atom type for Oxygen with only sigma bonds... 3111 # 3112 sub _GetAtomTypeForOxygenWithOnePiBond { 3113 my($This, $Atom) = @_; 3114 my($AtomType); 3115 3116 $AtomType = 'None'; 3117 3118 ATOMTYPE: { 3119 3120 # OFUR : AROMATIC OXYGEN AS IN FURAN 3121 if ($This->_IsAromaticOxygen($Atom)) { 3122 $AtomType = 'OFUR'; 3123 last ATOMTYPE; 3124 } 3125 3126 # O=+ : POSITIVELY CHARGED OXENIUM (DICOORDINATE) OXYGEN 3127 if ($This->_IsPositivelyChargedOxeniumOxygen($Atom)) { 3128 $AtomType = 'O=+'; 3129 last ATOMTYPE; 3130 } 3131 3132 # O=CN : CARBONYL OXYGEN, AMIDES 3133 if ($This->_IsAmideCarbonylOxygen($Atom)) { 3134 $AtomType = 'O=CN'; 3135 last ATOMTYPE; 3136 } 3137 3138 # O=CO : CARBONYL OXYGEN, CARBOXYLIC ACIDS AND ESTERS 3139 if ($This->_IsCarbobylCarboxylicAcidsOrEstersOxygen($Atom)) { 3140 $AtomType = 'O=CO'; 3141 last ATOMTYPE; 3142 } 3143 3144 # O=CR : CARBONYL OXYGEN, ALDEHYDES AND KETONES 3145 if ($This->_IsCarbonylAldehydeOrKetoneOxygen($Atom)) { 3146 $AtomType = 'O=CR'; 3147 last ATOMTYPE; 3148 } 3149 3150 # O=C : GENERAL C=O 3151 if ($This->_IsCarbonylOxygen($Atom)) { 3152 $AtomType = 'O=C'; 3153 last ATOMTYPE; 3154 } 3155 3156 # O2NO : NITRO-GROUP OXYGEN IN NITRATE 3157 if ($This->_IsNitroGroupNitrateOxygen($Atom)) { 3158 $AtomType = 'O2NO'; 3159 last ATOMTYPE; 3160 } 3161 3162 # O2N : NITRO OXYGEN 3163 if ($This->_IsNitroOxygen($Atom)) { 3164 $AtomType = 'O2N'; 3165 last ATOMTYPE; 3166 } 3167 3168 # O=N : NITROSO OXYGEN 3169 if ($This->_IsNitrosoOxygen($Atom)) { 3170 $AtomType = 'O=N'; 3171 last ATOMTYPE; 3172 } 3173 3174 # O4CL : OXYGEN IN CLO4(-) ANION - FORMAL CHARGE=-0.25 3175 if ($This->_IsPerChlorateAnionOxygen($Atom)) { 3176 $AtomType = 'O4CL'; 3177 last ATOMTYPE; 3178 } 3179 3180 $AtomType = 'None'; 3181 carp "Warning: ${ClassName}->_GetAtomTypeForOxygenWithOnePiBond: MMFF94 atom type for Oxygen cann't be assigned..."; 3182 } 3183 3184 return $AtomType; 3185 } 3186 3187 # OR : ALCOHOL OR ETHER OXYGEN 3188 # 3189 sub _IsAlcoholOrEtherOxygen { 3190 my($This, $Atom) = @_; 3191 3192 return ($This->_IsAlcoholOxygen($Atom) || $This->_IsEtherOxygen($Atom)) ? 1 : 0; 3193 } 3194 3195 # Alcohol Oxygen.. 3196 # 3197 sub _IsAlcoholOxygen { 3198 my($This, $Atom) = @_; 3199 3200 return $Atom->DoesAtomNeighborhoodMatch('O.TSB2', ['C', 'H'], ['-', '-']) ? 1 : 0; 3201 } 3202 3203 # Ether Oxygen.. 3204 # 3205 sub _IsEtherOxygen { 3206 my($This, $Atom) = @_; 3207 3208 return $Atom->DoesAtomNeighborhoodMatch('O.TSB2', ['C', 'C'], ['-', '-']) ? 1 : 0; 3209 } 3210 3211 3212 # OC=O : ESTER OR CARBOXYLIC ACID -O- 3213 # 3214 # Notes: 3215 # . Carboxylate anion Oxygen is matched using O2CM atom type. 3216 # 3217 sub _IsEsterOrCarboxylicAcidOxygen { 3218 my($This, $Atom) = @_; 3219 my($AtomNeighbor); 3220 3221 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2')) { 3222 return 0; 3223 } 3224 3225 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 3226 if ($This->_IsCarboxylicAcidOrEsterCarbonylCarbon($AtomNeighbor)) { 3227 return 1; 3228 } 3229 } 3230 return 0; 3231 } 3232 3233 # OC=C : ENOLIC OR PHENOLIC OXYGEN 3234 # 3235 sub _IsEnolicOrPhenolicOxygen { 3236 my($This, $Atom) = @_; 3237 my($AtomNeighbor); 3238 3239 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2')) { 3240 return 0; 3241 } 3242 3243 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 3244 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.T3.DB1', ['C', 'O', '*'], ['=', '-', '-'])) { 3245 return 1; 3246 } 3247 } 3248 return 0; 3249 } 3250 3251 # OC=N : DIVALENT OXYGEN 3252 # 3253 sub _IsOCNDivalentOxygen { 3254 my($This, $Atom) = @_; 3255 my($AtomNeighbor); 3256 3257 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2')) { 3258 return 0; 3259 } 3260 3261 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 3262 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.T3.DB1', ['N', 'O', '*'], ['=', '-', '-'])) { 3263 return 1; 3264 } 3265 } 3266 return 0; 3267 } 3268 3269 # OC=S : THIOESTER OR THIOACID -O- 3270 # 3271 sub _IsThioEsterOrThioAcidOxygen { 3272 my($This, $Atom) = @_; 3273 my($AtomNeighbor); 3274 3275 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2,O.X1.FC-1')) { 3276 return 0; 3277 } 3278 3279 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 3280 # Thio ester, acid or anion Oxygen... 3281 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.T3.DB1', ['S', 'O.X1.FC0,O.X2,O.X1.FC-1', 'C,H'], ['=', '-', '-'], ['C', 'C,H', 'C,H'])) { 3282 return 1; 3283 } 3284 } 3285 return 0; 3286 } 3287 3288 # ONO2 : DIVALENT NITRATE ETHER OXYGEN 3289 # 3290 # Notes: 3291 # . Nitrate anion Oxygen is matched using O3N atom type. 3292 # . Divalent Oxygen in Nitrate with one Hydrogen atom is not treated as ether ONO2. 3293 # 3294 sub _IsDivalentNitrateEtherOxygen { 3295 my($This, $Atom) = @_; 3296 my($AtomNeighbor); 3297 3298 if (!$Atom->DoesAtomNeighborhoodMatch('O.X2')) { 3299 return 0; 3300 } 3301 3302 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('N.DB1')) { 3303 if ($This->_IsNitrateNitrogen($AtomNeighbor)) { 3304 return 1; 3305 } 3306 } 3307 return 0; 3308 } 3309 3310 # ON=O : DIVALENT NITRITE ETHER OXYGEN 3311 # 3312 # Notes: 3313 # . Divalent Oxygen in Nitrite with one Hydrogen atom is not treated as ether ON=O. 3314 # 3315 sub _IsDivalentNitriteEtherOxygen { 3316 my($This, $Atom) = @_; 3317 my($AtomNeighbor); 3318 3319 if (!$Atom->DoesAtomNeighborhoodMatch('O.X2')) { 3320 return 0; 3321 } 3322 3323 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('N.DB1')) { 3324 # R-O-N=O 3325 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('N.T2.DB1.FC0', ['O', 'O.FC0'], ['=', '-'])) { 3326 return 1; 3327 } 3328 } 3329 return 0; 3330 } 3331 3332 # OSO3 : DIVALENT OXYGEN ATTACHED TO SULFUR 3333 # 3334 # Notes: 3335 # . It corresponds to divalent Oxygen in Sulfates. 3336 # . Oxygen attached to one heavy atom and one Hydrogen atom is treated as divalent 3337 # Oxygen and matched to OSO3. 3338 # . Anion Oxygen attached to one heavy atom with no Hydrogen atom is treated as terminal 3339 # Oxygen and matched to O4S. 3340 # 3341 sub _IsOSO3DivalentOxygen { 3342 my($This, $Atom) = @_; 3343 my($AtomNeighbor); 3344 3345 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2', ['S.T4'])) { 3346 return 0; 3347 } 3348 3349 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T4')) { 3350 # R'-O-S(=O)(=O)-O-R" 3351 if ($This->_IsSulfateSulfur($AtomNeighbor)) { 3352 return 1; 3353 } 3354 } 3355 return 0; 3356 } 3357 3358 # OSO2 : DIVALENT OXYGEN ATTACHED TO SULFUR 3359 # 3360 # Notes: 3361 # . It corresponds to divalent Oxygen in Sulfonates, Sulfones and so on. 3362 # . Oxygen attached to one heavy atom and one Hydrogen atom is treated as divalent 3363 # Oxygen and matched to OSO2. 3364 # . Anion Oxygen attached to one heavy atom with no Hydrogen atom is treated as terminal 3365 # Oxygen and matched to O3S. 3366 # 3367 sub _IsOSO2DivalentOxygen { 3368 my($This, $Atom) = @_; 3369 my($AtomNeighbor); 3370 3371 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2', ['S.T4'])) { 3372 return 0; 3373 } 3374 3375 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T4')) { 3376 # R'-O-S(=O)(=O)-R" 3377 if ($This->_IsSulfonateSulfur($AtomNeighbor)) { 3378 return 1; 3379 } 3380 } 3381 return 0; 3382 } 3383 3384 # OSO : DIVALENT OXYGEN ATTACHED TO SULFUR 3385 # 3386 # Notes: 3387 # . It corresponds to divalent Oxygen attached to Sulfur with single bond. 3388 # . Oxygen attached to one heavy atom and one Hydrogen atom is treated as divalent 3389 # Oxygen and matched to OSO. 3390 # 3391 sub _IsOSODivalentOxygen { 3392 my($This, $Atom) = @_; 3393 my($AtomNeighbor); 3394 3395 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2', ['S.T2'])) { 3396 return 0; 3397 } 3398 3399 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T2.DB0')) { 3400 # R'-O-S-O-R" 3401 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('S', ['O', 'O'], ['-', '-'])) { 3402 return 1; 3403 } 3404 } 3405 return 0; 3406 } 3407 3408 # OS=O : DIVALENT OXYGEN ATTACHED TO SULFOXIDE SULFUR 3409 # 3410 # Notes: 3411 # . It corresponds to divalent Oxygen in Sulfoxides. 3412 # . Oxygen attached to one heavy atom and one Hydrogen atom is treated as divalent 3413 # Oxygen and matched to OS=O. 3414 # 3415 sub _IsSulfoxideDivalentOxygen { 3416 my($This, $Atom) = @_; 3417 my($AtomNeighbor); 3418 3419 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2', ['S.T3'])) { 3420 return 0; 3421 } 3422 3423 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T3.DB1')) { 3424 # R'-O-S(=O)-R" 3425 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('S.T3.DB1', ['O', 'O', '*'], ['=', '-', '-'])) { 3426 return 1; 3427 } 3428 } 3429 return 0; 3430 } 3431 3432 # -OS : GENERAL DIVALENT OXYGEN ATTACHED TO S 3433 # 3434 # Notes: 3435 # . It covers any divalent Oxygen attached to Sulfur. 3436 # 3437 sub _IsOSDivalentOxygen { 3438 my($This, $Atom) = @_; 3439 my($AtomNeighbor); 3440 3441 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2', ['S'])) { 3442 return 0; 3443 } 3444 3445 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S')) { 3446 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('S', ['O'], ['-'])) { 3447 return 1; 3448 } 3449 } 3450 return 0; 3451 } 3452 3453 # OPO3 : DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 3454 # 3455 # Notes: 3456 # . It corresponds to divalent Oxygen in Phopsphates or Phosphodiesters. 3457 # 3458 sub _IsOPO3DivalentOxygen { 3459 my($This, $Atom) = @_; 3460 my($AtomNeighbor); 3461 3462 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2')) { 3463 return 0; 3464 } 3465 3466 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P.T4')) { 3467 if ($This->_IsPhosphateOrPhosphodiesterPhosphorus($AtomNeighbor)) { 3468 return 1; 3469 } 3470 } 3471 return 0; 3472 } 3473 3474 # OPO2 : DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 3475 # 3476 # Notes: 3477 # . It corresponds to divalent Oxygen in Phopsphonates or their esters. 3478 # 3479 sub _IsOPO2DivalentOxygen { 3480 my($This, $Atom) = @_; 3481 my($AtomNeighbor); 3482 3483 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2')) { 3484 return 0; 3485 } 3486 3487 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P.T4')) { 3488 if ($This->_IsPhosphonatePhosphorus($AtomNeighbor)) { 3489 return 1; 3490 } 3491 } 3492 return 0; 3493 } 3494 3495 # OPO : DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 3496 # 3497 # Notes: 3498 # . It corresponds to divalent Oxygen in Phopsphinates. 3499 # 3500 sub _IsOPODivalentOxygen { 3501 my($This, $Atom) = @_; 3502 my($AtomNeighbor); 3503 3504 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2')) { 3505 return 0; 3506 } 3507 3508 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P.T4')) { 3509 if ($This->_IsPhosphinatePhosphorus($AtomNeighbor)) { 3510 return 1; 3511 } 3512 } 3513 return 0; 3514 } 3515 3516 # -OP : DIVALENT OXYGEN ATTACHED TO PHOSPHOROUS 3517 # 3518 sub _IsOPDivalentOxygen { 3519 my($This, $Atom) = @_; 3520 my($AtomNeighbor); 3521 3522 if (!$Atom->DoesAtomNeighborhoodMatch('O.TSB2')) { 3523 return 0; 3524 } 3525 3526 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P')) { 3527 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('P', ['O'], ['-'])) { 3528 return 1; 3529 } 3530 } 3531 return 0; 3532 } 3533 3534 # -O- : GENERAL DIVALENT O 3535 # 3536 sub _IsDivalentOxygen { 3537 my($This, $Atom) = @_; 3538 3539 return $Atom->DoesAtomNeighborhoodMatch('O.TSB2') ? 1 : 0; 3540 } 3541 3542 # O=C : GENERAL C=O 3543 # 3544 sub _IsCarbonylOxygen { 3545 my($This, $Atom) = @_; 3546 3547 return $Atom->DoesAtomNeighborhoodMatch('O.T1.DB1', ['C'], ['=']) ? 1 : 0; 3548 } 3549 3550 # O=CN : CARBONYL OXYGEN, AMIDES 3551 # 3552 sub _IsAmideCarbonylOxygen { 3553 my($This, $Atom) = @_; 3554 my($AtomNeighbor); 3555 3556 if (!$Atom->DoesAtomNeighborhoodMatch('O.T1.DB1')) { 3557 return 0; 3558 } 3559 3560 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 3561 if ($This->_IsAmideCarbonylCarbon($AtomNeighbor)) { 3562 return 1; 3563 } 3564 } 3565 return 0; 3566 } 3567 3568 # O=CR : CARBONYL OXYGEN, ALDEHYDES AND KETONES 3569 # 3570 sub _IsCarbonylAldehydeOrKetoneOxygen { 3571 my($This, $Atom) = @_; 3572 my($AtomNeighbor); 3573 3574 if (!$Atom->DoesAtomNeighborhoodMatch('O.T1.DB1')) { 3575 return 0; 3576 } 3577 3578 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 3579 if ($This->_IsKetoneOrAldehydeCarbonylCarbon($AtomNeighbor)) { 3580 return 1; 3581 } 3582 } 3583 return 0; 3584 } 3585 3586 # O=CO : CARBONYL OXYGEN, CARBOXYLIC ACIDS AND ESTERS 3587 # 3588 sub _IsCarbobylCarboxylicAcidsOrEstersOxygen { 3589 my($This, $Atom) = @_; 3590 my($AtomNeighbor); 3591 3592 if (!$Atom->DoesAtomNeighborhoodMatch('O.T1.DB1')) { 3593 return 0; 3594 } 3595 3596 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 3597 if ($This->_IsCarboxylicAcidOrEsterCarbonylCarbon($AtomNeighbor)) { 3598 return 1; 3599 } 3600 } 3601 return 0; 3602 } 3603 3604 # O=N : NITROSO OXYGEN 3605 # 3606 sub _IsNitrosoOxygen { 3607 my($This, $Atom) = @_; 3608 3609 return $Atom->DoesAtomNeighborhoodMatch('O.T1.DB1', ['N'], ['=']) ? 1 : 0; 3610 } 3611 3612 # O=S : O=S IN SULFOXIDES 3613 # 3614 sub _IsSulfoxideOxygen { 3615 my($This, $Atom) = @_; 3616 my($AtomNeighbor); 3617 3618 if (!$Atom->DoesAtomNeighborhoodMatch('O.T1.DB1')) { 3619 return 0; 3620 } 3621 3622 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.DB1')) { 3623 if ($This->_IsSulfoxideSulfur($AtomNeighbor)) { 3624 return 1; 3625 } 3626 } 3627 return 0; 3628 } 3629 3630 # O=S= : O=S ON SULFUR DOUBLY BONDED TO, E.G., CARBON 3631 # 3632 sub _IsDoublyBondedOSOxygen { 3633 my($This, $Atom) = @_; 3634 my($AtomNeighbor); 3635 3636 if (!$Atom->DoesAtomNeighborhoodMatch('O.T1.DB1')) { 3637 return 0; 3638 } 3639 3640 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.DB2')) { 3641 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('S', ['O', '!O'], ['=', '='])) { 3642 return 1; 3643 } 3644 } 3645 return 0; 3646 } 3647 3648 # O2CM : OXYGEN IN CARBOXYLATE ANION 3649 # 3650 sub _IsCarboxylateAnionOxygen { 3651 my($This, $Atom) = @_; 3652 my($AtomNeighbor); 3653 3654 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1.FC-1')) { 3655 return 0; 3656 } 3657 3658 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.T3.DB1')) { 3659 if ($This->_IsCarboxylateAnionCarbon($AtomNeighbor)) { 3660 return 1; 3661 } 3662 } 3663 return 0; 3664 } 3665 3666 # OXN : N-OXIDE OXYGEN 3667 # 3668 sub _IsNOxideOxygen { 3669 my($This, $Atom) = @_; 3670 3671 return $Atom->DoesAtomNeighborhoodMatch('O.X1.FC-1', ['N.FC+1'], ['-']) ? 1 : 0; 3672 } 3673 3674 # O2N : NITRO OXYGEN 3675 # 3676 sub _IsNitroOxygen { 3677 my($This, $Atom) = @_; 3678 my($AtomNeighbor); 3679 3680 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1.DB1,O.X1.FC-1')) { 3681 return 0; 3682 } 3683 3684 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('N.T3.DB1')) { 3685 if ($This->_IsNitroNitrogen($AtomNeighbor)) { 3686 return 1; 3687 } 3688 } 3689 return 0; 3690 } 3691 3692 # O2NO : NITRO-GROUP OXYGEN IN NITRATE 3693 # 3694 sub _IsNitroGroupNitrateOxygen { 3695 my($This, $Atom) = @_; 3696 my($AtomNeighbor); 3697 3698 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1.DB1')) { 3699 return 0; 3700 } 3701 3702 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('N.T3.DB1')) { 3703 if ($This->_IsNitrateNitrogen($AtomNeighbor)) { 3704 return 1; 3705 } 3706 } 3707 return 0; 3708 } 3709 3710 # O3N : NITRATE ANION OXYGEN 3711 # 3712 sub _IsNitrateAnionOxygen { 3713 my($This, $Atom) = @_; 3714 my($AtomNeighbor); 3715 3716 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1.FC-1')) { 3717 return 0; 3718 } 3719 3720 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('N.T3.DB1')) { 3721 if ($This->_IsNitrateNitrogen($AtomNeighbor)) { 3722 return 1; 3723 } 3724 } 3725 return 0; 3726 } 3727 3728 # O-S : SINGLE TERMINAL OXYGEN ON TETRACOORD SULFUR 3729 # 3730 sub _IsOSTerminalOxygen { 3731 my($This, $Atom) = @_; 3732 my($AtomNeighbor); 3733 3734 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1', ['S.T4'])) { 3735 return 0; 3736 } 3737 3738 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T4')) { 3739 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('S', ['O.X1', '!O', '!O', '!O'])) { 3740 return 1; 3741 } 3742 } 3743 return 0; 3744 } 3745 3746 # O2S : TERMINAL O-S IN SULFONES AND SULFONAMIDES 3747 # 3748 sub _IsSulfoneOrSulfonamideTerminalOxygen { 3749 my($This, $Atom) = @_; 3750 my($AtomNeighbor); 3751 3752 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1', ['S.T4'])) { 3753 return 0; 3754 } 3755 3756 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T4')) { 3757 if ($This->_IsSulfonamideSulfur($AtomNeighbor) || $This->_IsSulfoneSulfur($AtomNeighbor)) { 3758 return 1; 3759 } 3760 } 3761 return 0; 3762 } 3763 3764 # O3S : TERMINAL O IN SULFONATES 3765 # 3766 # Notes: 3767 # . It corresponds to monovalent Oxygen in Sulfonates. 3768 # . Anion Oxygen attached to one heavy atom with no Hydrogen atom is treated as terminal 3769 # Oxygen and matched to O3S. 3770 # 3771 sub _IsSulfonateTerminalOxygen { 3772 my($This, $Atom) = @_; 3773 my($AtomNeighbor); 3774 3775 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1', ['S.T4'])) { 3776 return 0; 3777 } 3778 3779 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T4')) { 3780 # R'-O-S(=O)(=O)-R", [O-]-S(=O)(=O)-R", 3781 if ($This->_IsSulfonateSulfur($AtomNeighbor)) { 3782 return 1; 3783 } 3784 } 3785 return 0; 3786 } 3787 3788 # O4S : TERMINAL O IN SO4(-3) 3789 # 3790 # Notes: 3791 # . It corresponds to monovalent Oxygen in Sulfates. 3792 # . As far I can tell, SO4 should have a formal charge of -2. 3793 # . Anion Oxygen attached to one heavy atom with no Hydrogen atom is treated as terminal 3794 # Oxygen and matched to O4S. 3795 # 3796 sub _IsSulfateTerminalOxygen { 3797 my($This, $Atom) = @_; 3798 my($AtomNeighbor); 3799 3800 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1', ['S.T4'])) { 3801 return 0; 3802 } 3803 3804 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.T4')) { 3805 # R'-O-S(=O)(=O)-O-R", R'-O-S(=O)(=O)-[O-] 3806 if ($This->_IsSulfateSulfur($AtomNeighbor)) { 3807 return 1; 3808 } 3809 } 3810 return 0; 3811 } 3812 3813 # OSMS : TERM O IN THIOSULFINATE ANION - FORMAL CHARGE=-0.5 3814 # 3815 sub _IsThioSulfinateTerminalOxygen { 3816 my($This, $Atom) = @_; 3817 my($AtomNeighbor); 3818 3819 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1', ['S.FC+1'])) { 3820 return 0; 3821 } 3822 3823 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.FC+1')) { 3824 if ($This->_IsThioSulfinateSulfur($AtomNeighbor)) { 3825 return 1; 3826 } 3827 } 3828 return 0; 3829 } 3830 3831 # OP : TERMINAL O IN PHOSPHOXIDES 3832 # 3833 sub _IsPhosphoxideTerminalOxygen { 3834 my($This, $Atom) = @_; 3835 my($AtomNeighbor); 3836 3837 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1', ['P.T4'])) { 3838 return 0; 3839 } 3840 3841 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P.T4')) { 3842 if ($This->_IsPhosphoxidePhosphorus($AtomNeighbor)) { 3843 return 1; 3844 } 3845 } 3846 return 0; 3847 } 3848 3849 # O2P : TERMINAL O IN PHOSPHINATES 3850 # 3851 sub _IsPhosphinateTerminalOxygen { 3852 my($This, $Atom) = @_; 3853 my($AtomNeighbor); 3854 3855 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1', ['P.T4'])) { 3856 return 0; 3857 } 3858 3859 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P.T4')) { 3860 if ($This->_IsPhosphinatePhosphorus($AtomNeighbor)) { 3861 return 1; 3862 } 3863 } 3864 return 0; 3865 } 3866 3867 # O3P : TERMINAL OXYGEN IN PHOSPHONATES 3868 # 3869 sub _IsPhosphonateTerminalOxygen { 3870 my($This, $Atom) = @_; 3871 my($AtomNeighbor); 3872 3873 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1', ['P.T4'])) { 3874 return 0; 3875 } 3876 3877 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P.T4')) { 3878 if ($This->_IsPhosphonatePhosphorus($AtomNeighbor)) { 3879 return 1; 3880 } 3881 } 3882 return 0; 3883 } 3884 3885 # O4P : TERMINAL OXYGEN IN PHOSPHATES AND PHOSPHODIESTERS 3886 # 3887 sub _IsPhosphateOrPhosphodiesterTerminalOxygen { 3888 my($This, $Atom) = @_; 3889 my($AtomNeighbor); 3890 3891 if (!$Atom->DoesAtomNeighborhoodMatch('O.X1', ['P.T4'])) { 3892 return 0; 3893 } 3894 3895 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('P.T4')) { 3896 if ($This->_IsPhosphateOrPhosphodiesterPhosphorus($AtomNeighbor)) { 3897 return 1; 3898 } 3899 } 3900 return 0; 3901 } 3902 3903 # O4CL : OXYGEN IN CLO4(-) ANION - FORMAL CHARGE=-0.25 3904 # 3905 sub _IsPerChlorateAnionOxygen { 3906 my($This, $Atom) = @_; 3907 my($AtomNeighbor); 3908 3909 # All Oxygens in PerChlorate anion and ester are matched to O4Cl... 3910 if (!$Atom->DoesAtomNeighborhoodMatch('O', ['Cl'])) { 3911 return 0; 3912 } 3913 3914 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('Cl')) { 3915 if ($This->_IsPerChlorateAnionChlorine($AtomNeighbor)) { 3916 return 1; 3917 } 3918 } 3919 return 0; 3920 } 3921 3922 # OM : ALKOXIDE OXYGEN, NEGATIVELY CHARGED 3923 # 3924 sub _IsNegativelyChargedAlkoxideOxygen { 3925 my($This, $Atom) = @_; 3926 3927 # R-(O-) 3928 3929 return $Atom->DoesAtomNeighborhoodMatch('O.FC-1.T1', ['C,H'], ['-']) ? 1 : 0; 3930 } 3931 3932 # OM2 : OXIDE OXYGEN ON SP2 CARBON, NEGATIVELY CHARGED 3933 # 3934 sub _IsNegativelyChargedSP2OxideOxygen { 3935 my($This, $Atom) = @_; 3936 3937 return $Atom->DoesAtomNeighborhoodMatch('O.FC-1.T1', ['C.DB1.T3'], ['-']) ? 1 : 0; 3938 } 3939 3940 # O+ : POSITIVELY CHARGED OXONIUM (TRICOORDINATE) OXYGEN 3941 # 3942 sub _IsPositivelyChargedOxoniumOxygen { 3943 my($This, $Atom) = @_; 3944 3945 return $Atom->DoesAtomNeighborhoodMatch('O.FC+1.T3.DB0') ? 1 : 0; 3946 } 3947 3948 # O=+ : POSITIVELY CHARGED OXENIUM (DICOORDINATE) OXYGEN 3949 # 3950 sub _IsPositivelyChargedOxeniumOxygen { 3951 my($This, $Atom) = @_; 3952 3953 return $Atom->DoesAtomNeighborhoodMatch('O.FC+1.T2.DB1') ? 1 : 0; 3954 } 3955 3956 # OFUR : AROMATIC OXYGEN AS IN FURAN 3957 # 3958 sub _IsAromaticOxygen { 3959 my($This, $Atom) = @_; 3960 3961 return $Atom->DoesAtomNeighborhoodMatch('O.Ar.RA5') ? 1 : 0; 3962 } 3963 3964 # OH2 : OXYGEN ON WATER 3965 # 3966 sub _IsWaterOxygen { 3967 my($This, $Atom) = @_; 3968 3969 return $Atom->DoesAtomNeighborhoodMatch('O.T2.TSB2', ['H', 'H'], ['-', '-']) ? 1 : 0; 3970 } 3971 3972 # PO4 : PHOSPHOROUS IN PHOSPHATES AND PHOSPHODIESTERS 3973 # 3974 sub _IsPhosphateOrPhosphodiesterPhosphorus { 3975 my($This, $Atom) = @_; 3976 3977 # Phosphate: R-O-P(=O)(-O)-O; Phosphate diester: R'-O-P(=O)(-O)-O-R" 3978 3979 return $Atom->DoesAtomNeighborhoodMatch('P.T4.DB1', ['O', 'O', 'O', 'O'], ['=', '-', '-', '-']) ? 1 : 0; 3980 } 3981 3982 # PO3 : TETRACOORDINATE P WITH THREE ATTACHED OXYGENS 3983 # 3984 sub _IsPhosphonatePhosphorus { 3985 my($This, $Atom) = @_; 3986 3987 # Phosphonate: R-P(=O)(-O)-O; Phosphonate ester: R'-P(=O)(-O)-O-R" 3988 3989 return $Atom->DoesAtomNeighborhoodMatch('P.T4.DB1', ['O', 'O', 'O', '!O'], ['=', '-', '-', '-']) ? 1 : 0; 3990 } 3991 3992 # PO2 : TETRACOORDINATE P WITH TWO ATTACHED OXYGENS 3993 # 3994 sub _IsPhosphinatePhosphorus { 3995 my($This, $Atom) = @_; 3996 3997 # Phosphinate: R-P(=O)(-O)-R"; Phosphinate ester: R'-P(=O)(-O)-R" 3998 3999 return $Atom->DoesAtomNeighborhoodMatch('P.T4.DB1', ['O', 'O', '!O', '!O'], ['=', '-', '-', '-']) ? 1 : 0; 4000 } 4001 4002 # PO : TETRACOORDINATE P WITH ONE ATTACHED OXYGEN 4003 # 4004 sub _IsPhosphoxidePhosphorus { 4005 my($This, $Atom) = @_; 4006 4007 # Phosphoxide: R-P(=O)(-R")-R''' 4008 4009 return $Atom->DoesAtomNeighborhoodMatch('P.T4.DB1', ['O', '!O', '!O', '!O'], ['=', '-', '-', '-']) ? 1 : 0; 4010 } 4011 4012 # PTET : GENERAL TETRACOORDINATE PHOSPHORUS 4013 # 4014 sub _IsTetraCoordinatedPhosphorus { 4015 my($This, $Atom) = @_; 4016 4017 return $Atom->DoesAtomNeighborhoodMatch('P.T4') ? 1 : 0; 4018 } 4019 4020 # P : TRICOORDINATE P, AS IN PHOSPHINES 4021 # 4022 sub _IsTriCoordinatedPhosphorus { 4023 my($This, $Atom) = @_; 4024 4025 return $Atom->DoesAtomNeighborhoodMatch('P.T3') ? 1 : 0; 4026 } 4027 4028 # -P=C : PHOSPHOROUS DOUBLY BONDED TO CARBON 4029 # 4030 sub _IsDoublyBondedToCarbonPhosphorous { 4031 my($This, $Atom) = @_; 4032 4033 return $Atom->DoesAtomNeighborhoodMatch('P.DB1', ['C'], ['=']) ? 1 : 0; 4034 } 4035 4036 # S : SULFUR IN THIOETHERS AND MERCAPTANS 4037 # 4038 sub _IsThioEthersOrMercaptansSulfur { 4039 my($This, $Atom) = @_; 4040 4041 return ($This->_IsThioEtherSulfur($Atom) || $This->_IsMercaptansSulfur($Atom)) ? 1 : 0; 4042 4043 return 0; 4044 } 4045 4046 # Thioethers: R'-S-R" 4047 # 4048 sub _IsThioEtherSulfur { 4049 my($This, $Atom) = @_; 4050 my($AtomNeighbor); 4051 4052 return $Atom->DoesAtomNeighborhoodMatch('S.X2.T2', ['C', 'C'], ['-', '-']) ? 1 : 0; 4053 } 4054 4055 # Mercaptans or Thiols: R-S-H 4056 # 4057 sub _IsMercaptansSulfur { 4058 my($This, $Atom) = @_; 4059 4060 return $Atom->DoesAtomNeighborhoodMatch('S.T2', ['C', 'C,H'], ['-', '-']) ? 1 : 0; 4061 } 4062 4063 # Is it a divalent dicoordinated Sulfur... 4064 # 4065 sub _IsDivalentDiCoordinatedSulfur { 4066 my($This, $Atom) = @_; 4067 4068 return $Atom->DoesAtomNeighborhoodMatch('S.T2.FC0', ['*', '*'], ['-', '-']) ? 1 : 0; 4069 } 4070 4071 # S=C : TERMINAL SULFUR DOUBLY BONDED TO CARBON 4072 # 4073 sub _IsSCTerminalSulfur { 4074 my($This, $Atom) = @_; 4075 4076 return $Atom->DoesAtomNeighborhoodMatch('S.X1.DB1', ['C'], ['=']) ? 1 : 0; 4077 } 4078 4079 # >S=N : SULFUR, TRICOORD, DOUBLY BONDED TO N 4080 # 4081 sub _IsSNTricoordinatedSulfur { 4082 my($This, $Atom) = @_; 4083 4084 return $Atom->DoesAtomNeighborhoodMatch('S.T3.DB1', ['N', '*', '*'], ['=', '-', '-']) ? 1 : 0; 4085 } 4086 4087 # S=O : SULFUR IN SULFOXIDES 4088 # 4089 sub _IsSulfoxideSulfur { 4090 my($This, $Atom) = @_; 4091 4092 # Sulfone: R'-S(=O)-R", R'-S(=O)-O-R", and so on... 4093 4094 return $Atom->DoesAtomNeighborhoodMatch('S.T3.DB1', ['O', '*', '*'], ['=', '-', '-']) ? 1 : 0; 4095 } 4096 4097 # SO2 : SULFUR IN SULFONES 4098 # 4099 sub _IsSulfoneSulfur { 4100 my($This, $Atom) = @_; 4101 4102 # Sulfone: R'-S(=O)(=O)-R" 4103 4104 return $Atom->DoesAtomNeighborhoodMatch('S.T4.DB2', ['O', 'O', '!O', '!O'], ['=', '=', '-', '-']) ? 1 : 0; 4105 } 4106 4107 # =SO2: SULFONE SULPHER DOUBLY BONDED TO CARBON 4108 # 4109 sub _IsDoublyBondedToCarbonSulfoneSulfur { 4110 my($This, $Atom) = @_; 4111 4112 return $Atom->DoesAtomNeighborhoodMatch('S.T3.DB3', ['C', 'O', 'O'], ['=', '=', '=']) ? 1 : 0; 4113 } 4114 4115 # SO2N : SULFUR IN SULFONAMIDES 4116 # 4117 sub _IsSulfonamideSulfur { 4118 my($This, $Atom) = @_; 4119 4120 # Sulfonamide: R-S(=O)(=O)-N(-R)(-R") 4121 4122 return $Atom->DoesAtomNeighborhoodMatch('S.T4.DB2', ['O', 'O', 'N', '!O'], ['=', '=', '-', '-']) ? 1 : 0; 4123 } 4124 4125 # SO3 : SULFONATE SULFUR 4126 # 4127 sub _IsSulfonateSulfur { 4128 my($This, $Atom) = @_; 4129 4130 # Sulfonate ion: R'-S(=O)(=O)-(O-); Sulfonate ester: R'-S(=O)(=O)-O-R" 4131 4132 return $Atom->DoesAtomNeighborhoodMatch('S.T4.DB2', ['O', 'O', 'O', '!O'], ['=', '=', '-', '-']) ? 1 : 0; 4133 } 4134 4135 # SO4 : SULFATE SULFUR 4136 # 4137 sub _IsSulfateSulfur { 4138 my($This, $Atom) = @_; 4139 4140 # Sulfate ion: (O-)-S(=O)(=O)-(O-); Sulfate esters: R-O-S(=O)(=O)-O-R" 4141 4142 return $Atom->DoesAtomNeighborhoodMatch('S.T4.DB2', ['O', 'O', 'O', 'O'], ['=', '=', '-', '-']) ? 1 : 0; 4143 } 4144 4145 # SNO : SULFUR IN NITROGEN ANALOG OF A SULFONE 4146 # 4147 sub _IsNitrogenAnalogOfSulfoneSulfur { 4148 my($This, $Atom) = @_; 4149 4150 # Sulfone: R'-S(=N)(=O)-R" 4151 4152 return $Atom->DoesAtomNeighborhoodMatch('S.T4.DB2', ['N', 'O', '!O', '!O'], ['=', '=', '-', '-']) ? 1 : 0; 4153 } 4154 4155 # STHI : SULFUR AS IN THIOPHENE 4156 # 4157 sub _IsSTHISulfur { 4158 my($This, $Atom) = @_; 4159 4160 # Is it an aromatic atom in a five membered ring? 4161 if (!$Atom->DoesAtomNeighborhoodMatch('S.Ar.RA5.FC0')) { 4162 return 0; 4163 } 4164 4165 # Is it part of five membered ring containing only one hetero atom? 4166 my($RingAtomsRef, $RingIsAromatic, $NumOfHeteroAtoms); 4167 4168 for $RingAtomsRef ($Atom->GetRingsWithSize(5)) { 4169 ($RingIsAromatic, $NumOfHeteroAtoms) = $This->_GetHeteroAtomsInformationInRing($RingAtomsRef); 4170 if ($RingIsAromatic && $NumOfHeteroAtoms == 1) { 4171 return 1; 4172 } 4173 } 4174 return 0; 4175 } 4176 4177 # S-P : TERMINAL SULFUR BONDED TO PHOSPHORUS 4178 # 4179 sub _IsSPTerminalSulfur { 4180 my($This, $Atom) = @_; 4181 4182 return $Atom->DoesAtomNeighborhoodMatch('S.X1.T2', ['P', '*'], ['-', '-']) ? 1 : 0; 4183 } 4184 4185 # S2CM : TERMINAL SULFUR IN THIOCARBOXYLATE ANION 4186 # 4187 sub _IsThioCarboxylateAnionTerminalSulfur { 4188 my($This, $Atom) = @_; 4189 my($AtomNeighbor); 4190 4191 if (!$Atom->DoesAtomNeighborhoodMatch('S.X1.FC-1, S.X1.DB1.FC0')) { 4192 return 0; 4193 } 4194 4195 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C.DB1')) { 4196 if ($This->_IsThioCarboxylateAnionCarbon($AtomNeighbor)) { 4197 return 1; 4198 } 4199 } 4200 return 0; 4201 } 4202 4203 # SM : TERMINAL SULFUR - FORMAL CHARGE=-1 4204 # 4205 sub _IsNegativelyChargedTerminalSulfur { 4206 my($This, $Atom) = @_; 4207 4208 return $Atom->DoesAtomNeighborhoodMatch('S.X1.FC-1', ['*'], ['-']) ? 1 : 0; 4209 } 4210 4211 # SSMO : TERMINAL SULFUR IN THIOSULFINATE GROUP 4212 # 4213 sub _IsThioSulfinateTerminalSulfur { 4214 my($This, $Atom) = @_; 4215 my($AtomNeighbor); 4216 4217 if (!$Atom->DoesAtomNeighborhoodMatch('S.X1', ['S.FC+1'])) { 4218 return 0; 4219 } 4220 4221 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('S.FC+1')) { 4222 if ($This->_IsThioSulfinateSulfur($AtomNeighbor)) { 4223 return 1; 4224 } 4225 } 4226 return 0; 4227 } 4228 4229 # SO2M : SULFUR IN NEGATIVELY CHARGED SULFINATE GROUP 4230 # 4231 sub _IsNegativelyChargedSulfinateSulfur { 4232 my($This, $Atom) = @_; 4233 4234 # Sulfinate ion: R'-S(=O)-(O-) 4235 4236 return $Atom->DoesAtomNeighborhoodMatch('S.T3.DB1', ['O', 'O.X1.FC-1', '!O'], ['=', '-', '-']) ? 1 : 0; 4237 } 4238 4239 # Sulfinate: R'-S(=O)-OH; Sulfinate esters: R'-S(=O)-O-R 4240 # 4241 sub _IsSulfinateSulfur { 4242 my($This, $Atom) = @_; 4243 4244 return $Atom->DoesAtomNeighborhoodMatch('S.T3.DB1', ['O', 'O.X1.FC0,O.X2', '!O'], ['=', '-', '-']) ? 1 : 0; 4245 } 4246 4247 # SSOM : TRICOORD SULFUR IN THIOSULFINATE GROUP 4248 # 4249 sub _IsTriCoordinatedThioSulfinateSulfur { 4250 my($This, $Atom) = @_; 4251 my($AtomNeighbor); 4252 4253 if (!$Atom->DoesAtomNeighborhoodMatch('S.X3', ['S'])) { 4254 return 0; 4255 } 4256 4257 if ($This->_IsThioSulfinateSulfur($Atom)) { 4258 return 1; 4259 } 4260 4261 return 0; 4262 } 4263 4264 # Is it a Thiosulfinate group? 4265 # 4266 sub _IsThioSulfinateSulfur { 4267 my($This, $Atom) = @_; 4268 4269 # R'-[S+1](-[O-1])-S-R" 4270 4271 return $Atom->DoesAtomNeighborhoodMatch('S.FC+1', ['O.FC-1', 'S', '!O'], ['-', '-', '-']) ? 1 : 0; 4272 } 4273 4274 # =S=O: SULFINYL SULFUR, EG. IN C=S=O 4275 # 4276 sub _IsSulfinylSulfur { 4277 my($This, $Atom) = @_; 4278 4279 return $Atom->DoesAtomNeighborhoodMatch('S.X2.DB2', ['C', 'O'], ['=', '=']) ? 1 : 0; 4280 } 4281 4282 # CLO4 : CHLORINE IN PERCHLORATE ANION, CLO4(-) 4283 # 4284 sub _IsPerChlorateAnionChlorine { 4285 my($This, $Atom) = @_; 4286 4287 # R-O-Cl(=O)(=O)=O or (O-)-Cl(=O)(=O)=O 4288 if ($Atom->DoesAtomNeighborhoodMatch('Cl.X4.DB3', ['O.X1.FC-1,O.T2.FC0', 'O', 'O', 'O'], ['-', '=', '=', '='])) { 4289 return 1; 4290 } 4291 4292 # Match distributed formal charge of -0.25 on each Oxygen? 4293 if ($Atom->DoesAtomNeighborhoodMatch('Cl.X4.DB3', ['O.FC-0.25', 'O.FC-0.25', 'O.FC-0.25', 'O.FC-0.25'], ['*', '*', '*', '*'])) { 4294 return 1; 4295 } 4296 4297 return 0; 4298 } 4299 4300 # Get MMFF94 atom type for Hydrogen attached to Carbon... 4301 # 4302 sub _GetAtomTypeForHydrogenAttachedToCarbon { 4303 my($This, $CarbonAtom) = @_; 4304 my($AtomType); 4305 4306 # HC : H ATTACHED TO C 4307 $AtomType = 'HC'; 4308 4309 return $AtomType; 4310 } 4311 4312 # Get MMFF94 atom type for Hydrogen attached to Nitrogen... 4313 # 4314 # 25 AtomTypeSymbols for element H: 4315 # 4316 # AtomTypeSymbol AtomTypeNum AtomTypeDefinition 4317 # HNR 23 H-N(SP3) 4318 # H3N 23 H-N(SP3), AMMONIA 4319 # HPYL 23 H-N IN PYRROLE 4320 # HNOX 23 H-N IN IN A N-OXIDE 4321 # HNM 23 H ON DICOORD, NEGATIVELY CHARGED NITROGEN 4322 # HN 23 GENERAL H ON NITROGEN 4323 # HN=N 27 AZO HYDROGEN 4324 # HN=C 27 IMINE HYDROGEN 4325 # HNCO 28 AMIDE HYDROGEN 4326 # HNCS 28 THIOAMIDE HYDROGEN 4327 # HNCC 28 H-N IN ENAMINES 4328 # HNCN 28 H-N IN H-N-C=N 4329 # HNNC 28 H-N IN H-N-N=C 4330 # HNNN 28 H-N IN H-N-N=N 4331 # HNSO 28 H-N IN SULFONAMIDE 4332 # HNPO 28 H-N IN PHOSPHONAMIDE 4333 # HNC% 28 HYDROGEN ON N ATTACHED TO TRIPLY BONDED CARBON 4334 # HSP2 28 GENERAL H ON SP2 NITROGEN 4335 # HNR+ 36 H ON QUATERNARY NITROGEN 4336 # HIM+ 36 H ON IMIDAZOLIUM-TYPE NITROGEN 4337 # HPD+ 36 H ON PROTONATED PYRIDINE NITROGEN 4338 # HNN+ 36 H ON AMIDINIUM-TYPE NITROGEN 4339 # HNC+ 36 H ON PROTONATED IMINE NITROGEN 4340 # HGD+ 36 H ON GUANIDINIUM-TYPE NITROGEN 4341 # HN5+ 36 H ON N5+, N5A+ OR N5B+ 4342 # 4343 sub _GetAtomTypeForHydrogenAttachedToNitrogen { 4344 my($This, $NitrogenAtom) = @_; 4345 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 4346 4347 $AtomType = 'None'; 4348 4349 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 4350 4351 ($NumOfSigmaBonds, $NumOfPiBonds) = $NitrogenAtom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 4352 $NumOfSigmaBonds += $NitrogenAtom->GetAtomicInvariantValue('H'); 4353 4354 ATOMTYPE: { 4355 4356 if ($NumOfPiBonds == 0) { 4357 $AtomType = $This->_GetAtomTypeForHydrogenAttachedToNitrogenWithOnlySigmaBonds($NitrogenAtom); 4358 last ATOMTYPE; 4359 } 4360 4361 if ($NumOfPiBonds == 1) { 4362 $AtomType = $This->_GetAtomTypeForHydrogenAttachedToNitrogenWithOnePiBond($NitrogenAtom); 4363 last ATOMTYPE; 4364 } 4365 4366 if ($NumOfPiBonds == 2) { 4367 $AtomType = $This->_GetAtomTypeForHydrogenAttachedToNitrogenWithTwoPiBonds($NitrogenAtom); 4368 last ATOMTYPE; 4369 } 4370 4371 # HN : GENERAL H ON NITROGEN 4372 $AtomType = 'HN'; 4373 } 4374 return $AtomType; 4375 } 4376 4377 # Get atom type for Hydrogen attached to a Nitrogen with only sigma bonds... 4378 # 4379 sub _GetAtomTypeForHydrogenAttachedToNitrogenWithOnlySigmaBonds { 4380 my($This, $NitrogenAtom) = @_; 4381 my($AtomType); 4382 4383 $AtomType = 'None'; 4384 4385 ATOMTYPE: { 4386 4387 # HNC% : HYDROGEN ON N ATTACHED TO TRIPLY BONDED CARBON 4388 if ($This->_IsHydrogenAttachedToTriplyBondedToCarbonNitrogen($NitrogenAtom)) { 4389 $AtomType = 'HNC%'; 4390 last ATOMTYPE; 4391 } 4392 4393 # HPYL : H-N IN PYRROLE 4394 if ($This->_IsHydrogenAttachedToPyrroleNitrogen($NitrogenAtom)) { 4395 $AtomType = 'HPYL'; 4396 last ATOMTYPE; 4397 } 4398 4399 # HN5+ : H ON N5+, N5A+ OR N5B+ 4400 if ($This->_IsHydrogenAttachedToFiveMemberedHetreoCyclicPostivelyChargedNitrogen($NitrogenAtom)) { 4401 $AtomType = 'HN5+'; 4402 last ATOMTYPE; 4403 } 4404 4405 # HGD+ : H ON GUANIDINIUM-TYPE NITROGEN 4406 if ($This->_IsHydrogenAttachedToGuanidiniumNitrogen($NitrogenAtom)) { 4407 $AtomType = 'HGD+'; 4408 last ATOMTYPE; 4409 } 4410 4411 # HNCS : THIOAMIDE HYDROGEN 4412 if ($This->_IsHydrogenAttachedToThioamideNitrogen($NitrogenAtom)) { 4413 $AtomType = 'HNCS'; 4414 last ATOMTYPE; 4415 } 4416 4417 # HNCO : AMIDE HYDROGEN 4418 if ($This->_IsHydrogenAttachedToAmideNitrogen($NitrogenAtom)) { 4419 $AtomType = 'HNCO'; 4420 last ATOMTYPE; 4421 } 4422 4423 # HNSO : H-N IN SULFONAMIDE 4424 if ($This->_IsHydrogenAttachedToSulfonamideNitrogen($NitrogenAtom)) { 4425 $AtomType = 'HNSO'; 4426 last ATOMTYPE; 4427 } 4428 4429 # HNPO : H-N IN PHOSPHONAMIDE 4430 if ($This->_IsHydrogenAttachedToPhosphonamideNitrogen($NitrogenAtom)) { 4431 $AtomType = 'HNPO'; 4432 last ATOMTYPE; 4433 } 4434 4435 # HNOX : H-N IN IN A N-OXIDE 4436 if ($This->_IsHydrogenAttachedToNOXideNitrogen($NitrogenAtom)) { 4437 $AtomType = 'HNOX'; 4438 last ATOMTYPE; 4439 } 4440 4441 # HNCC : H-N IN ENAMINES (H-N-C=C) 4442 if ($This->_IsHydrogenAttachedToEnamineNitrogen($NitrogenAtom)) { 4443 $AtomType = 'HNCC'; 4444 last ATOMTYPE; 4445 } 4446 4447 # HNCN : H-N IN H-N-C=N 4448 if ($This->_IsHydrogenAttachedToNCNNitrogen($NitrogenAtom)) { 4449 $AtomType = 'HNCN'; 4450 last ATOMTYPE; 4451 } 4452 4453 # HNNC : H-N IN H-N-N=C 4454 if ($This->_IsHydrogenAttachedToNNCNitrogen($NitrogenAtom)) { 4455 $AtomType = 'HNNC'; 4456 last ATOMTYPE; 4457 } 4458 4459 # HNNN : H-N IN H-N-N=N 4460 if ($This->_IsHydrogenAttachedToNNNNitrogen($NitrogenAtom)) { 4461 $AtomType = 'HNNN'; 4462 last ATOMTYPE; 4463 } 4464 4465 # HNM : H ON DICOORD, NEGATIVELY CHARGED NITROGEN 4466 if ($This->_IsHydrogenAttachedToNegativelyChargedDicoordinatedNitrogen($NitrogenAtom)) { 4467 $AtomType = 'HNM'; 4468 last ATOMTYPE; 4469 } 4470 4471 # H3N : H-N(SP3), AMMONIA 4472 if ($This->_IsHydrogenAttachedToSP3AmmoniaNitrogen($NitrogenAtom)) { 4473 $AtomType = 'H3N'; 4474 last ATOMTYPE; 4475 } 4476 4477 # HNR : H-N(SP3) 4478 if ($This->_IsHydrogenAttachedToSP3Nitrogen($NitrogenAtom)) { 4479 $AtomType = 'HNR'; 4480 last ATOMTYPE; 4481 } 4482 4483 # HNR+ : H ON QUATERNARY NITROGEN 4484 if ($This->_IsHydrogenAttachedToQuaternaryNitrogen($NitrogenAtom)) { 4485 $AtomType = 'HNR+'; 4486 last ATOMTYPE; 4487 } 4488 4489 # HN : GENERAL H ON NITROGEN 4490 $AtomType = 'HN'; 4491 } 4492 return $AtomType; 4493 } 4494 4495 # Get atom type for Hydrogen attached to a Nitrogen with one pi bonds... 4496 # 4497 sub _GetAtomTypeForHydrogenAttachedToNitrogenWithOnePiBond { 4498 my($This, $NitrogenAtom) = @_; 4499 my($AtomType); 4500 4501 $AtomType = 'None'; 4502 4503 ATOMTYPE: { 4504 4505 # HPYL : H-N IN PYRROLE 4506 if ($This->_IsHydrogenAttachedToPyrroleNitrogen($NitrogenAtom)) { 4507 $AtomType = 'HPYL'; 4508 last ATOMTYPE; 4509 } 4510 4511 # HIM+ : H ON IMIDAZOLIUM-TYPE NITROGEN 4512 if ($This->_IsHydrogenAttachedToImidazoliumNitrogen($NitrogenAtom)) { 4513 $AtomType = 'HIM+'; 4514 last ATOMTYPE; 4515 } 4516 4517 # HN5+ : H ON N5+, N5A+ OR N5B+ 4518 if ($This->_IsHydrogenAttachedToFiveMemberedHetreoCyclicPostivelyChargedNitrogen($NitrogenAtom)) { 4519 $AtomType = 'HN5+'; 4520 last ATOMTYPE; 4521 } 4522 4523 # HPD+ : H ON PROTONATED PYRIDINE NITROGEN 4524 if ($This->_IsHydrogenAttachedToPositivelyChargedPyridineNitrogen($NitrogenAtom)) { 4525 $AtomType = 'HPD+'; 4526 last ATOMTYPE; 4527 } 4528 4529 # HNOX : H-N IN IN A N-OXIDE 4530 if ($This->_IsHydrogenAttachedToNOXideNitrogen($NitrogenAtom)) { 4531 $AtomType = 'HNOX'; 4532 last ATOMTYPE; 4533 } 4534 4535 # HGD+ : H ON GUANIDINIUM-TYPE NITROGEN 4536 if ($This->_IsHydrogenAttachedToGuanidiniumNitrogen($NitrogenAtom)) { 4537 $AtomType = 'HGD+'; 4538 last ATOMTYPE; 4539 } 4540 4541 # HNN+ : H ON AMIDINIUM-TYPE NITROGEN 4542 if ($This->_IsHydrogenAttachedToAmidiniumNitrogen($NitrogenAtom)) { 4543 $AtomType = 'HNN+'; 4544 last ATOMTYPE; 4545 } 4546 4547 # HNC+ : H ON PROTONATED IMINE NITROGEN 4548 if ($This->_IsHydrogenAttachedToPositivelyChargedImineNitrogen($NitrogenAtom)) { 4549 $AtomType = 'HNC+'; 4550 last ATOMTYPE; 4551 } 4552 4553 # HN=N : AZO HYDROGEN 4554 if ($This->_IsHydrogenAttachedToAzoNitrogen($NitrogenAtom)) { 4555 $AtomType = 'HN=N'; 4556 last ATOMTYPE; 4557 } 4558 4559 # HN=C : IMINE HYDROGEN 4560 if ($This->_IsHydrogenAttachedToImineNitrogen($NitrogenAtom)) { 4561 $AtomType = 'HN=C'; 4562 last ATOMTYPE; 4563 } 4564 4565 # HSP2: GENERAL H ON SP2 NITROGEN 4566 $AtomType = 'HSP2'; 4567 } 4568 return $AtomType; 4569 } 4570 4571 # Get atom type for Hydrogen attached to a Nitrogen with two pi bonds... 4572 # 4573 sub _GetAtomTypeForHydrogenAttachedToNitrogenWithTwoPiBonds { 4574 my($This, $NitrogenAtom) = @_; 4575 my($AtomType); 4576 4577 $AtomType = 'None'; 4578 4579 ATOMTYPE: { 4580 4581 # HN : GENERAL H ON NITROGEN 4582 $AtomType = 'HN'; 4583 } 4584 return $AtomType; 4585 } 4586 4587 # HNR : H-N(SP3) 4588 # 4589 sub _IsHydrogenAttachedToSP3Nitrogen { 4590 my($This, $NitrogenAtom) = @_; 4591 4592 return $NitrogenAtom->DoesAtomNeighborhoodMatch('N.T3.FC0', ['*', '*', '*'], ['-', '-', '-']) ? 1 : 0; 4593 } 4594 4595 # H3N : H-N(SP3), AMMONIA 4596 # 4597 sub _IsHydrogenAttachedToSP3AmmoniaNitrogen { 4598 my($This, $NitrogenAtom) = @_; 4599 4600 return $NitrogenAtom->DoesAtomNeighborhoodMatch('N.T4.FC+1', ['H', 'H', 'H', 'H'], ['-', '-', '-', '-']) ? 1 : 0; 4601 } 4602 4603 # HPYL : H-N IN PYRROLE 4604 # 4605 sub _IsHydrogenAttachedToPyrroleNitrogen { 4606 my($This, $NitrogenAtom) = @_; 4607 4608 return $This->_IsPyrroleNitrogen($NitrogenAtom) ? 1 : 0; 4609 } 4610 4611 # HNOX : H-N IN IN A N-OXIDE 4612 # 4613 sub _IsHydrogenAttachedToNOXideNitrogen { 4614 my($This, $NitrogenAtom) = @_; 4615 4616 return $NitrogenAtom->DoesAtomNeighborhoodMatch('N.FC+1', ['O.X1.FC-1'], ['-']) ? 1 : 0; 4617 } 4618 4619 # HNM : H ON DICOORD, NEGATIVELY CHARGED NITROGEN 4620 # 4621 sub _IsHydrogenAttachedToNegativelyChargedDicoordinatedNitrogen { 4622 my($This, $NitrogenAtom) = @_; 4623 4624 return $NitrogenAtom->DoesAtomNeighborhoodMatch('N.T2.FC-1', ['*', '*'], ['-', '-']) ? 1 : 0; 4625 } 4626 4627 # HN=N : AZO HYDROGEN 4628 # 4629 sub _IsHydrogenAttachedToAzoNitrogen { 4630 my($This, $NitrogenAtom) = @_; 4631 4632 return $This->_IsAzoNitrogen($NitrogenAtom) ? 1 : 0; 4633 } 4634 4635 # HN=C : IMINE HYDROGEN 4636 # 4637 sub _IsHydrogenAttachedToImineNitrogen { 4638 my($This, $NitrogenAtom) = @_; 4639 4640 return $This->_IsImineNitrogen($NitrogenAtom) ? 1 : 0; 4641 } 4642 4643 # HNCO : AMIDE HYDROGEN 4644 # 4645 sub _IsHydrogenAttachedToAmideNitrogen { 4646 my($This, $NitrogenAtom) = @_; 4647 4648 return $This->_IsAmideNitrogen($NitrogenAtom) ? 1 : 0; 4649 } 4650 4651 # HNCS : THIOAMIDE HYDROGEN 4652 # 4653 sub _IsHydrogenAttachedToThioamideNitrogen { 4654 my($This, $NitrogenAtom) = @_; 4655 4656 return $This->_IsThioAmideNitrogen($NitrogenAtom) ? 1 : 0; 4657 } 4658 4659 # HNCC : H-N IN ENAMINES (H-N-C=C) 4660 # 4661 sub _IsHydrogenAttachedToEnamineNitrogen { 4662 my($This, $NitrogenAtom) = @_; 4663 4664 return $This->_IsNCCNitrogen($NitrogenAtom) ? 1 : 0; 4665 } 4666 4667 # HNCN : H-N IN H-N-C=N 4668 # 4669 sub _IsHydrogenAttachedToNCNNitrogen { 4670 my($This, $NitrogenAtom) = @_; 4671 4672 return $This->_IsNCNNitrogen($NitrogenAtom) ? 1 : 0; 4673 } 4674 4675 # HNNC : H-N IN H-N-N=C 4676 # 4677 sub _IsHydrogenAttachedToNNCNitrogen { 4678 my($This, $NitrogenAtom) = @_; 4679 4680 return $This->_IsNNCNitrogen($NitrogenAtom) ? 1 : 0; 4681 } 4682 4683 # HNNN : H-N IN H-N-N=N 4684 # 4685 sub _IsHydrogenAttachedToNNNNitrogen { 4686 my($This, $NitrogenAtom) = @_; 4687 4688 return $This->_IsNNNNitrogen($NitrogenAtom) ? 1 : 0; 4689 } 4690 4691 # HNSO : H-N IN SULFONAMIDE 4692 # 4693 sub _IsHydrogenAttachedToSulfonamideNitrogen { 4694 my($This, $NitrogenAtom) = @_; 4695 4696 return $This->_IsNSO2SulfonamideNitrogen($NitrogenAtom) ? 1 : 0; 4697 } 4698 4699 # HNPO : H-N IN PHOSPHONAMIDE 4700 # 4701 sub _IsHydrogenAttachedToPhosphonamideNitrogen { 4702 my($This, $NitrogenAtom) = @_; 4703 4704 return $This->_IsNPO2PhosphonamideNitrogen($NitrogenAtom) ? 1 : 0; 4705 } 4706 4707 # HNC% : HYDROGEN ON N ATTACHED TO TRIPLY BONDED CARBON 4708 # 4709 sub _IsHydrogenAttachedToTriplyBondedToCarbonNitrogen { 4710 my($This, $NitrogenAtom) = @_; 4711 4712 return $This->_IsAttchedToCCTripleBondNitrogen($NitrogenAtom) ? 1 : 0; 4713 } 4714 4715 # HSP2 : GENERAL H ON SP2 NITROGEN 4716 # 4717 sub _IsHydrogenAttachedToSP2Nitrogen { 4718 my($This, $NitrogenAtom) = @_; 4719 4720 return $NitrogenAtom->DoesAtomNeighborhoodMatch('N.DB1') ? 1 : 0; 4721 } 4722 4723 # HNR+ : H ON QUATERNARY NITROGEN 4724 # 4725 sub _IsHydrogenAttachedToQuaternaryNitrogen { 4726 my($This, $NitrogenAtom) = @_; 4727 4728 return $NitrogenAtom->DoesAtomNeighborhoodMatch('N.T4.FC+1', ['*', '*', '*', '*'], ['-', '-', '-', '-']) ? 1 : 0; 4729 } 4730 4731 # HIM+ : H ON IMIDAZOLIUM-TYPE NITROGEN 4732 # 4733 sub _IsHydrogenAttachedToImidazoliumNitrogen { 4734 my($This, $NitrogenAtom) = @_; 4735 4736 return $This->_IsImidazoliumNitrogen($NitrogenAtom) ? 1 : 0; 4737 } 4738 4739 # HPD+ : H ON PROTONATED PYRIDINE NITROGEN 4740 # 4741 sub _IsHydrogenAttachedToPositivelyChargedPyridineNitrogen { 4742 my($This, $NitrogenAtom) = @_; 4743 4744 return $This->_IsPyridiniumNitrogen($NitrogenAtom) ? 1 : 0; 4745 } 4746 4747 # HNN+ : H ON AMIDINIUM-TYPE NITROGEN 4748 # 4749 sub _IsHydrogenAttachedToAmidiniumNitrogen { 4750 my($This, $NitrogenAtom) = @_; 4751 4752 return $This->_IsPositivelyChargedAzoNitrogen($NitrogenAtom) ? 1 : 0; 4753 } 4754 4755 # HNC+ : H ON PROTONATED IMINE NITROGEN 4756 # 4757 sub _IsHydrogenAttachedToPositivelyChargedImineNitrogen { 4758 my($This, $NitrogenAtom) = @_; 4759 4760 return $This->_IsPositivelyChargedIminiumNitrogen($NitrogenAtom) ? 1 : 0; 4761 } 4762 4763 # HGD+ : H ON GUANIDINIUM-TYPE NITROGEN 4764 # 4765 sub _IsHydrogenAttachedToGuanidiniumNitrogen { 4766 my($This, $NitrogenAtom) = @_; 4767 4768 return $This->_IsGuanidiniumNitrogen($NitrogenAtom) ? 1 : 0; 4769 } 4770 4771 # HN5+ : H ON N5+, N5A+ OR N5B+ 4772 # 4773 sub _IsHydrogenAttachedToFiveMemberedHetreoCyclicPostivelyChargedNitrogen { 4774 my($This, $NitrogenAtom) = @_; 4775 4776 if (!$NitrogenAtom->DoesAtomNeighborhoodMatch('N.RA5.FC+1')) { 4777 return 0; 4778 } 4779 4780 return ($This->_IsPositivelyChargedFiveMemberedHeteroAromaticRingAlphaNitrogen($NitrogenAtom) || 4781 $This->_IsPositivelyChargedFiveMemberedHeteroAromaticRingBetaNitrogen($NitrogenAtom) || 4782 $This->_IsPositivelyChargedFiveMemberedHeteroCyclicRingNitrogen($NitrogenAtom)) ? 1 : 0; 4783 } 4784 4785 # Get MMFF94 atom type for Hydrogen attached to Oxygen... 4786 # 4787 # 11 AtomTypeSymbols for element H: 4788 # 4789 # AtomTypeSymbol AtomTypeNum AtomTypeDefinition 4790 # HOR 21 HYDROGEN IN ALCOHOLS 4791 # HO 21 GENERAL H ON OXYGEN 4792 # HOM 21 HYDROGEN IN HYDROXIDE ANION 4793 # HOCO 24 H-O IN CARBOXYLIC ACIDS 4794 # HOP 24 HYDROGEN ON OXYGEN ATTACHED TO PHOSPHOROUS 4795 # HOCC 29 H-O IN ENOLS AND PHENOLS 4796 # HOCN 29 H-O IN HO-C=N 4797 # HOH 31 HYDROGEN IN H2O 4798 # HOS 33 H ON OXYGEN ATTACHED TO SULFUR 4799 # HO+ 50 HYDROGEN ON O+ OXYGEN 4800 # HO=+ 52 HYDROGEN ON OXENIUM OXYGEN 4801 # 4802 sub _GetAtomTypeForHydrogenAttachedToOxygen { 4803 my($This, $OxygenAtom) = @_; 4804 my($AtomType); 4805 4806 $AtomType = 'None'; 4807 4808 ATOMTYPE: { 4809 4810 # HOP : HYDROGEN ON OXYGEN ATTACHED TO PHOSPHOROUS 4811 if ($This->_IsHydrogenAttachedToOPOxygen($OxygenAtom)) { 4812 $AtomType = 'HOP'; 4813 last ATOMTYPE; 4814 } 4815 4816 # HOS : H ON OXYGEN ATTACHED TO SULFUR 4817 if ($This->_IsHydrogenAttachedToOSOxygen($OxygenAtom)) { 4818 $AtomType = 'HOS'; 4819 last ATOMTYPE; 4820 } 4821 4822 # HOCO : H-O IN CARBOXYLIC ACIDS 4823 if ($This->_IsHydrogenAttachedToCarboxylicAcidOxygen($OxygenAtom)) { 4824 $AtomType = 'HOCO'; 4825 last ATOMTYPE; 4826 } 4827 4828 # HOCC : H-O IN ENOLS AND PHENOLS 4829 if ($This->_IsHydrogenAttachedToEnolOrPhenolOxygen($OxygenAtom)) { 4830 $AtomType = 'HOCC'; 4831 last ATOMTYPE; 4832 } 4833 4834 # HOCN : H-O IN HO-C=N 4835 if ($This->_IsHydrogenAttachedToOCNOxygen($OxygenAtom)) { 4836 $AtomType = 'HOCN'; 4837 last ATOMTYPE; 4838 } 4839 4840 # HOM : HYDROGEN IN HYDROXIDE ANION 4841 if ($This->_IsHydrogenAttachedToHydroxideAnionOxygen($OxygenAtom)) { 4842 $AtomType = 'HOM'; 4843 last ATOMTYPE; 4844 } 4845 4846 # HO+ : HYDROGEN ON O+ OXYGEN 4847 if ($This->_IsHydrogenAttachedToPositivelyChargedOxygen($OxygenAtom)) { 4848 $AtomType = 'HO+'; 4849 last ATOMTYPE; 4850 } 4851 4852 # HO=+ : HYDROGEN ON OXENIUM OXYGEN 4853 if ($This->_IsHydrogenAttachedToOxeniumOxygen($OxygenAtom)) { 4854 $AtomType = 'HO=+'; 4855 last ATOMTYPE; 4856 } 4857 4858 # HOR : HYDROGEN IN ALCOHOLS 4859 if ($This->_IsHydrogenAttachedToAlcoholOxygen($OxygenAtom)) { 4860 $AtomType = 'HOR'; 4861 last ATOMTYPE; 4862 } 4863 4864 # HOH : HYDROGEN IN H2O 4865 if ($This->_IsHydrogenAttachedToWaterOxygen($OxygenAtom)) { 4866 $AtomType = 'HOH'; 4867 last ATOMTYPE; 4868 } 4869 4870 # HO: GENERAL H ON OXYGEN 4871 $AtomType = 'HO'; 4872 } 4873 return $AtomType; 4874 } 4875 4876 # HOR : HYDROGEN IN ALCOHOLS 4877 # 4878 sub _IsHydrogenAttachedToAlcoholOxygen { 4879 my($This, $OxygenAtom) = @_; 4880 4881 return $This->_IsAlcoholOxygen($OxygenAtom) ? 1 : 0; 4882 } 4883 4884 # HO : GENERAL H ON OXYGEN 4885 # 4886 sub _IsHydrogenAttachedToOxygen { 4887 my($This, $OxygenAtom) = @_; 4888 4889 return 1; 4890 } 4891 4892 # HOM : HYDROGEN IN HYDROXIDE ANION 4893 # 4894 sub _IsHydrogenAttachedToHydroxideAnionOxygen { 4895 my($This, $OxygenAtom) = @_; 4896 4897 # H-(O-) 4898 return $OxygenAtom->DoesAtomNeighborhoodMatch('O.FC-1.T1', ['H'], ['-']) ? 1 : 0; 4899 } 4900 4901 # HOCO : H-O IN CARBOXYLIC ACIDS 4902 # 4903 sub _IsHydrogenAttachedToCarboxylicAcidOxygen { 4904 my($This, $OxygenAtom) = @_; 4905 4906 return $This->_IsEsterOrCarboxylicAcidOxygen($OxygenAtom) ? 1 : 0; 4907 } 4908 4909 # HOP : HYDROGEN ON OXYGEN ATTACHED TO PHOSPHOROUS 4910 # 4911 sub _IsHydrogenAttachedToOPOxygen { 4912 my($This, $OxygenAtom) = @_; 4913 4914 return $OxygenAtom->DoesAtomNeighborhoodMatch('O', ['P'], ['*']) ? 1 : 0; 4915 } 4916 4917 # HOCC : H-O IN ENOLS AND PHENOLS 4918 # 4919 sub _IsHydrogenAttachedToEnolOrPhenolOxygen { 4920 my($This, $OxygenAtom) = @_; 4921 4922 return $This->_IsEnolicOrPhenolicOxygen($OxygenAtom) ? 1 : 0; 4923 } 4924 4925 # HOCN : H-O IN HO-C=N 4926 # 4927 sub _IsHydrogenAttachedToOCNOxygen { 4928 my($This, $OxygenAtom) = @_; 4929 4930 return $This->_IsOCNDivalentOxygen($OxygenAtom) ? 1 : 0; 4931 } 4932 4933 # HOH : HYDROGEN IN H2O 4934 # 4935 sub _IsHydrogenAttachedToWaterOxygen { 4936 my($This, $OxygenAtom) = @_; 4937 4938 return $This->_IsWaterOxygen($OxygenAtom) ? 1 : 0; 4939 } 4940 4941 # HOS : H ON OXYGEN ATTACHED TO SULFUR 4942 # 4943 sub _IsHydrogenAttachedToOSOxygen { 4944 my($This, $OxygenAtom) = @_; 4945 4946 return $OxygenAtom->DoesAtomNeighborhoodMatch('O', ['S'], ['*']) ? 1 : 0; 4947 } 4948 4949 # HO+ : HYDROGEN ON O+ OXYGEN 4950 # 4951 sub _IsHydrogenAttachedToPositivelyChargedOxygen { 4952 my($This, $OxygenAtom) = @_; 4953 4954 return $This->_IsPositivelyChargedOxoniumOxygen($OxygenAtom) ? 1 : 0; 4955 } 4956 4957 # HO=+ : HYDROGEN ON OXENIUM OXYGEN 4958 # 4959 sub _IsHydrogenAttachedToOxeniumOxygen { 4960 my($This, $OxygenAtom) = @_; 4961 4962 return $This->_IsPositivelyChargedOxeniumOxygen($OxygenAtom) ? 1 : 0; 4963 } 4964 4965 # Get MMFF94 atom type for Hydrogen attached to Phosphorus... 4966 # 4967 sub _GetAtomTypeForHydrogenAttachedToPhosphorus { 4968 my($This, $PhosphorusAtom) = @_; 4969 my($AtomType); 4970 4971 # HP : H ATTACHED TO TRI- OR TETRACOORDINATE PHOSPHORUS 4972 $AtomType = 'HP'; 4973 4974 return $AtomType; 4975 } 4976 4977 # Get MMFF94 atom type for Hydrogen attached to Sulfur... 4978 # 4979 sub _GetAtomTypeForHydrogenAttachedToSulfur { 4980 my($This, $SulfurAtom) = @_; 4981 my($AtomType); 4982 4983 $AtomType = 'None'; 4984 4985 ATOMTYPE: { 4986 4987 # HS=N : H ATTACHED TO TETRAVALENT, TRICOODR S DBL BONDED TO N 4988 if ($This->_IsSNTricoordinatedSulfur($SulfurAtom)) { 4989 $AtomType = 'HS=N'; 4990 last ATOMTYPE; 4991 } 4992 4993 # HS : H ATTACHED TO DIVALENT, DICOORDINATE S 4994 if ($This->_IsDivalentDiCoordinatedSulfur($SulfurAtom)) { 4995 $AtomType = 'HS'; 4996 last ATOMTYPE; 4997 } 4998 4999 $AtomType = 'None'; 5000 carp "Warning: ${ClassName}->_GetAtomTypeForHydrogenAttachedToSulfur: MMFF94 atom type for Sulfur cann't be assigned..."; 5001 } 5002 return $AtomType; 5003 } 5004 5005 # Get MMFF94 atom type for Hydrogen attached to Silicon... 5006 # 5007 sub _GetAtomTypeForHydrogenAttachedToSilicon { 5008 my($This, $SiliconAtom) = @_; 5009 my($AtomType); 5010 5011 # HSI : H ATTACHED TO SI 5012 $AtomType = 'HSI'; 5013 5014 return $AtomType; 5015 } 5016 5017 # Get information about number and types of hetero atoms present in ring... 5018 # 5019 # Note: 5020 # . Any atom other than Carbon and Hydrogen atom is considered a hetero atom. 5021 # 5022 sub _GetHeteroAtomsInformationInRing { 5023 my($This, $RingAtomsRef) = @_; 5024 my($RingAtom, $RingAtomSymbol, $RingIsAromatic, $NumOfAromaticAtoms, $NumOfHeteroAtoms, %HeteroAtomSymbolsMap); 5025 5026 %HeteroAtomSymbolsMap = (); 5027 5028 $NumOfAromaticAtoms = 0; 5029 $NumOfHeteroAtoms = 0; 5030 5031 RINGATOM: for $RingAtom (@{$RingAtomsRef}) { 5032 if ($RingAtom->IsAromatic()) { 5033 $NumOfAromaticAtoms++; 5034 } 5035 5036 if (!$This->_IsHeteroAtom($RingAtom)) { 5037 next RINGATOM; 5038 } 5039 $NumOfHeteroAtoms++; 5040 5041 $RingAtomSymbol = $RingAtom->GetAtomSymbol(); 5042 if (exists $HeteroAtomSymbolsMap{$RingAtomSymbol}) { 5043 $HeteroAtomSymbolsMap{$RingAtomSymbol} += 1; 5044 } 5045 else { 5046 $HeteroAtomSymbolsMap{$RingAtomSymbol} = 1; 5047 } 5048 } 5049 $RingIsAromatic = ($NumOfAromaticAtoms == scalar @{$RingAtomsRef}) ? 1 : 0; 5050 5051 return ($RingIsAromatic, $NumOfHeteroAtoms, \%HeteroAtomSymbolsMap); 5052 } 5053 5054 # Check whether specified atom has a hetero atom at alpha position in an aromatic ring... 5055 # 5056 sub _IsAtomPositionAlphaInHeteroAromaticRing { 5057 my($This, $Atom, $RingAtomsRef) = @_; 5058 my($CheckRingAromaticity); 5059 5060 $CheckRingAromaticity = 1; 5061 5062 return $This->_IsAtomPositionAlphaInHeteroRing($Atom, $RingAtomsRef, $CheckRingAromaticity); 5063 } 5064 5065 # Check whether specified atom has a hetero atom at beta position in an aromatic ring... 5066 # 5067 sub _IsAtomPositionBetaInHeteroAromaticRing { 5068 my($This, $Atom, $RingAtomsRef) = @_; 5069 my($CheckRingAromaticity); 5070 5071 $CheckRingAromaticity = 1; 5072 5073 return $This->_IsAtomPositionBetaInHeteroRing($Atom, $RingAtomsRef, $CheckRingAromaticity); 5074 } 5075 5076 # Check whether specified atom has a hetero atom at alpha position in an aromatic or non-aromatic 5077 # ring... 5078 # 5079 sub _IsAtomPositionAlphaInHeteroRing { 5080 my($This, $Atom, $RingAtomsRef, $CheckRingAromaticity) = @_; 5081 my($RingIsAromatic, $NumOfHeteroAtoms, $NumOfAllowedHeteroAtoms, $HeteroAtomPositionsRef); 5082 5083 $CheckRingAromaticity = defined($CheckRingAromaticity) && $CheckRingAromaticity ? 1 : 0; 5084 5085 # Is it an aromatic ring containing appropriate number hertero atoms? 5086 ($RingIsAromatic, $NumOfHeteroAtoms) = $This->_GetHeteroAtomsInformationInRing($RingAtomsRef); 5087 $NumOfAllowedHeteroAtoms = $Atom->IsCarbon() ? 1 : 2; 5088 5089 if ($CheckRingAromaticity && !$RingIsAromatic) { 5090 return 0; 5091 } 5092 5093 if ($NumOfHeteroAtoms != $NumOfAllowedHeteroAtoms) { 5094 return 0; 5095 } 5096 5097 # Does ring contain hetero atoms at alpha position? 5098 $HeteroAtomPositionsRef = $This->_GetHeteroAtomPositionsInRing($Atom, $RingAtomsRef); 5099 if (exists($HeteroAtomPositionsRef->{Alpha}) && !exists($HeteroAtomPositionsRef->{Beta})) { 5100 return 1; 5101 } 5102 5103 return 0; 5104 } 5105 5106 # Check whether specified atom has a hetero atom at alpha position in an aromatic or non-aromatic 5107 # ring... 5108 # 5109 sub _IsAtomPositionBetaInHeteroRing { 5110 my($This, $Atom, $RingAtomsRef, $CheckRingAromaticity) = @_; 5111 my($RingIsAromatic, $NumOfHeteroAtoms, $NumOfAllowedHeteroAtoms, $HeteroAtomPositionsRef); 5112 5113 $CheckRingAromaticity = defined($CheckRingAromaticity) && $CheckRingAromaticity ? 1 : 0; 5114 5115 # Is it an aromatic ring containing hertero atoms? 5116 ($RingIsAromatic, $NumOfHeteroAtoms) = $This->_GetHeteroAtomsInformationInRing($RingAtomsRef); 5117 $NumOfAllowedHeteroAtoms = $Atom->IsCarbon() ? 1 : 2; 5118 5119 if ($CheckRingAromaticity && !$RingIsAromatic) { 5120 return 0; 5121 } 5122 5123 if ($NumOfHeteroAtoms != $NumOfAllowedHeteroAtoms) { 5124 return 0; 5125 } 5126 5127 # Does ring contain hetero atoms at alpha position? 5128 $HeteroAtomPositionsRef = $This->_GetHeteroAtomPositionsInRing($Atom, $RingAtomsRef); 5129 if (exists($HeteroAtomPositionsRef->{Beta}) && !exists($HeteroAtomPositionsRef->{Alpha})) { 5130 return 1; 5131 } 5132 5133 return 0; 5134 } 5135 5136 # Get hetro atom positions relative to atom position... 5137 # 5138 # Notes: 5139 # . Any atom other than Carbon and Hydrogen atom is considered a hetero atom. 5140 # 5141 sub _GetHeteroAtomPositionsInRing { 5142 my($This, $Atom, $RingAtomsRef) = @_; 5143 my($RingAtom, $Index, $AtomIndex, $NumOfHeteroAtoms, %HeteroAtomPositionsMap); 5144 5145 %HeteroAtomPositionsMap = (); 5146 5147 $NumOfHeteroAtoms = 0; 5148 $AtomIndex = 0; 5149 $Index = 0; 5150 5151 # Find position of specified atom in the ring and count hetero atoms... 5152 for $RingAtom (@{$RingAtomsRef}) { 5153 if ($This->_IsHeteroAtom($RingAtom)) { 5154 $NumOfHeteroAtoms++; 5155 } 5156 if ($RingAtom->GetID() == $Atom->GetID()) { 5157 $AtomIndex = $Index; 5158 } 5159 $Index++; 5160 } 5161 5162 # Does ring contain any hetereo atoms? 5163 if (!$NumOfHeteroAtoms) { 5164 return \%HeteroAtomPositionsMap; 5165 } 5166 5167 # Check hetero atoms around specified atom to determine their position using their 5168 # their distance from specified atom: 1 - Alpha, 2 - Beta, 3 - Gamma, 4 - Delta, 5 - Omega 5169 # 5170 my($RingSize, $MaxPositionNum, $PositionNum, $PositionName, $MaxAtomIndex, $BeforeAtomIndex, $AfterAtomIndex, $BeforeAtom, $AfterAtom, %PositionNumToNameMap); 5171 5172 %PositionNumToNameMap = ('1' => 'Alpha', '2' => 'Beta', '3' => 'Gamma', '4' => 'Delta', '5' => 'Omega'); 5173 5174 $RingSize = scalar @{$RingAtomsRef}; 5175 $MaxPositionNum = int $RingSize/2; 5176 $MaxAtomIndex = $RingSize - 1; 5177 5178 POSITIONNUM: for $PositionNum (1 .. $MaxPositionNum) { 5179 # Get atom before atom at a specific position... 5180 $BeforeAtomIndex = $AtomIndex - $PositionNum; 5181 if ($BeforeAtomIndex < 0) { 5182 $BeforeAtomIndex = $MaxAtomIndex + $BeforeAtomIndex + 1; 5183 } 5184 $BeforeAtom = $RingAtomsRef->[$BeforeAtomIndex]; 5185 5186 $PositionName = exists $PositionNumToNameMap{$PositionNum} ? $PositionNumToNameMap{$PositionNum} : 'Unknown'; 5187 5188 # Is atom before atom at a specific position a hetero atom? 5189 if (!$BeforeAtom->IsCarbon()) { 5190 $This->_TrackHeteroAtomPositionInRing($BeforeAtom, $PositionName, \%HeteroAtomPositionsMap); 5191 } 5192 5193 # Get atom after atom at a specific position... 5194 $AfterAtomIndex = $AtomIndex + $PositionNum; 5195 if ($AfterAtomIndex > $MaxAtomIndex) { 5196 $AfterAtomIndex = $AfterAtomIndex - $MaxAtomIndex - 1; 5197 } 5198 5199 # Is it a different atom? 5200 if ($AfterAtomIndex == $BeforeAtomIndex) { 5201 next POSITIONNUM; 5202 } 5203 5204 # Is atom after atom at a specific position a hetero atom? 5205 $AfterAtom = $RingAtomsRef->[$AfterAtomIndex]; 5206 5207 if (!$AfterAtom->IsCarbon()) { 5208 $This->_TrackHeteroAtomPositionInRing($AfterAtom, $PositionName, \%HeteroAtomPositionsMap); 5209 } 5210 } 5211 return \%HeteroAtomPositionsMap; 5212 } 5213 5214 # Is it a hetero atom? 5215 # 5216 # Notes: 5217 # . Any atom other than Carbon and Hydrogen atom is considered a hetero atom. 5218 # 5219 sub _IsHeteroAtom { 5220 my($This, $Atom) = @_; 5221 5222 return ($Atom->IsCarbon() || $Atom->IsHydrogen()) ? 0 : 1; 5223 } 5224 5225 # Track hetero atom positions in ring by updating data in specified data hash reference... 5226 # 5227 sub _TrackHeteroAtomPositionInRing { 5228 my($This, $HeteroAtom, $PositionName, $HeteroAtomPositionsMapRef) = @_; 5229 my($HeteroAtomSymbol); 5230 5231 # Is it a new hetero atom position? 5232 if (!exists $HeteroAtomPositionsMapRef->{$PositionName}) { 5233 %{$HeteroAtomPositionsMapRef->{$PositionName}} = (); 5234 } 5235 5236 $HeteroAtomSymbol = $HeteroAtom->GetAtomSymbol(); 5237 if (exists $HeteroAtomPositionsMapRef->{$PositionName}{$HeteroAtomSymbol}) { 5238 $HeteroAtomPositionsMapRef->{$PositionName}{$HeteroAtomSymbol} += 1; 5239 } 5240 else { 5241 $HeteroAtomPositionsMapRef->{$PositionName}{$HeteroAtomSymbol} += 1; 5242 } 5243 return $This; 5244 } 5245 5246 # Return a string containg data for MMFF94AtomTypes object... 5247 # 5248 sub StringifyMMFF94AtomTypes { 5249 my($This) = @_; 5250 my($AtomTypesString); 5251 5252 # Type of AtomTypes... 5253 $AtomTypesString = "AtomTypes: $This->{Type}; IgnoreHydrogens: " . ($This->{IgnoreHydrogens} ? "Yes" : "No"); 5254 5255 # Setup atom types information... 5256 my($AtomID, $AtomType, @AtomTypesInfo, %AssignedAtomTypes); 5257 5258 @AtomTypesInfo = (); 5259 %AssignedAtomTypes = $This->GetAtomTypes(); 5260 5261 for $AtomID (sort { $a <=> $b } keys %AssignedAtomTypes) { 5262 $AtomType = $AssignedAtomTypes{$AtomID} ? $AssignedAtomTypes{$AtomID} : 'None'; 5263 push @AtomTypesInfo, "$AtomID:$AtomType"; 5264 } 5265 $AtomTypesString .= "; AtomIDs:AtomTypes: <" . TextUtil::JoinWords(\@AtomTypesInfo, ", ", 0) . ">"; 5266 5267 return $AtomTypesString; 5268 } 5269 5270 # Is it a MMFF94AtomTypes object? 5271 sub _IsMMFF94AtomTypes { 5272 my($Object) = @_; 5273 5274 return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0; 5275 } 5276 5277 # Check and load MMFF94 atom types data... 5278 # 5279 sub _CheckAndLoadMMFF94AtomTypesData { 5280 5281 # Is it already loaded? 5282 if (exists $MMFF94AtomTypesDataMap{AtomTypes}) { 5283 return; 5284 } 5285 5286 _LoadMMFF94AtomTypesData(); 5287 } 5288 5289 # Load MMFF94 atom types data from the file assuming first column to be atom type symbol.. 5290 # 5291 # Format: 5292 # 5293 # "AtomTypeSymbol","AtomTypeNum","ElementSymbol","AtomTypeDefinition" 5294 # "CR","1","C","ALKYL CARBON, SP3" 5295 # "C=C","2","C","VINYLIC CARBON, SP2" 5296 # 5297 sub _LoadMMFF94AtomTypesData { 5298 my($AtomTypesDataFile, $MayaChemToolsLibDir); 5299 5300 $MayaChemToolsLibDir = FileUtil::GetMayaChemToolsLibDirName(); 5301 5302 $AtomTypesDataFile = "$MayaChemToolsLibDir" . "/data/MMFF94AtomTypes.csv"; 5303 if (! -e "$AtomTypesDataFile") { 5304 croak "Error: MayaChemTools package file, $AtomTypesDataFile, is missing: Possible installation problems..."; 5305 } 5306 5307 %MMFF94AtomTypesDataMap = (); 5308 AtomTypes::AtomTypes::LoadAtomTypesData($AtomTypesDataFile, \%MMFF94AtomTypesDataMap); 5309 } 5310