MayaChemTools

   1 package AtomTypes::SYBYLAtomTypes;
   2 #
   3 # $RCSfile: SYBYLAtomTypes.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 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(GetSYBYLAtomTypesData GetAllPossibleSYBYLAtomTypes GetAllPossibleSYBYLNonHydrogenAtomTypes);
  40 @EXPORT_OK = qw();
  41 
  42 %EXPORT_TAGS = (all  => [@EXPORT, @EXPORT_OK]);
  43 
  44 # Setup class variables...
  45 my($ClassName, %SYBYLAtomTypesDataMap);
  46 _InitializeClass();
  47 
  48 # Overload Perl functions...
  49 use overload '""' => 'StringifySYBYLAtomTypes';
  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->_InitializeSYBYLAtomTypes();
  59 
  60   $This->_InitializeSYBYLAtomTypesProperties(%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   %SYBYLAtomTypesDataMap = ();
  72 }
  73 
  74 
  75 # Initialize object data...
  76 #
  77 sub _InitializeSYBYLAtomTypes {
  78   my($This) = @_;
  79 
  80   # Type of AtomTypes...
  81   $This->{Type} = 'SYBYL';
  82 
  83   # By default, SYBYL atom types are also assigned to hydrogens...
  84   $This->{IgnoreHydrogens} = 0;
  85 
  86   return $This;
  87 }
  88 
  89 # Initialize object properties...
  90 #
  91 sub _InitializeSYBYLAtomTypesProperties {
  92   my($This, %NamesAndValues) = @_;
  93 
  94   my($Name, $Value, $MethodName);
  95   while (($Name, $Value) = each  %NamesAndValues) {
  96     $MethodName = "Set${Name}";
  97     $This->$MethodName($Value);
  98   }
  99 
 100   # Make sure molecule object was specified...
 101   if (!exists $NamesAndValues{Molecule}) {
 102     croak "Error: ${ClassName}->New: Object can't be instantiated without specifying molecule...";
 103   }
 104 
 105   return $This;
 106 }
 107 
 108 # Get SYBYL atom types and associated data loaded from SYBYL data file as
 109 # a reference to hash with the following hash data format:
 110 #
 111 # @{$SYBYLAtomTypesDataMap{AtomTypes}} - Array of all possible atom types for all atoms
 112 # @{$SYBYLAtomTypesDataMap{NonHydrogenAtomTypes}} - Array of all possible atom types for non-hydrogen atoms
 113 # @{$SYBYLAtomTypesDataMap->{ColLabels}} - Array of column labels
 114 # %{$SYBYLAtomTypesDataMap->{DataCol<Num>}} - Hash keys pair: <DataCol<Num>, AtomType>
 115 #
 116 # This functionality can be either invoked as a class function or an
 117 # object method.
 118 #
 119 sub GetSYBYLAtomTypesData {
 120 
 121   # Make sure data is loaded...
 122   _CheckAndLoadSYBYLAtomTypesData();
 123 
 124   return \%SYBYLAtomTypesDataMap;
 125 }
 126 
 127 # Get all possible SYBYL atom types corresponding to hydrogen and non-hydrogen
 128 # atoms as an array reference...
 129 #
 130 # This functionality can be either invoked as a class function or an
 131 # object method.
 132 #
 133 sub GetAllPossibleSYBYLAtomTypes {
 134   return _GetAllPossibleSYBYLAtomTypes();
 135 }
 136 
 137 # Get all possible SYBYL atom types corresponding to non-hydrogen atoms
 138 # as an array reference...
 139 #
 140 # This functionality can be either invoked as a class function or an
 141 # object method.
 142 #
 143 sub GetAllPossibleSYBYLNonHydrogenAtomTypes {
 144   my($NonHydrogensOnly);
 145 
 146   $NonHydrogensOnly = 1;
 147   return _GetAllPossibleSYBYLAtomTypes($NonHydrogensOnly);
 148 }
 149 
 150 # Get all possible SYBYL atom types as an array reference...
 151 #
 152 sub _GetAllPossibleSYBYLAtomTypes {
 153   my($NonHydrogensOnly) = @_;
 154   my($SYBYLAtomTypesDataRef);
 155 
 156   $NonHydrogensOnly = defined $NonHydrogensOnly ? $NonHydrogensOnly : 0;
 157 
 158   $SYBYLAtomTypesDataRef = GetSYBYLAtomTypesData();
 159 
 160   return $NonHydrogensOnly ? \@{$SYBYLAtomTypesDataRef->{NonHydrogenAtomTypes}}: \@{$SYBYLAtomTypesDataRef->{AtomTypes}};
 161 }
 162 # Assign Tripos SYBYL [ Ref 79-80 ] atom types to all atoms...
 163 #
 164 # Notes:
 165 #   . 8 SYBYL listed atom types - O.spc, O.t3p, H.spc, H.t3p, Du, Du.C, HEV, LP -
 166 #     are not assigned to any atom
 167 #   . N.pl3 atom type is assigned to Nitrogens in a guadinium group attached
 168 #     to Carbon C.cat
 169 #
 170 #
 171 sub AssignAtomTypes {
 172   my($This) = @_;
 173   my($Atom, $AtomType);
 174 
 175   ATOM: for $Atom ($This->GetMolecule()->GetAtoms()) {
 176     if ($This->{IgnoreHydrogens} && $Atom->IsHydrogen()) {
 177       next ATOM;
 178     }
 179     $AtomType = $This->_GetAtomType($Atom);
 180     $This->SetAtomType($Atom, $AtomType);
 181   }
 182   return $This;
 183 }
 184 
 185 # Get SYBYL atom type for atom...
 186 #
 187 sub _GetAtomType {
 188   my($This, $Atom) = @_;
 189   my($AtomType);
 190 
 191   $AtomType = 'Any';
 192 
 193   ATOM: {
 194     if ($Atom->IsCarbon()) {
 195       $AtomType = $This->_GetAtomTypeForCarbon($Atom);
 196       last ATOM;
 197     }
 198     if ($Atom->IsNitrogen()) {
 199       $AtomType = $This->_GetAtomTypeForNitrogen($Atom);
 200       last ATOM;
 201     }
 202     if ($Atom->IsOxygen()) {
 203       $AtomType = $This->_GetAtomTypeForOxygen($Atom);
 204       last ATOM;
 205     }
 206     if ($Atom->IsPhosphorus()) {
 207       $AtomType = $This->_GetAtomTypeForPhosphorus($Atom);
 208       last ATOM;
 209     }
 210     if ($Atom->IsSulfur()) {
 211       $AtomType = $This->_GetAtomTypeForSulfur($Atom);
 212       last ATOM;
 213     }
 214     if ($Atom->IsHydrogen()) {
 215       $AtomType = $This->_GetAtomTypeForHydrogen($Atom);
 216       last ATOM;
 217     }
 218     $AtomType = $This->_GetAtomTypeForOtherAtoms($Atom);
 219   }
 220 
 221   return $AtomType;
 222 }
 223 
 224 # Get SYBYL atom type for Carbon atom...
 225 #
 226 sub _GetAtomTypeForCarbon {
 227   my($This, $Atom) = @_;
 228   my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds);
 229 
 230   $AtomType = 'Any';
 231 
 232   ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2;
 233 
 234   ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms();
 235   $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H');
 236 
 237   ATOMTYPE: {
 238     if ($Atom->IsAromatic()) {
 239       $AtomType = 'C.ar';
 240       last ATOMTYPE;
 241     }
 242 
 243     if ($Atom->IsGuadiniumCarbon()) {
 244       $AtomType = 'C.cat';
 245       last ATOMTYPE;
 246     }
 247 
 248     # Only single bonds...
 249     if ($NumOfPiBonds == 0) {
 250       $AtomType = 'C.3';
 251       last ATOMTYPE;
 252     }
 253 
 254     # One double bond...
 255     if ($NumOfPiBonds == 1) {
 256       $AtomType = 'C.2';
 257       last ATOMTYPE;
 258     }
 259 
 260     # One triple bond or two double bonds...
 261     if ($NumOfPiBonds == 2) {
 262       $AtomType = 'C.1';
 263       last ATOMTYPE;
 264     }
 265 
 266     $AtomType = 'Any';
 267   }
 268 
 269   return $AtomType;
 270 }
 271 
 272 # Get SYBYL atom type for Nitrogen atom...
 273 #
 274 sub _GetAtomTypeForNitrogen {
 275   my($This, $Atom) = @_;
 276   my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds);
 277 
 278   $AtomType = 'Het';
 279 
 280   ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2;
 281 
 282   ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms();
 283   $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H');
 284 
 285   ATOMTYPE: {
 286     if ($Atom->IsAromatic()) {
 287       $AtomType = 'N.ar';
 288       last ATOMTYPE;
 289     }
 290 
 291     if ($Atom->IsGuadiniumNitrogen()) {
 292       $AtomType = 'N.pl3';
 293       last ATOMTYPE;
 294     }
 295 
 296     if ($Atom->IsAmideNitrogen()) {
 297       $AtomType = 'N.am';
 298       last ATOMTYPE;
 299     }
 300 
 301     # Only single bonds...
 302     if ($NumOfSigmaBonds == 4 && $NumOfPiBonds == 0) {
 303       $AtomType = 'N.4';
 304       last ATOMTYPE;
 305     }
 306 
 307     # Only single bonds...
 308     if ($NumOfSigmaBonds == 3 && $NumOfPiBonds == 0) {
 309       $AtomType = $This->_IsN3NitrogenPlanar($Atom) ? 'N.pl3' : 'N.3';
 310       last ATOMTYPE;
 311     }
 312 
 313     # One double bond...
 314     if ($NumOfPiBonds == 1) {
 315       $AtomType = 'N.2';
 316       last ATOMTYPE;
 317     }
 318 
 319     # One triple bond or two double bonds...
 320     if ($NumOfPiBonds == 2) {
 321       $AtomType = 'N.1';
 322       last ATOMTYPE;
 323     }
 324 
 325     $AtomType = 'Het';
 326   }
 327 
 328   return $AtomType;
 329 }
 330 
 331 # Get SYBYL atom type for Oxygen atom...
 332 #
 333 sub _GetAtomTypeForOxygen {
 334   my($This, $Atom) = @_;
 335   my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds);
 336 
 337   $AtomType = 'Het';
 338 
 339   ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2;
 340 
 341   ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms();
 342   $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H');
 343 
 344   ATOMTYPE: {
 345     if ($Atom->IsCarboxylateOxygen() || $Atom->IsCarboxylOxygen() || $Atom->IsPhosphateOxygen()) {
 346       $AtomType = 'O.co2';
 347       last ATOMTYPE;
 348     }
 349 
 350     # Only single bonds...
 351     if ($NumOfPiBonds == 0) {
 352       $AtomType = 'O.3';
 353       last ATOMTYPE;
 354     }
 355 
 356     # One double bond...
 357     if ($NumOfPiBonds == 1) {
 358       $AtomType = 'O.2';
 359       last ATOMTYPE;
 360     }
 361 
 362     $AtomType = 'Het';
 363   }
 364 
 365   return $AtomType;
 366 }
 367 
 368 # Get SYBYL atom type for Phosphorus atom...
 369 #
 370 sub _GetAtomTypeForPhosphorus {
 371   my($This, $Atom) = @_;
 372   my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds);
 373 
 374   $AtomType = 'Het';
 375 
 376   ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2;
 377 
 378   ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms();
 379   $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H');
 380 
 381   ATOMTYPE: {
 382     # -P(-)-, =P(-)(-)-
 383     if (($NumOfSigmaBonds == 3 && $NumOfPiBonds == 0) || ($NumOfSigmaBonds == 4 && $NumOfPiBonds == 1)) {
 384       $AtomType = 'P.3';
 385       last ATOMTYPE;
 386     }
 387 
 388     $AtomType = 'Het';
 389   }
 390 
 391   return $AtomType;
 392 }
 393 
 394 # Get SYBYL atom type for Sulfur atom...
 395 #
 396 sub _GetAtomTypeForSulfur {
 397   my($This, $Atom) = @_;
 398   my($AtomType, $NumOfSigmaBonds, $NumOfPiBonds);
 399 
 400   $AtomType = 'Het';
 401 
 402   ($NumOfSigmaBonds, $NumOfPiBonds) = ('0') x 2;
 403 
 404   ($NumOfSigmaBonds, $NumOfPiBonds) = $Atom->GetNumOfSigmaAndPiBondsToNonHydrogenAtoms();
 405   $NumOfSigmaBonds += $Atom->GetAtomicInvariantValue('H');
 406 
 407   ATOMTYPE: {
 408     if ($This->_IsSulfoneSulfur($Atom)) {
 409       $AtomType = 'S.O2';
 410       last ATOMTYPE;
 411     }
 412 
 413     if ($This->_IsSulfoxideSulfur($Atom)) {
 414       $AtomType = 'S.O';
 415       last ATOMTYPE;
 416     }
 417 
 418     # -S-
 419     if ($NumOfSigmaBonds == 2 && $NumOfPiBonds == 0) {
 420       $AtomType = 'S.3';
 421       last ATOMTYPE;
 422     }
 423 
 424     # S=
 425     if ($NumOfSigmaBonds == 1 && $NumOfPiBonds == 1) {
 426       $AtomType = 'S.2';
 427       last ATOMTYPE;
 428     }
 429 
 430     $AtomType = 'Het';
 431   }
 432 
 433   return $AtomType;
 434 }
 435 
 436 # Get SYBYL atom type for Hydrogen atom...
 437 #
 438 sub _GetAtomTypeForHydrogen {
 439   my($This, $Atom) = @_;
 440   my($AtomType);
 441 
 442   $AtomType = 'H';
 443 
 444   return $AtomType;
 445 }
 446 
 447 # Get SYBYL atom type for atoms other than Carbon, Nitrogen, Oxygen, Phosporus
 448 # and Sulfur...
 449 #
 450 sub _GetAtomTypeForOtherAtoms {
 451   my($This, $Atom) = @_;
 452   my($AtomType, $AtomicNumber, $AtomSymbol);
 453 
 454   $AtomType = 'Any';
 455 
 456   $AtomicNumber = $Atom->GetAtomicNumber();
 457   $AtomSymbol = $Atom->GetAtomSymbol();
 458 
 459   ATOMICNUMBER: {
 460     if ($AtomicNumber =~ /^(9|17|35|53)$/i) {
 461       # F, Cl, Br, I
 462       $AtomType = $AtomSymbol;
 463       last ATOMICNUMBER;
 464     }
 465 
 466     if ($AtomicNumber =~ /^(3|11|12|13|14)$/i) {
 467       # Li, Na, Mg, Al, Si
 468       $AtomType = $AtomSymbol;
 469       last ATOMICNUMBER;
 470     }
 471 
 472     if ($AtomicNumber =~ /^(19|20|25|26|29|30|34)$/i) {
 473       # K, Ca, Mn, Fe, Cu, Zn, Se
 474       $AtomType = $AtomSymbol;
 475       last ATOMICNUMBER;
 476     }
 477 
 478     if ($AtomicNumber =~ /^24$/i) {
 479       $AtomType = $This->_GetAtomTypeForChromium($Atom);
 480       last ATOMICNUMBER;
 481     }
 482 
 483     if ($AtomicNumber =~ /^27$/i) {
 484       $AtomType = $This->_GetAtomTypeForCobalt($Atom);
 485       last ATOMICNUMBER;
 486     }
 487 
 488     if ($AtomicNumber =~ /^(42|50)$/i) {
 489       # Mo, Sn
 490       $AtomType = $AtomSymbol;
 491       last ATOMICNUMBER;
 492     }
 493 
 494     $AtomType = 'Any';
 495   }
 496 
 497   return $AtomType;
 498 }
 499 
 500 # Get SYBYL atom type for Chromium atom...
 501 #
 502 sub _GetAtomTypeForChromium {
 503   my($This, $Atom) = @_;
 504   my($AtomType, $NumOfNeighbors);
 505 
 506   $AtomType = 'Any';
 507   $NumOfNeighbors = $Atom->GetNumOfNeighbors();
 508 
 509   NUMOFNEIGHBORS: {
 510     if ($NumOfNeighbors == 4) {
 511       $AtomType = 'Cr.th';
 512       last NUMOFNEIGHBORS;
 513     }
 514 
 515     if ($NumOfNeighbors == 6) {
 516       $AtomType = 'Cr.oh';
 517       last NUMOFNEIGHBORS;
 518     }
 519 
 520     $AtomType = 'Cr.oh';
 521     carp "Warning: ${ClassName}->_GetAtomTypeForChromium: SYBYL atom types for Cromimum, Co.th or Cr.oh, corresponding to tetrahedral or octahedral geometry cann't be assigned; Number of neighbors, $NumOfNeighbors, is different from 4 or 6. Default SYBYL atom type, Cr.oh, has been assigned...";
 522   }
 523 
 524   return $AtomType;
 525 }
 526 
 527 # Get SYBYL atom type for Cobalt atom...
 528 #
 529 sub _GetAtomTypeForCobalt {
 530   my($This, $Atom) = @_;
 531   my($AtomType, $NumOfNeighbors);
 532 
 533   $AtomType = 'Any';
 534 
 535   $NumOfNeighbors = $Atom->GetNumOfNeighbors();
 536 
 537   if ($NumOfNeighbors == 6) {
 538     $AtomType = 'Co.oh';
 539   }
 540   else {
 541     $AtomType = 'Co.oh';
 542     carp "Warning: ${ClassName}->_GetAtomTypeForCobalt: SYBYL atom type for Cobalt, Co.oh, corresponding to octahedral geometry cann't be assigned; Number of neighbors, $NumOfNeighbors, is different from 6. Default SYBYL atom type, Co.oh, has been assigned...";
 543   }
 544 
 545   return $AtomType;
 546 }
 547 
 548 # Is it N.3 Nitrogen a planar Nitrogen?
 549 #
 550 # A N.3 Nitrogen is a planar Nitrogen when it meets any of the following constraints:
 551 #
 552 #   . Nitrogen atom is in a ring
 553 #   . Attached to only one heavy atom which is an aromatic atom or in a ring
 554 #   . Attached to two or more heavy atom which are aromatic atoms or in a ring
 555 #
 556 sub _IsN3NitrogenPlanar {
 557   my($This, $Atom) = @_;
 558 
 559   # Is it a ring Nitrogen atom?
 560   if ($Atom->IsInRing()) {
 561     return 1;
 562   }
 563 
 564   # Count number of ring and aromatic heavy atoms attached to Nitrogen...
 565   my($AtomNeighbor, $NumOfAromaticAtomNeighbors, $NumOfRingAotmNeighbors, $NumOfNeighbors, @AtomNeighbors);
 566 
 567   @AtomNeighbors = $Atom->GetHeavyAtomNeighbors();
 568   $NumOfNeighbors = scalar @AtomNeighbors;
 569 
 570   $NumOfAromaticAtomNeighbors = 0;  $NumOfRingAotmNeighbors = 0;
 571 
 572   for $AtomNeighbor (@AtomNeighbors) {
 573     if ($AtomNeighbor->IsAromatic()) {
 574       $NumOfAromaticAtomNeighbors++;
 575     }
 576     if ($AtomNeighbor->IsInRing()) {
 577       $NumOfRingAotmNeighbors++;
 578     }
 579   }
 580 
 581   # Is attached to only one heavy atom which is in a ring or aromatic?
 582   if ($NumOfNeighbors == 1) {
 583     if ($NumOfAromaticAtomNeighbors || $NumOfRingAotmNeighbors) {
 584       return 1;
 585     }
 586   }
 587 
 588   # Is attached to more than heavy atoms which are in a ring or aromatic?
 589   if ($NumOfAromaticAtomNeighbors >= 2 || $NumOfRingAotmNeighbors >= 2) {
 590     return 1;
 591   }
 592 
 593   return 0;
 594 }
 595 
 596 # Is it a Sulfur atom in Sulfoxide group?
 597 #
 598 # SYBYL Sulfoxide group definition: A-S(=O)-A
 599 #
 600 #   where:
 601 #      . A = Any atom
 602 #
 603 sub _IsSulfoxideSulfur {
 604   my($This, $Atom) = @_;
 605 
 606   # Is it Sulfur?
 607   if (!$Atom->IsSulfur()) {
 608     return 0;
 609   }
 610   # Match atom neighborhood...
 611   my($CentralAtomSpec, @NbrAtomSpecsRef, @NbrBondSpecsRef);
 612 
 613   $CentralAtomSpec = 'S.X3.BO4';
 614   @NbrAtomSpecsRef = ('O', '*', '*');
 615   @NbrBondSpecsRef = ('=', '-', '-');
 616 
 617   if ($Atom->DoesAtomNeighborhoodMatch($CentralAtomSpec, \@NbrAtomSpecsRef, \@NbrBondSpecsRef)) {
 618     return 1;
 619   }
 620 
 621   return 0;
 622 }
 623 
 624 # Is it a Sulfur atom in Sulfone group?
 625 #
 626 # Sulfoxide group definition: A-(O=)S(=O)-A
 627 #
 628 #   where:
 629 #      . A = Any atom
 630 #
 631 sub _IsSulfoneSulfur {
 632   my($This, $Atom) = @_;
 633 
 634   # Is it Sulfur?
 635   if (!$Atom->IsSulfur()) {
 636     return 0;
 637   }
 638 
 639   # Match atom neighborhood...
 640   my($CentralAtomSpec, @NbrAtomSpecsRef, @NbrBondSpecsRef);
 641 
 642   $CentralAtomSpec = 'S.X4.BO6';
 643   @NbrAtomSpecsRef = ('O', 'O', '*', '*');
 644   @NbrBondSpecsRef = ('=', '=', '-', '-');
 645 
 646   if ($Atom->DoesAtomNeighborhoodMatch($CentralAtomSpec, \@NbrAtomSpecsRef, \@NbrBondSpecsRef)) {
 647     return 1;
 648   }
 649 
 650   return 0;
 651 }
 652 
 653 # Return a string containg data for SYBYLAtomTypes object...
 654 #
 655 sub StringifySYBYLAtomTypes {
 656   my($This) = @_;
 657   my($AtomTypesString);
 658 
 659   # Type of AtomTypes...
 660   $AtomTypesString = "AtomTypes: $This->{Type}; IgnoreHydrogens: " . ($This->{IgnoreHydrogens} ? "Yes" : "No");
 661 
 662   # Setup atom types information...
 663   my($AtomID, $AtomType, @AtomTypesInfo, %AssignedAtomTypes);
 664 
 665   @AtomTypesInfo = ();
 666   %AssignedAtomTypes = $This->GetAtomTypes();
 667 
 668   for $AtomID (sort { $a <=> $b } keys %AssignedAtomTypes) {
 669     $AtomType = $AssignedAtomTypes{$AtomID} ? $AssignedAtomTypes{$AtomID} : 'None';
 670     push @AtomTypesInfo, "$AtomID:$AtomType";
 671   }
 672   $AtomTypesString .= "; AtomIDs:AtomTypes: <" . TextUtil::JoinWords(\@AtomTypesInfo, ", ", 0) . ">";
 673 
 674   return $AtomTypesString;
 675 }
 676 
 677 # Is it a SYBYLAtomTypes object?
 678 sub _IsSYBYLAtomTypes {
 679   my($Object) = @_;
 680 
 681   return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0;
 682 }
 683 
 684 # Check and load SYBYL atom types data...
 685 #
 686 sub _CheckAndLoadSYBYLAtomTypesData {
 687 
 688   # Is it already loaded?
 689   if (exists $SYBYLAtomTypesDataMap{AtomTypes}) {
 690     return;
 691   }
 692 
 693   _LoadSYBYLAtomTypesData();
 694 }
 695 
 696 # Load SYBYL atom types data from the file assuming first column to be atom type symbol..
 697 #
 698 # Format:
 699 #
 700 # "AtomType","Description"
 701 # "C.3","sp3 carbon"
 702 # "C.2","sp2 carbon"
 703 #
 704 sub _LoadSYBYLAtomTypesData {
 705   my($AtomTypesDataFile, $MayaChemToolsLibDir);
 706 
 707   $MayaChemToolsLibDir = FileUtil::GetMayaChemToolsLibDirName();
 708 
 709   $AtomTypesDataFile =  "$MayaChemToolsLibDir" . "/data/SYBYLAtomTypes.csv";
 710   if (! -e "$AtomTypesDataFile") {
 711     croak "Error: MayaChemTools package file, $AtomTypesDataFile, is missing: Possible installation problems...";
 712   }
 713 
 714   %SYBYLAtomTypesDataMap = ();
 715   AtomTypes::AtomTypes::LoadAtomTypesData($AtomTypesDataFile, \%SYBYLAtomTypesDataMap);
 716 }
 717 
 718