1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
|
## Time-stamp: <2006/08/21 10:46:03 bruce>
######################################################################
## This module is copyright (c) 1999-2006 Bruce Ravel
## <bravel@anl.gov>
## http://cars9.uchicago.edu/~ravel/software/exafs/
##
## -------------------------------------------------------------------
## All rights reserved. This program is free software; you can
## redistribute it and/or modify it under the same terms as Perl
## itself.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## Artistic License for more details.
## -------------------------------------------------------------------
######################################################################
## Code:
=head1 NAME
Xray::Absorption - obtain X-ray absorption data for the elements
=head1 SYNOPSIS
use Xray::Absorption;
Xray::Absorption -> load("mcmaster");
$xsec = Xray::Absorption->cross_section('Cu', 9000);
This example returns the cross section of Copper at 9000 eV using the
McMaster tables.
=head1 DESCRIPTION
This module supports access to X-ray absorption data. It is designed
to be a transparent interface to absorption data from a variety of
sources. Currently, the only sources of data are the 1969 McMaster
tables, the 1999 Elam tables, the 1993 Henke tables, and the 1995
Chantler tables. The Brennan-Cowen implementation of the
Cromer-Liberman tables is available as a drop-on-top addition to this
package. More resources can be added easily.
Information used to compute the mass energy-absorption coefficient is
taken from the tabulations of Hubbell and Seltzer:
http://physics.nist.gov/PhysRefData/XrayMassCoef/cover.html
Because this is an object-oriented approach to X-ray absorption data,
you must call subroutines as class methods rather than as subroutines:
$xsec = Xray::Absorption->cross_section('Cu', 9000);
is correct, but
$xsec = Xray::Absorption::cross_section('Cu', 9000);
is incorrect. Using class methods rather than a function oriented
approach allows the user of the C<Xray::Absorption> module to I<hot
swap> absorption data resources. For example
foreach $resource (Xray::Absorption->available) {
Xray::Absorption->load($resource);
print $resource, " : ",
Xray::Absorption->cross_section('Cu', 9000), $/;
};
compares the cross section of copper at 9 keV as calculated from the
all available data resources.
It is necessary to initialize C<Xray::Absorption> to use a particular
database by invoking the C<load> method. This method establishes and
changes inheritance.
=head1 METHODS
=over 4
=item C<current_resource>
Example:
$this = Xray::Absorption -> current_resource;
Identifies the currently selected resource.
=item C<in_resource>
Example:
$is_there = Xray::Absorption -> in_resource($elem);
Returns true if C<$elem> is tabulated in the current resource.
C<$elem> can be a two letter symbol, the full name of the element, or
a Z number.
=item C<get_energy>
Example:
$energy = $energy = Xray::Absorption -> get_energy($elem, $edge);
Returns the edge energy for C<$elem>. C<$edge> is one of K, L1, L2,
L3, M1, etc. C<$edge> may also be the Siegbahn or IUPAC symbol for a
fluorescence line. Some data resources provide more lines than
others. Some may provide no lines at all. See the documentation for
each resource for which lines are available. When either C<$elem> or
C<$edge> is an unrecognized symbol, this method returns 0.
=item C<next_energy>
Example:
$next = Xray::Absorption -> next_energy($elem, $edge, @list);
Given a list of atomic symbols C<@list>, return a list containing the
element symbol, edge symbol, and energy in eV of the next highest edge
energy after the C<$edge> edge of C<$elem>. This returns an empty list
if the any argument is unrecognizable.
=item C<cross_section>
Examples:
$xsec = Xray::Absorption -> cross_section($elem, $en, $mode);
@xsec = Xray::Absorption -> cross_section($elem, \@en, $mode);
In scalar context, return the cross section in barns/atom of C<$elem>
at C<$energy>. In list context, return a list of cross-sections given
a reference to a list of energies. For some data resources, list
context may be significantly faster than repeated calls in scalar
context, i.e. this
@xsec = Xray::Absorption -> cross_section($elem, \@en, $mode);
foreach (0 .. $#en) {
... do something with energy $xsec[$_] ...
};
will be way faster than
foreach (@en) {
$xsec = Xray::Absorption -> cross_section($elem, $en, $mode);
... do something with $xsec ...
};
The optional C<$mode> argument tells this method what kind of data to
return. The default for all data resources is to return the cross
section, however each resource has several other option. For example,
the McMaster tables offer along with the absorption cross section, the
coherent scattering, the incoherent scattering, or the sum of the
three contributions. The allowed values for C<$mode> depend on the
data contained in the absorption resource currently loaded, but the
default is always to return the photoelectron cross section, or the
full cross section if the coherent and incoherent scattering portions
are included in the resource. See the documentation for the
individual resource modules. If C<$mode> is not given or is given
incorrectly, the full cross section is returned.
If an energy is requested which is right on an edge, all data
resources assume that you want the cross-section just above the edge.
The granularity of the comparison between the requested energy and the
edge energy is 1 milivolt, so if you want a cross-section just below
an edge, you should request an energy that is more than 1 milivolt
less than the value returned by C<get_energy>.
=item C<data_available>
Example:
$is_there = Xray::Absorption -> data_available($elem, $edge);
Returns true if the selected resource contains sufficient data for
handling the specified element in the energy range around the
specified edge. Returns false otherwise.
=back
=cut
package Xray::Absorption;
require Exporter;
use vars qw(@ISA $VERSION $cvs_info $cvs_version);
$VERSION = '0.11';
$cvs_info = '$Id: Absorption.pm,v 1.13 2001/09/20 17:40:58 bruce Exp $ ';
$cvs_version = 1.14; #(split(' ', $cvs_info))[2] || "pre_release";
@ISA = qw(Exporter);
@EXPORT = qw();
@EXPORT_OK = qw($resource $verbose);
## @EXPORT_OK = qw($resource get_atomic_weight get_conversion get_density
## get_l get_Siegbahn get_IUPAC);
use strict;
use Carp;
use Chemistry::Elements qw(get_Z get_symbol);
use Ifeffit::FindFile;
use Storable;
use Math::Spline qw(spline);
use vars qw($resource $verbose $data_dir);
$resource = "elam";
$verbose = 0;
sub identify_self {
my @caller = caller;
use File::Basename qw(dirname);
return dirname($caller[1]);
};
$data_dir = ($Ifeffit::FindFile::is_windows) ?
Ifeffit::FindFile->find("other", "absorption") :
File::Spec->catfile(identify_self(), "Absorption");
sub load {
shift;
$resource = $_[0] || $resource;
$resource = lc($resource);
@ISA = load_database('Xray::Absorption', $resource);
};
sub load_database {
my($class,$resource) = @_;
if ($resource eq 'mcmaster') {
require Xray::Absorption::McMaster;
'Xray::Absorption::McMaster';
} elsif ($resource eq 'elam') {
require Xray::Absorption::Elam;
'Xray::Absorption::Elam';
} elsif ($resource eq 'henke') {
require Xray::Absorption::Henke;
'Xray::Absorption::Henke';
} elsif ($resource eq 'chantler') {
require Xray::Absorption::Chantler;
'Xray::Absorption::Chantler';
} elsif ($resource eq 'cl') {
require Xray::Absorption::CL;
'Xray::Absorption::CL';
} elsif ($resource eq 'none') {
require Xray::Absorption::None;
'Xray::Absorption::None';
} else {
croak "$resource is an unknown Xray::Absorption resource";
}
};
load(1, $resource);
=over 4
=item C<available>
Example:
@list = Xray::Absorption -> available;
Returns a list of all available data resource.
=back
=cut
#my @cl_ok = ('linux', 'irix');
#my $cl_match = join('|', @cl_ok);
my $ifeffit_exists = (eval "require Ifeffit");
my $make_cl = $ifeffit_exists; #($^O =~ /$cl_match/);
sub available {
shift;
my @list = ("Elam", "McMaster", "Henke", "Chantler", "None");
($make_cl) and push @list, "CL";
return @list;
};
=over 4
=item C<scattering>
Example:
@list = Xray::Absorption -> scattering;
Returns a list of all available data resource which contain anomalous
scattering functions.
=back
=cut
sub scattering {
shift;
my @list = ("Henke", "Chantler", "None");
($make_cl) and push @list, "CL";
return @list;
};
=over 4
=item C<verbose>
Example:
@list = Xray::Absorption -> verbose($arg);
Turn verbose operation on or off. If C<$arg> evaluates to true, then
warning messages will be printed to standard error. If C<$arg>
evaluates to false, then methods will silently return 0 when they
encounter problems.
=back
=cut
sub verbose {
shift;
$verbose = $_[0];
};
## This hash contains general atomic data useful to absorption
## calculations which do not depend upon which absorption data
## resource is selected. More properties can be added.
##
## density of Chlorine from Donal O'Leary http://www.ucc.ie/
## ucc/depts/chem/dolchem/html/elem/ELEM017.HTM
##
## atomic density of conversion factor for
## weight pure mat. barns/atoms -> cm^2/gr
my %elements = ( #* ==> interpolated
'h' => [ 1.008, 0.000090, 1.674],
'he' => [ 4.003, 0.000179, 6.647],
'li' => [ 6.940, 0.534000, 11.520],
'be' => [ 9.012, 1.848000, 14.960],
'b' => [ 10.811, 2.340000, 17.950],
'c' => [ 12.010, 2.250000, 19.940],
'n' => [ 14.008, 0.001250, 23.260],
'o' => [ 16.000, 0.001429, 26.570],
'f' => [ 19.000, 1.108000, 31.550],
'ne' => [ 20.183, 0.000900, 33.510],
'na' => [ 22.997, 0.970000, 38.190],
'mg' => [ 24.320, 1.740000, 40.380],
'al' => [ 26.970, 2.720000, 44.780],
'si' => [ 28.086, 2.330000, 46.630],
'p' => [ 30.975, 1.820000, 51.430],
's' => [ 32.066, 2.000000, 53.240],
'cl' => [ 35.457, 0.003000, 58.870], # was 1.56
'ar' => [ 39.944, 0.001784, 66.320],
'k' => [ 39.102, 0.862000, 64.930],
'ca' => [ 40.080, 1.550000, 66.550],
'sc' => [ 44.960, 2.992000, 74.650],
'ti' => [ 47.900, 4.540000, 79.530],
'v' => [ 50.942, 6.110000, 84.590],
'cr' => [ 51.996, 7.190000, 86.340],
'mn' => [ 54.940, 7.420000, 91.220],
'fe' => [ 55.850, 7.860000, 92.740],
'co' => [ 58.933, 8.900000, 97.850],
'ni' => [ 58.690, 8.900000, 97.450],
'cu' => [ 63.540, 8.940000, 105.500],
'zn' => [ 65.380, 7.140000, 108.600],
'ga' => [ 69.720, 5.903000, 115.800],
'ge' => [ 72.590, 5.323000, 120.500],
'as' => [ 74.920, 5.730000, 124.400],
'se' => [ 78.960, 4.790000, 131.100],
'br' => [ 79.920, 3.120000, 132.700],
'kr' => [ 83.800, 0.003740, 139.100],
'rb' => [ 85.480, 1.532000, 141.900],
'sr' => [ 87.620, 2.540000, 145.500],
'y' => [ 88.905, 4.405000, 147.600],
'zr' => [ 91.220, 6.530000, 151.500],
'nb' => [ 92.906, 8.570000, 154.300],
'mo' => [ 95.950, 10.220000, 159.300],
'tc' => [ 99.000, 11.500000, 164.400],
'ru' => [101.070, 12.410000, 167.800],
'rh' => [102.910, 12.440000, 170.900],
'pd' => [106.400, 12.160000, 176.700],
'ag' => [107.880, 10.500000, 179.100],
'cd' => [112.410, 8.650000, 186.600],
'in' => [114.820, 7.280000, 190.700],
'sn' => [118.690, 5.760000, 197.100],
'sb' => [121.760, 6.691000, 202.200],
'te' => [127.600, 6.240000, 211.900],
'i' => [126.910, 4.940000, 210.700],
'xe' => [131.300, 0.005900, 218.000],
'cs' => [132.910, 1.873000, 220.700],
'ba' => [137.360, 3.500000, 228.100],
'la' => [138.920, 6.150000, 230.700],
'ce' => [140.130, 6.670000, 232.700],
'pr' => [140.920, 6.769000, 234.000],
'nd' => [144.270, 6.960000, 239.600],
'pm' => [147.000, 6.782000, 244.100],
'sm' => [150.350, 7.536000, 249.600],
'eu' => [152.000, 5.259000, 252.400],
'gd' => [157.260, 7.950000, 261.100],
'tb' => [158.930, 8.272000, 263.900],
'dy' => [162.510, 8.536000, 269.800],
'ho' => [164.940, 8.803000, 273.900],
'er' => [167.270, 9.051000, 277.700],
'tm' => [168.940, 9.332000, 280.500],
'yb' => [173.040, 6.977000, 287.300],
'lu' => [174.990, 9.842000, 290.600],
'hf' => [178.500, 13.300000, 296.400],
'ta' => [180.950, 16.600000, 300.500],
'w' => [183.920, 19.300000, 305.400],
're' => [186.207, 20.980000, 310.600], #*
'os' => [190.200, 22.500000, 315.800],
'ir' => [192.200, 22.420000, 319.100],
'pt' => [195.090, 21.370000, 323.900],
'au' => [197.200, 19.370000, 327.400],
'hg' => [200.610, 13.546000, 333.100],
'tl' => [204.390, 11.860000, 339.400],
'pb' => [207.210, 11.340000, 344.100],
'bi' => [209.000, 9.800000, 347.000],
'po' => [208.982, 9.300000, 353.900], #*
'at' => [209.987, 0.000000, 360.800], #*
'rn' => [222.000, 0.009730, 368.600],
'fr' => [223.000, 0.000000, 372.750], #*
'ra' => [226.025, 5.000000, 376.900], #*
'ac' => [227.028, 10.050000, 381.050], #*
'th' => [232.000, 11.700000, 385.200],
'pa' => [231.036, 15.340000, 390.200], #*
'u' => [238.070, 19.050000, 395.300],
'np' => [237.048, 20.210000, 396.000], #* w/d from Data Booklet
'pu' => [239.100, 19.700000, 397.000],
);
## this section has the resource-independent class methods. more can
## be added in the future.
=over 4
=item C<get_atomic_weight>
Example:
$value = Xray::Absorption -> get_atomic_weight($elem);
Return the atomic weight of C<$elem>.
=back
=cut
sub get_atomic_weight {
shift;
my $sym = $_[0];
$sym = lc( get_symbol($sym) );
return exists($elements{$sym}) ? $elements{$sym} -> [0] : 0;
};
=over 4
=item C<get_density>
Example:
$value = Xray::Absorption -> get_density($elem);
Return the specific gravity of the pure material of C<$elem>.
=back
=cut
sub get_density {
shift;
my $sym = $_[0];
$sym = lc( get_symbol($sym) );
return exists($elements{$sym}) ? $elements{$sym} -> [1] : 0;
};
=over 4
=item C<get_conversion>
Example:
$value = Xray::Absorption -> get_conversion($elem);
Return the factor for converting between barns/atom and cm
squared/gram for C<$elem>.
=back
=cut
sub get_conversion {
shift;
my $sym = $_[0];
$sym = lc( get_symbol($sym) );
return exists($elements{$sym}) ? $elements{$sym} -> [2] : 0;
};
sub get_l {
shift;
my $z = $_[0];
$z = &get_Z($z);
(not $z) and return 0;
(defined $z) or return 0;
($z <= 10) and return 1;
($z <= 36) and return 2;
return 3;
};
## these three hashes are used to quickly convert between the Siegbahn
## and IUPAC symbols for the fluorescence lines
my %sieg2iup = ("ka1" => "k-l3",
"ka2" => "k-l2",
"ka3" => "k-l1",
"kb1" => "k-m3",
"kb2" => "k-n2,3",
"kb3" => "k-m2",
"kb4" => "k-n4,5",
"kb5" => "k-m4,5",
"lb3" => "l1-m3",
"lb4" => "l1-m2",
"lg2" => "l1-n2",
"lg3" => "l1-n3",
"lb1" => "l2-m4",
"ln" => "l2-m1",
"lg1" => "l2-n4",
"lg6" => "l2-o4",
"la1" => "l3-m5",
#"lb2,15" => "l3-n4,5",
"lb2" => "l3-n4,5",
"la2" => "l3-m4",
"lb5" => "l3-o4,5",
"lb6" => "l3-n1",
"ll" => "l3-m1",
"ma" => "m5-n6,7",
"mb" => "m4-n6",
"mg" => "m3-n5",
"mz" => "m4,5-n6,7",
);
my %iup2sieg = ("k-l3" => "ka1",
"k-l2" => "ka2",
"k-l1" => "ka3",
"k-m3" => "kb1",
"k-n2,3" => "kb2",
"k-m2" => "kb3",
"k-n4,5" => "kb4",
"k-m4,5" => "kb5",
"l1-m3" => "lb3",
"l1-m2" => "lb4",
"l1-n2" => "lg2",
"l1-n3" => "lg3",
"l2-m4" => "lb1",
"l2-m1" => "ln" ,
"l2-n4" => "lg1",
"l2-o4" => "lg6",
"l3-m5" => "la1",
"l3-n4,5" => "lb2",
#"l3-n4,5" => "lb2,15",
"l3-m4" => "la2",
"l3-o4,5" => "lb5",
"l3-n1" => "lb6",
"l3-m1" => "ll",
"m5-n6,7" => "ma",
"m4-n6" => "mb",
"m3-n5" => "mg",
"m4,5-n6,7" => "mz",
);
my %gr2lett = ("kalpha1" => "ka1",
"kalpha2" => "ka2",
"kalpha3" => "ka3",
"kbeta1" => "kb1",
"kbeta2" => "kb2",
"kbeta3" => "kb3",
"kbeta4" => "kb4",
"kbeta5" => "kb5",
"lbeta3" => "lb3",
"lbeta4" => "lb4",
"lgamma2" => "lg2",
"lgamma3" => "lg3",
"lbeta1" => "lb1",
"lnu" => "ln" ,
"lgamma1" => "lg1",
"lgamma6" => "lg6",
"lalpha1" => "la1",
#"lbeta2,15" => "lb2,15",
"lbeta2" => "lb2",
"lalpha2" => "la2",
"lbeta5" => "lb5",
"lbeta6" => "lb6",
"ll" => "ll",
"malpha" => "ma",
"mbeta" => "mb",
"mgamma" => "mg",
"mzeta" => "mz",
);
=over 4
=item C<get_Siegbahn>
Example:
$symbol = Xray::Absorption -> get_Siegbahn($sym);
Return the short Siegbahn symbol for an x-ray fluorescence line. Thus
"Ka1", "Kalpha1", and "K-L3" all return "Ka1". The case of the input
symbol does not matter and the symbol is returned capitalized. White
space and underscores will be removed from the input symbol. The
symbol "lb2,15" is translated to "lb2". This returns 0 is C<$sym> is
not a recognizable symbol for a line.
=back
=cut
sub get_Siegbahn {
shift;
my $sym = $_[0];
$sym = lc($sym);
$sym =~ s/ //g;
$sym =~ s/_//g;
($sym eq "lb2,15") and ($sym = "lb2");
exists $sieg2iup{$sym} and return ucfirst($sym);
exists $iup2sieg{$sym} and return ucfirst($iup2sieg{$sym});
exists $gr2lett{$sym} and return ucfirst($gr2lett{$sym});
return 0;
};
=over 4
=item C<get_Siegbahn_full>
Example:
$symbol = Xray::Absorption -> get_Siegbahn_full($sym);
Return the full Siegbahn symbol for an x-ray fluorescence line. Thus
"Ka1", "Kalpha1", and "K-L3" all return "Kalpha1". The case of the
input symbol does not matter and the symbol is returned capitalized.
White space and underscores will be removed from the input symbol.
This returns 0 is C<$sym> is not a recognizable symbol for a line.
=back
=cut
sub get_Siegbahn_full {
shift;
my $sym = Xray::Absorption->get_Siegbahn($_[0]);
my %greek = ("a"=>"alpha", "b"=>"beta", "g"=>"gamma", "l"=>"l",
"n"=>"nu", "z"=>"zeta");
my $letters = join("", keys(%greek));
(substr($sym, 1, 1) =~ /[$letters]/) and do {
substr($sym, 1, 1) = $greek{substr($sym, 1, 1)};
return $sym;
};
return $sym;
};
=over 4
=item C<get_IUPAC>
Example:
$symbol = Xray::Absorption -> get_IUPAC($sym);
Return the IUPAC symbol for an x-ray fluorescence line. Thus "Ka1",
"Kalpha1", and "K-L3" all return "K-L3". The case of the input symbol
does not matter and the symbol is returned in all capitals. White
space and underscores will be removed from the input symbol. This
returns 0 is C<$sym> is not a recognizable symbol for a line.
=back
=cut
sub get_IUPAC {
shift;
my $sym = $_[0];
$sym = lc($sym);
$sym =~ s/ //g;
$sym =~ s/_//g;
($sym eq "lb2,15") and ($sym = "lb2");
exists $iup2sieg{$sym} and return uc($sym);
exists $sieg2iup{$sym} and return uc($sieg2iup{$sym});
exists $gr2lett{$sym} and return uc($sieg2iup{$gr2lett{$sym}});
return 0;
};
=over 4
=item C<get_gamma>
Example:
$symbol = Xray::Absorption -> get_gamma($sym, $edge);
Return an approximation of the core-hole lifetime for the given atomic
symbol and edge. This follows Feff very closely. In fact the data
used is swiped from the setgam subroutine in Feff, which is in turn
swiped from K. Rahkonen and K. Krause, Atomic Data and Nuclear Data
Tables, Vol 14, Number 2, 1974. The values given by this routine are
a bit different from those given by Feff since a different
interpolation is used. For O and P edges a value of 0.1 is returned,
as in Feff. If the arguments are not interpretable, a value of 0 is
returned.
=back
=cut
my %zhash =
(
'k' => [ 0.99, 10.0, 20.0, 40.0, 50.0, 60.0, 80.0, 95.1],
'l1' => [ 0.99, 18.0, 22.0, 35.0, 50.0, 52.0, 75.0, 95.1],
'l2' => [ 0.99, 17.0, 28.0, 31.0, 45.0, 60.0, 80.0, 95.1],
'l3' => [ 0.99, 17.0, 28.0, 31.0, 45.0, 60.0, 80.0, 95.1],
'm1' => [ 0.99, 20.0, 28.0, 30.0, 36.0, 53.0, 80.0, 95.1],
'm2' => [ 0.99, 20.0, 22.0, 30.0, 40.0, 68.0, 80.0, 95.1],
'm3' => [ 0.99, 20.0, 22.0, 30.0, 40.0, 68.0, 80.0, 95.1],
'm4' => [ 0.99, 36.0, 40.0, 48.0, 58.0, 76.0, 79.0, 95.1],
'm5' => [ 0.99, 36.0, 40.0, 48.0, 58.0, 76.0, 79.0, 95.1],
'n1' => [ 0.99, 30.0, 40.0, 47.0, 50.0, 63.0, 80.0, 95.1],
'n2' => [ 0.99, 40.0, 42.0, 49.0, 54.0, 70.0, 87.0, 95.1],
'n3' => [ 0.99, 40.0, 42.0, 49.0, 54.0, 70.0, 87.0, 95.1],
'n4' => [ 0.99, 40.0, 50.0, 55.0, 60.0, 70.0, 81.0, 95.1],
'n5' => [ 0.99, 40.0, 50.0, 55.0, 60.0, 70.0, 81.0, 95.1],
'n6' => [ 0.99, 71.0, 73.0, 79.0, 86.0, 90.0, 95.0, 100.0],
'n7' => [ 0.99, 71.0, 73.0, 79.0, 86.0, 90.0, 95.0, 100.0],
);
my %gamach =
(
'k' => [0.02, 0.28, 0.75, 4.8, 10.5, 21.0, 60.0, 105.0],
'l1' => [0.07, 3.9, 3.8, 7.0, 6.0, 3.7, 8.0, 19.0],
'l2' => [0.001, 0.12, 1.4, 0.8, 2.6, 4.1, 6.3, 10.5],
'l3' => [0.001, 0.12, 0.55, 0.7, 2.1, 3.5, 5.4, 9.0],
'm1' => [0.001, 1.0, 2.9, 2.2, 5.5, 10.0, 22.0, 22.0],
'm2' => [0.001, 0.001, 0.5, 2.0, 2.6, 11.0, 15.0, 16.0],
'm3' => [0.001, 0.001, 0.5, 2.0, 2.6, 11.0, 10.0, 10.0],
'm4' => [0.0006, 0.09, 0.07, 0.48, 1.0, 4.0, 2.7, 4.7],
'm5' => [0.0006, 0.09, 0.07, 0.48, 0.87, 2.2, 2.5, 4.3],
'n1' => [0.001, 0.001, 6.2, 7.0, 3.2, 12.0, 16.0, 13.0],
'n2' => [0.001, 0.001, 1.9, 16.0, 2.7, 13.0, 13.0, 8.0],
'n3' => [0.001, 0.001, 1.9, 16.0, 2.7, 13.0, 13.0, 8.0],
'n4' => [0.001, 0.001, 0.15, 0.1, 0.8, 8.0, 8.0, 5.0],
'n5' => [0.001, 0.001, 0.15, 0.1, 0.8, 8.0, 8.0, 5.0],
'n6' => [0.001, 0.001, 0.05, 0.22, 0.1, 0.16, 0.5, 0.9],
'n7' => [0.001, 0.001, 0.05, 0.22, 0.1, 0.16, 0.5, 0.9]
);
sub get_gamma {
shift;
my ($sym, $edge) = @_;
my $z = &get_Z($sym);
$z or return 0;
$edge = lc($edge);
($edge =~ /\b(o[1-5]|p[1-3])\b/) and return 0.1;
($edge =~ /\b(k|l[1-3]|m[1-5]|n[1-7]|o[1-5]|p[1-3])\b/) or return 0;
my $x = $zhash{$edge};
my $y = $gamach{$edge};
my $spline = new Math::Spline($x,$y);
return $spline->evaluate($z);
};
=over 4
=item C<get_one_minus_g>
Example:
$symbol = Xray::Absorption -> get_g($sym, $energy);
Return an approximation of the factor required to translate tabulated
cross-section data to the mass energy-absorption coefficient, as
described by Hubbell at
http://physics.nist.gov/PhysRefData/XrayMassCoef/cover.html.
This term, returned as C<1-g> relates the the mass attenuation
coefficient, C<mu/rho>, to the mass energy-absorption coefficient,
C<mu_en/rho>, as
mu_en/rho = (1-g) * mu_tr/rho
where the mass energy-transfer coefficient, C<mu_tr>, is the sum of
the photoabsorption and incoherent cross-sections. (At the energies
at which this module is applicable, other cross-sections such as
pair production can be ignored.)
So, to use this factor, compute the sum of the photoabsorption and
incoherent cross-sections at some energy and multiply by the number
this method returns.
The importance of this term depends on energy and on element. For
nitrogen, for example, this term becomes increasingly important above
10 keV. For argon, it is near unity up to about 30 keV.
No great care is taken to interpolate correctly around absorption
edges. That should be considered a bug.
This method returns 1 whenever it's imput data is confusing. That
seems safest.
=back
=cut
my $g_file = File::Spec->catfile($Xray::Absorption::data_dir, "hubbell_g.db");
use vars qw($r_one_minus_g);
$r_one_minus_g = retrieve($g_file);
sub get_one_minus_g {
shift;
my ($sym, $energy) = @_;
my $z = &get_Z($sym);
$z or return 1;
($z > 92) and return 1;
($z < 1) and return 1;
($energy < 1000) and return 1;
my $e = $$r_one_minus_g[$z] -> {energy};
my $g = $$r_one_minus_g[$z] -> {one_minus_g};
my $spline = new Math::Spline($e,$g);
return 1/$spline->evaluate($energy);
};
1;
__END__
=head1 SYMBOLS FOR FLUORESCENCE LINES
To specify fluorescence lines, Siegbahn or IUPAC symbols may be used.
methods are provided for converting between these notations. The
Siegbahn notations can be in the short or full forms. Here is a table
of all recognized symbols:
Full Siegbahn Short Siegbahn IUPAC
-------------------------------------------------
Kalpha1 Ka1 K-L3
Kalpha2 Ka2 K-L2
Kalpha3 Ka3 K-L1
Kbeta1 Kb1 K-M3
Kbeta2 Kb2 K-N2,3
Kbeta3 Kb3 K-M2
Kbeta4 Kb4 K-N4,5
Kbeta5 Kb5 K-M4,5
Lalpha1 La1 L3-M5
Lalpha2 La2 L3-M4
Lbeta1 Lb1 L2-M4
Lbeta2 Lb2 L3-N4,5
Lbeta3 Lb3 L1-M3
Lbeta4 Lb4 L1-M2
Lbeta5 Lb5 L3-O4,5
Lbeta6 Lb6 L3-N1
Lgamma1 Lg1 L2-N4
Lgamma2 Lg2 L1-N2
Lgamma3 Lg3 L1-N3
Lgamma6 Lg6 L2-O4
Ll Ll L3-M1
Lnu Ln L2-M1
Malpha Ma M5-N6,7
Mbeta Mb M4-N6
Mgamma Mg M3-N5
Mzeta Mz M4,5-N6,7
In addition, the symbols C<Lb2,15> and C<Lbeta2,15> are recognized as
synonyms for C<Lbeta2>. The methods which interpret these symbols
will remove spaces and underscores from the input string. Thus
C<K_alpha_1> and C<K a 1> will both be recognized as C<Kalpha1>.
Since hyphens are part of the IUPAC notation, C<K-alpha-1> will not be
recognized as C<Kalpha1>. Thus use spaces or underscores if you want
to make the Siegbahn notation more legible.
=head1 ABSORPTION DATA RESOURCES
Currently, C<Xray::Absorption> has the McMaster, Elam, Henke, and
Chantler tables as its data resources. New resources may be added
over time. This section offers a few guidelines to anyone interested
in supplying more resources. It does not matter how the new resource
calculates the cross section. That is hidden behind the
object-orientedness of the C<Xray::Absorption> module. It is
essential that the new resource take the namespace
C<Xray::Absorption::>I<Resource>, where I<Resource> is a descriptive
name, like C<McMaster> or C<Elam>. It is essential that the new
resource supply these methods
current_resource
in_resource
get_energy
next_energy
cross_section
and that they use the semantics described above. All other methods
decribed in the last section are defined in F<Absorption.pm> and do
not need to be redefined in the resource modules.
New resources are welcome to define new methods particular to that
data resource in addition to the 5 required methods.
=head1 UNITS
All energies returned by the methods of C<Xray::Absorption> are in
electron volts. All cross sections are in units of barns per atom. A
conversion constant between that unit and cm squared per gram is
supplied by the C<get_conversion> method. Atomic weights are in
atomic units. Densities are given as specific gravity
(i.e. dimensionless).
=head1 BUGS AND THINGS TO DO
=over 4
=item *
Check to be sure things are properly unloaded and overloaded when
switching resources.
=item *
Test for pathelogical cases, such as elements that don't exist, that
have Z's in the hundreds, energies that are very low or very high, and
so on.
=item *
It would be nice to implement the list that is used by the
C<next_energy> method as a doubly linked list. In that way, a
C<previous_energy> method would be trivial.
=back
=head1 AUTHOR
Bruce Ravel <bravel@anl.gov>
http://cars9.uchicago.edu/~ravel/software/
=cut
1;
|