MayaChemTools

   1 package AtomicDescriptors::AtomicDescriptors;
   2 #
   3 # $RCSfile: AtomicDescriptors.pm,v $
   4 # $Date: 2015/02/28 20:47:48 $
   5 # $Revision: 1.17 $
   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 ObjectProperty;
  34 use TextUtil ();
  35 
  36 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  37 
  38 @ISA = qw(ObjectProperty Exporter);
  39 @EXPORT = qw();
  40 @EXPORT_OK = qw();
  41 
  42 %EXPORT_TAGS = (all  => [@EXPORT, @EXPORT_OK]);
  43 
  44 # Setup class variables...
  45 my($ClassName);
  46 _InitializeClass();
  47 
  48 # Class constructor...
  49 sub new {
  50   my($Class, %PropertyNamesAndValues) = @_;
  51 
  52   # Initialize object...
  53   my $This = {};
  54   bless $This, ref($Class) || $Class;
  55   $This->_InitializeAtomicDescriptors();
  56 
  57   $This->_InitializeAtomicDescriptorsProperties(%PropertyNamesAndValues);
  58 
  59   return $This;
  60 }
  61 
  62 # Initialize object data...
  63 #
  64 sub _InitializeAtomicDescriptors {
  65   my($This) = @_;
  66 
  67   # Molecule object...
  68   $This->{Molecule} = '';
  69 
  70   # Type of atomic descriptors...
  71   $This->{Type} = '';
  72 
  73   # By default, atomic decriptor values are also calculated for hydrogens...
  74   $This->{IgnoreHydrogens} = 0;
  75 
  76   # Calculated atomic descriptor values hash. Instead of assigning the calculated values to Atom
  77   # objects, these values are stored in the current object in a hash with atom ID and atomic descriptor
  78   # values as key/value pairs.
  79   #
  80   # Unlike molecular descriptors, no descriptor names are assigned to individual atomic descriptor
  81   # values.
  82   #
  83   %{$This->{DescriptorValues}} = ();
  84 }
  85 
  86 # Initialize class ...
  87 sub _InitializeClass {
  88   #Class name...
  89   $ClassName = __PACKAGE__;
  90 }
  91 
  92 # Initialize object properties....
  93 sub _InitializeAtomicDescriptorsProperties {
  94   my($This, %PropertiesNamesAndValues) = @_;
  95 
  96   my($Name, $Value, $MethodName);
  97   while (($Name, $Value) = each  %PropertiesNamesAndValues) {
  98     $MethodName = "Set${Name}";
  99     $This->$MethodName($Value);
 100   }
 101 
 102   return $This;
 103 }
 104 
 105 # Initialize descriptor values for all atoms in a molecule...
 106 #
 107 sub _InitializeDescriptorValues {
 108   my($This) = @_;
 109 
 110   if (!$This->{Molecule}) {
 111     return $This;
 112   }
 113 
 114   # Assign 'None' to all atomic descriptor values...
 115   #
 116   my($Atom, $AtomID);
 117 
 118   ATOM: for $Atom ($This->{Molecule}->GetAtoms()) {
 119     $AtomID = $Atom->GetID();
 120     $This->{DescriptorValues}{$AtomID} = 'None';
 121   }
 122 
 123   return $This;
 124 }
 125 
 126 # Set molecule object and make sure it's not already set...
 127 #
 128 sub SetMolecule {
 129   my($This, $Molecule) = @_;
 130 
 131   if ($This->{Molecule}) {
 132     croak "Error: ${ClassName}->SetMolecule: Can't change molecule object:  It's already set...";
 133   }
 134   $This->{Molecule} = $Molecule;
 135 
 136   # Weaken the reference to disable increment of reference count...
 137   Scalar::Util::weaken($This->{Molecule});
 138 
 139   return $This;
 140 }
 141 
 142 # Set type and make sure it's not already set...
 143 #
 144 sub SetType {
 145   my($This, $Type) = @_;
 146 
 147   if ($This->{Type}) {
 148     croak "Error: ${ClassName}->SetType: Can't change AtomicDescriptors type:  It's already set...";
 149   }
 150   $This->{Type} = $Type;
 151 
 152   return $This;
 153 }
 154 
 155 # Set specific atomic descriptor value...
 156 #
 157 sub SetDescriptorValue {
 158   my($This, $Atom, $AtomicDescriptor) = @_;
 159   my($AtomID);
 160 
 161   $AtomID = $Atom->GetID();
 162   $This->{DescriptorValues}{$AtomID} = $AtomicDescriptor;
 163 
 164   return $This;
 165 }
 166 
 167 # Get specific atomic descriptor value...
 168 #
 169 sub GetDescriptorValue {
 170   my($This, $Atom) = @_;
 171   my($AtomID);
 172 
 173   $AtomID = $Atom->GetID();
 174 
 175   return exists $This->{DescriptorValues}{$AtomID} ? $This->{DescriptorValues}{$AtomID} : 'None';
 176 }
 177 
 178 # Get calculated atomic descriptor values as a  hash with atom ID and atomic descriptor
 179 # values as key/value pairs...
 180 #
 181 sub GetDescriptorValues {
 182   my($This) = @_;
 183 
 184   return %{$This->{DescriptorValues}};
 185 }
 186 
 187 # Are all atomic descriptor values successfully calculated?
 188 #
 189 # Notes:
 190 #   . Dynamic checking of calculated descriptor values for atoms eliminates the need
 191 #     to check and synchronize valid descriptor values during SetDescriptorValue.
 192 #
 193 sub IsDescriptorsGenerationSuccessful {
 194   my($This) = @_;
 195   my($Atom, $DescriptorValue, @Atoms);
 196 
 197   ATOM: for $Atom ($This->{Molecule}->GetAtoms()) {
 198     if ($This->{IgnoreHydrogens} && $Atom->IsHydrogen()) {
 199       next ATOM;
 200     }
 201     $DescriptorValue = $This->GetDescriptorValue($Atom);
 202     if ($DescriptorValue =~ /^None$/i) {
 203       return 0;
 204     }
 205   }
 206 
 207   return 1;
 208 }
 209