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