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