[Ifeffit] Rebinning
Carlo U. Segre
segre at iit.edu
Tue Mar 11 12:16:24 CST 2003
Matt and Bruce:
Following our previous discussion of rebinning continuous scan data, I am
attaching a python code fragment which we use to perform this function.
You are free to use it as you like. It was written by Ken McIvor, a
student at IIT as part of a larger project to manipulate and preview
MR-CAT XAFS data. We simply pulled out the code and annotated it
somewhat.
Carlo
--
Carlo U. Segre -- Professor of Physics
Associate Dean for Research, Armour College
Illinois Institute of Technology
Voice: 312.567.3498 Fax: 312.567.3494
Carlo.Segre at iit.edu http://www.iit.edu/~segre
-------------- next part --------------
# Name: rebin-alg.py
# Purpose: An algorithm to perform XAFS data reduction.
# Author: Ken McIvor <mcivken at iit.edu>
#
# Copyright 2003 Illinois Institute of Technology
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL ILLINOIS INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of Illinois Institute
# of Technology shall not be used in advertising or otherwise to promote
# the sale, use or other dealings in this Software without prior written
# authorization from Illinois Institute of Technology.
import math
import bisect
import Numeric
def grid(start, stop, stepSize):
"""Create an array which can be used as an abscissa for interpolation.
Returns an array of regular values, increasing by 'stepSize', which go from
'start' to 'stop' inclusively.
"""
r = Numeric.arange(start, stop + stepSize, stepSize)
while r[-1] > stop:
r = r[:-1]
if r[-1] < stop:
r = Numeric.resize(r, (r.shape[0]+1, ) )
r[-1] = stop
return r
def rebin(data, eColumn, Eo, after, kstep, file='', msgStream=None):
"""XAFS data reduction.
'data' is a Numerical Python matrix (rank 2 array) which contains the XAFS
data to be reduced. 'eColumn' is the column index of the energy values of
each point. 'Eo' is the edge energy of the data.
All points for which the energy is greater than 'Eo'+'after' are
reduced to a new set of points in which the energy varies in
equally-spaced steps in k-space, defined by 'kstep'.
'file' is the file name corresponding to this data set, and if specified
will be used in any exceptions raised by this functions.
If 'msgStream' is specified it must be an output stream (an object
implementing a write() method), which will used to print status
information.
"""
# if file is specified, reformat it for use in error messages
if file:
file = '[%s] ' % file
# acquire the energy vector of the data and find its minimum and maximum
E = data[:,eColumn]
Min, Max = min(E), max(E)
if Max <= Eo:
raise RebinError, (
'%sno energy values larger than Eo (incomplete data set?)'
% file)
# start rebinning points at Eo+after
start = Eo + after
if Max <= start:
raise RebinError, '%sthe value of "after" is too large' % file
# find the index of the energy vector which corresponds to the start point
startPoint = bisect.bisect_left(E, start)
# slice the energy vector and data matrix to get the points for rebinning
eRange = E[startPoint:]
dataRange = data[startPoint:, :]
if msgStream:
msgStream.write('%s%d points in E from %.4f to %.4f (Eo = %.4f)\n' %
(file, eRange.shape[0], start, Max, Eo))
def k(E, Eo=Eo):
"""Calculate K for some energy level E, using the edge energy argument
passed to rebin().
"""
return 0.512 * math.sqrt(E - Eo)
# Generate the regular k-space abscissa that will be rebined to.
# grid(start, end, step) returns a vector of values from 'start' to 'end'
# by 'step', inclusive.
kgrid = grid(k(start), k(Max), kstep)
if msgStream:
msgStream.write(
'%srebinning to %d points in k-space from %.4f to %.4f\n'
% (file, kgrid.shape[0], kgrid[0], kgrid[-1]))
# newData is matrix which is BINCOUNT-1 rows long and contains the same
# number of columns as the data matrix. It accumulates the sums of the
# points which fall in each bin
newData = Numeric.zeros((kgrid.shape[0]-1, data.shape[1]), data.typecode())
# binCounts is a vector of BINCOUNT elements, which accumulates the number
# of points that fall in each bin
binCounts = Numeric.zeros( (newData.shape[0],) , data.typecode())
for i in range(0, eRange.shape[0]):
# locate the index of the bin in which the current energy level falls
where = bisect.bisect_right(kgrid, k(eRange[i])) - 1
if where == newData.shape[0]:
where = where - 1
# bin the data
newData[where] += dataRange[i]
binCounts[where] += 1
# check that all of the bins contain data
for i in range(0, newData.shape[0]):
if binCounts[i] == 0:
raise RebinError, ('%sbin %d (%.4f < k < %.4f) is empty'
% (file, i, kgrid[i], kgrid[i+1]))
# average the binned points
for i in range(0, newData.shape[0]):
newData[i,:] /= binCounts[i]
# The length of E[0:startPoint] is the number of points which were not
# rebinned. The result matrix will contain that many rows plus one row for
# each bin.
Len = E[0:startPoint].shape[0] + newData.shape[0]
# create a new matrix to hold the final result
result = Numeric.zeros((Len, data.shape[1]), data.typecode())
# copy unrebinned and rebinned data into the result matrix
result[0:startPoint, :] = data[0:startPoint, :]
result[startPoint:, :] = newData
return result
More information about the Ifeffit
mailing list