MayaChemTools

   1 package AtomTypes::EStateAtomTypes;
   2 #
   3 # $RCSfile: EStateAtomTypes.pm,v $
   4 # $Date: 2015/02/28 20:48:03 $
   5 # $Revision: 1.21 $
   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 AtomTypes::AtomTypes;
  34 use Molecule;
  35 
  36 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  37 
  38 @ISA = qw(AtomTypes::AtomTypes Exporter);
  39 @EXPORT = qw(GetEStateAtomTypesData GetAllPossibleEStateAtomTypes GetAllPossibleEStateNonHydrogenAtomTypes);
  40 @EXPORT_OK = qw();
  41 
  42 %EXPORT_TAGS = (all  => [@EXPORT, @EXPORT_OK]);
  43 
  44 # Setup class variables...
  45 my($ClassName, %EStateAtomTypesDataMap);
  46 _InitializeClass();
  47 
  48 # Overload Perl functions...
  49 use overload '""' => 'StringifyEStateAtomTypes';
  50 
  51 # Class constructor...
  52 sub new {
  53   my($Class, %NamesAndValues) = @_;
  54 
  55   # Initialize object...
  56   my $This = $Class->SUPER::new();
  57   bless $This, ref($Class) || $Class;
  58   $This->_InitializeEStateAtomTypes();
  59 
  60   $This->_InitializeEStateAtomTypesProperties(%NamesAndValues);
  61 
  62   return $This;
  63 }
  64 
  65 # Initialize class ...
  66 sub _InitializeClass {
  67   #Class name...
  68   $ClassName = __PACKAGE__;
  69 
  70   # Initialize the data hash. It'll be loaded on demand later...
  71   %EStateAtomTypesDataMap = ();
  72 }
  73 
  74 # Initialize object data...
  75 #
  76 sub _InitializeEStateAtomTypes {
  77   my($This) = @_;
  78 
  79   # Type of AtomTypes...
  80   $This->{Type} = 'EState';
  81 
  82   # By default, EState atom types are also assigned to hydrogens...
  83   $This->{IgnoreHydrogens} = 0;
  84 
  85   return $This;
  86 }
  87 
  88 # Initialize object properties...
  89 #
  90 sub _InitializeEStateAtomTypesProperties {
  91   my($This, %NamesAndValues) = @_;
  92 
  93   my($Name, $Value, $MethodName);
  94   while (($Name, $Value) = each  %NamesAndValues) {
  95     $MethodName = "Set${Name}";
  96     $This->$MethodName($Value);
  97   }
  98 
  99   # Make sure molecule object was specified...
 100   if (!exists $NamesAndValues{Molecule}) {
 101     croak "Error: ${ClassName}->New: Object can't be instantiated without specifying molecule...";
 102   }
 103 
 104   return $This;
 105 }
 106 
 107 # Get EState atom types and associated data loaded from EState data file as
 108 # a reference to hash with the following hash data format:
 109 #
 110 # @{$EStateAtomTypesDataMap{AtomTypes}} - Array of all possible atom types for all atoms
 111 # @{$EStateAtomTypesDataMap{NonHydrogenAtomTypes}} - Array of all possible atom types for non-hydrogen atoms
 112 # @{$EStateAtomTypesDataMap->{ColLabels}} - Array of column labels
 113 # %{$EStateAtomTypesDataMap->{DataCol<Num>}} - Hash keys pair: <DataCol<Num>, AtomType>
 114 #
 115 # This functionality can be either invoked as a class function or an
 116 # object method.
 117 #
 118 sub GetEStateAtomTypesData {
 119 
 120   # Make sure data is loaded...
 121   _CheckAndLoadEStateAtomTypesData();
 122 
 123   return \%EStateAtomTypesDataMap;
 124 }
 125 
 126 # Get all possible E-state atom types corresponding to hydrogen and non-hydrogen
 127 # atoms as an array reference...
 128 #
 129 # This functionality can be either invoked as a class function or an
 130 # object method.
 131 #
 132 sub GetAllPossibleEStateAtomTypes {
 133   return _GetAllPossibleEStateAtomTypes();
 134 }
 135 
 136 # Get all possible E-state atom types corresponding to non-hydrogen atoms
 137 # as an array reference...
 138 #
 139 # This functionality can be either invoked as a class function or an
 140 # object method.
 141 #
 142 sub GetAllPossibleEStateNonHydrogenAtomTypes {
 143   my($NonHydrogensOnly);
 144 
 145   $NonHydrogensOnly = 1;
 146   return _GetAllPossibleEStateAtomTypes($NonHydrogensOnly);
 147 }
 148 
 149 # Get all possible E-state atom types as an array reference...
 150 #
 151 sub _GetAllPossibleEStateAtomTypes {
 152   my($NonHydrogensOnly) = @_;
 153   my($EStateAtomTypesDataRef);
 154 
 155   $NonHydrogensOnly = defined $NonHydrogensOnly ? $NonHydrogensOnly : 0;
 156 
 157   $EStateAtomTypesDataRef = GetEStateAtomTypesData();
 158 
 159   return $NonHydrogensOnly ? \@{$EStateAtomTypesDataRef->{NonHydrogenAtomTypes}}: \@{$EStateAtomTypesDataRef->{AtomTypes}};
 160 }
 161 
 162 # Assign electrotopological state (E-state) [ Ref 75-78 ] atom types to all atoms...
 163 #
 164 # E-state atom types for various different atom groups [Appendix Table 1 in Ref 76, Appendix III
 165 # in Ref 77 ] are defined using central atom environments indicating its topological and valence state
 166 # along with bonded hydrogens.
 167 #
 168 # The current release of MayaChemTools implements an extended E-state atom assignment
 169 # methodology which is able to assign atom types to any valid non-hydrogen atom in any
 170 # atom group instead of a fixed set of E-state atom types [ Ref 77].
 171 #
 172 # Let:
 173 #   As = Atom symbol corresponding to element symbol
 174 #
 175 #   H<n>   = Number of implicit and explicit hydrogens for atom
 176 #
 177 #   s = Single bond to non-hydrogen atom neighbors or heavy atoms attached to atom
 178 #   s<x> = Symbol s repeated x times to indicate multiple single bonds
 179 #
 180 #   d = Double bond to non-hydrogen atom neighbors or heavy atoms attached to atom
 181 #   d<x> = Symbol d repeated x times to indicate multiple double bonds
 182 #
 183 #   t = Triple bond to non-hydrogen atom neighbors or heavy atoms attached to atom
 184 #   t<x> = Symbol t repeated x times to indicate multiple triple bonds
 185 #
 186 #   a = Aromatic to bond non-hydrogen atom neighbors or heavy atoms attached to atom
 187 #   t<x> = Symbol a repeated x times to indicate multiple aromatic bonds
 188 #
 189 #   p = Plus or positive formal charge
 190 #   m = Minus or negative formal charge
 191 #
 192 # Then:
 193 #
 194 #   AtomType specification corresponds to:
 195 #
 196 #     t<x>d<x>a<x>s<x>AsH<n>p or t<x>d<x>a<x>s<x>AsH<n>m
 197 #
 198 # Notes:
 199 #   . p and n with values of 0 are not shown.
 200 #   . s, d, t, and a bond symbol with values of zero are not shown.
 201 #   . s and d bonds which are also aromatic don't contribute to the count of single and
 202 #     double bonds; instead, aromatic bond count reflect these bonds.
 203 #   . The E-state atom type assignment scheme implemented in the current release of
 204 #     MayaChemToools package supports assignment of atom types to all the periodic tab'e
 205 #     element.
 206 #
 207 # Hydrogen E-state [ Ref 76-77 ] atom type definitions:
 208 #
 209 # HGroup    AtomType
 210 #
 211 #   -OH        HsOH
 212 #   -SH        HsSH
 213 #
 214 #   -NH2       HsNH2
 215 #   >NH        HssNH
 216 #   =NH        HdNH
 217 #   :NH:       HaaNH
 218 #   -NH3+      HsNH3p
 219 #   >NH2+     HssNH2p
 220 #   >NH-+      HsssNHp
 221 #
 222 #   #CH        HtCH
 223 #   =CH2       HdCH2 - H attached to a terminal vinyl group
 224 #   =CH-       HdsCH - H attached a non-terminal vinyl group
 225 #   :CH:       HaaCH
 226 #
 227 #   >CHF       HCHF
 228 #   -CH2F      HCH2F
 229 #   >CHCl      HCHCl
 230 #   -CH2Cl     HCH2Cl
 231 #
 232 #   CHn (saturated)      HCsats   - H attached to sp3 carbon attached to saturated carbon(s)
 233 #   CHn (unsatd.)        HCsatu   - H attached to sp3 carbon attached to unsaturated carbon(s)
 234 #
 235 #   CHn (aromatic)       Havin    - H attached to a non-terminal vinyl group, =CH-, attached to an aromatic carbon
 236 #
 237 #   CHn        Hother    - H attached to any other type of C, N, O or S
 238 #   AHn        Hmisc     - H not attached to C, N, O or  S
 239 #
 240 # Notes:
 241 #   . - : Single bond; = : Double bond; # : Triple bond
 242 #   . Hother atom type capture Hydrogen atom groups not explicitly defined.
 243 #   . HGroup doesn't explicitly corresponds to functional groups
 244 #     . -OH group could be a hydroxyl group or part of carboxylic acid group and so on
 245 #     . -NH2 group could be primary amine or part of an amide group and so on
 246 #
 247 sub AssignAtomTypes {
 248   my($This) = @_;
 249   my($Atom);
 250 
 251   ATOM: for $Atom ($This->GetMolecule()->GetAtoms()) {
 252     if ($Atom->IsHydrogen()) {
 253       if (!$This->{IgnoreHydrogens}) {
 254         $This->_AssignAtomTypeToHydrogenAtom($Atom);
 255       }
 256       next ATOM;
 257     }
 258 
 259     # Handle non-hydrogen atoms..
 260     $This->_AssignAtomTypeToNonHydrogenAtom($Atom);
 261   }
 262   return $This;
 263 }
 264 
 265 # Assign E-State atom type to non-hydrogen atom...
 266 #
 267 sub _AssignAtomTypeToNonHydrogenAtom {
 268   my($This, $Atom) = @_;
 269   my($AtomType);
 270 
 271   $AtomType = $This->_GetAtomTypeForNonHydrogenAtom($Atom);
 272   $This->SetAtomType($Atom, $AtomType);
 273 
 274   return $This;
 275 }
 276 
 277 # Get E-State atom type for non-hydrogen atom...
 278 #
 279 sub _GetAtomTypeForNonHydrogenAtom {
 280   my($This, $Atom) = @_;
 281   my($AtomType, $AtomSymbol, $NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds, $CountAromaticBonds, $NumOfHydrogens, $FormalCharge, @EStateAtomInvariants);
 282 
 283   @EStateAtomInvariants = ();
 284 
 285   $AtomSymbol = $Atom->GetAtomicInvariantValue('AS');
 286   $NumOfHydrogens = $Atom->GetAtomicInvariantValue('H');
 287   $FormalCharge = $Atom->GetAtomicInvariantValue('FC');
 288 
 289   $CountAromaticBonds = 1;
 290   ($NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds) = $Atom->GetNumOfBondTypesToNonHydrogenAtoms($CountAromaticBonds);
 291 
 292   # Set up E-state atom invariants symbols...
 293   if ($NumOfTripleBonds > 0) {
 294     push @EStateAtomInvariants, "t" x $NumOfTripleBonds;
 295   }
 296   if ($NumOfDoubleBonds > 0) {
 297     push @EStateAtomInvariants, "d" x $NumOfDoubleBonds;
 298   }
 299   if ($NumOfAromaticBonds > 0) {
 300     push @EStateAtomInvariants, "a" x $NumOfAromaticBonds;
 301   }
 302   if ($NumOfSingleBonds > 0) {
 303     push @EStateAtomInvariants, "s" x $NumOfSingleBonds;
 304   }
 305   push @EStateAtomInvariants, $AtomSymbol;
 306   if ($NumOfHydrogens > 0) {
 307     push @EStateAtomInvariants, ($NumOfHydrogens > 1) ? "H${NumOfHydrogens}" : "H";
 308   }
 309   if ($FormalCharge > 0) {
 310     push @EStateAtomInvariants, "p";
 311   }
 312   elsif ($FormalCharge < 0) {
 313     push @EStateAtomInvariants, "m";
 314   }
 315 
 316   $AtomType = TextUtil::JoinWords(\@EStateAtomInvariants, "", 0);
 317 
 318   return $AtomType;
 319 }
 320 
 321 # Assign E-State atom type to hydrogen atom...
 322 #
 323 sub _AssignAtomTypeToHydrogenAtom {
 324   my($This, $Atom) = @_;
 325   my($AtomType);
 326 
 327   $AtomType = $This->_GetAtomTypeForHydrogenAtom($Atom);
 328   $This->SetAtomType($Atom, $AtomType);
 329 
 330   return $This;
 331 }
 332 
 333 # Get E-State atom type for hydrogen atom...
 334 #
 335 sub _GetAtomTypeForHydrogenAtom {
 336   my($This, $Atom) = @_;
 337   my($AtomType, $AtomNeighbor);
 338 
 339   $AtomType = "Hmisc";
 340 
 341   # Get non-hydrogen atom neighbor...
 342   $AtomNeighbor = $Atom->GetNonHydrogenNeighborOfHydrogenAtom();
 343   if (!$AtomNeighbor) {
 344     return $AtomType;
 345   }
 346 
 347   ATOMNEIGHBOR: {
 348     if ($AtomNeighbor->IsCarbon()) {
 349       $AtomType = $This->_GetAtomTypeForHydrogenAttachedToCarbon($AtomNeighbor);
 350       last ATOMNEIGHBOR;
 351     }
 352     if ($AtomNeighbor->IsNitrogen()) {
 353       $AtomType = $This->_GetAtomTypeForHydrogenAttachedToNitrogen($AtomNeighbor);
 354       last ATOMNEIGHBOR;
 355     }
 356     if ($AtomNeighbor->IsOxygen()) {
 357       $AtomType = $This->_GetAtomTypeForHydrogenAttachedToOxygen($AtomNeighbor);
 358       last ATOMNEIGHBOR;
 359     }
 360     if ($AtomNeighbor->IsSulfur()) {
 361       $AtomType = $This->_GetAtomTypeForHydrogenAttachedToSulfur($AtomNeighbor);
 362       last ATOMNEIGHBOR;
 363     }
 364     $AtomType = "Hmisc";
 365   }
 366   return $AtomType;
 367 }
 368 
 369 # Get E-state atom type for Hydrogen attached to Carbon...
 370 #
 371 # HGroup    AtomType
 372 #
 373 #   #CH        HtCH
 374 #   =CH2       HdCH2 - H attached to a terminal vinyl group
 375 #   =CH-       HdsCH - H attached a non-terminal vinyl group
 376 #   :CH:       HaaCH
 377 #
 378 #   >CHF       HCHF
 379 #   -CH2F      HCH2F
 380 #   >CHCl      HCHCl
 381 #   -CH2Cl     HCH2Cl
 382 #
 383 #   CHn (saturated)      HCsats   - H attached to sp3 carbon attached to saturated carbon(s)
 384 #   CHn (unsatd.)        HCsatu   - H attached to sp3 carbon attached to unsaturated carbon(s)
 385 #
 386 #   CHn (aromatic)       Havin    - H attached to a non-terminal vinyl group, =CH-, attached to an aromatic carbon
 387 #
 388 #
 389 sub _GetAtomTypeForHydrogenAttachedToCarbon {
 390   my($This, $CarbonAtom) = @_;
 391   my($AtomType, $AtomNeighbor, $NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds, $CountAromaticBonds, $NumOfHydrogens, $NumOfFluorines, $NumOfChlorines);
 392 
 393   $AtomType = "Hother";
 394 
 395   $NumOfHydrogens = $CarbonAtom->GetAtomicInvariantValue('H');
 396 
 397   $CountAromaticBonds = 1;
 398   ($NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds) = $CarbonAtom->GetNumOfBondTypesToNonHydrogenAtoms($CountAromaticBonds);
 399 
 400   ($NumOfFluorines,  $NumOfChlorines) = $This->_GetNumOfFluorineAndChlorineNeighbors($CarbonAtom);
 401 
 402   ATOMTYPE: {
 403     if ($NumOfHydrogens == 1 && $NumOfSingleBonds == 0 && $NumOfDoubleBonds == 0 && $NumOfTripleBonds == 1 && $NumOfAromaticBonds == 0) {
 404       $AtomType = "HtCH";
 405       last ATOMTYPE;
 406     }
 407     if ($NumOfHydrogens == 2 && $NumOfSingleBonds == 0 && $NumOfDoubleBonds == 1 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 0) {
 408       $AtomType = "HdCH2";
 409       last ATOMTYPE;
 410     }
 411     if ($NumOfHydrogens == 1 && $NumOfSingleBonds == 1 && $NumOfDoubleBonds == 1 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 0) {
 412       if ($This->_IsAttachedToAromaticCarbon($CarbonAtom)) {
 413         $AtomType = "Havin";
 414       }
 415       else {
 416         $AtomType = "HdsCH";
 417       }
 418       last ATOMTYPE;
 419     }
 420     if ($NumOfHydrogens == 1 && $NumOfSingleBonds == 0 && $NumOfDoubleBonds == 0 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 2) {
 421       $AtomType = "HaaCH";
 422       last ATOMTYPE;
 423     }
 424 
 425     if ($NumOfFluorines == 1 && $NumOfHydrogens == 1 && $NumOfSingleBonds == 3 && $NumOfDoubleBonds == 0 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 0) {
 426       $AtomType = "HCHF";
 427       last ATOMTYPE;
 428     }
 429     if ($NumOfFluorines == 1 && $NumOfHydrogens == 2 && $NumOfSingleBonds == 2 && $NumOfDoubleBonds == 0 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 0) {
 430       $AtomType = "HCH2F";
 431       last ATOMTYPE;
 432     }
 433     if ($NumOfChlorines == 1 && $NumOfHydrogens == 1 && $NumOfSingleBonds == 3 && $NumOfDoubleBonds == 0 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 0) {
 434       $AtomType = "HCHCl";
 435       last ATOMTYPE;
 436     }
 437     if ($NumOfChlorines == 1 && $NumOfHydrogens == 2 && $NumOfSingleBonds == 2 && $NumOfDoubleBonds == 0 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 0) {
 438       $AtomType = "HCH2Cl";
 439       last ATOMTYPE;
 440     }
 441     if ($NumOfDoubleBonds == 0 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 0) {
 442       # H  attached to sp3 carbon...
 443       $AtomType = $This->_GetAtomTypeForHydrogenAttachedToSaturatedOrUnsaturatedCarbons($CarbonAtom);
 444       last ATOMTYPE;
 445     }
 446     $AtomType = "Hother";
 447   }
 448 
 449   return $AtomType;
 450 }
 451 
 452 # Get number of fluorines and chlorines atached to an atom...
 453 #
 454 sub _GetNumOfFluorineAndChlorineNeighbors {
 455   my($This, $Atom) = @_;
 456   my($NumOfFluorines, $NumOfChlorines, $AtomNeighbor);
 457 
 458   $NumOfFluorines = 0; $NumOfChlorines = 0;
 459   ATOMNEIGHBOR: for $AtomNeighbor ($Atom->GetNonHydrogenAtomNeighbors()) {
 460     if ($AtomNeighbor->IsFluorine()) {
 461       $NumOfFluorines++;
 462       next ATOMNEIGHBOR;
 463     }
 464     if ($AtomNeighbor->IsChlorine()) {
 465       $NumOfChlorines++;
 466       next ATOMNEIGHBOR;
 467     }
 468   }
 469   return ($NumOfFluorines, $NumOfChlorines);
 470 }
 471 
 472 # Get atom type of hydrogen atom attached to a sp3 carbon attached to saturated or
 473 # unsaturated carbons...
 474 #
 475 # HGroup    AtomType
 476 #
 477 #   CHn (saturated)      HCsats   - H attached to sp3 carbon attached to saturated carbon(s)
 478 #   CHn (unsatd.)        HCsatu   - H attached to sp3 carbon attached to unsaturated carbon(s)
 479 #
 480 sub _GetAtomTypeForHydrogenAttachedToSaturatedOrUnsaturatedCarbons {
 481   my($This, $CarbonAtom) = @_;
 482   my($AtomType, $AtomNeighbor, @AtomNeighbors);
 483 
 484   $AtomType = "Hother";
 485   @AtomNeighbors = $CarbonAtom->GetNonHydrogenAtomNeighbors();
 486 
 487   # Make sure all neighbors are carbon atoms...
 488   for $AtomNeighbor (@AtomNeighbors) {
 489     if (!$AtomNeighbor->IsCarbon()) {
 490       return $AtomType;
 491     }
 492   }
 493 
 494   $AtomType = "HCsats";
 495   ATOMNEIGHBOR: for $AtomNeighbor ($CarbonAtom->GetNonHydrogenAtomNeighbors()) {
 496     if ($AtomNeighbor->IsUnsaturated()) {
 497       $AtomType = "HCsatu";
 498       last ATOMNEIGHBOR;
 499     }
 500   }
 501 
 502   return $AtomType;
 503 }
 504 
 505 # Is vinyl carbon attached to an aromatic carbon?
 506 #
 507 sub _IsAttachedToAromaticCarbon {
 508   my($This, $CarbonAtom) = @_;
 509   my($Status, $AtomNeighbor, @AtomNeighbors);
 510 
 511   $Status = 0;
 512 
 513   @AtomNeighbors = $CarbonAtom->GetNonHydrogenAtomNeighbors();
 514   ATOMNEIGHBOR: for $AtomNeighbor (@AtomNeighbors) {
 515     if ($AtomNeighbor->IsCarbon() && $AtomNeighbor->IsAromatic()) {
 516       $Status = 1;
 517       last ATOMNEIGHBOR;
 518     }
 519   }
 520   return $Status;
 521 }
 522 
 523 
 524 # Get E-state atom type for Hydrogen attached to Nitrogen...
 525 #
 526 # HGroup    AtomType
 527 #
 528 #   -NH2       HsNH2
 529 #   >NH        HssNH
 530 #   =NH        HdNH
 531 #   :NH:       HaaNH
 532 #   -NH3+      HsNH3p
 533 #   >NH2+     HssNH2p
 534 #   >NH-+      HsssNHp
 535 #
 536 sub _GetAtomTypeForHydrogenAttachedToNitrogen {
 537   my($This, $NitrogenAtom) = @_;
 538   my($AtomType, $NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds, $CountAromaticBonds, $NumOfHydrogens, $FormalCharge);
 539 
 540   $AtomType = "Hother";
 541 
 542   $NumOfHydrogens = $NitrogenAtom->GetAtomicInvariantValue('H');
 543   $FormalCharge = $NitrogenAtom->GetAtomicInvariantValue('FC');
 544 
 545   $CountAromaticBonds = 1;
 546   ($NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds) = $NitrogenAtom->GetNumOfBondTypesToNonHydrogenAtoms($CountAromaticBonds);
 547 
 548   if (!($NumOfTripleBonds == 0)) {
 549     return $AtomType;
 550   }
 551 
 552   ATOMTYPE: {
 553     if ($FormalCharge == 0) {
 554       if ($NumOfHydrogens == 2 && $NumOfSingleBonds == 1 &&  $NumOfDoubleBonds == 0 && $NumOfAromaticBonds == 0) {
 555         $AtomType = "HsNH2";
 556         last ATOMTYPE;
 557       }
 558       if ($NumOfHydrogens == 1 && $NumOfSingleBonds == 2 && $NumOfDoubleBonds == 0 && $NumOfAromaticBonds == 0) {
 559         $AtomType = "HssNH";
 560         last ATOMTYPE;
 561       }
 562       if ($NumOfHydrogens == 1 && $NumOfSingleBonds == 0 && $NumOfDoubleBonds == 1 && $NumOfAromaticBonds == 0) {
 563         $AtomType = "HdNH";
 564         last ATOMTYPE;
 565       }
 566       if ($NumOfHydrogens == 1 && $NumOfSingleBonds == 0 && $NumOfDoubleBonds == 0 && $NumOfAromaticBonds == 2) {
 567         $AtomType = "HaaNH";
 568         last ATOMTYPE;
 569       }
 570       $AtomType = "Hother";
 571       last ATOMTYPE;
 572     }
 573     if ($FormalCharge == 1) {
 574       if ($NumOfHydrogens == 3 && $NumOfSingleBonds == 1 && $NumOfDoubleBonds == 0 && $NumOfAromaticBonds == 0) {
 575         $AtomType = "HsNH3p";
 576         last ATOMTYPE;
 577       }
 578       if ( $NumOfHydrogens == 2 && $NumOfSingleBonds == 2 && $NumOfDoubleBonds == 0 && $NumOfAromaticBonds == 0) {
 579         $AtomType = "HssNH2p";
 580         last ATOMTYPE;
 581       }
 582       if ($NumOfHydrogens == 1 && $NumOfSingleBonds == 3 && $NumOfDoubleBonds == 0 && $NumOfAromaticBonds == 0) {
 583         $AtomType = "HsssNHp";
 584         last ATOMTYPE;
 585       }
 586       $AtomType = "Hother";
 587       last ATOMTYPE;
 588     }
 589     $AtomType = "Hother";
 590   }
 591 
 592   return $AtomType;
 593 }
 594 
 595 # Get E-state atom type for Hydrogen attached to Oxygen...
 596 #
 597 # HGroup    AtomType
 598 #
 599 #   -OH        HsOH
 600 #
 601 sub _GetAtomTypeForHydrogenAttachedToOxygen {
 602   my($This, $OxygenAtom) = @_;
 603   my($NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds, $CountAromaticBonds, $NumOfHydrogens);
 604 
 605   $NumOfHydrogens = $OxygenAtom->GetAtomicInvariantValue('H');
 606 
 607   $CountAromaticBonds = 1;
 608   ($NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds) = $OxygenAtom->GetNumOfBondTypesToNonHydrogenAtoms($CountAromaticBonds);
 609 
 610   return ($NumOfSingleBonds == 1 && $NumOfHydrogens == 1 && $NumOfDoubleBonds == 0 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 0) ? "HsOH" : "Hother";
 611 }
 612 
 613 # Get E-state atom type for Hydrogen attached to Sulfur...
 614 #
 615 # HGroup    AtomType
 616 #
 617 #   -SH        HsSH
 618 #
 619 sub _GetAtomTypeForHydrogenAttachedToSulfur {
 620   my($This, $SulfurAtom) = @_;
 621   my($NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds, $CountAromaticBonds, $NumOfHydrogens);
 622 
 623   $NumOfHydrogens = $SulfurAtom->GetAtomicInvariantValue('H');
 624 
 625   $CountAromaticBonds = 1;
 626   ($NumOfSingleBonds, $NumOfDoubleBonds, $NumOfTripleBonds, $NumOfAromaticBonds) = $SulfurAtom->GetNumOfBondTypesToNonHydrogenAtoms($CountAromaticBonds);
 627 
 628   return ($NumOfSingleBonds == 1 && $NumOfHydrogens == 1 && $NumOfDoubleBonds == 0 && $NumOfTripleBonds == 0 && $NumOfAromaticBonds == 0) ? "HsSH" : "Hother";
 629 }
 630 
 631 # Return a string containg data for EStateAtomTypes object...
 632 #
 633 sub StringifyEStateAtomTypes {
 634   my($This) = @_;
 635   my($AtomTypesString);
 636 
 637   # Type of AtomTypes...
 638   $AtomTypesString = "AtomTypes: $This->{Type}; IgnoreHydrogens: " . ($This->{IgnoreHydrogens} ? "Yes" : "No");
 639 
 640   # Setup atom types information...
 641   my($AtomID, $AtomType, @AtomTypesInfo, %AssignedAtomTypes);
 642 
 643   @AtomTypesInfo = ();
 644   %AssignedAtomTypes = $This->GetAtomTypes();
 645 
 646   for $AtomID (sort { $a <=> $b } keys %AssignedAtomTypes) {
 647     $AtomType = $AssignedAtomTypes{$AtomID} ? $AssignedAtomTypes{$AtomID} : 'None';
 648     push @AtomTypesInfo, "$AtomID:$AtomType";
 649   }
 650   $AtomTypesString .= "; AtomIDs:AtomTypes: <" . TextUtil::JoinWords(\@AtomTypesInfo, ", ", 0) . ">";
 651 
 652   return $AtomTypesString;
 653 }
 654 
 655 # Is it a EStateAtomTypes object?
 656 sub _IsEStateAtomTypes {
 657   my($Object) = @_;
 658 
 659   return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0;
 660 }
 661 
 662 # Check and load EState atom types data...
 663 #
 664 sub _CheckAndLoadEStateAtomTypesData {
 665 
 666   # Is it already loaded?
 667   if (exists $EStateAtomTypesDataMap{AtomTypes}) {
 668     return;
 669   }
 670 
 671   _LoadEStateAtomTypesData();
 672 }
 673 
 674 # Load EState atom types data from the file assuming first column to be atom type symbol..
 675 #
 676 # Format:
 677 #
 678 # "AtomType","AtomGroup"
 679 # "sLi","-Li"
 680 # "ssBe","-Be-"
 681 # "ssssBem",">Be<-2"
 682 #
 683 sub _LoadEStateAtomTypesData {
 684   my($AtomTypesDataFile, $MayaChemToolsLibDir);
 685 
 686   $MayaChemToolsLibDir = FileUtil::GetMayaChemToolsLibDirName();
 687 
 688   $AtomTypesDataFile =  "$MayaChemToolsLibDir" . "/data/EStateAtomTypes.csv";
 689   if (! -e "$AtomTypesDataFile") {
 690     croak "Error: MayaChemTools package file, $AtomTypesDataFile, is missing: Possible installation problems...";
 691   }
 692 
 693   %EStateAtomTypesDataMap = ();
 694   AtomTypes::AtomTypes::LoadAtomTypesData($AtomTypesDataFile, \%EStateAtomTypesDataMap);
 695 }
 696