1 package MolecularDescriptors::WeightAndMassDescriptors; 2 # 3 # File: WeightAndMassDescriptors.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 TextUtil (); 31 use MathUtil (); 32 use Atom; 33 use Molecule; 34 use MolecularDescriptors::MolecularDescriptors; 35 36 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 37 38 @ISA = qw(MolecularDescriptors::MolecularDescriptors Exporter); 39 @EXPORT = qw(); 40 @EXPORT_OK = qw(GetDescriptorNames); 41 42 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 43 44 # Setup class variables... 45 my($ClassName, @DescriptorNames); 46 _InitializeClass(); 47 48 # Overload Perl functions... 49 use overload '""' => 'StringifyWeightAndMassDescriptors'; 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->_InitializeWeightAndMassDescriptors(); 59 60 $This->_InitializeWeightAndMassDescriptorsProperties(%NamesAndValues); 61 62 return $This; 63 } 64 65 # Initialize class ... 66 sub _InitializeClass { 67 #Class name... 68 $ClassName = __PACKAGE__; 69 70 # Descriptor names... 71 @DescriptorNames = ('MolecularWeight', 'ExactMass'); 72 73 } 74 75 # Get descriptor names as an array. 76 # 77 # This functionality can be either invoked as a class function or an 78 # object method. 79 # 80 sub GetDescriptorNames { 81 return @DescriptorNames; 82 } 83 84 # Initialize object data... 85 # 86 sub _InitializeWeightAndMassDescriptors { 87 my($This) = @_; 88 89 # Type of MolecularDescriptor... 90 $This->{Type} = 'WeightAndMass'; 91 92 # Precision for molecular weight and exact mass values... 93 $This->{WeightPrecision} = 2; 94 $This->{MassPrecision} = 4; 95 96 # Intialize descriptor names and values... 97 $This->_InitializeDescriptorNamesAndValues(@DescriptorNames); 98 99 return $This; 100 } 101 102 # Initialize object properties... 103 # 104 sub _InitializeWeightAndMassDescriptorsProperties { 105 my($This, %NamesAndValues) = @_; 106 107 my($Name, $Value, $MethodName); 108 while (($Name, $Value) = each %NamesAndValues) { 109 $MethodName = "Set${Name}"; 110 $This->$MethodName($Value); 111 } 112 113 return $This; 114 } 115 116 # Set weight precision for moelcular weight... 117 # 118 sub SetWeightPrecision { 119 my($This, $Value) = @_; 120 121 if (!TextUtil::IsInteger($Value)) { 122 croak "Error: ${ClassName}->SetWeightPrecision: WeightPrecision value, $Value, is not valid: It must be a an integer..."; 123 } 124 $This->{WeightPrecision} = $Value; 125 126 return $This; 127 } 128 129 # Set mass precision for exact weight... 130 # 131 sub SetMassPrecision { 132 my($This, $Value) = @_; 133 134 if (!TextUtil::IsInteger($Value)) { 135 croak "Error: ${ClassName}->SetMassPrecision: MassPrecision value, $Value, is not valid: It must be a an integer..."; 136 } 137 $This->{MassPrecision} = $Value; 138 139 return $This; 140 } 141 142 # Generate molecular weight and exact mass values... 143 # 144 sub GenerateDescriptors { 145 my($This) = @_; 146 147 # Initialize descriptor values... 148 $This->_InitializeDescriptorValues(); 149 150 # Check availability of molecule... 151 if (!$This->{Molecule}) { 152 carp "Warning: ${ClassName}->GenerateDescriptors: $This->{Type} molecular descriptors generation didn't succeed: Molecule data is not available: Molecule object hasn't been set..."; 153 return undef; 154 } 155 156 # Calculate descriptor values... 157 if (!$This->_CalculateDescriptorValues()) { 158 carp "Warning: ${ClassName}->GenerateDescriptors: $This->{Type} molecular descriptors generation didn't succeed..."; 159 return undef; 160 } 161 162 # Set final descriptor values... 163 $This->_SetFinalDescriptorValues(); 164 165 return $This; 166 } 167 168 # Calculate molecular weight and exact mass values.. 169 # 170 sub _CalculateDescriptorValues { 171 my($This) = @_; 172 my($MolecularWeight, $ExactMass); 173 174 $MolecularWeight = $This->{Molecule}->GetMolecularWeight(); 175 $ExactMass = $This->{Molecule}->GetExactMass(); 176 177 # Track values... 178 $This->{MolecularWeight} = MathUtil::round($MolecularWeight, $This->{WeightPrecision}); 179 $This->{ExactMass} = MathUtil::round($ExactMass, $This->{MassPrecision}); 180 181 return $This; 182 } 183 184 # Setup final descriptor values... 185 # 186 sub _SetFinalDescriptorValues { 187 my($This) = @_; 188 189 $This->{DescriptorsGenerated} = 1; 190 191 $This->SetDescriptorValues($This->{MolecularWeight}, $This->{ExactMass}); 192 193 return $This; 194 } 195 196 # Return a string containg data for WeightAndMassDescriptors object... 197 # 198 sub StringifyWeightAndMassDescriptors { 199 my($This) = @_; 200 my($TheString); 201 202 $TheString = "MolecularDescriptorType: $This->{Type}; " . $This->_StringifyDescriptorNamesAndValues(); 203 204 return $TheString; 205 } 206 207 # Is it a WeightAndMassDescriptors object? 208 sub _IsWeightAndMassDescriptors { 209 my($Object) = @_; 210 211 return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0; 212 } 213