NAME Ifeffit::Demeter - An object oriented EXAFS data analysis system VERSION This documentation refers to Ifeffit::Demeter version 0.0.1 SYNOPSIS Import Demeter components into your program: use Ifeffit::Demeter; This will import all Demeter components into your program. The components are: Atoms Data Path Plot Config GDS Fit Feff ScatteringPath Importing the Fit component forces the import of the Data, Path, and GDS components. You can also specify subsets of the Demeter system for import. use Ifeffit::Demeter qw(Data); Typically, the third form is EXAMPLE Here is a complete script for analyzing copper data: #!/usr/bin/perl -I/home/bruce/codes/demeter use warnings; use strict; use Ifeffit::Demeter; # print "Sample fit to copper data using Demeter $Ifeffit::Demeter::VERSION\n"; Ifeffit::Demeter->set_mode({screen=>1, ifeffit=>1}); my $plot_features = Ifeffit::Demeter::Plot -> new(); # ## Data object: set the processing and fit parameters my $dobject = Ifeffit::Demeter::Data -> new({group => 'data0',}); $dobject ->set({file => "example/cu/cu10k.chi", is_chi => 1, fft_kmax => 3, # \ note that this gets fft_kmin => 14,# / fixed automagically bft_rmax => "4.3", fit_space => 'K', fit_k1 => 1, fit_k3 => 1, label => 'My copper data', }); # ## GDS objects for isotropic expansion + correlated Debye model my @gdsobjects = (Ifeffit::Demeter::GDS -> new({type => 'guess', name => 'alpha', mathexp => 0}), Ifeffit::Demeter::GDS -> new({type => 'guess', name => 'amp', mathexp => 1}), Ifeffit::Demeter::GDS -> new({type => 'guess', name => 'enot', mathexp => 0}), Ifeffit::Demeter::GDS -> new({type => 'guess', name => 'theta', mathexp => 500}), Ifeffit::Demeter::GDS -> new({type => 'set', name => 'temp', mathexp => 300}), Ifeffit::Demeter::GDS -> new({type => 'set', name => 'sigmm', mathexp => 0.00052}), ); # ## Path objects for the first 5 paths in copper (3 shell fit) my @pobjects = (); foreach my $i (0 .. 4) { my $j = $i+1; $pobjects[$i] = Ifeffit::Demeter::Path -> new(); $pobjects[$i]->set({data => $dobject, folder => 'example/cu/', file => "feff000$j.dat", s02 => 'amp', e0 => 'enot', delr => 'alpha*reff', sigma2 => 'debye(temp, theta) + sigmm', }); }; # ## Fit object: collection of GDS, Data, and Path objects my $fitobject = Ifeffit::Demeter::Fit -> new({gds => \@gdsobjects, data => [$dobject], paths => \@pobjects, }); ## do the fit (or the sum of paths) $fitobject -> fit; # ## plot the data + fit + paths in a space $plot_features->set({plot_data => 1, plot_fit => 1, plot_res => 0, plot_win => 1,}); foreach my $obj ($dobject, @pobjects,) { $obj -> plot("r"); }; # ## save the results of the fit and write a log file $dobject->save_fit("cufit.fit"); my ($header, $footer) = ("Fit to copper data\n", q{}); $fitobject -> logfile("cufit.log", $header, $footer); This example starts by defining each of the data objects. There is one plot object, one data object, 5 path objects, 5 GDS objects, and one fit object. The "set_mode" method defines how the Ifeffit command generated will be dispatched. After the fit is defined by calling the "fit" method on the Fit object, a number of chores can be done. First, the results of the fit are evaluated. This retrieves best fit values for all GDS parameters from Ifeffit, evaluates all path parameters for all the Path objects, and retrieves the correlations between guess parameters from Ifeffit. Then plots are made, theresults of the fit are saved as an ascii data file, and a log file is written. DESCRIPTION This module provides an object oriented interface to the EXAFS data analysis capabilities of the popular and powerful Ifeffit package. Mindful that the Ifeffit API involves streams of text commands, this package is, at heart, a code generator. Most methods of this package return text. All actual interaction with Ifeffit is handled through a single method, "dispose", which is described below. The typical use of this package is to accumulate text in a scalar variable through successive calls to the various code generating methods. This text is then disposed to Ifeffit, to a file, or elsewhere. This package is aimed at many targets. It can be the back-end of a graphical data analysis program, providing the glue between the on-screen representation of the fit and the actual command executed by Ifeffit. It can be used for one-off data analysis chores -- indeed most of the examples that come with the package can be reworked into useful one-off scripts. It can also be the back-end to sophisticated data analysis chores such as high-throughout data fitting or complex physical modeling. Ifeffit::Demeter is actually a parent class for the objects that are directly manipulated in any real program using Ifeffit::Demeter. These are the major subclasses: Ifeffit::Demeter::Data The data object used to import chi(k) data from a file and set parameters for Fourier transforms, fitting range, and other aspects of the fit. This, in turn, has several major subclasses devoted to specific data processing chores. Ifeffit::Demeter::Path The path object used to define a path in a fit and to set math expressions for its path parameters. Ifeffit::Demeter::GDS The object used to define a guess, def or set parameter for use in the fit. This is also used to define restraints and a few other kinds of parameters. Ifeffit::Demeter::Fit This object is the collection of Data, Path, and GDS objects which compromises a fit. This, in turn, has several subclasses devoted to particular aspects of the fitting problem. Ifeffit::Demeter::Plot The object which controls how plots are made from the other Ifeffit::Demeter objects Ifeffit::Demeter::Atoms A crystallography object which is used to generate the structure data for a Feff object. Ifeffit::Demeter::Feff A object defining the contents of a Feff calculation and providing methods for running parts of Feff. Ifeffit::Demeter::ScatteringPath On object defining a scattering path from a Feff object. This may be linked to a Path object used in a fit. Each of these objects is implemented as an inside-out object, as described in "Perl Best Practices" by Damian Conway () and in the Class::Std and Class::Std::Utils module. Inside-out objects provide complete data encapsolation. This means that the only way to access the data associated with the various objects is to use the methods described below and in the documentation pages for the various subclasses. Additionally, there is an Ifeffit::Demeter::Tools module which provides a variety of useful class methods. METHODS An object of this class represents a part of the problem of interacting with the EXAFS data analysis part of Ifeffit. That component might be data, a path from Feff, a parameter, a fit, or a plot. Because all objects of this class are inside-out objects, complete encapsolation is implemented. The only way to interact with the data associated with each object is through the methods described here and in the documents for each of the sub classes. Not every method shown in the example above is described here. you need to see the subclass documentation for methods specific to those subclasses. Constructor and accessor methods These are the basic methods for constructing objects and accessing their attributes. "new" This the constructor method. It builds and initializes new objects. use Ifeffit::Demeter; $data_object -> Ifeffit::Demeter::Data -> new; $path_object -> Ifeffit::Demeter::Path -> new; $gds_object -> Ifeffit::Demeter::GDS -> new; New can optionally take an argument which is a reference to a hash of attributes and values for the object. See the "set" method for a discussion of why you may not want to pass that hash reference to "new". "clone" This method clones an object, returning the reference to the new object. $newobject = $oldobject->clone(\%new_arguments); Cloning returns the reference and sets all attributes of the new object to the values for the old object. The optional argument is a reference to a hash of those attributes which you wish to change for the new object. Passing this hash reference is equivalent to cloning the object, then calling the "set" method on the new object with that hash reference. "set" This method sets object attributes. $data_object -> set({kmin=>3.1, kmax=>12.7}); $path_object -> set({file=>'feff0123.dat'}); $gds_object -> set({type=>'set'}); The set method of each subclass behaves slightly differently for each subclass. The differences are discussed in the subclass documentation, but they are small. Each subclass takes a hash reference as its argument, as shown above. An exception is thrown is you attempt to "set" an undefined attribute. The argument can be an anonymous hash or a reference to a names hash. The following are equivalent: $data_object -> set({file => "my.data", kmin => 2.5 }); and %hash = {file => "my.data", kmin => 2.5}; $data_object -> set(\%hash); I recommend that you construct and set new objects in separate steps. That is, do this: $data_object = Ifeffit::Demeter::Data -> new; $data_object -> set({group => "data", file => "my.data", kmin => 2.5 }); rather than this: $data_object = Ifeffit::Demeter::Data -> new({group => "data", file => "my.data", kmin => 2.5 }); Both work and both result in the same thing. However, the various objects have considerable amounts of code to validate attribute values. The exceptions that are thrown for invalid code are more useful if you set attributes using the accessor ("set") than if you use the constructor ("new"). Try running these two little snippets: use Ifeffit::Demeter qw(Data); $data_object = Ifeffit::Demeter::Data -> new({kmin=>"x"}); and use Ifeffit::Demeter qw(Data); $data_object = Ifeffit::Demeter::Data -> new; $data_object -> set({kmin=>"x"}); You will see that the error message for the second is much more indicative of where the mistake was made. If you are interested in what loopy, perl-ish thing is going on there, it has to do with the interactions of the Carp and Class::Std modules, both of which are used by Ifeffit::Demeter. On the other hand, you might appreciate the economy of lines of code that come with passing the arguments hash reference directly to the constructor.... "Push" This is used for pushing a value onto the array of an array-valued attribute. In that sense, it is much like perl's push. $atoms_object -> Push({titles=>"another title line"}); This is similar to $atoms_object -> set({titles=>["another title line"]}); but perhaps more convenient. "get" This is the accessor method. It works in scalar or array context. $kmin = $data_object -> get('kmin'); @window_parameters = $data_object -> get(qw(kmin kmax dk kwindow)); See the documentation for each subclass for complete lists of what attributes are available for each subclass. An exception is thrown if you attempt to "get" an undefined attribute. "label" or "name" This is a shortcut accessor for the object label. These are equivalent: $object -> label; $object -> get('label'); for Data, Path (and Feff (and Fit)) objects, as are $gds -> name; $gds -> get('name'); for GDS objects. "name" is an alias for "label". "serialize" Returns the YAML serialization string for the object. See the Fit objects serialize method for complete details of serialization of a fitting model. Data processing methods A system is built into Demeter for keeping track of the state of your objects. It is, therefore, rarely necessary to explicitly invoke the data processing methods. If you call the "plot", Demeter will call the "read_data", "normalize", "fft", and "bft" methods as needed to correctly make the plot. As you change the attributes of the Data object, Demeter will keep track of which data processing stages need to be redone. Consequently, the "plot" method may be the only data processing method you ever need to call. These methods call the corersponding code generating methods then dispose of that code. The code generators are documented below, but should rarely be necessary to call directly. "read_data" This method returns the Ifeffit command for importing data into Ifeffit $command = $data_object->read_data; This method is more commonly used for Data objects. Calling this method on a Path object will import the raw "feffNNNN.dat" file. See the "write_path" method of the Path subclass for importing a "feffNNNN.dat" file and turning it into chi(k) data. "fft" This method performs a forward Fourier transform on your chi(k) data using parameters that have been established using the "set" method. $object -> fft; If the data need to be imported, they will be automatically. "bft" This method performs a backward Fourier transform on your chi(R) data using parameters that have been established using the "set" method. $object -> bft; If the data need to be imported or forward transformed, they will be automatically. "plot" This method plots your data in the indicated space, where the space is one of E, k, R, or q. The details of how that plot is made are determined by the Plot object. $object -> plot($space); If the data need to be imported, forward transformed, or backward transformed, they will be automatically. "save" This saves data or a path as a column data file. $command = $object -> save($argument); The types of saved file, indicated by the argument, are xmu 7 columns: energy, mu(E), bkg(E), pre-edge line, post-edge line, derivative of mu(E), second derivative of mu(E). norm 7 columns: energy, norm(E), bkg(E), flattened mu(E), flattened background, derivative of norm(E), second derivative of norm(E). chi 6 or 7 columns: k, chi(k), window, k*chi(k), k^2*chi(k), k^3*chi(k). If an arbitrary k-weighting is used, an additional column with that k-weighting will be written. R 6 columns: R, real part, imaginary part, magnitude, phase, R window q 7 columns: q, real part, imaginary part, magnitude, phase, k window, k-weighted chi(k) using the k-weighting of the Fourier transform. This last column can be plotted with the real part to make a kq plot. fit 6 or 7 columns: k, chi(k), fit(k), residual, background (if fitted), window. "dispose" This method is used to dispatch Ifeffit commands by hand. It is used internally by many of the methods typically used in a program. $object -> dispose($ifeffit_command); See the document page for Ifeffit::Demeter::Dispose for complete details. Operation modes There are a few attributes of a Demeter application that are set within the base class and so apply to all Demeter objects in use in that application. Most of these attributes have to do with how the command generated by the various Demeter methods get disposed of by the "dispose" method. Here is a list of all these global attributes: ifeffit This is a boolean attribute. When true, the "dispose" method sends commands to the Ifeffit process. By default this is true. screen This is a boolean attribute. When true, the "dispose" method sends commands to STDOUT, which is probably displayed of the screen in a terminal emulator. By default this is false. file When true, the "dispose" method sends commands to a file. The true value of this attribute is interpreted as the file name. The file is opened and closed each time "dispose" is called. Therefore it is probably prudent to give this attribute a value starting with an open angle bracket, such as ">filename". This will result in commands being appended to the end of t he named file. Note also that you will need to unlink the file at the beginning of your script if you do not want your commands appended to the end of an existing file. By default this is false. buffer When true, the "dispose" method stores commands in a memory buffer. The true value of this attribute can either be a reference to a scalar or a reference to an array. If the value is a scalar reference, the commands will be appended to the end of the scalar. If the value is an array reference, each command line (where a line is terminated with a carriage return) will become an entry in the array. By default this is false. plot This attribute is the reference to the current Plot object. When a plot object is created using the normal constructor method, it becomes the value of this attribute. Then the attributes of that Plot object are used whenever plots are made from other kinds of objects. If you create and use a single Plot object in your script, you never really need to be concerned with this attribute. However, if you maintain two or more Plot objects, this attribute is the mechanism for controlling which gets used when plots are made. template_process Set the template set for data processing. Currently in the distribution are "feffit", "ifeffit" and "iff_columns". template_fit Set the template set for data analysis. Currently in the distribution are "feffit", "ifeffit" and "iff_columns". template_plot Set the template set for plotting. Currently in the distribution is "pgplot". template_feff Set the template set for generating feff files. Currently in the distribution are "feff6", "feff7", and "feff8". The methods for accessing the operation modes are: "set_mode" This is the method used to set the attributes described above. Any Demeter object can call this method. Ifeffit::Demeter -> set_mode({ifeffit=>1, screen=>1, buffer=>\@buffer_array}); See Ifeffit::Demeter:Dispose for more details. "get_mode" When called with no arguments, this method returns a hash of all attributes their values. When called with an argument (which must be one of the attributes), it returns the value of that attribute. Any Demeter object can call this method. %hash = Ifeffit::Demeter -> get_mode; $value = Ifeffit::Demeter -> get_mode("screen"); See Ifeffit::Demeter:Dispose for more details. The first time you attempt to access the Plot object contained in the mode hash, a Plot object will be created if one is needed. Convenience methods "config" This returns the Config object. This is a wrapper around "get_mode". The following are equivalent: my $config = $data->get_mode("params"); $config -> set_default("clamp", "medium", 20); and $data -> config -> set_default("clamp", "medium", 20); "po" This returns the Plot object. This is a wrapper around "get_mode". The following are equivalent: my $plot = $data->get_mode("plot"); $plot -> set("c9", 'yellowchiffon3'); and $data -> po -> set("c9", 'yellowchiffon3'); Utility methods Here are a number of methods used internally, but which are available for your use. "title_glob" This pushes the title generated by the "data_parameter_report" or "fit_parameter_report" methods into Ifeffit scalars which can then be accessed by an Ifeffit title glob. $object -> title_glob($name, $which) $name is the base of the name of the string scalars in Ifeffit and $which is one of "e", "n", "k", "r", "q", or "f" depending on whether you wish to generate title lines for mu(E), normalized mu(E), chi(k), chi(R), chi(q), or a fit. "default_k_weight" This returns the value of the default k-weight for a Data or Path object. A Data object can have up to four k-weights associated with it: 1, 2, 3, and an arbitrary value. This method returns the arbitrary value (if it is defined) or the lowest of the three remaining values (if they are defined). If none of the four are defined, this returns 1. For a Path object, the associated Data object is used to determine the return value. An exception is thrown using Carp::carp for other objects and 1 is returned. $kw = $data_object -> default_k_weight; "regexp" This returns an appropriate regular expression. $regexp1 = $object->regexp; $regexp2 = $object->regexp($arg, $bare); When called without an argument, the regular expression returned matches all valid attributes of the object. This regular expression is terminated by the \A and \z metacharacters. When called with an argument, it returns a regular expression (terminated with \A and \z) appropriate to the argument. When called with the second argument, the terminators, \A and \z, are suppressed. The current crop of arguments includes: *commands* All Ifeffit commands. *function* All Ifeffit math functions. *program* All Ifeffit program variables. *window* All Ifeffit window types. *pathparams* All Ifeffit path parameters. *element* All element symbols. *edge* All absorption edges. *feffcards* All feff input file keywords. *separator* The regex matching word separators in atoms or feff input files. *clamp* All descriptive clamp values. *config* All configuration parameter types. *stats* All fitting statistic types. *atoms_lattice* All Atoms keywords related to specifying the lattice. *atoms_gas* All Atoms keywords related to specifying gases in ion chambers. *atoms_obsolete* All deprecated Atoms keywords from earlier versions. *spacegroup* All keys from the space groups database. "get_array" Read an array from Ifeffit. The argument is the Ifeffit array suffix of the array to import. @array = $data->get_array("xmu"); "floor_ceil" Return a two element list containingthe smallest and largest values of an array in Ifeffit. ($min, $max) = $data->floor_ceil("xmu"); "yofx" Return the y value corresponding to an given x-value. This is found by interpolation from the specified array. $y = $data->yofx("xmu", q{}, $x); The second argument ("q{}") in this example, is used to specify a part of a fit, i.e. "bkg" or "res". "parameter_list" This method returns a list of all attributes of the object. The list is sorted asciibetically. @list = $object->parameter_list; "hashes" This returns a string which can be used as a comment character in Ifeffit. The idea is that every comment included in the commands generated by methods of this class use this string. That provides a way of distinguishing comments generated by the methods of this class from other comment lines sent to Ifeffit. This is a user interface convenience. $string = $object->hashes; print "$string\n"; ==> ###___ "plottable" This returns a true value if the object is one that can be plotted. Currently, Data and Path objects return a true value. All others return false. $can_plot = $object -> plottable; DIAGNOSTICS CONFIGURATION AND ENVIRONMENT See Ifeffit::Demeter::Config for details about the configuration system. DEPENDENCIES The dependencies of the Ifeffit::Demeter system are in the Bundle/DemeterBundle.pm file. BUGS AND LIMITATIONS * Templates need their own pod document. * Serialization is only partly implemented at this time. Please report problems to Bruce Ravel (bravel AT bnl DOT gov) Patches are welcome. AUTHOR Bruce Ravel (bravel AT bnl DOT gov) http://cars9.uchicago.edu/~ravel/software/ LICENCE AND COPYRIGHT Copyright (c) 2006-2008 Bruce Ravel (bravel AT bnl DOT gov). All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. 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.