[Ifeffit] status: potential surface scanning

Bruce Ravel ravel at phys.washington.edu
Mon Jul 28 10:21:34 CDT 2003


On Monday 28 July 2003 10:48 am, Norbert Weiher wrote:
> I know there are some good PERL hackers around. So do you have an
> idea how to do this? Recursion shurely helps - I experimented a lot
> with it but it still does not do what I need it to do. Just for your
> convenience: I stored the parameters in an array of hashes, so that
> I can have something like
> 
> $shell[0]{E0} = $something
> $shell[0]{dr} = $somethingelse...
> 
> So the loop for one shell is just looping through the hashkeys of
> element 0 of this array...

Hi Norbert,

I am not certain that I understand the problem as you explained it,
but it seems that what you need to do is to harvest the entire list of
parameters that need to be varied from the array of hashes.  Your data
structure (the AoH) is an excellent one for storing the data, but
isn't the right one for exploring the surface.  Probably there is no
single data structure that will do everything you want, so you end up
needing to spend time shuffling data between different structures.

Initially define @shell as a zero-length array like so:

  my @shell = ();

Perl will autovivify new array elements as needed.  Thus, for a one
shell fit, you will do

  $shell[0]{e0}   = $parameter_1;
  $shell[0]{delr} = $parameter_2;
  ##  and so on...

When and if you need a second shell, the next array element will spring
into existance whenever you do something like this:

  $shell[1]{e0}   = $parameter_N;

and will *not* spring into existence *unless* you do something like
that.
  
To get a list of all the parameters, try this:

  my @parameter_list = ();
  foreach my $i (0 .. $#shells) {
    foreach my $k (keys %{$shell[$i]}) {
       push @parameter_list, $shell[$i]{$k};
    };
  };

This little idiom will fill @parameter_list with all the parameters
with no prior knowledge of how many shells you actually defined.
Indeed, you can add such things as the third cumulant and Ei to the
fit without fretting that @parameter_list will miss them.

You can also do clever things like checking $shell[$i]{$k} against the
current contents of @parameter_list.  This will allow you to use the
same parameter for, say, e0 for each path without varying it against
itself when you go to measure the surface.  (Use recipe 4.6 in "The
Perl Cookbook" by Christiansen and Torkington -- highly recommended if
you do not already have a copy.  I usually use the solution labeled
"faster but different".)

HTH,
B

P.S. The object oriented programming purist would insist that you
     should create an object based on your array of hashes and define
     a method to return the list of parameters.  That's not wrong and
     it's highly reusable, but it may be overkill for your current
     project.  In any case, all the method would do is shuffle data
     between data structures using nested foreach loops.

  
-- 
 Bruce Ravel  ----------------------------------- ravel at phys.washington.edu
 Code 6134, Building 3, Room 222
 Naval Research Laboratory                          phone: (1) 202 767 5947
 Washington DC 20375, USA                             fax: (1) 202 767 1697

 NRL Synchrotron Radiation Consortium (NRL-SRC)
 Beamlines X11a, X11b, X23b, X24c, U4b
 National Synchrotron Light Source
 Brookhaven National Laboratory, Upton, NY 11973

 My homepage:    http://feff.phys.washington.edu/~ravel 
 EXAFS software: http://feff.phys.washington.edu/~ravel/software/exafs/



More information about the Ifeffit mailing list