       1 package MolecularDescriptors::WeightAndMassDescriptors;
       2 #
       3 # File: WeightAndMassDescriptors.pm
       4 # Author: Manish Sud <msud@san.rr.com>
       5 #
       6 # Copyright (C) 2018 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