Ifeffit::Demeter - OO interface to Ifeffit for EXAFS data analysis
This documentation refers to Ifeffit::Demeter version 0.0.1
Import Demeter components into your program:
use Ifeffit::Demeter qw(Data); use Ifeffit::Demeter qw(:all); use Ifeffit::Demeter;
The first example imports only the Data component. The second and thrid lines are equivalent and import all Demeter components into your program. The components are Plot, Data, Path, GDS, Fit. Importing the Fit component forces the import of the Data, Path, and GDS components.
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.
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 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:
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.
The path object used to define a feffNNNN.dat file from Feff and to
set math expressions for its path parameters.
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.
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.
The object which controls how plots are made from the other Ifeffit::Demeter objects
Each of these objects is implemented as an inside-out object, as described in ``Perl Best Practices'' by Damian Conway (http://www.oreilly.com/catalog/perlbp/) and in the the Class::Std manpage and the Class::Std::Utils manpage 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 the Ifeffit::Demeter::Tools manpage module which provides a variety of useful utilities as normal, rightside-out class methods.
At this time, there is not a Feff object, although that will be coming along eventually, allowing for fine-grained control of running and interpreting Feff from within the Demeter system.
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.
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 qw(:all); $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});
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
});
%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....
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 is
you attempt to get an undefined attribute.
label
This is a shortcut accessor for the object label. It is equivalent to
$object -> get('label');
for Data, Path (and Feff (and Fit)) objects, and to
$gds -> get('name');
for GDS objects.
serialize
Returns the YAML serialization string for the object. See the Fit objects serialize method for complete details of serialization of a fitting model.
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.
$object -> fft;
bft
This method performs a backward Fourier transform on your chi(R) data.
$object -> bft;
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);
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
7 columns: energy, mu(E), bkg(E), pre-edge line, post-edge line, derivative of mu(E), second derivative of mu(E).
7 columns: energy, norm(E), bkg(E), flattened mu(E), flattened background, derivative of norm(E), second derivative of norm(E).
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.
6 columns: R, real part, imaginary part, magnitude, phase, R window
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.
6 or 7 columns: k, chi(k), fit(k), residual, background (if fitted), window.
For the sake of complete documentation, here are the methods that generate Ifeffit code without disposing of that code. These all return a string containing the Ifeffit code. Each one is called by the corresponding data processing method, which in turn disposes of the code. These are also called by the display method, which then disposes of them.
_read_data_command
This generates the code for importing a file using Ifeffit's read_data()
command. The argument is either ``xmu'', ``chi'', or ``feff.dat''.
$string = $self->_read_data_command($type)
_fft_command
This generates the code for doing a forward transform using Ifeffit's fftf()
command.
$string = $self->_fft_command()
_bft_command
This generates the code for doing a backward transform using Ifeffit's fftb()
command.
$string = $self->_fft_command()
_plot_command
This generates the code for plotting something using Ifeffit's newplot() or
plot() command. The argument is the space of the plot.
$string = $self->_plot_command($space)
_plotk_command
This generates the code for plotting something in k-space using Ifeffit's
newplot() or plot() command.
$string = $self->_plotk_command()
_plotR_command
This generates the code for plotting something in R-space using Ifeffit's
newplot() or plot() command.
$string = $self->_plotR_command()
_plotq_command
This generates the code for plotting something in q-space using Ifeffit's
newplot() or plot() command.
$string = $self->_plotq_command()
display
This convenience method is a wrapper around the _read_data_command,
_fft_command, _bft_command, and _plot_command methods.
$object -> display($space, [qw(data fit res win)]);
This method makes no use of the mechanism for keeping objects up to
date. If you want to plot an object is R-space, this method will
return Ifeffit commands for reading the data, doing a background
removal (for mu(E) data), doing a Fourier transform, and plotting.
If the object is a Data object, you can also specify which part of the
data to display. The parts are data, fit, res, bkg, and
win. These represent the data, the fit (or the summation), the
residual, the background function, and the Foruier transform window,
respectively.
disposeThis 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.
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:
This is a boolean attribute. When true, the dispose method sends commands
to the Ifeffit process. By default this is true.
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.
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.
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.
deprecated
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.
Currently in the distribution are ifeffit and iff_columns.
Currently in the distribution are ifeffit and iff_columns.
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});
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");
Here are a number of methods used internally, but which are available for your use.
title_glob
$object -> title_glob($name, $
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);
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. The current crop of arguments includes:
get_array
floor_ceil
yofx
match all ifeffit commands
match all valid mathematical functions for use in math expressions
match all program variables in Ifeffit, wh9ich are treated by Demeter as reserved words for the sake of naming GDS objects.
match all valid window types
match all valid path parameters
math all 1 or 2 letter element symbols
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.
$can_plot = $object -> plottable;
Discuss templating system. List of required templates. How to pass parameters to the templates. Which templates expect which parameters.
See the Ifeffit::Demeter::Config manpage for details about the configuration system.
The dependencies of the Ifeffit::Demeter system are in the Bundle/DemeterBundle.pm file.
A graceful interface between Path and ScatteringPath objects has not yet been written.
Templates need their own pod document.
Atoms has not been incorporated into Demeter yet.
Serialization is only partly implemented at this time.
Configuration is only partly implemented at this time.
See the file `notes/notes' from the SVN repository for a complete
list of chores in the queue for Demeter.
Please report problems to Bruce Ravel (bravel AT anl DOT gov)
Patches are welcome.
Bruce Ravel (bravel AT anl DOT gov)
http://cars9.uchicago.edu/~ravel/software/
Copyright (c) 2006-2007 Bruce Ravel (bravel AT anl 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.