MayaChemTools

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