1
package Chemistry::Elements;
5
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD
6
$debug %names %elements $maximum_Z);
11
@EXPORT_OK = qw(get_Z get_symbol get_name);
15
use subs qw(_get_name_by_Z
123
91 => 'Protactinium',
133
101 => 'Mendelevium',
135
103 => 'Lawerencium',
136
104 => 'Rutherfordium',
145
my @a = sort {$a <=> $b } keys %names;
150
'H' => '1', '1' => 'H',
151
'He' => '2', '2' => 'He',
152
'Li' => '3', '3' => 'Li',
153
'Be' => '4', '4' => 'Be',
154
'B' => '5', '5' => 'B',
155
'C' => '6', '6' => 'C',
156
'N' => '7', '7' => 'N',
157
'O' => '8', '8' => 'O',
158
'F' => '9', '9' => 'F',
159
'Ne' => '10', '10' => 'Ne',
160
'Na' => '11', '11' => 'Na',
161
'Mg' => '12', '12' => 'Mg',
162
'Al' => '13', '13' => 'Al',
163
'Si' => '14', '14' => 'Si',
164
'P' => '15', '15' => 'P',
165
'S' => '16', '16' => 'S',
166
'Cl' => '17', '17' => 'Cl',
167
'Ar' => '18', '18' => 'Ar',
168
'K' => '19', '19' => 'K',
169
'Ca' => '20', '20' => 'Ca',
170
'Sc' => '21', '21' => 'Sc',
171
'Ti' => '22', '22' => 'Ti',
172
'V' => '23', '23' => 'V',
173
'Cr' => '24', '24' => 'Cr',
174
'Mn' => '25', '25' => 'Mn',
175
'Fe' => '26', '26' => 'Fe',
176
'Co' => '27', '27' => 'Co',
177
'Ni' => '28', '28' => 'Ni',
178
'Cu' => '29', '29' => 'Cu',
179
'Zn' => '30', '30' => 'Zn',
180
'Ga' => '31', '31' => 'Ga',
181
'Ge' => '32', '32' => 'Ge',
182
'As' => '33', '33' => 'As',
183
'Se' => '34', '34' => 'Se',
184
'Br' => '35', '35' => 'Br',
185
'Kr' => '36', '36' => 'Kr',
186
'Rb' => '37', '37' => 'Rb',
187
'Sr' => '38', '38' => 'Sr',
188
'Y' => '39', '39' => 'Y',
189
'Zr' => '40', '40' => 'Zr',
190
'Nb' => '41', '41' => 'Nb',
191
'Mo' => '42', '42' => 'Mo',
192
'Tc' => '43', '43' => 'Tc',
193
'Ru' => '44', '44' => 'Ru',
194
'Rh' => '45', '45' => 'Rh',
195
'Pd' => '46', '46' => 'Pd',
196
'Ag' => '47', '47' => 'Ag',
197
'Cd' => '48', '48' => 'Cd',
198
'In' => '49', '49' => 'In',
199
'Sn' => '50', '50' => 'Sn',
200
'Sb' => '51', '51' => 'Sb',
201
'Te' => '52', '52' => 'Te',
202
'I' => '53', '53' => 'I',
203
'Xe' => '54', '54' => 'Xe',
204
'Cs' => '55', '55' => 'Cs',
205
'Ba' => '56', '56' => 'Ba',
206
'La' => '57', '57' => 'La',
207
'Ce' => '58', '58' => 'Ce',
208
'Pr' => '59', '59' => 'Pr',
209
'Nd' => '60', '60' => 'Nd',
210
'Pm' => '61', '61' => 'Pm',
211
'Sm' => '62', '62' => 'Sm',
212
'Eu' => '63', '63' => 'Eu',
213
'Gd' => '64', '64' => 'Gd',
214
'Tb' => '65', '65' => 'Tb',
215
'Dy' => '66', '66' => 'Dy',
216
'Ho' => '67', '67' => 'Ho',
217
'Er' => '68', '68' => 'Er',
218
'Tm' => '69', '69' => 'Tm',
219
'Yb' => '70', '70' => 'Yb',
220
'Lu' => '71', '71' => 'Lu',
221
'Hf' => '72', '72' => 'Hf',
222
'Ta' => '73', '73' => 'Ta',
223
'W' => '74', '74' => 'W',
224
'Re' => '75', '75' => 'Re',
225
'Os' => '76', '76' => 'Os',
226
'Ir' => '77', '77' => 'Ir',
227
'Pt' => '78', '78' => 'Pt',
228
'Au' => '79', '79' => 'Au',
229
'Hg' => '80', '80' => 'Hg',
230
'Tl' => '81', '81' => 'Tl',
231
'Pb' => '82', '82' => 'Pb',
232
'Bi' => '83', '83' => 'Bi',
233
'Po' => '84', '84' => 'Po',
234
'At' => '85', '85' => 'At',
235
'Rn' => '86', '86' => 'Rn',
236
'Fr' => '87', '87' => 'Fr',
237
'Ra' => '88', '88' => 'Ra',
238
'Ac' => '89', '89' => 'Ac',
239
'Th' => '90', '90' => 'Th',
240
'Pa' => '91', '91' => 'Pa',
241
'U' => '92', '92' => 'U',
242
'Np' => '93', '93' => 'Np',
243
'Pu' => '94', '94' => 'Pu',
244
'Am' => '95', '95' => 'Am',
245
'Cm' => '96', '96' => 'Cm',
246
'Bk' => '97', '97' => 'Bk',
247
'Cf' => '98', '98' => 'Cf',
248
'Es' => '99', '99' => 'Es',
249
'Fm' => '100', '100' => 'Fm',
250
'Md' => '101', '101' => 'Md',
251
'No' => '102', '102' => 'No',
252
'Lr' => '103', '103' => 'Lr',
253
'Rf' => '104', '104' => 'Rf',
254
'Ha' => '105', '105' => 'Ha',
255
'Sg' => '106', '106' => 'Sg',
256
'Bh' => '107', '107' => 'Bh',
257
'Hs' => '108', '108' => 'Hs',
258
'Mt' => '109', '109' => 'Mt'
273
elsif( _is_symbol $data )
275
$self->symbol($data);
277
elsif( _is_name $data )
294
return $self->{'Z'} unless $data;
296
unless( _is_Z $data )
298
$self->error('$data is not a valid proton number');
302
$self->{'Z'} = $data;
303
$self->{'name'} = _get_name_by_Z $data;
304
$self->{'symbol'} = _get_symbol_by_Z $data;
314
return $self->{'name'} unless $data;
316
unless( _is_name $data)
318
$self->error('$data is not a valid name');
322
$self->{'name'} = _format_name $data;
323
$self->{'Z'} = _get_Z_by_name $data;
324
$self->{'symbol'} = _get_symbol_by_Z($self->Z);
334
return $self->{'symbol'} unless $data;
336
unless( _is_symbol $data )
338
$self->error('$data is not a valid chemical symbol');
342
$self->{'symbol'} = _format_symbol $data;
343
$self->{'Z'} = _get_Z_by_symbol $data;
344
$self->{'name'} = _get_name_by_Z $self->Z;
353
#since we were asked for a name, we'll suppose that we were passed
354
#either a chemical symbol or a Z.
355
return _get_symbol_by_Z($thingy) if _is_Z $thingy;
356
return _get_symbol_by_name($thingy) if _is_name $thingy;
358
#maybe it's already a symbol...
359
return _format_symbol $thingy if _is_symbol $thingy;
361
#we were passed something wierd. pretend we don't know anything.
365
sub _get_symbol_by_name
369
return unless _is_name $name;
371
$name = _format_name $name;
373
#not much we can do if they don't pass a proper name
374
foreach( keys %names )
376
next unless $name eq $names{$_};
387
#just in case we were passed a symbol rather
389
return unless _is_Z $Z;
391
return $elements{$Z} if defined $elements{$Z};
400
#since we were asked for a name, we'll suppose that we were passed
401
#either a chemical symbol or a Z.
402
return _get_name_by_symbol($thingy) if _is_symbol $thingy;
403
return _get_name_by_Z($thingy) if _is_Z $thingy;
405
#maybe it's already a name
406
return _format_name $thingy if _is_name $thingy;
408
#we were passed something wierd. pretend we don't know anything.
413
sub _get_name_by_symbol
415
return _get_name_by_Z( _get_Z_by_symbol(shift) );
422
return unless _is_Z $Z;
424
#not much we can do if they don't pass a proper number
425
if( defined $names{$Z} )
437
#since we were asked for a name, we'll suppose that we were passed
438
#either a chemical symbol or a Z.
439
return _get_Z_by_symbol($thingy) if _is_symbol $thingy;
440
return _get_Z_by_name($thingy) if _is_name $thingy;
442
#maybe it's already a Z
443
return $thingy if _is_Z $thingy;
445
#we were passed something wierd. pretend we don't know anything.
454
while( ($key, $value) = each %names )
456
#do a case insensitive match
457
if( lc($value) eq lc($name) )
470
#ensure that the first letter is upper case and that the
471
#others are lower case. this way we can accept data from
472
#sources too dumb to know about chemical symbols or proper
473
#cases. (and they exist. i've seen them.)
474
$symbol =~ s/^(.)(.*)$/uc($1).lc($2)/e;
476
if( defined $elements{$symbol} )
478
return $elements{$symbol};
484
########################################################################
485
########################################################################
487
# the _is_* functions do some minimal data checking to help other
488
# functions guess what sort of input they received
490
########################################################################
495
#at least three alphabetic characters
496
return 0 unless $data =~ m/^[a-z][a-z][a-z][a-z]*$/i;
498
$data = _format_name $data;
500
foreach( keys %names )
502
return 1 if $data eq $names{$_};
508
########################################################################
513
return 0 unless $data =~ m/^u?[a-z]?[a-z]$/i;
515
$data =~ s/^(.)(.*)/uc($1) . lc($2)/e;
517
return 1 if defined $elements{$data};
522
########################################################################
527
return 0 unless $data =~ m/^1?\d?\d$/;
528
return 1 if $data > 0 and $data <= $maximum_Z;
532
########################################################################
535
# input: a string that is supoosedly a chemical symbol
536
# output: the string with the first character in uppercase and the
539
# there is no data checking involved. this function doens't know
540
# and doesn't care if the data are valid. it just does its thing.
545
$data =~ s/^(.)(.*)/uc($1).lc($2)/e;
550
########################################################################
553
# input: a string that is supoosedly a chemical element's name
554
# output: the string with the first character in uppercase and the
557
# there is no data checking involved. this function doens't know
558
# and doesn't care if the data are valid. it just does its thing.
560
# this looks like _format_symbol, but it logically isn't. someday
561
# it might do something different than _format_symbol
566
$data =~ s/^(.)(.*)/uc($1).lc($2)/e;
571
########################################################################
577
return unless ref $self;
579
my $method_name = $AUTOLOAD;
581
$method_name =~ s/.*:://;
585
$self->{$method_name} = $data;
587
elsif( defined $self->{$method_name} )
589
return $self->{$method_name};
603
Chemistry::Elements - Perl extension for working with Chemical Elements
607
use Chemistry::Elements qw(get_name get_Z get_symbol);
609
# the constructor can use different input
610
$element = new Chemistry::Elements $atomic_number;
611
$element = new Chemistry::Elements $chemical_symbol;
612
$element = new Chemistry::Elements $element_name;
614
# you can make up your own attributes by specifying
615
# a method (which is really AUTOLOAD)
616
$element->molar_mass(22.989) #sets the attribute
617
$MM = $element->molar_mass #retrieves the value
621
There are two parts to the module: the object stuff and the exportable
622
functions for use outside of the object stuff. The exportable
623
functions are discussed in EXPORTABLE FUNCTIONS.
625
Chemistry::Elements provides an easy, object-oriented way to
626
keep track of your chemical data. Using either the atomic
627
number, chemical symbol, or element name you can construct
628
an Element object. Once you have an element object, you can
629
associate your data with the object by making up your own
630
methods, which the AUTOLOAD function handles. Since each
631
chemist is likely to want to use his or her own data, or
632
data for some unforesee-able property, this module does not
633
try to be a repository for chemical data.
635
The Element object constructor tries to be as flexible as possible -
636
pass it an atomic number, chemical symbol, or element name and it
637
tries to create the object.
639
# the constructor can use different input
640
$element = new Chemistry::Elements $atomic_number;
641
$element = new Chemistry::Elements $chemical_symbol;
642
$element = new Chemistry::Elements $element_name;
644
once you have the object, you can define your own methods simply
645
by using them. Giving the method an argument (others will be
646
ignored) creates an attribute with the method's name and
647
the argument's value.
649
# you can make up your own attributes by specifying
650
# a method (which is really AUTOLOAD)
651
$element->molar_mass(22.989) #sets the attribute
652
$MM = $element->molar_mass #retrieves the value
654
The atomic number, chemical symbol, and element name can be
655
retrieved in the same way.
657
$atomic_number = $element->Z;
658
$name = $element->name;
659
$symbol = $element->symbol;
661
These methods can also be used to set values, although changing
662
any of the three affects the other two.
664
$element = new Chemistry::Elements('Lead');
666
$atomic_number = $element->Z; # $atomic_number is 82
670
$name = $element->name; # $name is 'Gold'
672
=head2 Instance methods
676
=item new( Z | SYMBOL | NAME )
678
Create a new instance from either the atomic number, symbol, or
683
Return the atomic number of the element.
687
Return the name of the element.
691
Return the symbol of the element.
695
=head2 Exportable functions
697
These functions can be exported. They are not exported by default.
703
This function attempts to return the symbol of the chemical element given
704
either the chemical symbol, element name, or atmoic number. The
705
function does its best to interpret inconsistent input data (e.g.
706
chemcial symbols of mixed and single case).
708
use Chemistry::Elements qw(get_symbol);
710
$name = get_symbol('Fe'); #$name is 'Fe'
711
$name = get_symbol('fe'); #$name is 'Fe'
712
$name = get_symbol(26); #$name is 'Fe'
713
$name = get_symbol('Iron'); #$name is 'Fe'
714
$name = get_symbol('iron'); #$name is 'Fe'
716
If no symbol can be found, nothing is returned.
718
Since this function will return the symbol if it is given a symbol,
719
you can use it to test whether a string is a chemical symbol
720
(although you have to play some tricks with case since get_symbol
721
will try its best despite the case of the input data).
723
if( lc($string) eq lc( get_symbol($string) ) )
728
You can modify the symbols (e.g. you work for UCal ;) ) by changing
729
the data at the end of this module.
733
This function attempts to return the name the chemical element given
734
either the chemical symbol, element name, or atomic number. The
735
function does its best to interpret inconsistent input data (e.g.
736
chemcial symbols of mixed and single case).
738
$name = get_name('Fe'); #$name is 'Iron'
739
$name = get_name('fe'); #$name is 'Iron'
740
$name = get_name(26); #$name is 'Iron'
741
$name = get_name('Iron'); #$name is 'Iron'
742
$name = get_name('iron'); #$name is 'Iron'
744
If there is no Z can be found, nothing is returned.
746
Since this function will return the name if it is given a name,
747
you can use it to test whether a string is a chemical element name
748
(although you have to play some tricks with case since get_name
749
will try its best despite the case of the input data).
751
if( lc($string) eq lc( get_name($string) ) )
756
You can modify the names (e.g. for different languages) by changing
757
the data at the end of this module.
761
This function attempts to return the atomic number of the chemical
762
element given either the chemical symbol, element name, or atomic
763
number. The function does its best to interpret inconsistent input data
764
(e.g. chemcial symbols of mixed and single case).
766
$name = get_Z('Fe'); #$name is 26
767
$name = get_Z('fe'); #$name is 26
768
$name = get_Z(26); #$name is 26
769
$name = get_Z('Iron'); #$name is 26
770
$name = get_Z('iron'); #$name is 26
772
If there is no Z can be found, nothing is returned.
774
Since this function will return the Z if it is given a Z,
775
you can use it to test whether a string is an atomic number.
776
You might want to use the string comparison in case the
777
$string is not a number (in which case the comparison
778
will be false save for the case when $string is undefined).
780
if( $string eq get_Z($string) )
787
The package constructor automatically finds the largest defined
788
atomic number (in case you add your own heavy elements).
790
=head2 AUTOLOADing methods
792
You can pseudo-define additional methods to associate data with objects.
793
For instance, if you wanted to add a molar mass attribute, you
794
simply pretend that there is a molar_mass method:
796
$element->molar_mass($MM); #add molar mass datum in $MM to object
798
Similiarly, you can retrieve previously set values by not specifying
799
an argument to your pretend method:
801
$datum = $element->molar_mass();
803
#or without the parentheses
804
$datum = $element->molar_mass;
806
If a value has not been associated with the pretend method and the
807
object, the pretend method returns nothing.
809
I had thought about providing basic data for the elements, but
810
thought that anyone using this module would probably have their
811
own data. If there is an interest in canned data, perhaps I can
816
I would like make this module easily localizable so that one could
817
specify other names or symbols for the elements (i.e. a different
818
language or a different perspective on the heavy elements). If
819
anyone should make changes to the data, i would like to get a copy
820
so that i can include it in future releases :)
824
Copright 2005, brian d foy
826
You can use this module under the same terms as Perl itself.
830
brian d foy, CC< <bdfoy@cpan.org> >>