1 package AtomTypes::SLogPAtomTypes; 2 # 3 # File: SLogPAtomTypes.pm 4 # Author: Manish Sud <msud@san.rr.com> 5 # 6 # Copyright (C) 2025 Manish Sud. All rights reserved. 7 # 8 # This file is part of MayaChemTools. 9 # 10 # MayaChemTools is free software; you can redistribute it and/or modify it under 11 # the terms of the GNU Lesser General Public License as published by the Free 12 # Software Foundation; either version 3 of the License, or (at your option) any 13 # later version. 14 # 15 # MayaChemTools is distributed in the hope that it will be useful, but without 16 # any warranty; without even the implied warranty of merchantability of fitness 17 # for a particular purpose. See the GNU Lesser General Public License for more 18 # details. 19 # 20 # You should have received a copy of the GNU Lesser General Public License 21 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or 22 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, 23 # Boston, MA, 02111-1307, USA. 24 # 25 26 use strict; 27 use Carp; 28 use Exporter; 29 use Scalar::Util (); 30 use Text::ParseWords; 31 use FileUtil (); 32 use AtomTypes::AtomTypes; 33 use Molecule; 34 35 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 36 37 @ISA = qw(AtomTypes::AtomTypes Exporter); 38 @EXPORT = qw(GetSLogPAtomTypesData GetAllPossibleSLogPAtomTypes GetAllPossibleSLogPNonHydrogenAtomTypes); 39 @EXPORT_OK = qw(); 40 41 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 42 43 # Setup class variables... 44 my($ClassName, %SLogPAtomTypesDataMap); 45 _InitializeClass(); 46 47 # Overload Perl functions... 48 use overload '""' => 'StringifySLogPAtomTypes'; 49 50 # Class constructor... 51 sub new { 52 my($Class, %NamesAndValues) = @_; 53 54 # Initialize object... 55 my $This = $Class->SUPER::new(); 56 bless $This, ref($Class) || $Class; 57 $This->_InitializeSLogPAtomTypes(); 58 59 $This->_InitializeSLogPAtomTypesProperties(%NamesAndValues); 60 61 return $This; 62 } 63 64 # Initialize class ... 65 sub _InitializeClass { 66 #Class name... 67 $ClassName = __PACKAGE__; 68 69 # Initialize the data hash. It'll be loaded on demand later... 70 %SLogPAtomTypesDataMap = (); 71 } 72 73 # Initialize object data... 74 # 75 sub _InitializeSLogPAtomTypes { 76 my($This) = @_; 77 78 # Type of AtomTypes... 79 $This->{Type} = 'SLogP'; 80 81 # By default, SLogP atom types are also assigned to hydrogens... 82 $This->{IgnoreHydrogens} = 0; 83 84 return $This; 85 } 86 87 # Initialize object properties... 88 # 89 sub _InitializeSLogPAtomTypesProperties { 90 my($This, %NamesAndValues) = @_; 91 92 my($Name, $Value, $MethodName); 93 while (($Name, $Value) = each %NamesAndValues) { 94 $MethodName = "Set${Name}"; 95 $This->$MethodName($Value); 96 } 97 98 # Make sure molecule object was specified... 99 if (!exists $NamesAndValues{Molecule}) { 100 croak "Error: ${ClassName}->New: Object can't be instantiated without specifying molecule..."; 101 } 102 103 return $This; 104 } 105 106 # Get SLogP atom types and associated data loaded from SLogP data file as 107 # a reference to hash with the following hash data format: 108 # 109 # @{$SLogPAtomTypesDataMap{AtomTypes}} - Array of all possible atom types for all atoms 110 # @{$SLogPAtomTypesDataMap{NonHydrogenAtomTypes}} - Array of all possible atom types for non-hydrogen atoms 111 # @{$SLogPAtomTypesDataMap->{ColLabels}} - Array of column labels 112 # %{$SLogPAtomTypesDataMap->{DataCol<Num>}} - Hash keys pair: <DataCol<Num>, AtomType> 113 # 114 # This functionality can be either invoked as a class function or an 115 # object method. 116 # 117 sub GetSLogPAtomTypesData { 118 119 # Make sure data is loaded... 120 _CheckAndLoadSLogPAtomTypesData(); 121 122 return \%SLogPAtomTypesDataMap; 123 } 124 125 # Get all possible SLogP atom types corresponding to hydrogen and non-hydrogen 126 # atoms as an array reference... 127 # 128 # This functionality can be either invoked as a class function or an 129 # object method. 130 # 131 sub GetAllPossibleSLogPAtomTypes { 132 return _GetAllPossibleSLogPAtomTypes(); 133 } 134 135 # Get all possible SLogP atom types corresponding to non-hydrogen atoms 136 # as an array reference... 137 # 138 # This functionality can be either invoked as a class function or an 139 # object method. 140 # 141 sub GetAllPossibleSLogPNonHydrogenAtomTypes { 142 my($NonHydrogensOnly); 143 144 $NonHydrogensOnly = 1; 145 return _GetAllPossibleSLogPAtomTypes($NonHydrogensOnly); 146 } 147 148 # Get all possible SLogP atom types as an array reference... 149 # 150 sub _GetAllPossibleSLogPAtomTypes { 151 my($NonHydrogensOnly) = @_; 152 my($SLogPAtomTypesDataRef); 153 154 $NonHydrogensOnly = defined $NonHydrogensOnly ? $NonHydrogensOnly : 0; 155 156 $SLogPAtomTypesDataRef = GetSLogPAtomTypesData(); 157 158 return $NonHydrogensOnly ? \@{$SLogPAtomTypesDataRef->{NonHydrogenAtomTypes}}: \@{$SLogPAtomTypesDataRef->{AtomTypes}}; 159 } 160 161 # Assign SLogP [ Ref 89 ] atom types to all atoms... 162 # 163 # Notes: 164 # o 72 SLogP atom type symbols are listed 165 # o Number of atom types symbols for: 166 # o C: 28 167 # o N: 15 168 # o O: 13 169 # o P: 1 170 # o S: 3 171 # o H: 5 172 # o F, Cl, Br, I: 1 each 173 # o Ionic halogen: 1 174 # o p-block elements: 1 175 # o d-block elements: 1 176 # 177 sub AssignAtomTypes { 178 my($This) = @_; 179 my($Atom, $AtomType); 180 181 ATOM: for $Atom ($This->GetMolecule()->GetAtoms()) { 182 if ($This->{IgnoreHydrogens} && $Atom->IsHydrogen()) { 183 next ATOM; 184 } 185 $AtomType = $This->_GetAtomType($Atom); 186 $This->SetAtomType($Atom, $AtomType); 187 } 188 189 return $This; 190 } 191 192 # Get SLogP atom type for atom... 193 # 194 sub _GetAtomType { 195 my($This, $Atom) = @_; 196 my($AtomType); 197 198 $AtomType = 'None'; 199 200 ATOM: { 201 if ($Atom->IsCarbon()) { 202 $AtomType = $This->_GetAtomTypeForCarbon($Atom); 203 last ATOM; 204 } 205 206 if ($Atom->IsNitrogen()) { 207 $AtomType = $This->_GetAtomTypeForNitrogen($Atom); 208 last ATOM; 209 } 210 211 if ($Atom->IsOxygen()) { 212 $AtomType = $This->_GetAtomTypeForOxygen($Atom); 213 last ATOM; 214 } 215 216 if ($Atom->IsPhosphorus()) { 217 $AtomType = $This->_GetAtomTypeForPhosphorus($Atom); 218 last ATOM; 219 } 220 221 if ($Atom->IsSulfur()) { 222 $AtomType = $This->_GetAtomTypeForSulfur($Atom); 223 last ATOM; 224 } 225 226 if ($Atom->IsHydrogen()) { 227 $AtomType = $This->_GetAtomTypeForHydrogen($Atom); 228 last ATOM; 229 } 230 231 $AtomType = $This->_GetAtomTypeForOtherAtoms($Atom); 232 } 233 234 return $AtomType; 235 } 236 237 # Get SLogP atom type for Carbon atom... 238 # 239 # 28 AtomTypeSymbols for element C: 240 # 241 # AtomTypeSymbol - Description - SMARTS 242 # C1 - primary, secondary aliphatic - '[CH4]','[CH3]C','[CH2](C)C' 243 # C2 - tertiary, quaternary aliphatic - '[CH](C)(C)C','[C](C)(C)(C)C' 244 # C3 - primary, secondary heteroatom - '[CH3][(N,O,P,S,F,Cl,Br,I)]','[CH2X4](N,O,P,S,F,Cl,Br,I)]' 245 # C4 - tertiary, quaternary heteroatom - '[CH1X4][(N,O,P,S,F,Cl,Br,I)]','[CH0X4][(N,O,P,S,F,Cl,Br,I)]' 246 # C5 - C = heteroatom - '[C]=[A#X]' 247 # C6 - C = C aliphatic - '[CH2]=C','[CH1](=C)A','[CH0](=C)(A)A','[C](=C)=C' 248 # C7 - acetylene, nitrile - '[CX2]#A' 249 # C8 - primary aromatic carbon - '[CH3]c' 250 # C9 - primary aromatic heteroatom - '[CH3][a#X]' 251 # C10 - secondary aromatic - '[CH2X4]a' 252 # C11 - tertiary aromatic - '[CHX4]a' 253 # C12 - quaternary aromatic - '[CH0X4]a' 254 # C13 - aromatic heteroatom - '[cH0]-[!(C,N,O,S,F,Cl,Br,I)]' 255 # C14 - aromatic halide - '[c][#9]' 256 # C15 - aromatic halide - '[c][#17]' 257 # C16 - aromatic halide - '[c][#35]' 258 # C17 - aromatic halide - '[c][#53]' 259 # C18 - aromatic - '[cH]' 260 # C19 - aromatic bridgehead - '[c](:a)(:a):a' 261 # C20 - quaternary aromatic - '[c](:a)(:a)-a' 262 # C21 - quaternary aromatic - '[c](:a)(:a)-C' 263 # C22 - quaternary aromatic - '[c](:a)(:a)-N' 264 # C23 - quaternary aromatic - '[c](:a)(:a)-O' 265 # C24 - quaternary aromatic - '[c](:a)(:a)-S' 266 # C25 - quaternary aromatic - '[c](:a)(:a)=C','[c](:a)(:a)=N','[c](:a)(:a)=O' 267 # C26 - C = C aromatic - '[C](=C)(a)A','[C](=C)(c)a','[CH](=C)a','[C]=c' 268 # C27 - aliphatic heteroatom - '[CX4][!(C,N,O,P,S,F,Cl,Br,I)]' 269 # CS - carbon supplemental not matching any basic C type - '[#6]' 270 # 271 sub _GetAtomTypeForCarbon { 272 my($This, $Atom) = @_; 273 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 274 275 $AtomType = 'None'; 276 277 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 278 279 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 280 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 281 282 ATOMTYPE: { 283 284 # Only single bonds... 285 if ($NumOfPiBonds == 0) { 286 $AtomType = $This->_GetAtomTypeForCarbonWithOnlySigmaBonds($Atom); 287 last ATOMTYPE; 288 } 289 290 # One double bond... 291 if ($NumOfPiBonds == 1) { 292 $AtomType = $This->_GetAtomTypeForCarbonWithOnePiBond($Atom); 293 last ATOMTYPE; 294 } 295 296 # One triple bond or two double bonds... 297 if ($NumOfPiBonds == 2) { 298 $AtomType = $This->_GetAtomTypeForCarbonWithTwoPiBonds($Atom); 299 last ATOMTYPE; 300 } 301 302 $AtomType = 'CS'; 303 } 304 return $AtomType; 305 } 306 307 # Get SLogP atom type for Nitrogen atom... 308 # 309 # 15 AtomTypeSymbols for element N: 310 # 311 # AtomTypeSymbol - Description - SMARTS 312 # N1 - primary amine - '[NH2+0]A' 313 # N2 - secondary amine - '[NH+0](A)A' 314 # N3 - primary aromatic amine - '[NH2+0]a' 315 # N4 - secondary aromatic amine - '[NH+0](A)a','[NH+0](a)a' 316 # N5 - imine - '[NH+0]=A','[NH+0]=a' 317 # N6 - substituted imine - '[N+0](=A)A','[N+0](=A)a','[N+0](=a)A','[N+0](=a)a' 318 # N7 - tertiary amine - '[N+0](A)(A)A' 319 # N8 - tertiary aromatic amine - '[N+0](a)(A)A','[N+0](a)(a)A','[N+0](a)(a)a' 320 # N9 - nitrile - '[N+0]#A' 321 # N10 - protonated amine - '[NH3+*]','[NH2+*]','[NH+*]' 322 # N11 - unprotonated aromatic - '[n+0]' 323 # N12 - protonated aromatic - '[n+*]' 324 # N13 - quaternary amine - '[NH0+*](A)(A)(A)A','[NH0+*](=A)(A)A','[NH0+*](=A)(A)a','[NH0+*](=[#6])=[#7]' 325 # N14 - other ionized nitrogen - '[N+*]#A','[N-*]','[N+*](=[N-*])=N' 326 # NS - nitrogen supplemental not matching any basic N type - '[#7]' 327 # 328 sub _GetAtomTypeForNitrogen { 329 my($This, $Atom) = @_; 330 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 331 332 $AtomType = 'None'; 333 334 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 335 336 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 337 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 338 339 ATOMTYPE: { 340 341 # Only single bonds... 342 if ($NumOfPiBonds == 0) { 343 $AtomType = $This->_GetAtomTypeForNitrogenWithOnlySigmaBonds($Atom); 344 last ATOMTYPE; 345 } 346 347 # One double bond... 348 if ($NumOfPiBonds == 1) { 349 $AtomType = $This->_GetAtomTypeForNitrogenWithOnePiBond($Atom); 350 last ATOMTYPE; 351 } 352 353 # One triple bond or two double bonds... 354 if ($NumOfPiBonds == 2) { 355 $AtomType = $This->_GetAtomTypeForNitrogenWithTwoPiBonds($Atom); 356 last ATOMTYPE; 357 } 358 359 $AtomType = 'NS'; 360 } 361 return $AtomType; 362 } 363 364 # Get SLogP atom type for Oxygen atom... 365 # 366 # 13 AtomTypeSymbols for element O: 367 # 368 # AtomTypeSymbol - Description - SMARTS 369 # O1 - aromatic - '[o]' 370 # O2 - alcohol - '[OH]','[OH2]' 371 # O3 - aliphatic ether - '[O](C)C','[O](C)[A#X]','[O]([A#X])[A#X]' 372 # O4 - aromatic ether - '[O](A)a','[O](a)a' 373 # O5 - oxide - '[O]=[#8]','[O]=[#7]','[OX1-*][#7]' 374 # O6 - oxide - '[OX1-*][#16]' 375 # O7 - oxide - '[OX1-*][!(N,S)]' 376 # O8 - aromatic carbonyl - '[O]=c' 377 # O9 - carbonyl aliphatic - '[O]=[CH]C','[O]=C(C)C','[O]=C(C)[A#X]','[O]=[CH]N','[O]=[CH]O','[O]=[CH2]','[O]=[CX2]=O' 378 # O10 - carbonyl aromatic - '[O]=[CH]c','[O]=C(C)c','[O]=C(c)c','[O]=C(c)[a#X]','[O]=C(c)[A#X]','[O]=C(C)[a#X]' 379 # O11 - carbonyl heteroatom - '[O]=C([A#X])[A#X]','[O]=C([A#X])[a#X]','[O]=C([a#X])[a#X]' 380 # O12 - acid - '[O-1]C(=O)' 381 # OS - oxygen supplemental not matching any basic O type - '[#8]' 382 # 383 sub _GetAtomTypeForOxygen { 384 my($This, $Atom) = @_; 385 my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds); 386 387 $AtomType = 'None'; 388 389 ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2; 390 391 ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms(); 392 $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H'); 393 394 ATOMTYPE: { 395 396 # Only single bonds... 397 if ($NumOfPiBonds == 0) { 398 $AtomType = $This->_GetAtomTypeForOxygenWithOnlySigmaBonds($Atom); 399 last ATOMTYPE; 400 } 401 402 # One double bond... 403 if ($NumOfPiBonds == 1) { 404 $AtomType = $This->_GetAtomTypeForOxygenWithOnePiBond($Atom); 405 last ATOMTYPE; 406 } 407 408 # OS - oxygen supplemental not matching any basic O type - '[#8]' 409 $AtomType = 'OS'; 410 } 411 return $AtomType; 412 } 413 414 # Get SLogP atom type for Phosphorus atom... 415 # 416 # 1 AtomTypeSymbols for element P: 417 # 418 # AtomTypeSymbol - Description - SMARTS 419 # P - phosphorous - '[#15]' 420 # 421 sub _GetAtomTypeForPhosphorus { 422 my($This, $Atom) = @_; 423 my($AtomType); 424 425 $AtomType = 'P'; 426 427 return $AtomType; 428 } 429 430 # Get SLogP atom type for Sulfur atom... 431 # 432 # 3 AtomTypeSymbols for element S: 433 # 434 # AtomTypeSymbol - Description - SMARTS 435 # S1 - aliphatic - '[S-0]' 436 # S2 - ionic sulfur - '[S-*]','[S+*]' 437 # S3 - aromatic - '[s]' 438 # 439 sub _GetAtomTypeForSulfur { 440 my($This, $Atom) = @_; 441 my($AtomType); 442 443 $AtomType = 'None'; 444 445 ATOMTYPE: { 446 447 # S1 - aliphatic - '[S-0]' 448 if ($This->_IsS1Sulfur($Atom)) { 449 $AtomType = 'S1'; 450 last ATOMTYPE; 451 } 452 453 # S2 - ionic sulfur - '[S-*]','[S+*]' 454 if ($This->_IsS2Sulfur($Atom)) { 455 $AtomType = 'S2'; 456 last ATOMTYPE; 457 } 458 459 # S3 - aromatic - '[s]' 460 if ($This->_IsS3Sulfur($Atom)) { 461 $AtomType = 'S3'; 462 last ATOMTYPE; 463 } 464 465 # S1 - aliphatic - '[S-0]' 466 $AtomType = 'S1'; 467 } 468 469 return $AtomType; 470 } 471 472 # Get SLogP atom type for Hydrogen atom... 473 # 474 # 5 AtomTypeSymbols for element H: 475 # 476 # AtomTypeSymbol - Description - SMARTS 477 # H1 - hydrocarbon - '[#1][#6]','[#1][#1]' 478 # H2 - alcohol - '[#1]O[CX4]','[#1]Oc','[#1]O[!(C,N,O,S)]','[#1][!C,N,O)]' 479 # H3 - amine - '[#1][#7]','[#1]O[#7]' 480 # H4 - acid - '[#1]OC=[#6]','[#1]OC=[#7]','[#1]OC=O','[#1]OC=S','[#1]OO','[#1]OS' 481 # HS - hydrogen supplemental not matching any basic H type - '[#1]' 482 # 483 sub _GetAtomTypeForHydrogen { 484 my($This, $Atom) = @_; 485 my($AtomType); 486 487 $AtomType = 'None'; 488 489 ATOMTYPE: { 490 491 # H1 - hydrocarbon - '[#1][#6]','[#1][#1]' 492 if ($This->_IsH1Hydrogen($Atom)) { 493 $AtomType = 'H1'; 494 last ATOMTYPE; 495 } 496 497 # H2 - alcohol - '[#1]O[CX4]','[#1]Oc','[#1]O[!(C,N,O,S)]','[#1][!C,N,O)]' 498 if ($This->_IsH2Hydrogen($Atom)) { 499 $AtomType = 'H2'; 500 last ATOMTYPE; 501 } 502 503 # H3 - amine - '[#1][#7]','[#1]O[#7]' 504 if ($This->_IsH3Hydrogen($Atom)) { 505 $AtomType = 'H3'; 506 last ATOMTYPE; 507 } 508 509 # H4 - acid - '[#1]OC=[#6]','[#1]OC=[#7]','[#1]OC=O','[#1]OC=S','[#1]OO','[#1]OS' 510 if ($This->_IsH4Hydrogen($Atom)) { 511 $AtomType = 'H4'; 512 last ATOMTYPE; 513 } 514 515 $AtomType = 'HS'; 516 } 517 return $AtomType; 518 } 519 520 # Get SLogP atom type for atoms other than Carbon, Nitrogen, Oxygen, Phosporus, 521 # Sulfur and Hydrogen... 522 # 523 # AtomTypeSymbol - Description - SMARTS 524 # F - fluorine - '[#9-0]' 525 # Cl - chlorine - '[#17-0]' 526 # Br - bromine - '[#35-0]' 527 # I - iodine - '[#53-0]' 528 # Hal - ionic halogens - '[#9-*]','[#17-*]','[#35-*]',[#53-*]','[#53+*]' 529 # Hal - all remaining s-block elements 530 # Me1 - all remaining p-block elements 531 # Me2 - all remaining d-block elements 532 # 533 sub _GetAtomTypeForOtherAtoms { 534 my($This, $Atom) = @_; 535 my($AtomType, $AtomSymbol); 536 537 $AtomType = 'None'; 538 $AtomSymbol = $Atom->GetAtomSymbol(); 539 540 ATOMTYPE: { 541 542 # Halogens... 543 if ($AtomSymbol =~ /^(F|Cl|Br|I)$/i) { 544 $AtomType = $Atom->GetFormalCharge() ? 'Hal' : $AtomSymbol; 545 last ATOMTYPE; 546 } 547 548 # Me1 - all remaining p-block elements 549 if ($This->_IsPBlockElement($Atom)) { 550 $AtomType = 'Me1'; 551 last ATOMTYPE; 552 } 553 554 # Me2 - all remaining d-block elements 555 if ($This->_IsDBlockElement($Atom)) { 556 $AtomType = 'Me2'; 557 last ATOMTYPE; 558 } 559 560 # Hal - all remaining s-block elements 561 if ($This->_IsSBlockElement($Atom)) { 562 $AtomType = 'Hal'; 563 last ATOMTYPE; 564 } 565 566 $AtomType = 'None'; 567 carp "Warning: ${ClassName}->_GetAtomTypeForOtherAtoms: SLogP atom type for $AtomSymbol cann't be assigned..."; 568 } 569 return $AtomType; 570 } 571 572 # Get SLogP atom type for Carbon with only sigma bonds... 573 # 574 sub _GetAtomTypeForCarbonWithOnlySigmaBonds { 575 my($This, $Atom) = @_; 576 my($AtomType); 577 578 $AtomType = 'None'; 579 580 ATOMTYPE: { 581 582 # C1 - primary, secondary aliphatic - '[CH4]','[CH3]C','[CH2](C)C' 583 if ($This->_IsC1Carbon($Atom)) { 584 $AtomType = 'C1'; 585 last ATOMTYPE; 586 } 587 588 # C2 - tertiary, quaternary aliphatic - '[CH](C)(C)C','[C](C)(C)(C)C' 589 if ($This->_IsC2Carbon($Atom)) { 590 $AtomType = 'C2'; 591 last ATOMTYPE; 592 } 593 594 # C3 - primary, secondary heteroatom - '[CH3][(N,O,P,S,F,Cl,Br,I)]','[CH2X4](N,O,P,S,F,Cl,Br,I)]' 595 if ($This->_IsC3Carbon($Atom)) { 596 $AtomType = 'C3'; 597 last ATOMTYPE; 598 } 599 600 # C4 - tertiary, quaternary heteroatom - '[CH1X4][(N,O,P,S,F,Cl,Br,I)]','[CH0X4][(N,O,P,S,F,Cl,Br,I)]' 601 if ($This->_IsC4Carbon($Atom)) { 602 $AtomType = 'C4'; 603 last ATOMTYPE; 604 } 605 606 # C8 - primary aromatic carbon - '[CH3]c' 607 if ($This->_IsC8Carbon($Atom)) { 608 $AtomType = 'C8'; 609 last ATOMTYPE; 610 } 611 612 # C9 - primary aromatic heteroatom - '[CH3][a#X]' 613 if ($This->_IsC9Carbon($Atom)) { 614 $AtomType = 'C9'; 615 last ATOMTYPE; 616 } 617 618 # C10 - secondary aromatic - '[CH2X4]a' 619 if ($This->_IsC10Carbon($Atom)) { 620 $AtomType = 'C10'; 621 last ATOMTYPE; 622 } 623 624 # C11 - tertiary aromatic - '[CHX4]a' 625 if ($This->_IsC11Carbon($Atom)) { 626 $AtomType = 'C11'; 627 last ATOMTYPE; 628 } 629 630 # C12 - quaternary aromatic - '[CH0X4]a' 631 if ($This->_IsC12Carbon($Atom)) { 632 $AtomType = 'C12'; 633 last ATOMTYPE; 634 } 635 636 # C27 - aliphatic heteroatom - '[CX4][!(C,N,O,P,S,F,Cl,Br,I)]' 637 if ($This->_IsC27Carbon($Atom)) { 638 $AtomType = 'C27'; 639 last ATOMTYPE; 640 } 641 642 # CS - carbon supplemental not matching any basic C type - '[#6]' 643 $AtomType = 'CS'; 644 } 645 646 return $AtomType; 647 } 648 649 # Get SLogP atom type for Carbon with one pi bond... 650 # 651 sub _GetAtomTypeForCarbonWithOnePiBond { 652 my($This, $Atom) = @_; 653 my($AtomType); 654 655 $AtomType = 'None'; 656 657 ATOMTYPE: { 658 659 # C5 - C = heteroatom - '[C]=[A#X]' 660 if ($This->_IsC5Carbon($Atom)) { 661 $AtomType = 'C5'; 662 last ATOMTYPE; 663 } 664 665 # C6 - C = C aliphatic - '[CH2]=C','[CH1](=C)A','[CH0](=C)(A)A','[C](=C)=C' 666 if ($This->_IsC6Carbon($Atom)) { 667 $AtomType = 'C6'; 668 last ATOMTYPE; 669 } 670 671 # C13 - aromatic heteroatom - '[cH0]-[!(C,N,O,S,F,Cl,Br,I)]' 672 if ($This->_IsC13Carbon($Atom)) { 673 $AtomType = 'C13'; 674 last ATOMTYPE; 675 } 676 677 # C14 - aromatic halide - '[c][#9]' 678 if ($This->_IsC14Carbon($Atom)) { 679 $AtomType = 'C14'; 680 last ATOMTYPE; 681 } 682 683 # C15 - aromatic halide - '[c][#17]' 684 if ($This->_IsC15Carbon($Atom)) { 685 $AtomType = 'C15'; 686 last ATOMTYPE; 687 } 688 689 # C16 - aromatic halide - '[c][#35]' 690 if ($This->_IsC16Carbon($Atom)) { 691 $AtomType = 'C16'; 692 last ATOMTYPE; 693 } 694 695 # C17 - aromatic halide - '[c][#53]' 696 if ($This->_IsC17Carbon($Atom)) { 697 $AtomType = 'C17'; 698 last ATOMTYPE; 699 } 700 701 # C18 - aromatic - '[cH]' 702 if ($This->_IsC18Carbon($Atom)) { 703 $AtomType = 'C18'; 704 last ATOMTYPE; 705 } 706 707 # C19 - aromatic bridgehead - '[c](:a)(:a):a' 708 if ($This->_IsC19Carbon($Atom)) { 709 $AtomType = 'C19'; 710 last ATOMTYPE; 711 } 712 713 # C20 - quaternary aromatic - '[c](:a)(:a)-a' 714 if ($This->_IsC20Carbon($Atom)) { 715 $AtomType = 'C20'; 716 last ATOMTYPE; 717 } 718 719 # C21 - quaternary aromatic - '[c](:a)(:a)-C' 720 if ($This->_IsC21Carbon($Atom)) { 721 $AtomType = 'C21'; 722 last ATOMTYPE; 723 } 724 725 # C22 - quaternary aromatic - '[c](:a)(:a)-N' 726 if ($This->_IsC22Carbon($Atom)) { 727 $AtomType = 'C22'; 728 last ATOMTYPE; 729 } 730 731 # C23 - quaternary aromatic - '[c](:a)(:a)-O' 732 if ($This->_IsC23Carbon($Atom)) { 733 $AtomType = 'C23'; 734 last ATOMTYPE; 735 } 736 737 # C24 - quaternary aromatic - '[c](:a)(:a)-S' 738 if ($This->_IsC24Carbon($Atom)) { 739 $AtomType = 'C24'; 740 last ATOMTYPE; 741 } 742 743 # C26 - C = C aromatic - '[C](=C)(a)A','[C](=C)(c)a','[CH](=C)a','[C]=c' 744 if ($This->_IsC26Carbon($Atom)) { 745 $AtomType = 'C26'; 746 last ATOMTYPE; 747 } 748 749 # CS - carbon supplemental not matching any basic C type - '[#6]' 750 $AtomType = 'CS'; 751 } 752 753 return $AtomType; 754 } 755 756 # Get SLogP atom type for Carbon with two pi bonds... 757 # 758 sub _GetAtomTypeForCarbonWithTwoPiBonds { 759 my($This, $Atom) = @_; 760 my($AtomType); 761 762 $AtomType = 'None'; 763 764 ATOMTYPE: { 765 766 # C6 - C = C aliphatic - '[CH2]=C','[CH1](=C)A','[CH0](=C)(A)A','[C](=C)=C' 767 if ($This->_IsC6Carbon($Atom)) { 768 $AtomType = 'C6'; 769 last ATOMTYPE; 770 } 771 772 # C7 - acetylene, nitrile - '[CX2]#A' 773 if ($This->_IsC7Carbon($Atom)) { 774 $AtomType = 'C7'; 775 last ATOMTYPE; 776 } 777 778 # CS - carbon supplemental not matching any basic C type - '[#6]' 779 $AtomType = 'CS'; 780 } 781 782 return $AtomType; 783 } 784 785 # C1 - primary, secondary aliphatic - '[CH4]','[CH3]C','[CH2](C)C' 786 # 787 sub _IsC1Carbon { 788 my($This, $Atom) = @_; 789 790 return $Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar', ['C.!Ar,H', 'C.!Ar,H', 'H', 'H'], ['-', '-', '-', '-']) ? 1 : 0; 791 } 792 793 # C2 - tertiary, quaternary aliphatic - '[CH](C)(C)C','[C](C)(C)(C)C' 794 # 795 sub _IsC2Carbon { 796 my($This, $Atom) = @_; 797 798 return $Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar', ['C.!Ar', 'C.!Ar', 'C.!Ar', 'C.!Ar,H'], ['-', '-', '-', '-']) ? 1 : 0; 799 } 800 801 # C3 - primary, secondary heteroatom - '[CH3][(N,O,P,S,F,Cl,Br,I)]','[CH2X4](N,O,P,S,F,Cl,Br,I)]' 802 # 803 sub _IsC3Carbon { 804 my($This, $Atom) = @_; 805 806 return $Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar', ['N.!Ar,O.!Ar,P.!Ar,S.!Ar,F,Cl,Br,I', 'N.!Ar,O.!Ar,P.!Ar,S.!Ar,F,Cl,Br,I,H', 'H', 'H'], ['-', '-', '-', '-']) ? 1 : 0; 807 } 808 809 # C4 - tertiary, quaternary heteroatom - '[CH1X4][(N,O,P,S,F,Cl,Br,I)]','[CH0X4][(N,O,P,S,F,Cl,Br,I)]' 810 # 811 sub _IsC4Carbon { 812 my($This, $Atom) = @_; 813 814 return $Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar', ['N.!Ar,O.!Ar,P.!Ar,.!ArS,F,Cl,Br,I', 'N.!Ar,O.!Ar,P.!Ar,S.!Ar,F,Cl,Br,I', 'N.!Ar,O.!Ar,P.!Ar,S.!Ar,F,Cl,Br,I', 'N.!Ar,O.!Ar,P.!Ar,S.!Ar,F,Cl,Br,I,H'], ['-', '-', '-', '-']) ? 1 : 0; 815 } 816 817 # C5 - C = heteroatom - '[C]=[A#X]' 818 # 819 sub _IsC5Carbon { 820 my($This, $Atom) = @_; 821 822 return $Atom->DoesAtomNeighborhoodMatch('C.!Ar', ['!C.!Ar'], ['=']) ? 1 : 0; 823 } 824 825 # C6 - C = C aliphatic - '[CH2]=C','[CH1](=C)A','[CH0](=C)(A)A','[C](=C)=C' 826 # 827 sub _IsC6Carbon { 828 my($This, $Atom) = @_; 829 830 if ($Atom->DoesAtomNeighborhoodMatch('C.DB1.!Ar', ['C.!Ar', 'H,!H.!Ar', 'H,!H.!Ar'], ['=', '-', '-']) || 831 $Atom->DoesAtomNeighborhoodMatch('C.H0.DB2.!Ar', ['C.!Ar', 'C.!Ar'], ['=', '='])) { 832 return 1; 833 } 834 return 0; 835 } 836 837 # C7 - acetylene, nitrile - '[CX2]#A' 838 # 839 sub _IsC7Carbon { 840 my($This, $Atom) = @_; 841 842 return $Atom->DoesAtomNeighborhoodMatch('C.T2.TB1', ['*', '*'], ['#', '-']) ? 1 : 0; 843 } 844 845 # C8 - primary aromatic carbon - '[CH3]c' 846 # 847 sub _IsC8Carbon { 848 my($This, $Atom) = @_; 849 850 return $Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar', ['C.Ar', 'H', 'H', 'H'], ['-', '-', '-', '-']) ? 1 : 0; 851 } 852 853 # C9 - primary aromatic heteroatom - '[CH3][a#X]' 854 # 855 sub _IsC9Carbon { 856 my($This, $Atom) = @_; 857 858 return $Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar', ['!C.Ar', 'H', 'H', 'H'], ['-', '-', '-', '-']) ? 1 : 0; 859 } 860 861 # C10 - secondary aromatic - '[CH2X4]a' 862 # 863 sub _IsC10Carbon { 864 my($This, $Atom) = @_; 865 866 return $Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar', ['!H.Ar', '!H', 'H', 'H'], ['-', '-', '-', '-']) ? 1 : 0; 867 } 868 869 # C11 - tertiary aromatic - '[CHX4]a' 870 # 871 sub _IsC11Carbon { 872 my($This, $Atom) = @_; 873 874 return $Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar', ['!H.Ar', '!H', '!H', 'H'], ['-', '-', '-', '-']) ? 1 : 0; 875 } 876 877 # C12 - quaternary aromatic - '[CH0X4]a' 878 # 879 sub _IsC12Carbon { 880 my($This, $Atom) = @_; 881 882 return $Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar', ['!H.Ar', '!H', '!H', '!H'], ['-', '-', '-', '-']) ? 1 : 0; 883 } 884 885 # C13 - aromatic heteroatom - '[cH0]-[!(C,N,O,S,F,Cl,Br,I)]' or matching [ Table 1 annotations, Ref 89 ] 886 # '[cH0]-[B,Si,P,As,Se,Sn,Hg]' 887 # 888 # 889 sub _IsC13Carbon { 890 my($This, $Atom) = @_; 891 892 return $Atom->DoesAtomNeighborhoodMatch('C.Ar.H0', ['B,Si,P,As,Se,Sn,Hg'], ['-']) ? 1 : 0; 893 } 894 895 # C14 - aromatic halide - '[c][#9]' 896 # 897 sub _IsC14Carbon { 898 my($This, $Atom) = @_; 899 900 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['F'], ['-']) ? 1 : 0; 901 } 902 903 # C15 - aromatic halide - '[c][#17]' 904 # 905 sub _IsC15Carbon { 906 my($This, $Atom) = @_; 907 908 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['Cl'], ['-']) ? 1 : 0; 909 } 910 911 # C16 - aromatic halide - '[c][#35]' 912 # 913 sub _IsC16Carbon { 914 my($This, $Atom) = @_; 915 916 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['Br'], ['-']) ? 1 : 0; 917 } 918 919 # C17 - aromatic halide - '[c][#53]' 920 # 921 sub _IsC17Carbon { 922 my($This, $Atom) = @_; 923 924 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['I'], ['-']) ? 1 : 0; 925 } 926 927 # C18 - aromatic - '[cH]' 928 # 929 sub _IsC18Carbon { 930 my($This, $Atom) = @_; 931 932 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['H'], ['-']) ? 1 : 0; 933 } 934 935 # C19 - aromatic bridgehead - '[c](:a)(:a):a' 936 # 937 sub _IsC19Carbon { 938 my($This, $Atom) = @_; 939 940 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['!H.Ar', '!H.Ar', '!H.Ar'], [':', ':', ':']) ? 1 : 0; 941 } 942 943 # C20 - quaternary aromatic - '[c](:a)(:a)-a' 944 # 945 sub _IsC20Carbon { 946 my($This, $Atom) = @_; 947 948 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['!H.Ar', '!H.Ar', '!H.Ar'], [':', ':', '-.!:']) ? 1 : 0; 949 } 950 951 # C21 - quaternary aromatic - '[c](:a)(:a)-C' 952 # 953 sub _IsC21Carbon { 954 my($This, $Atom) = @_; 955 956 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['!H.Ar', '!H.Ar', 'C.!Ar'], [':', ':', '-']) ? 1 : 0; 957 } 958 959 # C22 - quaternary aromatic - '[c](:a)(:a)-N' 960 # 961 sub _IsC22Carbon { 962 my($This, $Atom) = @_; 963 964 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['!H.Ar', '!H.Ar', 'N.!Ar'], [':', ':', '-']) ? 1 : 0; 965 } 966 967 # C23 - quaternary aromatic - '[c](:a)(:a)-O' 968 # 969 sub _IsC23Carbon { 970 my($This, $Atom) = @_; 971 972 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['!H.Ar', '!H.Ar', 'O.!Ar'], [':', ':', '-']) ? 1 : 0; 973 } 974 975 # C24 - quaternary aromatic - '[c](:a)(:a)-S' 976 # 977 sub _IsC24Carbon { 978 my($This, $Atom) = @_; 979 980 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['!H.Ar', '!H.Ar', 'S.!Ar'], [':', ':', '-']) ? 1 : 0; 981 } 982 983 # C25 - quaternary aromatic - '[c](:a)(:a)=C','[c](:a)(:a)=N','[c](:a)(:a)=O' 984 # 985 sub _IsC25Carbon { 986 my($This, $Atom) = @_; 987 988 return $Atom->DoesAtomNeighborhoodMatch('C.Ar', ['!H.Ar', '!H.Ar', 'C.!Ar,N.!Ar,O.!Ar'], [':', ':', '=']) ? 1 : 0; 989 } 990 991 # C26 - C = C aromatic - '[C](=C)(a)A','[C](=C)(c)a','[CH](=C)a','[C]=c' 992 # 993 sub _IsC26Carbon { 994 my($This, $Atom) = @_; 995 996 if ($Atom->DoesAtomNeighborhoodMatch('C.!Ar.T3', ['C.!Ar', '!H.Ar', '!H.!Ar'], ['=', '-', '-']) || 997 $Atom->DoesAtomNeighborhoodMatch('C.!Ar.T3', ['C.!Ar', 'C.Ar', '!H.Ar'], ['=', '-', '-']) || 998 $Atom->DoesAtomNeighborhoodMatch('C.!Ar.T3.H1', ['C.!Ar', '!H.Ar', 'H'], ['=', '-', '-']) || 999 $Atom->DoesAtomNeighborhoodMatch('C.!Ar', ['C.Ar'], ['='])) { 1000 return 1; 1001 } 1002 return 0; 1003 } 1004 1005 # C27 - aliphatic heteroatom - '[CX4][!(C,N,O,P,S,F,Cl,Br,I)]' 1006 # 1007 # Notes: 1008 # . X4 implies four neighbors including Hydrogen 1009 # . For C27 match, at least one of the neighbors must be a hetro atom other 1010 # than C,N,O,P,S,F,Cl,Br,I. In other words, it's primary, secondary, tertiary, 1011 # or queaternary aliphatic heteroatom not in (C,N,O,P,S,F,Cl,Br,I) group defined 1012 # using C3 and C4. 1013 # 1014 sub _IsC27Carbon { 1015 my($This, $Atom) = @_; 1016 my($AtomNeighbor, $AtomNeighborSymbol); 1017 1018 if (!$Atom->DoesAtomNeighborhoodMatch('C.T4.!Ar')) { 1019 return 0; 1020 } 1021 1022 ATOMNEIGHBOR: for $AtomNeighbor ($Atom->GetNonHydrogenAtomNeighbors()) { 1023 $AtomNeighborSymbol = $AtomNeighbor->GetAtomSymbol(); 1024 # Is it a heteroatom? 1025 if ($AtomNeighborSymbol =~ /^(C|N|O|P|S|F|Cl|Br|I|H)$/) { 1026 next ATOMNEIGHBOR; 1027 } 1028 # Is it aromatic? 1029 if ($AtomNeighbor->IsAromatic()) { 1030 next ATOMNEIGHBOR; 1031 } 1032 return 1; 1033 } 1034 return 0; 1035 } 1036 1037 # CS - carbon supplemental not matching any basic C type - '[#6]' 1038 # 1039 sub _IsCSCarbon { 1040 my($This, $Atom) = @_; 1041 1042 return $Atom->IsCarbon() ? 1 : 0; 1043 } 1044 1045 # Get SLogP atom type for Nitrogen with only sigma bonds... 1046 # 1047 sub _GetAtomTypeForNitrogenWithOnlySigmaBonds { 1048 my($This, $Atom) = @_; 1049 my($AtomType); 1050 1051 $AtomType = 'None'; 1052 1053 ATOMTYPE: { 1054 1055 # N1 - primary amine - '[NH2+0]A' 1056 if ($This->_IsN1Nitrogen($Atom)) { 1057 $AtomType = 'N1'; 1058 last ATOMTYPE; 1059 } 1060 1061 # N2 - secondary amine - '[NH+0](A)A' 1062 if ($This->_IsN2Nitrogen($Atom)) { 1063 $AtomType = 'N2'; 1064 last ATOMTYPE; 1065 } 1066 1067 # N3 - primary aromatic amine - '[NH2+0]a' 1068 if ($This->_IsN3Nitrogen($Atom)) { 1069 $AtomType = 'N3'; 1070 last ATOMTYPE; 1071 } 1072 1073 # N4 - secondary aromatic amine - '[NH+0](A)a','[NH+0](a)a' 1074 if ($This->_IsN4Nitrogen($Atom)) { 1075 $AtomType = 'N4'; 1076 last ATOMTYPE; 1077 } 1078 1079 # N7 - tertiary amine - '[N+0](A)(A)A' 1080 if ($This->_IsN7Nitrogen($Atom)) { 1081 $AtomType = 'N7'; 1082 last ATOMTYPE; 1083 } 1084 1085 # N8 - tertiary aromatic amine - '[N+0](a)(A)A','[N+0](a)(a)A','[N+0](a)(a)a' 1086 if ($This->_IsN8Nitrogen($Atom)) { 1087 $AtomType = 'N8'; 1088 last ATOMTYPE; 1089 } 1090 1091 # N10 - protonated amine - '[NH3+*]','[NH2+*]','[NH+*]' 1092 if ($This->_IsN10Nitrogen($Atom)) { 1093 $AtomType = 'N10'; 1094 last ATOMTYPE; 1095 } 1096 1097 # N11 - unprotonated aromatic - '[n+0]' 1098 if ($This->_IsN11Nitrogen($Atom)) { 1099 $AtomType = 'N11'; 1100 last ATOMTYPE; 1101 } 1102 1103 # N12 - protonated aromatic - '[n+*]' 1104 if ($This->_IsN12Nitrogen($Atom)) { 1105 $AtomType = 'N12'; 1106 last ATOMTYPE; 1107 } 1108 1109 # N13 - quaternary amine - '[NH0+*](A)(A)(A)A','[NH0+*](=A)(A)A','[NH0+*](=A)(A)a','[NH0+*](=[#6])=[#7]' 1110 if ($This->_IsN13Nitrogen($Atom)) { 1111 $AtomType = 'N13'; 1112 last ATOMTYPE; 1113 } 1114 1115 # N14 - other ionized nitrogen - '[N+*]#A','[N-*]','[N+*](=[N-*])=N' 1116 if ($This->_IsN14Nitrogen($Atom)) { 1117 $AtomType = 'N14'; 1118 last ATOMTYPE; 1119 } 1120 1121 $AtomType = 'NS'; 1122 } 1123 1124 return $AtomType; 1125 } 1126 1127 # Get SLogP atom type for Nitrogen with one pi bond... 1128 # 1129 sub _GetAtomTypeForNitrogenWithOnePiBond { 1130 my($This, $Atom) = @_; 1131 my($AtomType); 1132 1133 $AtomType = 'None'; 1134 1135 ATOMTYPE: { 1136 1137 # N5 - imine - '[NH+0]=A','[NH+0]=a' 1138 if ($This->_IsN5Nitrogen($Atom)) { 1139 $AtomType = 'N5'; 1140 last ATOMTYPE; 1141 } 1142 1143 # N6 - substituted imine - '[N+0](=A)A','[N+0](=A)a','[N+0](=a)A','[N+0](=a)a' 1144 if ($This->_IsN6Nitrogen($Atom)) { 1145 $AtomType = 'N6'; 1146 last ATOMTYPE; 1147 } 1148 1149 # N11 - unprotonated aromatic - '[n+0]' 1150 if ($This->_IsN11Nitrogen($Atom)) { 1151 $AtomType = 'N11'; 1152 last ATOMTYPE; 1153 } 1154 1155 # N12 - protonated aromatic - '[n+*]' 1156 if ($This->_IsN12Nitrogen($Atom)) { 1157 $AtomType = 'N12'; 1158 last ATOMTYPE; 1159 } 1160 1161 # N13 - quaternary amine - '[NH0+*](A)(A)(A)A','[NH0+*](=A)(A)A','[NH0+*](=A)(A)a','[NH0+*](=[#6])=[#7]' 1162 if ($This->_IsN13Nitrogen($Atom)) { 1163 $AtomType = 'N13'; 1164 last ATOMTYPE; 1165 } 1166 1167 # N14 - other ionized nitrogen - '[N+*]#A','[N-*]','[N+*](=[N-*])=N' 1168 if ($This->_IsN14Nitrogen($Atom)) { 1169 $AtomType = 'N14'; 1170 last ATOMTYPE; 1171 } 1172 1173 $AtomType = 'NS'; 1174 } 1175 1176 return $AtomType; 1177 } 1178 1179 # Get SLogP atom type for Nitrogen with two pi bonds... 1180 # 1181 sub _GetAtomTypeForNitrogenWithTwoPiBonds { 1182 my($This, $Atom) = @_; 1183 my($AtomType); 1184 1185 $AtomType = 'None'; 1186 1187 ATOMTYPE: { 1188 1189 # N9 - nitrile - '[N+0]#A' 1190 if ($This->_IsN9Nitrogen($Atom)) { 1191 $AtomType = 'N9'; 1192 last ATOMTYPE; 1193 } 1194 1195 # N13 - quaternary amine - '[NH0+*](A)(A)(A)A','[NH0+*](=A)(A)A','[NH0+*](=A)(A)a','[NH0+*](=[#6])=[#7]' 1196 if ($This->_IsN13Nitrogen($Atom)) { 1197 $AtomType = 'N13'; 1198 last ATOMTYPE; 1199 } 1200 1201 # N14 - other ionized nitrogen - '[N+*]#A','[N-*]','[N+*](=[N-*])=N' 1202 if ($This->_IsN14Nitrogen($Atom)) { 1203 $AtomType = 'N14'; 1204 last ATOMTYPE; 1205 } 1206 1207 $AtomType = 'NS'; 1208 } 1209 1210 return $AtomType; 1211 } 1212 1213 # N1 - primary amine - '[NH2+0]A' 1214 # 1215 sub _IsN1Nitrogen { 1216 my($This, $Atom) = @_; 1217 1218 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.T3.FC0', ['!H.!Ar', 'H', 'H'], ['-', '-', '-']) ? 1 : 0; 1219 } 1220 1221 # N2 - secondary amine - '[NH+0](A)A' 1222 # 1223 sub _IsN2Nitrogen { 1224 my($This, $Atom) = @_; 1225 1226 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.T3.FC0', ['!H.!Ar', '!H.!Ar', 'H'], ['-', '-', '-']) ? 1 : 0; 1227 } 1228 1229 # N3 - primary aromatic amine - '[NH2+0]a' 1230 # 1231 sub _IsN3Nitrogen { 1232 my($This, $Atom) = @_; 1233 1234 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.T3.FC0', ['!H.Ar', 'H', 'H'], ['-', '-', '-']) ? 1 : 0; 1235 } 1236 1237 # N4 - secondary aromatic amine - '[NH+0](A)a','[NH+0](a)a' 1238 # 1239 sub _IsN4Nitrogen { 1240 my($This, $Atom) = @_; 1241 1242 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.T3.FC0', ['!H.Ar', '!H', 'H'], ['-', '-', '-']) ? 1 : 0; 1243 } 1244 1245 # N5 - imine - '[NH+0]=A','[NH+0]=a' 1246 # 1247 sub _IsN5Nitrogen { 1248 my($This, $Atom) = @_; 1249 1250 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.T2.FC0', ['!H', 'H'], ['=', '-']) ? 1 : 0; 1251 } 1252 1253 # N6 - substituted imine - '[N+0](=A)A','[N+0](=A)a','[N+0](=a)A','[N+0](=a)a' 1254 # 1255 sub _IsN6Nitrogen { 1256 my($This, $Atom) = @_; 1257 1258 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.T2.FC0', ['!H', '!H'], ['=', '-']) ? 1 : 0; 1259 } 1260 1261 # N7 - tertiary amine - '[N+0](A)(A)A' 1262 # 1263 sub _IsN7Nitrogen { 1264 my($This, $Atom) = @_; 1265 1266 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.T3.FC0', ['!H.!Ar', '!H.!Ar', '!H.!Ar'], ['-', '-', '-']) ? 1 : 0; 1267 } 1268 1269 # N8 - tertiary aromatic amine - '[N+0](a)(A)A','[N+0](a)(a)A','[N+0](a)(a)a' 1270 # 1271 sub _IsN8Nitrogen { 1272 my($This, $Atom) = @_; 1273 1274 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.T3.FC0', ['!H.Ar', '!H', '!H'], ['-', '-', '-']) ? 1 : 0; 1275 } 1276 1277 # N9 - nitrile - '[N+0]#A' 1278 # 1279 sub _IsN9Nitrogen { 1280 my($This, $Atom) = @_; 1281 1282 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.T1.FC0', ['!H.!Ar'], ['#']) ? 1 : 0; 1283 } 1284 1285 # N10 - protonated amine - '[NH3+*]','[NH2+*]','[NH+*]' 1286 # 1287 sub _IsN10Nitrogen { 1288 my($This, $Atom) = @_; 1289 1290 return $Atom->DoesAtomNeighborhoodMatch('N.!Ar.FC+*.H3,N.!Ar.FC+*.H2,N.!Ar.FC+*.H1') ? 1 : 0; 1291 } 1292 1293 # N11 - unprotonated aromatic - '[n+0]' 1294 # 1295 sub _IsN11Nitrogen { 1296 my($This, $Atom) = @_; 1297 1298 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.FC0.H0') ? 1 : 0; 1299 } 1300 1301 # N12 - protonated aromatic - '[n+*]' 1302 # 1303 sub _IsN12Nitrogen { 1304 my($This, $Atom) = @_; 1305 1306 return $Atom->DoesAtomNeighborhoodMatch('N.Ar.FC+*.!H0') ? 1 : 0; 1307 } 1308 1309 # N13 - quaternary amine - '[NH0+*](A)(A)(A)A','[NH0+*](=A)(A)A','[NH0+*](=A)(A)a','[NH0+*](=[#6])=[#7]' 1310 # 1311 sub _IsN13Nitrogen { 1312 my($This, $Atom) = @_; 1313 1314 if ($Atom->DoesAtomNeighborhoodMatch('N.!Ar.FC+*.T4.H0', ['!H.!Ar', '!H.!Ar', '!H.!Ar', '!H.!Ar'], ['-', '-', '-', '-']) || 1315 $Atom->DoesAtomNeighborhoodMatch('N.!Ar.FC+*.T3.H0', ['!H.!Ar', '!H.!Ar', '!H.!Ar'], ['=', '-', '-']) || 1316 $Atom->DoesAtomNeighborhoodMatch('N.!Ar.FC+*.T3.H0', ['!H.!Ar', '!H.!Ar', '!H.Ar'], ['=', '-', '-']) || 1317 $Atom->DoesAtomNeighborhoodMatch('N.!Ar.FC+*.T2.H0', ['C.!Ar', 'N.!Ar'], ['=', '=']) ) { 1318 return 1; 1319 } 1320 return 0; 1321 } 1322 1323 # N14 - other ionized nitrogen - '[N+*]#A','[N-*]','[N+*](=[N-*])=N' 1324 # 1325 sub _IsN14Nitrogen { 1326 my($This, $Atom) = @_; 1327 1328 if ($Atom->DoesAtomNeighborhoodMatch('N.!Ar.FC+*', ['!H.!Ar'], ['#']) || 1329 $Atom->DoesAtomNeighborhoodMatch('N.!Ar.FC-*') || 1330 $Atom->DoesAtomNeighborhoodMatch('N.!Ar.FC+*', ['N.!Ar.FC-*', 'N.!Ar'], ['=', '=']) ) { 1331 return 1; 1332 } 1333 return 0; 1334 } 1335 1336 # NS - nitrogen supplemental not matching any basic N type - '[#7]' 1337 # 1338 sub _IsNSNitrogen { 1339 my($This, $Atom) = @_; 1340 1341 return $Atom->IsNitrogen() ? 1 : 0; 1342 } 1343 1344 # Get SLogP atom type for Oxygen with only sigma bonds... 1345 # 1346 sub _GetAtomTypeForOxygenWithOnlySigmaBonds { 1347 my($This, $Atom) = @_; 1348 my($AtomType); 1349 1350 $AtomType = 'None'; 1351 1352 ATOMTYPE: { 1353 1354 # O1 - aromatic - '[o]' 1355 if ($This->_IsO1Oxygen($Atom)) { 1356 $AtomType = 'O1'; 1357 last ATOMTYPE; 1358 } 1359 1360 # O2 - alcohol - '[OH]','[OH2]' 1361 if ($This->_IsO2Oxygen($Atom)) { 1362 $AtomType = 'O2'; 1363 last ATOMTYPE; 1364 } 1365 1366 # O3 - aliphatic ether - '[O](C)C','[O](C)[A#X]','[O]([A#X])[A#X]' 1367 if ($This->_IsO3Oxygen($Atom)) { 1368 $AtomType = 'O3'; 1369 last ATOMTYPE; 1370 } 1371 1372 # O4 - aromatic ether - '[O](A)a','[O](a)a' 1373 if ($This->_IsO4Oxygen($Atom)) { 1374 $AtomType = 'O4'; 1375 last ATOMTYPE; 1376 } 1377 1378 # O5 - oxide - '[O]=[#8]','[O]=[#7]','[OX1-*][#7]' 1379 if ($This->_IsO5Oxygen($Atom)) { 1380 $AtomType = 'O5'; 1381 last ATOMTYPE; 1382 } 1383 1384 # O6 - oxide - '[OX1-*][#16]' 1385 if ($This->_IsO6Oxygen($Atom)) { 1386 $AtomType = 'O6'; 1387 last ATOMTYPE; 1388 } 1389 1390 # O7 - oxide - '[OX1-*][!(N,S)]' 1391 if ($This->_IsO7Oxygen($Atom)) { 1392 $AtomType = 'O7'; 1393 last ATOMTYPE; 1394 } 1395 1396 # O12 - acid - '[O-1]C(=O)' 1397 if ($This->_IsO12Oxygen($Atom)) { 1398 $AtomType = 'O12'; 1399 last ATOMTYPE; 1400 } 1401 1402 $AtomType = 'OS'; 1403 } 1404 1405 return $AtomType; 1406 } 1407 1408 # Get SLogP atom type for Oxygen with only sigma bonds... 1409 # 1410 sub _GetAtomTypeForOxygenWithOnePiBond { 1411 my($This, $Atom) = @_; 1412 my($AtomType); 1413 1414 $AtomType = 'None'; 1415 1416 ATOMTYPE: { 1417 1418 # O1 - aromatic - '[o]' 1419 if ($This->_IsO1Oxygen($Atom)) { 1420 $AtomType = 'O1'; 1421 last ATOMTYPE; 1422 } 1423 1424 # O5 - oxide - '[O]=[#8]','[O]=[#7]','[OX1-*][#7]' 1425 if ($This->_IsO5Oxygen($Atom)) { 1426 $AtomType = 'O5'; 1427 last ATOMTYPE; 1428 } 1429 1430 # O8 - aromatic carbonyl - '[O]=c' 1431 if ($This->_IsO8Oxygen($Atom)) { 1432 $AtomType = 'O8'; 1433 last ATOMTYPE; 1434 } 1435 1436 # O9 - carbonyl aliphatic - '[O]=[CH]C','[O]=C(C)C','[O]=C(C)[A#X]','[O]=[CH]N','[O]=[CH]O','[O]=[CH2]','[O]=[CX2]=O' 1437 if ($This->_IsO9Oxygen($Atom)) { 1438 $AtomType = 'O9'; 1439 last ATOMTYPE; 1440 } 1441 1442 # O10 - carbonyl aromatic - '[O]=[CH]c','[O]=C(C)c','[O]=C(c)c','[O]=C(c)[a#X]','[O]=C(c)[A#X]','[O]=C(C)[a#X]' 1443 if ($This->_IsO10Oxygen($Atom)) { 1444 $AtomType = 'O10'; 1445 last ATOMTYPE; 1446 } 1447 1448 # O11 - carbonyl heteroatom - '[O]=C([A#X])[A#X]','[O]=C([A#X])[a#X]','[O]=C([a#X])[a#X]' 1449 if ($This->_IsO11Oxygen($Atom)) { 1450 $AtomType = 'O11'; 1451 last ATOMTYPE; 1452 } 1453 1454 $AtomType = 'OS'; 1455 } 1456 1457 return $AtomType; 1458 } 1459 1460 # O1 - aromatic - '[o]' 1461 # 1462 sub _IsO1Oxygen { 1463 my($This, $Atom) = @_; 1464 1465 return $Atom->DoesAtomNeighborhoodMatch('O.Ar') ? 1 : 0; 1466 } 1467 1468 # O2 - alcohol - '[OH]','[OH2]' 1469 # 1470 sub _IsO2Oxygen { 1471 my($This, $Atom) = @_; 1472 1473 if ($Atom->DoesAtomNeighborhoodMatch('O.TSB2.!Ar', ['C', 'H'], ['-', '-']) || 1474 $Atom->DoesAtomNeighborhoodMatch('O.TSB2.!Ar', ['H', 'H'])) { 1475 return 1; 1476 } 1477 return 0; 1478 } 1479 1480 # O3 - aliphatic ether - '[O](C)C','[O](C)[A#X]','[O]([A#X])[A#X]' 1481 # 1482 sub _IsO3Oxygen { 1483 my($This, $Atom) = @_; 1484 1485 return $Atom->DoesAtomNeighborhoodMatch('O.!Ar.X2', ['!H.!Ar', '!H.!Ar'], ['-', '-']) ? 1 : 0; 1486 } 1487 1488 # O4 - aromatic ether - '[O](A)a','[O](a)a' 1489 # 1490 sub _IsO4Oxygen { 1491 my($This, $Atom) = @_; 1492 1493 return $Atom->DoesAtomNeighborhoodMatch('O.X2.!Ar', ['!H', '!H.Ar'], ['-', '-']) ? 1 : 0; 1494 } 1495 1496 # O5 - oxide - '[O]=[#8]','[O]=[#7]','[OX1-*][#7]' 1497 # 1498 sub _IsO5Oxygen { 1499 my($This, $Atom) = @_; 1500 1501 if ($Atom->DoesAtomNeighborhoodMatch('O.DB1.FC0', ['N,O'], ['=']) || 1502 $Atom->DoesAtomNeighborhoodMatch('O.T1.FC-*', ['N'], ['-'])) { 1503 return 1; 1504 } 1505 return 0; 1506 } 1507 1508 # O6 - oxide - '[OX1-*][#16]' 1509 # 1510 sub _IsO6Oxygen { 1511 my($This, $Atom) = @_; 1512 1513 return $Atom->DoesAtomNeighborhoodMatch('O.T1.FC-*', ['S'], ['-']) ? 1 : 0; 1514 } 1515 1516 # O7 - oxide - '[OX1-*][!(N,S)]' or matching [ Table 1 annotations, Ref 89 ] 1517 # '[OX1-*](P,As,Tc,I) 1518 # 1519 sub _IsO7Oxygen { 1520 my($This, $Atom) = @_; 1521 1522 return $Atom->DoesAtomNeighborhoodMatch('O.T1.FC-*', ['P,As,Tc,I'], ['-']) ? 1 : 0; 1523 } 1524 1525 # O8 - aromatic carbonyl - '[O]=c' 1526 # 1527 sub _IsO8Oxygen { 1528 my($This, $Atom) = @_; 1529 1530 return $Atom->DoesAtomNeighborhoodMatch('O.DB1.!Ar', ['C.Ar'], ['=']) ? 1 : 0; 1531 } 1532 1533 # O9 - carbonyl aliphatic - '[O]=[CH]C','[O]=C(C)C','[O]=C(C)[A#X]','[O]=[CH]N','[O]=[CH]O','[O]=[CH2]','[O]=[CX2]=O' 1534 # 1535 sub _IsO9Oxygen { 1536 my($This, $Atom) = @_; 1537 my($AtomNeighbor); 1538 1539 # Is it a doubly bonded non-aromatic Oxygen? 1540 if (!$Atom->DoesAtomNeighborhoodMatch('O.DB1.!Ar.FC0')) { 1541 return 0; 1542 } 1543 1544 # Is it attached to appopriate Carbon? 1545 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C')) { 1546 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3', ['O.!Ar', 'C.!Ar', 'H,C.!Ar'], ['=', '-', '-']) || 1547 $AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3.H0', ['O.!Ar', '!C.!Ar', 'C.!Ar'], ['=', '-', '-']) || 1548 $AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3', ['O.!Ar', 'N.!Ar,O.!Ar', 'H'], ['=', '-', '-']) || 1549 $AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3', ['O.!Ar', 'H', 'H'], ['=', '-', '-']) || 1550 $AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB2.T2', ['O.!Ar', 'O.!Ar'], ['=', '='])) { 1551 return 1; 1552 } 1553 } 1554 return 0; 1555 } 1556 1557 # O10 - carbonyl aromatic - '[O]=[CH]c','[O]=C(C)c','[O]=C(c)c','[O]=C(c)[a#X]','[O]=C(c)[A#X]','[O]=C(C)[a#X]' 1558 # 1559 sub _IsO10Oxygen { 1560 my($This, $Atom) = @_; 1561 my($AtomNeighbor); 1562 1563 # Is it a doubly bonded non-aromatic Oxygen? 1564 if (!$Atom->DoesAtomNeighborhoodMatch('O.DB1.!Ar.FC0')) { 1565 return 0; 1566 } 1567 1568 # Is it attached to appopriate Carbon? 1569 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C')) { 1570 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3', ['O.!Ar', 'C.Ar', 'H'], ['=', '-', '-']) || 1571 $AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3', ['O.!Ar', 'C.Ar', 'C.!Ar'], ['=', '-', '-']) || 1572 $AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3', ['O.!Ar', 'C.Ar', 'C.Ar'], ['=', '-', '-']) || 1573 $AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3.H0', ['O.!Ar', '!C', 'C.Ar'], ['=', '-', '-']) || 1574 $AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3.H0', ['O.!Ar', '!C.Ar', 'C.!Ar'], ['=', '-', '-'])) { 1575 return 1; 1576 } 1577 } 1578 return 0; 1579 } 1580 1581 # O11 - carbonyl heteroatom - '[O]=C([A#X])[A#X]','[O]=C([A#X])[a#X]','[O]=C([a#X])[a#X]' 1582 # 1583 sub _IsO11Oxygen { 1584 my($This, $Atom) = @_; 1585 my($AtomNeighbor); 1586 1587 # Is it a doubly bonded non-aromatic Oxygen? 1588 if (!$Atom->DoesAtomNeighborhoodMatch('O.DB1.!Ar.FC0')) { 1589 return 0; 1590 } 1591 1592 # Is it attached to appopriate Carbon? 1593 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C')) { 1594 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3.H0', ['O.!Ar', '!C', '!C'], ['=', '-', '-'])) { 1595 return 1; 1596 } 1597 } 1598 return 0; 1599 } 1600 1601 # O12 - acid - '[O-1]C(=O)' 1602 # 1603 sub _IsO12Oxygen { 1604 my($This, $Atom) = @_; 1605 my($AtomNeighbor); 1606 1607 # Is it a acid Oxygen? 1608 if (!$Atom->DoesAtomNeighborhoodMatch('O.DB0.!Ar.FC-1')) { 1609 return 0; 1610 } 1611 1612 # Is it attached to appopriate Carbon? 1613 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('C')) { 1614 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('C.DB1.T3', ['O.FC0', 'O.FC-1'], ['=', '-'])) { 1615 return 1; 1616 } 1617 } 1618 return 0; 1619 } 1620 1621 # OS - oxygen supplemental not matching any basic O type - '[#8]' 1622 # 1623 sub _IsOSOxygen { 1624 my($This, $Atom) = @_; 1625 1626 return $Atom->IsOxygen() ? 1 : 0; 1627 } 1628 1629 # S1 - aliphatic - '[S-0]' 1630 # 1631 sub _IsS1Sulfur { 1632 my($This, $Atom) = @_; 1633 1634 return $Atom->DoesAtomNeighborhoodMatch('S.!Ar.FC0') ? 1 : 0; 1635 } 1636 1637 # S2 - ionic sulfur - '[S-*]','[S+*]' 1638 # 1639 sub _IsS2Sulfur { 1640 my($This, $Atom) = @_; 1641 1642 return $Atom->DoesAtomNeighborhoodMatch('S.!Ar.FC-*,S.!Ar.FC+*') ? 1 : 0; 1643 } 1644 1645 # S3 - aromatic - '[s]' 1646 # 1647 sub _IsS3Sulfur { 1648 my($This, $Atom) = @_; 1649 1650 return $Atom->DoesAtomNeighborhoodMatch('S.Ar') ? 1 : 0; 1651 } 1652 1653 # Hal - all remaining s-block elements 1654 # 1655 sub _IsSBlockElement { 1656 my($This, $Atom) = @_; 1657 my($GroupNumber); 1658 1659 $GroupNumber = $Atom->GetGroupNumber(); 1660 1661 return ($GroupNumber >= 1 && $GroupNumber <= 2) ? 1 : 0; 1662 } 1663 1664 # Me1 - all remaining p-block elements 1665 # 1666 sub _IsPBlockElement { 1667 my($This, $Atom) = @_; 1668 my($GroupNumber); 1669 1670 $GroupNumber = $Atom->GetGroupNumber(); 1671 1672 return ($GroupNumber >= 13 && $GroupNumber <= 18) ? 1 : 0; 1673 } 1674 1675 # Me2 - all remaining d-block elements 1676 # 1677 sub _IsDBlockElement { 1678 my($This, $Atom) = @_; 1679 my($GroupNumber); 1680 1681 $GroupNumber = $Atom->GetGroupNumber(); 1682 1683 return ($GroupNumber >= 3 && $GroupNumber <= 12) ? 1 : 0; 1684 } 1685 1686 # H1 - hydrocarbon - '[#1][#6]','[#1][#1]' 1687 # 1688 sub _IsH1Hydrogen { 1689 my($This, $Atom) = @_; 1690 1691 return $Atom->DoesAtomNeighborhoodMatch('H', ['C,H']) ? 1 : 0; 1692 } 1693 1694 # H2 - alcohol - '[#1]O[CX4]','[#1]Oc','[#1]O[!(C,N,O,S)]','[#1][!C,N,O)]' or matching [ Table 1 annotations, Ref 89 ] 1695 # '[H]O[CX4]', '[H]Oc', '[H]O[H,B,Si,P,As,Sn]','[H][B,Si,P,S,Sn]' 1696 # 1697 sub _IsH2Hydrogen { 1698 my($This, $Atom) = @_; 1699 my($AtomNeighbor); 1700 1701 # Is Hydrogen directly attached to B,Si,P,S,Sn? 1702 if ($Atom->DoesAtomNeighborhoodMatch('H', ['B,Si,P,S,Sn'], ['-'])) { 1703 return 1; 1704 } 1705 1706 # Is Hydrogen directly attached to Oxygen? 1707 if (!$Atom->DoesAtomNeighborhoodMatch('H', ['O'])) { 1708 return 0; 1709 } 1710 1711 # Is it attached to appropriate Oxygen? 1712 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('O')) { 1713 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('O.T2', ['C.T4', 'H'], ['-', '-']) || 1714 $AtomNeighbor->DoesAtomNeighborhoodMatch('O.T2', ['C.Ar', 'H'], ['-', '-']) || 1715 $AtomNeighbor->DoesAtomNeighborhoodMatch('O.T2', ['B,Si,P,As,Sn', 'H'], ['-', '-']) || 1716 $AtomNeighbor->DoesAtomNeighborhoodMatch('O.T2', ['H', 'H'], ['-', '-'])) { 1717 return 1; 1718 } 1719 } 1720 return 0; 1721 } 1722 1723 # H3 - amine - '[#1][#7]','[#1]O[#7]' 1724 # 1725 sub _IsH3Hydrogen { 1726 my($This, $Atom) = @_; 1727 my($AtomNeighbor); 1728 1729 # Is Hydrogen directly attached to Nitrogen? 1730 if ($Atom->DoesAtomNeighborhoodMatch('H', ['N'])) { 1731 return 1; 1732 } 1733 1734 # Is Hydrogen directly attached to Oxygen? 1735 if (!$Atom->DoesAtomNeighborhoodMatch('H', ['O'])) { 1736 return 0; 1737 } 1738 1739 # Is it attached to appropriate Oxygen? 1740 for $AtomNeighbor ($Atom->GetNeighborsUsingAtomSpecification('O')) { 1741 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('O.T2', ['N', 'H'], ['-', '-'])) { 1742 return 1; 1743 } 1744 } 1745 return 0; 1746 } 1747 1748 # H4 - acid - '[#1]OC=[#6]','[#1]OC=[#7]','[#1]OC=O','[#1]OC=S','[#1]OO','[#1]OS' 1749 # 1750 sub _IsH4Hydrogen { 1751 my($This, $Atom) = @_; 1752 my($AtomNeighbor, $AtomNbrOfNbr); 1753 1754 # Get non-hydrogen atom neighbor... 1755 $AtomNeighbor = $Atom->GetNonHydrogenNeighborOfHydrogenAtom(); 1756 if (!$AtomNeighbor) { 1757 return 0; 1758 } 1759 1760 # Is it Oxygen neighbor? 1761 if (!$AtomNeighbor->IsOxygen()) { 1762 return 0; 1763 } 1764 1765 # '[#1]OO','[#1]OS' 1766 if ($AtomNeighbor->DoesAtomNeighborhoodMatch('O.TSB2', ['O,S', 'H'], ['-', '-'])) { 1767 return 1; 1768 } 1769 1770 # '[#1]OC=[#6]','[#1]OC=[#7]','[#1]OC=O','[#1]OC=S' 1771 for $AtomNbrOfNbr ($AtomNeighbor->GetNeighborsUsingAtomSpecification('C.DB1')) { 1772 if ($AtomNbrOfNbr->DoesAtomNeighborhoodMatch('C.T3.DB1', ['O.H1', 'O,C,N,S', '*'], ['-', '=', '-'])) { 1773 return 1; 1774 } 1775 } 1776 return 0; 1777 } 1778 1779 # HS - hydrogen supplemental not matching any basic H type - '[#1]' 1780 # 1781 sub _IsHSHydrogen { 1782 my($This, $Atom) = @_; 1783 1784 return $Atom->IsHydrogen() ? 1 : 0; 1785 } 1786 1787 # Return a string containg data for SLogPAtomTypes object... 1788 # 1789 sub StringifySLogPAtomTypes { 1790 my($This) = @_; 1791 my($AtomTypesString); 1792 1793 # Type of AtomTypes... 1794 $AtomTypesString = "AtomTypes: $This->{Type}; IgnoreHydrogens: " . ($This->{IgnoreHydrogens} ? "Yes" : "No"); 1795 1796 # Setup atom types information... 1797 my($AtomID, $AtomType, @AtomTypesInfo, %AssignedAtomTypes); 1798 1799 @AtomTypesInfo = (); 1800 %AssignedAtomTypes = $This->GetAtomTypes(); 1801 1802 for $AtomID (sort { $a <=> $b } keys %AssignedAtomTypes) { 1803 $AtomType = $AssignedAtomTypes{$AtomID} ? $AssignedAtomTypes{$AtomID} : 'None'; 1804 push @AtomTypesInfo, "$AtomID:$AtomType"; 1805 } 1806 $AtomTypesString .= "; AtomIDs:AtomTypes: <" . TextUtil::JoinWords(\@AtomTypesInfo, ", ", 0) . ">"; 1807 1808 return $AtomTypesString; 1809 } 1810 1811 # Is it a SLogPAtomTypes object? 1812 sub _IsSLogPAtomTypes { 1813 my($Object) = @_; 1814 1815 return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0; 1816 } 1817 1818 # Check and load SLogP atom types data... 1819 # 1820 sub _CheckAndLoadSLogPAtomTypesData { 1821 1822 # Is it already loaded? 1823 if (exists $SLogPAtomTypesDataMap{AtomTypes}) { 1824 return; 1825 } 1826 1827 _LoadSLogPAtomTypesData(); 1828 } 1829 1830 # Load SLogP atom types data from the file assuming first column to be atom type symbol.. 1831 # 1832 # Format: 1833 # 1834 # "AtomTypeSymbol","Description","SMARTS","LogPContribution","MRContribution" 1835 # "C1","primary, secondary aliphatic","'[CH4]','[CH3]C','[CH2](C)C'","0.1441","2.503" 1836 # "C2","tertiary, quaternary aliphatic","'[CH](C)(C)C','[C](C)(C)(C)C'","0.0000","2.433" 1837 # 1838 sub _LoadSLogPAtomTypesData { 1839 my($AtomTypesDataFile, $MayaChemToolsLibDir); 1840 1841 $MayaChemToolsLibDir = FileUtil::GetMayaChemToolsLibDirName(); 1842 1843 $AtomTypesDataFile = "$MayaChemToolsLibDir" . "/data/SLogPAtomTypes.csv"; 1844 if (! -e "$AtomTypesDataFile") { 1845 croak "Error: MayaChemTools package file, $AtomTypesDataFile, is missing: Possible installation problems..."; 1846 } 1847 1848 %SLogPAtomTypesDataMap = (); 1849 AtomTypes::AtomTypes::LoadAtomTypesData($AtomTypesDataFile, \%SLogPAtomTypesDataMap); 1850 } 1851