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