MayaChemTools

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