NAME

Ifeffit::Demeter - OO interface to Ifeffit for EXAFS data analysis


VERSION

This documentation refers to Ifeffit::Demeter version 0.0.1


SYNOPSIS

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.


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 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 Ifeffit::Demeter::Data manpage

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 Ifeffit::Demeter::Path manpage

The path object used to define a feffNNNN.dat file from Feff and to set math expressions for its path parameters.

the Ifeffit::Demeter::GDS manpage

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.

the Ifeffit::Demeter::Fit manpage

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 Ifeffit::Demeter::Plot manpage

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.


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.

Object handling 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 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.

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.

  $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

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.

Code generating methods

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.

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.

process
  deprecated
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

Currently in the distribution are ifeffit and iff_columns.

template_fit

Currently in the distribution are ifeffit and iff_columns.

template_plot

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");

Utility methods

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
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;


TEMPLATES

Discuss templating system. List of required templates. How to pass parameters to the templates. Which templates expect which parameters.


DIAGNOSTICS


CONFIGURATION AND ENVIRONMENT

See the Ifeffit::Demeter::Config manpage for details about the configuration system.


DEPENDENCIES

The dependencies of the Ifeffit::Demeter system are in the Bundle/DemeterBundle.pm file.


BUGS AND LIMITATIONS

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.


AUTHOR

Bruce Ravel (bravel AT anl DOT gov)

http://cars9.uchicago.edu/~ravel/software/


LICENCE AND COPYRIGHT

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.