def __init__(self, dim=1, id=None, **kwargs): """ Object constructor. @param dim: The desired dimension for the spectral data @type dim: C{int} @param id: The pixel ID of the spectral data @type id: various @param kwargs: A list of keyword arguments that the class accepts: @keyword construct: Flag to switch on the creation of the C{NessiList}s for the independent and dependent axes. @type construct: C{boolean} """ try: construct = kwargs["construct"] except KeyError: construct = False if construct: self.y = nessi_list.NessiList() self.var_y = nessi_list.NessiList() else: self.y = None self.var_y = None self.id = id self.axis = [] for i in range(dim): self.axis.append(PrimaryAxis(i + 1, **kwargs)) self.__dim = dim
def calc_deltat_over_t(axis, axis_err2=None): """ This function takes a TOF axis and calculates the quantity Delta t / t for every element. @param axis: The TOF axis from which Delta t / t will be calculated @type axis: C{nessi_list.NessiList} @param axis_err2: (OPTIONAL) The error^2 on the incoming TOF axis @type axis_err2: C{nessi_list.NessiList} @return: The calculated Delta t / t @rtype: C{SOM.SOM} """ import nessi_list # Check to see if incoming is really a NessiList try: axis.__type__ except AttributeError: raise RuntimeError("The object passed to this function needs to be a "\ +"NessiList. Do not understand how to deal with "\ +"%s" % type(axis)) len_axis = len(axis) if axis_err2 is None: axis_err2 = nessi_list.NessiList(len_axis) deltat = nessi_list.NessiList() deltat_err2 = nessi_list.NessiList() # Calculate bin deltas, assume axis in ascending order for i in xrange(len_axis - 1): deltat.append(axis[i + 1] - axis[i]) deltat_err2.append(axis_err2[i + 1] - axis_err2[i]) # Calculate bin centers import utils (binc, binc_err2) = utils.calc_bin_centers(axis, axis_err2) # Calculate delta t / t import array_manip dtot = array_manip.div_ncerr(deltat, deltat_err2, binc, binc_err2) import SOM som = SOM.SOM() so = SOM.SO() so.y = dtot[0] so.var_y = dtot[1] som.append(so) som.setDataSetType("density") som.setYLabel("deltat_over_t") return som
def calc_EQ_Jacobian_dgs(*args): """ This function calculates the area of a polygon for use in the application of the Jacobian for DGS S(Q,E) data. @param args: A list of parameters used to calculate the area The following is a list of the arguments needed in their expected order 1. E_1 2. Q_1 3. E_2 4. Q_2 5. E_3 6. Q_3 7. E_4 8. Q_4 @type args: C{list} @return: The polygon areas @rtype: (C{nessi_list.NessiList}, C{nessi_list.NessiList}) """ import nessi_list import utils # Settle out the arguments to sensible names E1 = args[0] Q1 = args[1] E2 = args[2] Q2 = args[3] E3 = args[4] Q3 = args[5] E4 = args[6] Q4 = args[7] poly_size = 4 area = nessi_list.NessiList(len(E1)) area_err2 = nessi_list.NessiList(len(E1)) import itertools xvals = [xvals for xvals in itertools.izip(E1, E2, E3, E4, E1, E2)] yvals = [yvals for yvals in itertools.izip(Q1, Q2, Q3, Q4, Q1, Q2)] for x, y, i in itertools.izip(xvals, yvals, itertools.count()): xn = nessi_list.NessiList() xn.extend(x) yn = nessi_list.NessiList() yn.extend(y) area[i] = utils.calc_area_2D_polygon(xn, yn, poly_size) return (area, area_err2)
def make_axis_file(filename, **kwargs): """ This function takes a file of minimum, maximum and a delta values and converts those numbers into an axis. @param filename: Name of the file containing the axis values @type filename: C{string} @param kwargs: A list of keyword arguments that the function accepts: @keyword type: The type of axis desired. Type can be I{histogram}, I{coordinate} or I{density} (the last two are synonyms). If type is not provided the default is I{histogram} @type type: C{string} @return: The axis generated from the file information @rtype: C{nessi_list.NessiList} @raise RuntimeError: The type provided via kwarg type is not I{histogram} or I{density} or I{coordinate} """ import math import nessi_list axis = nessi_list.NessiList() ifile = open(filename, "r") alllines = ifile.readlines() for eachline in alllines: values = eachline.split(',') axis_min = float(values[0]) axis_max = float(values[1]) delta = float(values[2]) n_bins = int(math.fabs(axis_max - axis_min) / delta) for i in range(n_bins): axis.append(axis_min + i * delta) axis_max = float(alllines[-1].split(',')[1]) try: if(kwargs["type"] == "histogram"): axis.append(axis_max) elif(kwargs["type"] == "density" or kwargs["type"] == "coordinate"): pass else: raise RuntimeError("Do not understand type: %s" % kwargs["type"]) except KeyError: axis.append(axis_max) return axis
def getdata(handle, dims, use_slabs=False): if not use_slabs: data = nessi_list.NessiList(type="double") return sns_napi.getdata(handle, data) data = nessi_list.NessiList(type="double") for x in range(dims[0]): for y in range(dims[1]): slab = nessi_list.NessiList(type="double") start = (x, y, 0) stop = (1, 1, dims[2]) #x,y,dims[2]) print start, stop, slab = sns_napi.getslab(handle, start, stop) print slab data.extend(slab) print len(data), data return data
def make_axis(axis_min, axis_max, delta, **kwargs): """ This function takes a minimum, maximum and a delta value and converts those numbers into an axis. @param axis_min: The minimum value of the axis @type axis_min: C{float} @param axis_max: The maximum value of the axis @type axis_max: C{float} @param delta: The bin width for the axis @type delta: C{float} @param kwargs: A list of keyword arguments that the function accepts: @keyword type: The type of axis desired. Type can be I{histogram}, I{coordinate} or I{density} (the last two are synonyms). If type is not provided the default is I{histogram} @type type: C{string} @return: The axis generated from the file information @rtype: C{nessi_list.NessiList} @raise RuntimeError: The type provided via kwarg type is not I{histogram} or I{density} or I{coordinate} """ import math import nessi_list n_bins = int(math.fabs(axis_max - axis_min) / delta) axis = nessi_list.NessiList() for i in range(n_bins): axis.append(axis_min + i * delta) try: if(kwargs["type"] == "histogram"): axis.append(axis_max) elif(kwargs["type"] == "density" or kwargs["type"] == "coordinate"): pass else: raise RuntimeError("Do not understand type: %s" % kwargs["type"]) except KeyError: axis.append(axis_max) return axis
def get_err2(obj, index, descr=None, axis="y", pap=0): """ This function takes an arbitrary object and returns the uncertainty squared for the given index. If the object is not a collection the index is ignored. @param obj: Object from which to retrieve error^2 @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple} @param index: A possible index for use in a C{SOM} @type index: C{int} @param descr: (OPTIONAL) The object descriptor, default is C{None} @type descr: C{string} @param axis: (OPTIONAL) The axis from which to grab the error^2 @type axis: C{string}=<y or x> @param pap: (OPTIONAL) The primary axis position. This is used to pull the error^2 from the correct axis position in a multidimensional object. @type pap: C{int} @return: The appropriate object containing the error^2 @rtype: C{nessi_list.NessiList} or C{float} @raise TypeError: obj is not a recognized type """ if descr is None: obj_type = get_type(obj) else: obj_type = descr if obj_type == SOM_type: return get_err2(obj[index], index, "SO", axis, pap) elif obj_type == SO_type: if axis.lower() == "y": return obj.var_y elif axis.lower() == "x": if obj.axis[pap].var is None: return nessi_list.NessiList(len(obj.axis[pap].val)) else: return obj.axis[pap].var elif obj_type == list_type: return get_err2(obj[index], index, "number", axis, pap) elif obj_type == num_type: return obj[1] else: raise TypeError("Object type not recognized by get_err2 function.")
def __init__(self, id=1, **kwargs): """ Object constructor. @param id: The index ID of the independent axis @type id: C{int} @param kwargs: A list of keyword arguments that the class accepts: @keyword construct: Flag to switch on the creation of the C{NessiList}s @type construct: C{boolean} @keyword withVar: Flag to turn on use of square uncertainties. Should be used in conjunction with I{construct}. @type withVar: C{boolean} """ try: construct = kwargs["construct"] except KeyError: construct = False try: withVar = kwargs["withVar"] except KeyError: withVar = False if construct: self.val = nessi_list.NessiList() else: self.val = None if withVar: if construct: self.var = nessi_list.NessiList() else: self.var = None else: self.var = None self.pid = id
def toNessiList(self, type="histogram"): """ This method provides a mechanism for the class to generate a C{NessiList} axis based on the information contained within the C{Axis} object. The type parameter sets additional data depending on type. The main types of data are I{histogram} or I{density} (also I{coordinate}). @param type: The axis data type: I{histogram} or I{density} @type type: C{string} """ import nessi_list axis = nessi_list.NessiList() if self.__bintype == "lin": return self.__do_linear(type, axis) elif self.__bintype == "log": return self.__do_logarithmic(type, axis) else: raise RuntimeError("Have no method for creating axis of type %s" \ % self.__bintype)
def zero_bins(obj, z_bins): """ This function takes spectra and a set of bins and zeros the values in each spectrum at the bin location. @param obj: The object containing the spectra to be zeroed @type obj: C{SOM.SOM} @param z_bins: The set of bins from a given spectrum that will be zeroed @type z_bins: C{list} of C{int}s @return: Object containing the spectra with zeroed bins @rtype: C{SOM.SOM} @raise TypeError: The first argument is not a C{SOM} or C{SO} """ # Kickout if there are no bins to zero if z_bins is None: return obj # import the helper functions import hlr_utils # set up for working through data (result, res_descr) = hlr_utils.empty_result(obj) o_descr = hlr_utils.get_descr(obj) if o_descr == "number" or o_descr == "list": raise TypeError("First argument must be a SOM or a SO!") # Have a SOM or SO, go on else: pass result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr) # iterate through the values import nessi_list for i in xrange(hlr_utils.get_length(obj)): map_so = hlr_utils.get_map_so(obj, None, i) # Get information from SOM y_val = hlr_utils.get_value(obj, i, o_descr, "y") y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y") y_new = nessi_list.NessiList() var_y_new = nessi_list.NessiList() for j in xrange(len(y_val)): if j in z_bins: y_new.append(0.0) var_y_new.append(0.0) else: y_new.append(y_val[j]) var_y_new.append(y_err2[j]) hlr_utils.result_insert(result, res_descr, (y_new, var_y_new), map_so, "y") return result
def run(config): """ This method is where the plot processing gets done. @param config: Object containing the configuration information. @type config: L{hlr_utils.Configure} """ import dr_lib import nessi_list import numpy if config.data is None: raise RuntimeError("Need to pass a data filename(s) to the driver "\ +"script.") dst_type = hlr_utils.file_peeker(config.data[0]) if dst_type != "text/num-info": raise RuntimeError("Cannot handle DST type: %s" % dst_type) (bank_map, offset) = make_bank_map(config.data) num_banks = len(bank_map) len_x = config.num_tubes * num_banks len_data = config.num_pixels * len_x grid = nessi_list.NessiList(len_data) run_number = -1 instrument = "" for datafile in config.data: instrument = datafile.split('_')[0] d_som = dr_lib.add_files([datafile], dst_type=dst_type, Verbose=config.verbose) run_number = d_som.attr_list["normalization-run_number"] for so in d_som: bank_offset = bank_map[so.id[0]] # index = y + Ny * (x + b * Nx) index = so.id[1][1] + config.num_pixels * (so.id[1][0] + bank_offset * config.num_tubes) grid[index] = so.y del d_som # if run number is a list, it's separated by / run_number = run_number.split('/')[0] z = numpy.reshape(grid.toNumPy(), (len_x, config.num_pixels)) x = numpy.arange(len_x) y = numpy.arange(config.num_pixels) title = "%s %s" % (instrument, run_number) import matplotlib.cm as mcm if config.cmb: colormap = mcm.Blues else: colormap = mcm.hot figure = pylab.figure() figure.subplots_adjust(left=0.085, right=0.95) drplot.plot_2D_arr(x, y, numpy.transpose(z), ylabel="Pixel Number", xlabel="Bank Number", title=title, logz=config.logz, colormap=colormap, nocb=True) # Clip view so tube grid is correct pylab.xlim(0, x.shape[0]) pylab.ylim(0, y.shape[0]) # Set grid lines to dilineate the banks tl = [str(i+1) for i in range(offset, offset+num_banks+1)] drplot.grid_setter(locator=num_banks, ticklabels=tl, rotation='vertical') if config.pixel_grid: # Set some grid lines for the pixels drplot.grid_setter(axis="y", linestyle="-.") pylab.colorbar(orientation="horizontal", fraction=0.05, format=config.format) pylab.show()
def run(config, tim=None): """ This method is where the processing is done. @param config: Object containing the driver configuration information. @type config: L{hlr_utils.Configure} @param tim: (OPTIONAL) Object that will allow the method to perform timing evaluations. @type tim: C{sns_time.DiffTime} """ if config.data is None: raise RuntimeError("Need to pass a data filename to the driver "\ +"script.") dst_type = hlr_utils.file_peeker(config.data[0]) if dst_type != "text/Dave2d": raise TypeError("Only Dave2D ASCII files can be handled. Do not "\ +"know how to handle %s." % dst_type) import nessi_list import SOM import bisect if tim is not None: tim.getTime(False) old_time = tim.getOldTime() is_init = False Q_axis = None E_axis = None len_Q = 0 len_E = 0 so_id = None lo_val = -999 hi_val = -999 scan = nessi_list.NessiList() scan_err2 = nessi_list.NessiList() # Object to hold integrated data for each temperature scan result = SOM.SOM() result.attr_list["filename"] = config.data result.setAllAxisLabels(["Q", "T"]) result.setAllAxisUnits(["1/Angstroms", "Kelvin"]) result.setYLabel("Integral") result.setYUnits("") result.setDataSetType("density") int_so = SOM.SO() # Read in all data files for datafile in config.data: som = dr_lib.add_files([datafile], dst_type=dst_type, Verbose=config.verbose) if not is_init: Q_axis = som[0].axis[0].val len_Q = len(Q_axis) E_axis = som[0].axis[1].val len_E = len(E_axis) so_id = som[0].id int_so.id = so_id int_so.axis[0].val = E_axis lo_val = bisect.bisect_left(E_axis, config.int_range[0]) hi_val = bisect.bisect_left(E_axis, config.int_range[1]) for i in xrange(len_Q): int_so.y = som[0].y[i * len_E:(i + 1) * len_E] int_so.var_y = som[0].var_y[i * len_E:(i + 1) * len_E] value = dr_lib.integrate_axis_py(int_so, start=lo_val, end=hi_val) scan.append(value[0]) scan_err2.append(value[1]) is_init = True # Reorient data to make groups of temps for a single Q bin final_data = nessi_list.NessiList() final_data_err2 = nessi_list.NessiList() scann = scan.toNumPy() scann_err2 = scan_err2.toNumPy() import itertools for i in xrange(len_Q): sslice = scann[i::len_Q] sslice_err2 = scann_err2[i::len_Q] for val, err in itertools.izip(sslice, sslice_err2): final_data.append(val) final_data_err2.append(err) # Create placeholder for combined spectrum so = SOM.SO(2) so.id = so_id so.y = final_data so.var_y = final_data_err2 so.axis[0].val = Q_axis temp = nessi_list.NessiList() temp.extend(config.temps) so.axis[1].val = temp result.append(so) hlr_utils.write_file(config.output, "text/Dave2d", result, verbose=config.verbose, replace_ext=False, axis_ok=True, path_replacement=config.path_replacement, message="combined file") result.attr_list["config"] = config hlr_utils.write_file(config.output, "text/rmd", result, output_ext="rmd", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="metadata") if tim is not None: tim.setOldTime(old_time) tim.getTime(msg="Total Running Time")
@rtype: C{string} """ import os result = [] for key in self.__info_hash: result.append("%s: %s" % (key, str(self.__info_hash[key]))) return os.linesep.join(result) if __name__ == "__main__": import nessi_list val = nessi_list.NessiList() err2 = nessi_list.NessiList() val.extend(1.0, 2.0) err2.extend(0.5, 0.4) info1 = Information(val, None, "meter", "ZSelector") print "Info:", info1 info2 = Information(val, err2, "meter", "ZSelector") comp = CompositeInformation("bank1", info1, "bank2", info2) print "CompInfo:", comp
o_som[0].var_y = frac_area_err2 # Write out summed fractional area into file hlr_utils.write_file(config.output, "text/Spec", o_som, output_ext="fra", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="fractional area") return result if __name__ == "__main__": import hlr_test som1 = hlr_test.generate_som() axis = nessi_list.NessiList() axis.extend(0, 2.5, 5) print "********** SOM1" print "* ", som1[0] print "* ", som1[1] print "********** sum_by_rebin_frac" print "* rebin som:", sum_by_rebin_frac(som1, axis) print "* rebin so :", sum_by_rebin_frac(som1[0], axis)
def create_Qvec_vs_E_dgs(som, E_i, conf, **kwargs): """ This function starts with the energy transfer axis from DGS reduction and turns this into a 4D spectra with Qx, Qy, Qz and Et axes. @param som: The input object with initial IGS wavelength axis @type som: C{SOM.SOM} @param E_i: The initial energy for the given data. @type E_i: C{tuple} @param conf: Object that contains the current setup of the driver. @type conf: L{hlr_utils.Configure} @param kwargs: A list of keyword arguments that the function accepts: @keyword timer: Timing object so the function can perform timing estimates. @type timer: C{sns_timer.DiffTime} @keyword corner_angles: The object that contains the corner geometry information. @type corner_angles: C{dict} @keyword make_fixed: A flag that turns on writing the fixed grid mesh information to a file. @type make_fixed: C{boolean} @keyword output: The output filename and or directory. @type output: C{string} """ import array_manip import axis_manip import common_lib import hlr_utils import os # Check keywords try: t = kwargs["timer"] except KeyError: t = None corner_angles = kwargs["corner_angles"] try: make_fixed = kwargs["make_fixed"] except KeyError: make_fixed = False try: output = kwargs["output"] except KeyError: output = None # Convert initial energy to initial wavevector l_i = common_lib.energy_to_wavelength(E_i) k_i = common_lib.wavelength_to_scalar_k(l_i) # Since all the data is rebinned to the same energy transfer axis, we can # calculate the final energy axis once E_t = som[0].axis[0].val if som[0].axis[0].var is not None: E_t_err2 = som[0].axis[0].var else: import nessi_list E_t_err2 = nessi_list.NessiList(len(E_t)) E_f = array_manip.sub_ncerr(E_i[0], E_i[1], E_t, E_t_err2) # Check for negative final energies which will cause problems with # wavelength conversion due to square root if E_f[0][-1] < 0: E_f[0].reverse() E_f[1].reverse() index = 0 for E in E_f[0]: if E >= 0: break index += 1 E_f[0].__delslice__(0, index) E_f[1].__delslice__(0, index) E_f[0].reverse() E_f[1].reverse() len_E = len(E_f[0]) - 1 # Now we can get the final wavevector l_f = axis_manip.energy_to_wavelength(E_f[0], E_f[1]) k_f = axis_manip.wavelength_to_scalar_k(l_f[0], l_f[1]) # Grab the instrument from the som inst = som.attr_list.instrument if make_fixed: import SOM fixed_grid = {} for key in corner_angles: so_id = SOM.NeXusId.fromString(key).toTuple() try: pathlength = inst.get_secondary(so_id)[0] points = [] for j in range(4): points.extend( __calc_xyz(pathlength, corner_angles[key].getPolar(j), corner_angles[key].getAzimuthal(j))) fixed_grid[key] = points except KeyError: # Pixel ID is not in instrument geometry pass CNT = {} ERR2 = {} V1 = {} V2 = {} V3 = {} V4 = {} # Output positions for Qx, Qy, Qz coordinates X = 0 Y = 2 Z = 4 if t is not None: t.getTime(False) # Iterate though the data len_som = hlr_utils.get_length(som) for i in xrange(len_som): map_so = hlr_utils.get_map_so(som, None, i) yval = hlr_utils.get_value(som, i, "SOM", "y") yerr2 = hlr_utils.get_err2(som, i, "SOM", "y") CNT[str(map_so.id)] = yval ERR2[str(map_so.id)] = yerr2 cangles = corner_angles[str(map_so.id)] Q1 = axis_manip.init_scatt_wavevector_to_Q(k_i[0], k_i[1], k_f[0], k_f[1], cangles.getAzimuthal(0), 0.0, cangles.getPolar(0), 0.0) V1[str(map_so.id)] = {} V1[str(map_so.id)]["x"] = Q1[X] V1[str(map_so.id)]["y"] = Q1[Y] V1[str(map_so.id)]["z"] = Q1[Z] Q2 = axis_manip.init_scatt_wavevector_to_Q(k_i[0], k_i[1], k_f[0], k_f[1], cangles.getAzimuthal(1), 0.0, cangles.getPolar(1), 0.0) V2[str(map_so.id)] = {} V2[str(map_so.id)]["x"] = Q2[X] V2[str(map_so.id)]["y"] = Q2[Y] V2[str(map_so.id)]["z"] = Q2[Z] Q3 = axis_manip.init_scatt_wavevector_to_Q(k_i[0], k_i[1], k_f[0], k_f[1], cangles.getAzimuthal(2), 0.0, cangles.getPolar(2), 0.0) V3[str(map_so.id)] = {} V3[str(map_so.id)]["x"] = Q3[X] V3[str(map_so.id)]["y"] = Q3[Y] V3[str(map_so.id)]["z"] = Q3[Z] Q4 = axis_manip.init_scatt_wavevector_to_Q(k_i[0], k_i[1], k_f[0], k_f[1], cangles.getAzimuthal(3), 0.0, cangles.getPolar(3), 0.0) V4[str(map_so.id)] = {} V4[str(map_so.id)]["x"] = Q4[X] V4[str(map_so.id)]["y"] = Q4[Y] V4[str(map_so.id)]["z"] = Q4[Z] if t is not None: t.getTime(msg="After calculating verticies ") # Form the messages if t is not None: t.getTime(False) jobstr = 'MR' + hlr_utils.create_binner_string(conf) + 'JH' num_lines = len(CNT) * len_E linestr = str(num_lines) if output is not None: outdir = os.path.dirname(output) if outdir != '': if outdir.rfind('.') != -1: outdir = "" else: outdir = "" value = str(som.attr_list["data-run_number"].getValue()).split('/') topdir = os.path.join(outdir, value[0].strip() + "-mesh") try: os.mkdir(topdir) except OSError: pass outtag = os.path.basename(output) if outtag.rfind('.') == -1: outtag = "" else: outtag = outtag.split('.')[0] if outtag != "": filehead = outtag + "_bmesh" if make_fixed: filehead1 = outtag + "_fgrid" filehead2 = outtag + "_conf" else: filehead = "bmesh" if make_fixed: filehead1 = "fgrid" filehead2 = "conf" hfile = open(os.path.join(topdir, "%s.in" % filehead2), "w") print >> hfile, jobstr print >> hfile, linestr hfile.close() import utils use_zero_supp = not conf.no_zero_supp for k in xrange(len_E): ofile = open(os.path.join(topdir, "%s%04d.in" % (filehead, k)), "w") if make_fixed: ofile1 = open(os.path.join(topdir, "%s%04d.in" % (filehead1, k)), "w") for pid in CNT: if use_zero_supp: write_value = not utils.compare(CNT[pid][k], 0.0) == 0 else: write_value = True if write_value: result = [] result.append(str(k)) result.append(str(E_t[k])) result.append(str(E_t[k + 1])) result.append(str(CNT[pid][k])) result.append(str(ERR2[pid][k])) __get_coords(V1, pid, k, result) __get_coords(V2, pid, k, result) __get_coords(V3, pid, k, result) __get_coords(V4, pid, k, result) __get_coords(V1, pid, k + 1, result) __get_coords(V2, pid, k + 1, result) __get_coords(V3, pid, k + 1, result) __get_coords(V4, pid, k + 1, result) print >> ofile, " ".join(result) if make_fixed: result1 = [] result1.append(str(k)) result1.append(str(E_t[k])) result1.append(str(E_t[k + 1])) result1.append(str(CNT[pid][k])) result1.append(str(ERR2[pid][k])) result1.extend([str(x) for x in fixed_grid[pid]]) print >> ofile1, " ".join(result1) ofile.close() if make_fixed: ofile1.close() if t is not None: t.getTime(msg="After creating messages ")
def feff_correct_mon(obj, **kwargs): """ This function takes in a monitor spectra, calculates efficiencies based on the montior's wavelength axis and divides the monitor counts by the calculated efficiencies. The function is a M{constant * wavelength}. @param obj: Object containing monitor spectra @type obj: C{SOM.SOM} or C{SOM.SO} @param kwargs: A list of keyword arguments that the function accepts: @keyword units: The expected units for this function. The default for this function is I{Angstroms}. @type units: C{string} @keyword eff_const: Use this provided effieciency constant. The default is (0.00000085 / 1.8) Angstroms^-1. @type eff_const: L{hlr_utils.DrParameter} @keyword inst_name: The short name of an instrument. @type inst_name: C{string} @return: Efficiency corrected monitor spectra @rtype: C{SOM.SOM} or C{SOM.SO} """ # import the helper functions import hlr_utils if obj is None: return obj # set up for working through data (result, res_descr) = hlr_utils.empty_result(obj) o_descr = hlr_utils.get_descr(obj) # Setup keyword arguments try: units = kwargs["units"] except KeyError: units = "Angstroms" try: eff_const = kwargs["eff_const"] except KeyError: # This is for SNS (specifically BASIS) monitors eff_const = hlr_utils.DrParameter((0.00000085 / 1.8), 0.0, "Angstroms^-1") # A^-1 inst_name = kwargs.get("inst_name") # Primary axis for transformation. If a SO is passed, the function, will # assume the axis for transformation is at the 0 position if o_descr == "SOM": axis = hlr_utils.one_d_units(obj, units) else: axis = 0 result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr) # iterate through the values import array_manip import nessi_list import dr_lib for i in xrange(hlr_utils.get_length(obj)): val = hlr_utils.get_value(obj, i, o_descr, "x", axis) map_so = hlr_utils.get_map_so(obj, None, i) if inst_name is None: eff = nessi_list.NessiList() for j in xrange(len(val) - 1): bin_center = (val[j + 1] + val[j]) / 2.0 eff.append(eff_const.getValue() * bin_center) eff_err2 = nessi_list.NessiList(len(eff)) else: if inst_name == "SANS": (eff, eff_err2) = dr_lib.subexp_eff(eff_const, val) else: raise RuntimeError("Do not know how to handle %s instrument" \ % inst_name) y_val = hlr_utils.get_value(obj, i, o_descr, "y") y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y") value = array_manip.div_ncerr(y_val, y_err2, eff, eff_err2) hlr_utils.result_insert(result, res_descr, value, map_so, "y") return result
def getslab(handle, start, size): data = sns_napi.getslab(handle, start, size) nessi_data = nessi_list.NessiList() nessi_data.__array__.__set_from_NessiVector__(nessi_data.__array__, data) return nessi_data
def create_E_vs_Q_igs(som, *args, **kwargs): """ This function starts with the initial IGS wavelength axis and turns this into a 2D spectra with E and Q axes. @param som: The input object with initial IGS wavelength axis @type som: C{SOM.SOM} @param args: A mandatory list of axes for rebinning. There is a particular order to them. They should be present in the following order: Without errors 1. Energy transfer 2. Momentum transfer With errors 1. Energy transfer 2. Energy transfer error^2 3. Momentum transfer 4. Momentum transfer error ^2 @type args: C{nessi_list.NessiList}s @param kwargs: A list of keyword arguments that the function accepts: @keyword withXVar: Flag for whether the function should be expecting the associated axes to have errors. The default value will be I{False}. @type withXVar: C{boolean} @keyword data_type: Name of the data type which can be either I{histogram}, I{density} or I{coordinate}. The default value will be I{histogram} @type data_type: C{string} @keyword Q_filter: Flag to turn on or off Q filtering. The default behavior is I{True}. @type Q_filter: C{boolean} @keyword so_id: The identifier represents a number, string, tuple or other object that describes the resulting C{SO} @type so_id: C{int}, C{string}, C{tuple}, C{pixel ID} @keyword y_label: The y axis label @type y_label: C{string} @keyword y_units: The y axis units @type y_units: C{string} @keyword x_labels: This is a list of names that sets the individual x axis labels @type x_labels: C{list} of C{string}s @keyword x_units: This is a list of names that sets the individual x axis units @type x_units: C{list} of C{string}s @keyword split: This flag causes the counts and the fractional area to be written out into separate files. @type split: C{boolean} @keyword configure: This is the object containing the driver configuration. @type configure: C{Configure} @return: Object containing a 2D C{SO} with E and Q axes @rtype: C{SOM.SOM} @raise RuntimeError: Anything other than a C{SOM} is passed to the function @raise RuntimeError: An instrument is not contained in the C{SOM} """ import nessi_list # Setup some variables dim = 2 N_y = [] N_tot = 1 N_args = len(args) # Get T0 slope in order to calculate dT = dT_i + dT_0 try: t_0_slope = som.attr_list["Time_zero_slope"][0] t_0_slope_err2 = som.attr_list["Time_zero_slope"][1] except KeyError: t_0_slope = float(0.0) t_0_slope_err2 = float(0.0) # Check withXVar keyword argument and also check number of given args. # Set xvar to the appropriate value try: value = kwargs["withXVar"] if value.lower() == "true": if N_args != 4: raise RuntimeError("Since you have requested x errors, 4 x "\ +"axes must be provided.") else: xvar = True elif value.lower() == "false": if N_args != 2: raise RuntimeError("Since you did not requested x errors, 2 "\ +"x axes must be provided.") else: xvar = False else: raise RuntimeError("Do not understand given parameter %s" % \ value) except KeyError: if N_args != 2: raise RuntimeError("Since you did not requested x errors, 2 "\ +"x axes must be provided.") else: xvar = False # Check dataType keyword argument. An offset will be set to 1 for the # histogram type and 0 for either density or coordinate try: data_type = kwargs["data_type"] if data_type.lower() == "histogram": offset = 1 elif data_type.lower() == "density" or \ data_type.lower() == "coordinate": offset = 0 else: raise RuntimeError("Do not understand data type given: %s" % \ data_type) # Default is offset for histogram except KeyError: offset = 1 try: Q_filter = kwargs["Q_filter"] except KeyError: Q_filter = True # Check for split keyword try: split = kwargs["split"] except KeyError: split = False # Check for configure keyword try: configure = kwargs["configure"] except KeyError: configure = None so_dim = SOM.SO(dim) for i in range(dim): # Set the x-axis arguments from the *args list into the new SO if not xvar: # Axis positions are 1 (Q) and 0 (E) position = dim - i - 1 so_dim.axis[i].val = args[position] else: # Axis positions are 2 (Q), 3 (eQ), 0 (E), 1 (eE) position = dim - 2 * i so_dim.axis[i].val = args[position] so_dim.axis[i].var = args[position + 1] # Set individual value axis sizes (not x-axis size) N_y.append(len(args[position]) - offset) # Calculate total 2D array size N_tot = N_tot * N_y[-1] # Create y and var_y lists from total 2D size so_dim.y = nessi_list.NessiList(N_tot) so_dim.var_y = nessi_list.NessiList(N_tot) # Create area sum and errors for the area sum lists from total 2D size area_sum = nessi_list.NessiList(N_tot) area_sum_err2 = nessi_list.NessiList(N_tot) # Create area sum and errors for the area sum lists from total 2D size bin_count = nessi_list.NessiList(N_tot) bin_count_err2 = nessi_list.NessiList(N_tot) inst = som.attr_list.instrument lambda_final = som.attr_list["Wavelength_final"] inst_name = inst.get_name() import bisect import math import dr_lib import utils arr_len = 0 #: Vector of zeros for function calculations zero_vec = None for j in xrange(hlr_utils.get_length(som)): # Get counts counts = hlr_utils.get_value(som, j, "SOM", "y") counts_err2 = hlr_utils.get_err2(som, j, "SOM", "y") arr_len = len(counts) zero_vec = nessi_list.NessiList(arr_len) # Get mapping SO map_so = hlr_utils.get_map_so(som, None, j) # Get lambda_i l_i = hlr_utils.get_value(som, j, "SOM", "x") l_i_err2 = hlr_utils.get_err2(som, j, "SOM", "x") # Get lambda_f from instrument information l_f_tuple = hlr_utils.get_special(lambda_final, map_so) l_f = l_f_tuple[0] l_f_err2 = l_f_tuple[1] # Get source to sample distance (L_s, L_s_err2) = hlr_utils.get_parameter("primary", map_so, inst) # Get sample to detector distance L_d_tuple = hlr_utils.get_parameter("secondary", map_so, inst) L_d = L_d_tuple[0] # Get polar angle from instrument information (angle, angle_err2) = hlr_utils.get_parameter("polar", map_so, inst) # Get the detector pixel height dh_tuple = hlr_utils.get_parameter("dh", map_so, inst) dh = dh_tuple[0] # Need dh in units of Angstrom dh *= 1e10 # Calculate T_i (T_i, T_i_err2) = axis_manip.wavelength_to_tof(l_i, l_i_err2, L_s, L_s_err2) # Scale counts by lambda_f / lambda_i (l_i_bc, l_i_bc_err2) = utils.calc_bin_centers(l_i, l_i_err2) (ratio, ratio_err2) = array_manip.div_ncerr(l_f, l_f_err2, l_i_bc, l_i_bc_err2) (counts, counts_err2) = array_manip.mult_ncerr(counts, counts_err2, ratio, ratio_err2) # Calculate E_i (E_i, E_i_err2) = axis_manip.wavelength_to_energy(l_i, l_i_err2) # Calculate E_f (E_f, E_f_err2) = axis_manip.wavelength_to_energy(l_f, l_f_err2) # Calculate E_t (E_t, E_t_err2) = array_manip.sub_ncerr(E_i, E_i_err2, E_f, E_f_err2) if inst_name == "BSS": # Convert E_t from meV to ueV (E_t, E_t_err2) = array_manip.mult_ncerr(E_t, E_t_err2, 1000.0, 0.0) (counts, counts_err2) = array_manip.mult_ncerr(counts, counts_err2, 1.0 / 1000.0, 0.0) # Convert lambda_i to k_i (k_i, k_i_err2) = axis_manip.wavelength_to_scalar_k(l_i, l_i_err2) # Convert lambda_f to k_f (k_f, k_f_err2) = axis_manip.wavelength_to_scalar_k(l_f, l_f_err2) # Convert k_i and k_f to Q (Q, Q_err2) = axis_manip.init_scatt_wavevector_to_scalar_Q( k_i, k_i_err2, k_f, k_f_err2, angle, angle_err2) # Calculate dT = dT_0 + dT_i dT_i = utils.calc_bin_widths(T_i, T_i_err2) (l_i_bw, l_i_bw_err2) = utils.calc_bin_widths(l_i, l_i_err2) dT_0 = array_manip.mult_ncerr(l_i_bw, l_i_bw_err2, t_0_slope, t_0_slope_err2) dT_tuple = array_manip.add_ncerr(dT_i[0], dT_i[1], dT_0[0], dT_0[1]) dT = dT_tuple[0] # Calculate Jacobian if inst_name == "BSS": (x_1, x_2, x_3, x_4) = dr_lib.calc_BSS_coeffs( map_so, inst, (E_i, E_i_err2), (Q, Q_err2), (k_i, k_i_err2), (T_i, T_i_err2), dh, angle, E_f, k_f, l_f, L_s, L_d, t_0_slope, zero_vec) else: raise RuntimeError("Do not know how to calculate x_i "\ +"coefficients for instrument %s" % inst_name) (A, A_err2) = dr_lib.calc_EQ_Jacobian(x_1, x_2, x_3, x_4, dT, dh, zero_vec) # Apply Jacobian: C/dlam * dlam / A(EQ) = C/EQ (jac_ratio, jac_ratio_err2) = array_manip.div_ncerr(l_i_bw, l_i_bw_err2, A, A_err2) (counts, counts_err2) = array_manip.mult_ncerr(counts, counts_err2, jac_ratio, jac_ratio_err2) # Reverse counts, E_t, k_i and Q E_t = axis_manip.reverse_array_cp(E_t) E_t_err2 = axis_manip.reverse_array_cp(E_t_err2) Q = axis_manip.reverse_array_cp(Q) Q_err2 = axis_manip.reverse_array_cp(Q_err2) counts = axis_manip.reverse_array_cp(counts) counts_err2 = axis_manip.reverse_array_cp(counts_err2) k_i = axis_manip.reverse_array_cp(k_i) x_1 = axis_manip.reverse_array_cp(x_1) x_2 = axis_manip.reverse_array_cp(x_2) x_3 = axis_manip.reverse_array_cp(x_3) x_4 = axis_manip.reverse_array_cp(x_4) dT = axis_manip.reverse_array_cp(dT) # Filter for duplicate Q values if Q_filter: k_i_cutoff = k_f * math.cos(angle) k_i_cutbin = bisect.bisect(k_i, k_i_cutoff) counts.__delslice__(0, k_i_cutbin) counts_err2.__delslice__(0, k_i_cutbin) Q.__delslice__(0, k_i_cutbin) Q_err2.__delslice__(0, k_i_cutbin) E_t.__delslice__(0, k_i_cutbin) E_t_err2.__delslice__(0, k_i_cutbin) x_1.__delslice__(0, k_i_cutbin) x_2.__delslice__(0, k_i_cutbin) x_3.__delslice__(0, k_i_cutbin) x_4.__delslice__(0, k_i_cutbin) dT.__delslice__(0, k_i_cutbin) zero_vec.__delslice__(0, k_i_cutbin) try: if inst_name == "BSS": ((Q_1, E_t_1), (Q_2, E_t_2), (Q_3, E_t_3), (Q_4, E_t_4)) = dr_lib.calc_BSS_EQ_verticies( (E_t, E_t_err2), (Q, Q_err2), x_1, x_2, x_3, x_4, dT, dh, zero_vec) else: raise RuntimeError("Do not know how to calculate (Q_i, "\ +"E_t_i) verticies for instrument %s" \ % inst_name) except IndexError: # All the data got Q filtered, move on continue try: (y_2d, y_2d_err2, area_new, bin_count_new) = axis_manip.rebin_2D_quad_to_rectlin( Q_1, E_t_1, Q_2, E_t_2, Q_3, E_t_3, Q_4, E_t_4, counts, counts_err2, so_dim.axis[0].val, so_dim.axis[1].val) except IndexError, e: # Get the offending index from the error message index = int(str(e).split()[1].split('index')[-1].strip('[]')) print "Id:", map_so.id print "Index:", index print "Verticies: %f, %f, %f, %f, %f, %f, %f, %f" % ( Q_1[index], E_t_1[index], Q_2[index], E_t_2[index], Q_3[index], E_t_3[index], Q_4[index], E_t_4[index]) raise IndexError(str(e)) # Add in together with previous results (so_dim.y, so_dim.var_y) = array_manip.add_ncerr(so_dim.y, so_dim.var_y, y_2d, y_2d_err2) (area_sum, area_sum_err2) = array_manip.add_ncerr(area_sum, area_sum_err2, area_new, area_sum_err2) if configure.dump_pix_contrib or configure.scale_sqe: if inst_name == "BSS": dOmega = dr_lib.calc_BSS_solid_angle(map_so, inst) (bin_count_new, bin_count_err2) = array_manip.mult_ncerr( bin_count_new, bin_count_err2, dOmega, 0.0) (bin_count, bin_count_err2) = array_manip.add_ncerr( bin_count, bin_count_err2, bin_count_new, bin_count_err2) else: del bin_count_new
def create_E_vs_Q_dgs(som, E_i, Q_final, **kwargs): """ This function starts with the rebinned energy transfer and turns this into a 2D spectra with E and Q axes for DGS instruments. @param som: The input object with initial IGS wavelength axis @type som: C{SOM.SOM} @param E_i: The initial energy for the given data. @type E_i: C{tuple} @param Q_final: The momentum transfer axis to rebin the data to @type Q_final: C{nessi_list.NessiList} @param kwargs: A list of keyword arguments that the function accepts: @keyword corner_angles: The object that contains the corner geometry information. @type corner_angles: C{dict} @keyword so_id: The identifier represents a number, string, tuple or other object that describes the resulting C{SO} @type so_id: C{int}, C{string}, C{tuple}, C{pixel ID} @keyword y_label: The y axis label @type y_label: C{string} @keyword y_units: The y axis units @type y_units: C{string} @keyword x_labels: This is a list of names that sets the individual x axis labels @type x_labels: C{list} of C{string}s @keyword x_units: This is a list of names that sets the individual x axis units @type x_units: C{list} of C{string}s @keyword split: This flag causes the counts and the fractional area to be written out into separate files. @type split: C{boolean} @keyword configure: This is the object containing the driver configuration. @type configure: C{Configure} @return: Object containing a 2D C{SO} with E and Q axes @rtype: C{SOM.SOM} """ import array_manip import axis_manip import common_lib import hlr_utils import nessi_list import SOM import utils # Check for keywords corner_angles = kwargs["corner_angles"] configure = kwargs.get("configure") split = kwargs.get("split", False) # Setup output object so_dim = SOM.SO(2) so_dim.axis[0].val = Q_final so_dim.axis[1].val = som[0].axis[0].val # E_t # Calculate total 2D array size N_tot = (len(so_dim.axis[0].val) - 1) * (len(so_dim.axis[1].val) - 1) # Create y and var_y lists from total 2D size so_dim.y = nessi_list.NessiList(N_tot) so_dim.var_y = nessi_list.NessiList(N_tot) # Create area sum and errors for the area sum lists from total 2D size area_sum = nessi_list.NessiList(N_tot) area_sum_err2 = nessi_list.NessiList(N_tot) # Convert initial energy to initial wavevector l_i = common_lib.energy_to_wavelength(E_i) k_i = common_lib.wavelength_to_scalar_k(l_i) # Since all the data is rebinned to the same energy transfer axis, we can # calculate the final energy axis once E_t = som[0].axis[0].val if som[0].axis[0].var is not None: E_t_err2 = som[0].axis[0].var else: E_t_err2 = nessi_list.NessiList(len(E_t)) # Get the bin width arrays from E_t (E_t_bw, E_t_bw_err2) = utils.calc_bin_widths(E_t) E_f = array_manip.sub_ncerr(E_i[0], E_i[1], E_t, E_t_err2) # Now we can get the final wavevector l_f = axis_manip.energy_to_wavelength(E_f[0], E_f[1]) k_f = axis_manip.wavelength_to_scalar_k(l_f[0], l_f[1]) # Output position for Q X = 0 # Iterate though the data len_som = hlr_utils.get_length(som) for i in xrange(len_som): map_so = hlr_utils.get_map_so(som, None, i) yval = hlr_utils.get_value(som, i, "SOM", "y") yerr2 = hlr_utils.get_err2(som, i, "SOM", "y") cangles = corner_angles[str(map_so.id)] avg_theta1 = (cangles.getPolar(0) + cangles.getPolar(1)) / 2.0 avg_theta2 = (cangles.getPolar(2) + cangles.getPolar(3)) / 2.0 Q1 = axis_manip.init_scatt_wavevector_to_scalar_Q( k_i[0], k_i[1], k_f[0][:-1], k_f[1][:-1], avg_theta2, 0.0) Q2 = axis_manip.init_scatt_wavevector_to_scalar_Q( k_i[0], k_i[1], k_f[0][:-1], k_f[1][:-1], avg_theta1, 0.0) Q3 = axis_manip.init_scatt_wavevector_to_scalar_Q( k_i[0], k_i[1], k_f[0][1:], k_f[1][1:], avg_theta1, 0.0) Q4 = axis_manip.init_scatt_wavevector_to_scalar_Q( k_i[0], k_i[1], k_f[0][1:], k_f[1][1:], avg_theta2, 0.0) # Calculate the area of the E,Q polygons (A, A_err2) = utils.calc_eq_jacobian_dgs(E_t[:-1], E_t[:-1], E_t[1:], E_t[1:], Q1[X], Q2[X], Q3[X], Q4[X]) # Apply the Jacobian: C/dE_t * dE_t / A(EQ) = C/A(EQ) (jac_ratio, jac_ratio_err2) = array_manip.div_ncerr(E_t_bw, E_t_bw_err2, A, A_err2) (counts, counts_err2) = array_manip.mult_ncerr(yval, yerr2, jac_ratio, jac_ratio_err2) try: (y_2d, y_2d_err2, area_new, bin_count) = axis_manip.rebin_2D_quad_to_rectlin( Q1[X], E_t[:-1], Q2[X], E_t[:-1], Q3[X], E_t[1:], Q4[X], E_t[1:], counts, counts_err2, so_dim.axis[0].val, so_dim.axis[1].val) del bin_count except IndexError, e: # Get the offending index from the error message index = int(str(e).split()[1].split('index')[-1].strip('[]')) print "Id:", map_so.id print "Index:", index print "Verticies: %f, %f, %f, %f, %f, %f, %f, %f" % ( Q1[X][index], E_t[:-1][index], Q2[X][index], E_t[:-1][index], Q3[X][index], E_t[1:][index], Q4[X][index], E_t[1:][index]) raise IndexError(str(e)) # Add in together with previous results (so_dim.y, so_dim.var_y) = array_manip.add_ncerr(so_dim.y, so_dim.var_y, y_2d, y_2d_err2) (area_sum, area_sum_err2) = array_manip.add_ncerr(area_sum, area_sum_err2, area_new, area_sum_err2)
def calculate_ref_background(obj, no_bkg, inst, peak_excl, **kwargs): """ This function takes a set of reflectometer data spectra in TOF, slices the data along TOF channels, fits a linear function to the slice to determine the background and then reassembles the slice back into TOF spectra. @param obj: Object containing data spectra @type obj: C{SOM.SOM} or C{SOM.SO} @param no_bkg: Flag for actually requesting a background calculation @type no_bkg: C{boolean} @param inst: String containing the reflectometer short name @type inst: C{string} (I{REF_L} or I{REF_M}) @param peak_excl: The bounding pixel IDs for peak exclusion from fit @type peak_excl: C{tuple} containging the minimum and maximum pixel ID @param kwargs: A list of keyword arguments that the function accepts: @keyword aobj: An alternate data object containing the sizing information for the constructed background spectra. @type aobj: C{SOM.SOM} or C{SOM.SO} @return: Background spectra @rtype: C{SOM.SOM} """ if obj is None: return None if no_bkg: return None # import the helper functions import hlr_utils # Setup instrument specific stuff if inst == "REF_L": inst_pix_id = 1 elif inst == "REF_M": inst_pix_id = 0 else: raise RuntimeError("Do not know how to deal with instrument %s" % inst) # Check keywords try: aobj = kwargs["aobj"] except KeyError: aobj = None # set up for working through data (result, res_descr) = hlr_utils.empty_result(obj) o_descr = hlr_utils.get_descr(obj) result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr) # Set spectrum object to obtain background SOs from if aobj is None: bobj = obj else: bobj = aobj # Get the number of spectra for background calculation len_som = len(obj) # Get the number of spectra for final background object if aobj is None: len_bsom = len(obj) else: len_bsom = len(aobj) # Get the number of TOF channels len_tof = len(obj[0]) # Create blank SOs for background spectra so_list = [] import nessi_list import SOM import utils # Setup pixel axes pix_axis = nessi_list.NessiList() if peak_excl is not None: pix_axis_no_peak = nessi_list.NessiList() # Fill pixel axes and background SOs for k in xrange(len_bsom): map_so = hlr_utils.get_map_so(bobj, None, k) cur_pix_id = map_so.id[1][inst_pix_id] pix_axis.append(cur_pix_id) if peak_excl is not None: if cur_pix_id < peak_excl[0] or cur_pix_id > peak_excl[1]: pix_axis_no_peak.append(cur_pix_id) so = SOM.SO() hlr_utils.result_insert(so, "SO", map_so, None, "all") so_list.append(so) # Slice data, calculate weighted average and repackage spectra for i in xrange(len_tof): sliced_data = nessi_list.NessiList() sliced_data_err2 = nessi_list.NessiList() for j in xrange(len_som): obj1 = hlr_utils.get_value(obj, j, o_descr, "all") cur_pix_id = obj1.id[1][inst_pix_id] if peak_excl is None: filter_pixel = False else: if cur_pix_id < peak_excl[0] or cur_pix_id > peak_excl[1]: filter_pixel = False else: filter_pixel = True if not filter_pixel: if not (utils.compare(obj1.var_y[i], 0.0) == 0 and \ utils.compare(obj1.y[i], 0.0) == 0): sliced_data.append(obj1.y[i]) sliced_data_err2.append(obj1.var_y[i]) len_fit = len(sliced_data) if not len_fit: value = (0.0, 0.0) else: value = utils.weighted_average(sliced_data, sliced_data_err2, 0, len_fit - 1) for j in xrange(len_bsom): so_list[j].y[i] = value[0] so_list[j].var_y[i] = value[1] for m in xrange(len_bsom): hlr_utils.result_insert(result, res_descr, so_list[m], None, "all") return result
def rebin_axis_1D_linint(obj, axis_out): """ This function rebins the primary axis for a C{SOM} or a C{SO} based on the given C{NessiList} axis using a linear interpolation scheme. @param obj: Object to be rebinned @type obj: C{SOM.SOM} or C{SOM.SO} @param axis_out: The axis to rebin the C{SOM} or C{SO} to @type axis_out: C{NessiList} @return: Object that has been rebinned according to the provided axis @rtype: C{SOM.SOM} or C{SOM.SO} @raise TypeError: The rebinning axis given is not a C{NessiList} @raise TypeError: The object being rebinned is not a C{SOM} or a C{SO} """ # import the helper functions import hlr_utils # set up for working through data try: axis_out.__type__ except AttributeError: raise TypeError("Rebinning axis must be a NessiList!") o_descr = hlr_utils.get_descr(obj) if o_descr == "number" or o_descr == "list": raise TypeError("Do not know how to handle given type: %s" % \ o_descr) else: pass (result, res_descr) = hlr_utils.empty_result(obj) result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr) # Axis out never changes xvals = [] xvals.append(axis_out) # Need a vector of zeros for the next function call len_axis_out = len(axis_out) zero_vec = nessi_list.NessiList(len_axis_out) import utils bin_centers = utils.calc_bin_centers(axis_out, zero_vec) # iterate through the values for i in xrange(hlr_utils.get_length(obj)): axis_in = hlr_utils.get_value(obj, i, o_descr, "x", 0) axis_in_err2 = hlr_utils.get_err2(obj, i, o_descr, "x", 0) axis_in_bc = utils.calc_bin_centers(axis_in, axis_in_err2) val = hlr_utils.get_value(obj, i, o_descr) err2 = hlr_utils.get_err2(obj, i, o_descr) map_so = hlr_utils.get_map_so(obj, None, i) # Set zero errors to 1 for linear fit for j in xrange(len(err2)): if utils.compare(err2[j], 0.0) == 0 and \ utils.compare(val[j], 0.0) == 0: err2[j] = 1.0 # Create new NessiLists for rebinned values rebin_val = nessi_list.NessiList() rebin_err2 = nessi_list.NessiList() for k in xrange(len_axis_out - 1): index_pair = hlr_utils.bisect_helper(axis_in, axis_out[k], axis_out[k + 1]) # Requested range is outside axis boundaries if index_pair[0] == -1 and index_pair[1] == -1: rebin_val.append(0.0) rebin_err2.append(0.0) continue # If there is only one value, just use it directly if index_pair[0] == index_pair[1]: rebin_val.append(val[index_pair[0]]) rebin_err2.append(err2[index_pair[0]]) else: # Do linear interpolation fit_params = utils.fit_linear_background( axis_in_bc[0], val, err2, index_pair[0], index_pair[1]) # Evaluate the interpolation at the rebin axis bin center eval_out = utils.eval_linear_fit(bin_centers[0][k:k + 1], bin_centers[1][k:k + 1], fit_params["slope"][0], fit_params["slope"][1], fit_params["intercept"][0], fit_params["intercept"][1]) rebin_val.append(eval_out[0][0]) # Use a geometric average for the error bars new_err2 = 0.0 count = 0 for m in xrange(index_pair[0], index_pair[1] + 1): if utils.compare(val[m], 0.0) == 0: continue else: new_err2 += err2[m] count += 1 if count: new_err2 /= float(count) rebin_err2.append(new_err2) # Do one last clean up for n in xrange(len(rebin_val)): if utils.compare(rebin_val[n], 0.0) == 0: rebin_err2[n] = 0.0 hlr_utils.result_insert(result, res_descr, (rebin_val, rebin_err2), map_so, "all", 0, xvals) return result
def run(config): """ This method is where the processing is done. @param config: Object containing the driver configuration information. @type config: L{hlr_utils.Configure} """ if config.data is None: raise RuntimeError("Need to pass a data filename to the driver "\ +"script.") dst_type = hlr_utils.file_peeker(config.data[0]) if dst_type != "text/Dave2d": raise TypeError("Only Dave2D ASCII files can be handled. Do not "\ +"know how to handle %s." % dst_type) spectra = [] # Read in all data files for datafile in config.data: spectra.append( dr_lib.add_files([datafile], dst_type=dst_type, Verbose=config.verbose)) # Sort spectra on slowest axis (Q for BSS files) spectra.sort(lambda x, y: cmp(x[0].axis[0].val[0], y[0].axis[0].val[0])) # Create placeholder for combined spectrum Ny = len(spectra) Nx = len(spectra[0][0].axis[1].val) import nessi_list import SOM result = SOM.SOM() result = hlr_utils.copy_som_attr(result, "SOM", spectra[0], "SOM") so = SOM.SO(2) so.id = 0 so.y = nessi_list.NessiList(Nx * Ny) so.var_y = nessi_list.NessiList(Nx * Ny) so.axis[1].val = spectra[0][0].axis[1].val # Make the slowest axis slow_axis = [x[0].axis[0].val[0] for x in spectra] so.axis[0].val = nessi_list.NessiList() so.axis[0].val.extend(slow_axis) # Create combined spectrum import array_manip for i in xrange(Ny): value = hlr_utils.get_value(spectra[i], 0, "SOM", "y") err2 = hlr_utils.get_err2(spectra[i], 0, "SOM", "y") start = i * Nx (so.y, so.var_y) = array_manip.add_ncerr(so.y, so.var_y, value, err2, a_start=start) result.append(so) # Rescale data if necessary if config.rescale is not None: import common_lib result2 = common_lib.mult_ncerr(result, (config.rescale, 0.0)) else: result2 = result del result hlr_utils.write_file(config.output, dst_type, result2, verbose=config.verbose, replace_ext=False, path_replacement=config.path_replacement, axis_ok=True, message="combined file")
def run(config, tim): """ This method is where the data reduction process gets done. @param config: Object containing the data reduction configuration information. @type config: L{hlr_utils.Configure} @param tim: Object that will allow the method to perform timing evaluations. @type tim: C{sns_time.DiffTime} """ import DST import math if config.inst == "REF_M": import axis_manip import utils if tim is not None: tim.getTime(False) old_time = tim.getOldTime() if config.data is None: raise RuntimeError("Need to pass a data filename to the driver "\ +"script.") # Read in sample data geometry if one is provided if config.data_inst_geom is not None: if config.verbose: print "Reading in sample data instrument geometry file" data_inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.data_inst_geom) else: data_inst_geom_dst = None # Read in normalization data geometry if one is provided if config.norm_inst_geom is not None: if config.verbose: print "Reading in normalization instrument geometry file" norm_inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.norm_inst_geom) else: norm_inst_geom_dst = None # Perform Steps 1-6 on sample data d_som1 = dr_lib.process_ref_data(config.data, config, config.data_roi_file, config.dbkg_roi_file, config.no_bkg, tof_cuts=config.tof_cuts, inst_geom_dst=data_inst_geom_dst, timer=tim) # Perform Steps 1-6 on normalization data if config.norm is not None: n_som1 = dr_lib.process_ref_data(config.norm, config, config.norm_roi_file, config.nbkg_roi_file, config.no_norm_bkg, dataset_type="norm", tof_cuts=config.tof_cuts, inst_geom_dst=norm_inst_geom_dst, timer=tim) else: n_som1 = None if config.Q_bins is None and config.scatt_angle is not None: import copy tof_axis = copy.deepcopy(d_som1[0].axis[0].val) # Closing sample data instrument geometry file if data_inst_geom_dst is not None: data_inst_geom_dst.release_resource() # Closing normalization data instrument geometry file if norm_inst_geom_dst is not None: norm_inst_geom_dst.release_resource() # Step 7: Sum all normalization spectra together if config.norm is not None: n_som2 = dr_lib.sum_all_spectra(n_som1) else: n_som2 = None del n_som1 # Step 8: Divide data by normalization if config.verbose and config.norm is not None: print "Scale data by normalization" if config.norm is not None: d_som2 = common_lib.div_ncerr(d_som1, n_som2, length_one_som=True) else: d_som2 = d_som1 if tim is not None and config.norm is not None: tim.getTime(msg="After normalizing signal spectra") del d_som1, n_som2 if config.dump_rtof_comb: d_som2_1 = dr_lib.sum_all_spectra(d_som2) d_som2_2 = dr_lib.data_filter(d_som2_1) del d_som2_1 if config.inst == "REF_M": tof_bc = utils.calc_bin_centers(d_som2_2[0].axis[0].val) d_som2_2[0].axis[0].val = tof_bc[0] d_som2_2.setDataSetType("density") hlr_utils.write_file(config.output, "text/Spec", d_som2_2, output_ext="crtof", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="combined R(TOF) information") del d_som2_2 if config.dump_rtof: if config.inst == "REF_M": d_som2_1 = d_som2 else: d_som2_1 = dr_lib.filter_ref_data(d_som2) hlr_utils.write_file(config.output, "text/Spec", d_som2_1, output_ext="rtof", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="R(TOF) information") del d_som2_1 if config.inst == "REF_L": # Step 9: Convert TOF to scalar Q if config.verbose: print "Converting TOF to scalar Q" # Check to see if polar angle offset is necessary if config.angle_offset is not None: # Check on units, offset must be in radians p_temp = config.angle_offset.toFullTuple(True) if p_temp[2] == "degrees" or p_temp[2] == "degree": deg_to_rad = (math.pi / 180.0) p_off_rads = p_temp[0] * deg_to_rad p_off_err2_rads = p_temp[1] * deg_to_rad * deg_to_rad else: p_off_rads = p_temp[0] p_off_err2_rads = p_temp[1] p_offset = (p_off_rads, p_off_err2_rads) d_som2.attr_list["angle_offset"] = config.angle_offset else: p_offset = None if tim is not None: tim.getTime(False) d_som3 = common_lib.tof_to_scalar_Q(d_som2, units="microsecond", angle_offset=p_offset, lojac=False) del d_som2 if tim is not None: tim.getTime(msg="After converting wavelength to scalar Q ") if config.dump_rq: d_som3_1 = dr_lib.data_filter(d_som3, clean_axis=True) hlr_utils.write_file(config.output, "text/Spec", d_som3_1, output_ext="rq", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="pixel R(Q) information") del d_som3_1 if not config.no_filter: if config.verbose: print "Filtering final data" if tim is not None: tim.getTime(False) d_som4 = dr_lib.data_filter(d_som3) if tim is not None: tim.getTime(msg="After filtering data") else: d_som4 = d_som3 del d_som3 else: d_som4 = d_som2 # Step 10: Rebin all spectra to final Q axis if config.Q_bins is None: if config.scatt_angle is None: config.Q_bins = dr_lib.create_axis_from_data(d_som4) rebin_axis = config.Q_bins.toNessiList() else: # Get scattering angle and make Q conversion from TOF axis # Check on units, scattering angle must be in radians sa_temp = config.scatt_angle.toFullTuple(True) if sa_temp[2] == "degrees" or sa_temp[2] == "degree": deg_to_rad = (math.pi / 180.0) sa_rads = sa_temp[0] * deg_to_rad sa_err2_rads = sa_temp[1] * deg_to_rad * deg_to_rad else: sa_rads = sa_temp[0] sa_err2_rads = sa_temp[1] sa = (sa_rads, sa_err2_rads) pl = d_som4.attr_list.instrument.get_total_path(d_som4[0].id, det_secondary=True) import nessi_list tof_axis_err2 = nessi_list.NessiList(len(tof_axis)) rebin_axis = axis_manip.tof_to_scalar_Q(tof_axis, tof_axis_err2, pl[0], pl[1], sa[0], sa[1])[0] axis_manip.reverse_array_nc(rebin_axis) else: rebin_axis = config.Q_bins.toNessiList() if config.inst == "REF_L": if config.verbose: print "Rebinning spectra" if tim is not None: tim.getTime(False) d_som5 = common_lib.rebin_axis_1D_linint(d_som4, rebin_axis) if tim is not None: tim.getTime(msg="After rebinning spectra") del d_som4 if config.dump_rqr: hlr_utils.write_file(config.output, "text/Spec", d_som5, output_ext="rqr", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="pixel R(Q) (after rebinning) "\ +"information") # Step 11: Sum all rebinned spectra if config.verbose: print "Summing spectra" if tim is not None: tim.getTime(False) d_som6 = dr_lib.sum_all_spectra(d_som5) if tim is not None: tim.getTime(msg="After summing spectra") del d_som5 else: d_som5 = d_som4 if config.inst == "REF_M": d_som5A = dr_lib.sum_all_spectra(d_som5) del d_som5 d_som6 = dr_lib.data_filter(d_som5A) del d_som5A axis_manip.reverse_array_nc(d_som6[0].y) axis_manip.reverse_array_nc(d_som6[0].var_y) d_som6.setYLabel("Intensity") d_som6.setYUnits("Counts/A-1") d_som6.setAllAxisLabels(["scalar wavevector transfer"]) d_som6.setAllAxisUnits(["1/Angstroms"]) Q_bc = utils.calc_bin_centers(rebin_axis) d_som6[0].axis[0].val = Q_bc[0] d_som6.setDataSetType("density") hlr_utils.write_file(config.output, "text/Spec", d_som6, replace_ext=False, replace_path=False, verbose=config.verbose, message="combined Reflectivity information") d_som6.attr_list["config"] = config hlr_utils.write_file(config.output, "text/rmd", d_som6, output_ext="rmd", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="metadata") if tim is not None: tim.setOldTime(old_time) tim.getTime(msg="Total Running Time")
def calc_substrate_trans(obj, subtrans_coeff, substrate_diam, **kwargs): """ This function calculates substrate transmission via the following formula: T = exp[-(A + B * wavelength) * d] where A is a constant with units of cm^-1, B is a constant with units of cm^-2 and d is the substrate diameter in units of cm. @param obj: The data object that contains the TOF axes to calculate the transmission from. @type obj: C{SOM.SOM} or C{SOM.SO} @param subtrans_coeff: The two coefficients for substrate transmission calculation. @type subtrans_coeff: C{tuple} of two C{float}s @param substrate_diam: The diameter of the substrate. @type substrate_diam: C{float} @param kwargs: A list of keyword arguments that the function accepts: @keyword pathlength: The pathlength and its associated error^2 @type pathlength: C{tuple} or C{list} of C{tuple}s @keyword units: The expected units for this function. The default for this function is I{microsecond}. @type units: C{string} @return: The calculate transmission for the given substrate parameters @rtype: C{SOM.SOM} or C{SOM.SO} @raise TypeError: The object used for calculation is not a C{SOM} or a C{SO} @raise RuntimeError: The C{SOM} x-axis units are not I{microsecond} @raise RuntimeError: A C{SOM} does not contain an instrument and no pathlength was provided @raise RuntimeError: No C{SOM} is provided and no pathlength given """ # import the helper functions import hlr_utils # set up for working through data (result, res_descr) = hlr_utils.empty_result(obj) o_descr = hlr_utils.get_descr(obj) if o_descr == "number" or o_descr == "list": raise TypeError("Do not know how to handle given type: %s" % o_descr) else: pass # Setup keyword arguments try: pathlength = kwargs["pathlength"] except KeyError: pathlength = None try: units = kwargs["units"] except KeyError: units = "microsecond" # Primary axis for transformation. If a SO is passed, the function, will # assume the axis for transformation is at the 0 position if o_descr == "SOM": axis = hlr_utils.one_d_units(obj, units) else: axis = 0 if pathlength is not None: p_descr = hlr_utils.get_descr(pathlength) else: if o_descr == "SOM": try: obj.attr_list.instrument.get_primary() inst = obj.attr_list.instrument except RuntimeError: raise RuntimeError("A detector was not provided") else: raise RuntimeError("If no SOM is provided, then pathlength "\ +"information must be provided") result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr) if res_descr == "SOM": result.setYLabel("Transmission") # iterate through the values import array_manip import axis_manip import nessi_list import utils import math len_obj = hlr_utils.get_length(obj) for i in xrange(len_obj): val = hlr_utils.get_value(obj, i, o_descr, "x", axis) err2 = hlr_utils.get_err2(obj, i, o_descr, "x", axis) map_so = hlr_utils.get_map_so(obj, None, i) if pathlength is None: (pl, pl_err2) = hlr_utils.get_parameter("total", map_so, inst) else: pl = hlr_utils.get_value(pathlength, i, p_descr) pl_err2 = hlr_utils.get_err2(pathlength, i, p_descr) value = axis_manip.tof_to_wavelength(val, err2, pl, pl_err2) value1 = utils.calc_bin_centers(value[0]) del value # Convert Angstroms to centimeters value2 = array_manip.mult_ncerr(value1[0], value1[1], subtrans_coeff[1] * 1.0e-8, 0.0) del value1 # Calculate the exponential value3 = array_manip.add_ncerr(value2[0], value2[1], subtrans_coeff[0], 0.0) del value2 value4 = array_manip.mult_ncerr(value3[0], value3[1], -1.0 * substrate_diam, 0.0) del value3 # Calculate transmission trans = nessi_list.NessiList() len_trans = len(value4[0]) for j in xrange(len_trans): trans.append(math.exp(value4[0][j])) trans_err2 = nessi_list.NessiList(len(trans)) hlr_utils.result_insert(result, res_descr, (trans, trans_err2), map_so) return result
def create_param_vs_Y(som, param, param_func, param_axis, **kwargs): """ This function takes a group of single spectrum with any given axes (wavelength, energy etc.). The function can optionally rebin those axes to a given axis. It then creates a 2D spectrum by using a parameter, parameter functiona and a given axis for the lookup locations and places each original spectrum in the found location. @param som: The input object with arbitrary (but same) axis spectra @type som: C{SOM.SOM} @param param: The parameter that will be used for creating the lookups. @type param: C{string} @param param_func: The function that will convert the parameter into the values for lookups. @type param_func: C{string} @param param_axis: The axis that will be searched for the lookup values. @type param_axis: C{nessi_list.NessiList} @param kwargs: A list of keyword arguments that the function accepts: @keyword rebin_axis: An axis to rebin the given spectra to. @type rebin_axis: C{nessi_list.NessiList} @keyword data_type: The name of the data type which can be either I{histogram}, I{density} or I{coordinate}. The default value will be I{histogram}. @type data_type: C{string} @keyword pixnorm: A flag to track the number of pixels that contribute to a bin and then normalize the bin by that number. @type pixnorm: C{boolean} @keyword prnorm: A parameter to track and determine a range (max - min) for each bin the requested parameter axis. The range will then be divided into the final summed spectrum for the given bin. @type prnorm: C{string} @keyword binnorm: A flag that turns on the scaling of each stripe of the y-axis by the individual bins widths from the y-axis. @type binnorm: C{boolean} @keyword so_id: The identifier represents a number, string, tuple or other object that describes the resulting C{SO}. @type so_id: C{int}, C{string}, C{tuple}, C{pixel ID} @keyword y_label: The dependent axis label @type y_label: C{string} @keyword y_units: The dependent axis units @type y_units: C{string} @keyword x_labels: The two independent axis labels @type x_labels: C{list} of C{string}s @keyword x_units: The two independent axis units @type x_units: C{list} of C{string}s @return: A two dimensional spectrum with the parameter as the x-axis and the given spectra axes as the y-axis. @rtype: C{SOM.SOM} """ import array_manip import dr_lib import hlr_utils import nessi_list import SOM import utils # Check for rebinning axis try: rebin_axis = kwargs["rebin_axis"] except KeyError: rebin_axis = None # Check for pixnorm flag try: pixnorm = kwargs["pixnorm"] except KeyError: pixnorm = False try: binnorm = kwargs["binnorm"] except KeyError: binnorm = False # Check for prnorm flag try: prpar = kwargs["prnorm"] prnorm = True except KeyError: prnorm = False # Check dataType keyword argument. An offset will be set to 1 for the # histogram type and 0 for either density or coordinate try: data_type = kwargs["data_type"] if data_type.lower() == "histogram": offset = 1 elif data_type.lower() == "density" or \ data_type.lower() == "coordinate": offset = 0 else: raise RuntimeError("Do not understand data type given: %s" % \ data_type) # Default is offset for histogram except KeyError: offset = 1 # Setup some variables dim = 2 N_tot = 1 # Create 2D spectrum object so_dim = SOM.SO(dim) # Set the axis locations param_axis_loc = 0 arb_axis_loc = 1 # Rebin original data to rebin_axis if necessary if rebin_axis is not None: (som1, som2) = dr_lib.rebin_axis_1D_frac(som, rebin_axis) len_arb_axis = len(rebin_axis) - offset so_dim.axis[arb_axis_loc].val = rebin_axis else: som1 = som len_arb_axis = len(som[0].axis[0].val) - offset so_dim.axis[arb_axis_loc].val = som[0].axis[0].val del som # Get parameter axis information len_param_axis = len(param_axis) - offset so_dim.axis[param_axis_loc].val = param_axis if pixnorm: pixarr = nessi_list.NessiList(len_param_axis) if prnorm: prarr = [] for i in xrange(len_param_axis): prarr.append(nessi_list.NessiList()) # Get the parameters for all the spectra ppfunc = hlr_utils.__getattribute__("param_array") prarr_lookup = ppfunc(som1, prpar) # Get the parameter lookup array pfunc = hlr_utils.__getattribute__(param_func) lookup_array = pfunc(som1, param) # Create y and var_y lists from total 2D size N_tot = len_param_axis * len_arb_axis so_dim.y = nessi_list.NessiList(N_tot) so_dim.var_y = nessi_list.NessiList(N_tot) if rebin_axis is not None: frac_area = nessi_list.NessiList(N_tot) frac_area_err2 = nessi_list.NessiList(N_tot) # Loop through data and create 2D spectrum len_som = hlr_utils.get_length(som1) for i in xrange(len_som): val = hlr_utils.get_value(som1, i, "SOM", "y") err2 = hlr_utils.get_err2(som1, i, "SOM", "y") bin_index = utils.bisect_helper(param_axis, lookup_array[i]) start = bin_index * len_arb_axis if pixnorm: pixarr[bin_index] += 1 if prnorm: prarr[bin_index].append(prarr_lookup[i]) (so_dim.y, so_dim.var_y) = array_manip.add_ncerr(so_dim.y, so_dim.var_y, val, err2, a_start=start) if rebin_axis is not None: val1 = hlr_utils.get_value(som2, i, "SOM", "y") err1_2 = hlr_utils.get_err2(som2, i, "SOM", "y") (frac_area, frac_area_err2) = array_manip.add_ncerr(frac_area, frac_area_err2, val1, err1_2, a_start=start) if rebin_axis is not None: (so_dim.y, so_dim.var_y) = array_manip.div_ncerr(so_dim.y, so_dim.var_y, frac_area, frac_area_err2) # If parameter range normalization enabled, find the range for the # parameter if prnorm: import math prrange = nessi_list.NessiList(len_param_axis) for i in xrange(len(prrange)): try: max_val = max(prarr[i]) except ValueError: max_val = 0.0 try: min_val = min(prarr[i]) except ValueError: min_val = 0.0 prrange[i] = math.fabs(max_val - min_val) # If pixel normalization tracking enabled, divided slices by pixel counts if pixnorm or prnorm: tmp_y = nessi_list.NessiList(N_tot) tmp_var_y = nessi_list.NessiList(N_tot) for i in range(len_param_axis): start = i * len_arb_axis end = (i + 1) * len_arb_axis slice_y = so_dim.y[start:end] slice_var_y = so_dim.var_y[start:end] divconst = 1.0 if pixnorm: divconst *= pixarr[i] # Scale division constant if parameter range normalization enabled if prnorm: divconst *= prrange[i] (dslice_y, dslice_var_y) = array_manip.div_ncerr(slice_y, slice_var_y, divconst, 0.0) (tmp_y, tmp_var_y) = array_manip.add_ncerr(tmp_y, tmp_var_y, dslice_y, dslice_var_y, a_start=start) so_dim.y = tmp_y so_dim.var_y = tmp_var_y if binnorm: tmp_y = nessi_list.NessiList(N_tot) tmp_var_y = nessi_list.NessiList(N_tot) if rebin_axis is not None: bin_const = utils.calc_bin_widths(rebin_axis) else: bin_const = utils.calc_bin_widths(som1[0].axis[1].val) for i in range(len_param_axis): start = i * len_arb_axis end = (i + 1) * len_arb_axis slice_y = so_dim.y[start:end] slice_var_y = so_dim.var_y[start:end] (dslice_y, dslice_var_y) = array_manip.mult_ncerr(slice_y, slice_var_y, bin_const[0], bin_const[1]) (tmp_y, tmp_var_y) = array_manip.add_ncerr(tmp_y, tmp_var_y, dslice_y, dslice_var_y, a_start=start) so_dim.y = tmp_y so_dim.var_y = tmp_var_y # Create final 2D spectrum object container comb_som = SOM.SOM() comb_som.copyAttributes(som1) del som1 # Check for so_id keyword argument try: so_dim.id = kwargs["so_id"] except KeyError: so_dim.id = 0 # Check for y_label keyword argument try: comb_som.setYLabel(kwargs["y_label"]) except KeyError: comb_som.setYLabel("Counts") # Check for y_units keyword argument try: comb_som.setYUnits(kwargs["y_units"]) except KeyError: comb_som.setYUnits("Counts / Arb") # Check for x_label keyword argument try: comb_som.setAllAxisLabels(kwargs["x_labels"]) except KeyError: comb_som.setAllAxisLabels(["Parameter", "Arbitrary"]) # Check for x_units keyword argument try: comb_som.setAllAxisUnits(kwargs["x_units"]) except KeyError: comb_som.setAllAxisUnits(["Arb", "Arb"]) comb_som.append(so_dim) del so_dim return comb_som
return to_filter if __name__ == "__main__": import nessi_list import SOM som = SOM.SOM() som.attr_list["instrument_name"] = "BSS" som.setAllAxisLabels(["wavelength"]) so1 = SOM.SO() so1.id = 0 # 1D data x_axis = nessi_list.NessiList() y_axis = nessi_list.NessiList() y_axis_err2 = nessi_list.NessiList() x_axis.extend(0, 1, 2, float("inf")) y_axis.extend(10, float("nan"), 12) y_axis_err2.extend(1, 1, 1) so1.y = y_axis so1.var_y = y_axis_err2 so1.axis[0].val = x_axis som.append(so1) print "************ SOM (1D)" print "* ", som
def sum_spectra_weighted_ave(obj, **kwargs): """ This function takes a set of data and sums the individual bins by weighted average. That information is then assembled back into a single spectrum. The individual spectra should already have been rebinned. @param obj: Object containing data spectra @type obj: C{SOM.SOM} or C{SOM.SO} @param kwargs: A list of keyword arguments that the function accepts: @return: The summed spectra (one) @rtype: C{SOM.SOM} """ if obj is None: return None # import the helper functions import hlr_utils # set up for working through data (result, res_descr) = hlr_utils.empty_result(obj) o_descr = hlr_utils.get_descr(obj) result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr) # Get the number of axis channels len_axis = len(obj[0]) import nessi_list import SOM import utils # Empty SO for final spctrum so = SOM.SO() len_som = hlr_utils.get_length(obj) # Slice data, calculate weighted average and repackage spectra for i in xrange(len_axis): sliced_data = nessi_list.NessiList() sliced_data_err2 = nessi_list.NessiList() for j in xrange(len_som): obj1 = hlr_utils.get_value(obj, j, o_descr, "all") if i == 0 and j == 0: map_so = hlr_utils.get_map_so(obj, None, j) hlr_utils.result_insert(so, "SO", map_so, None, "all") sliced_data.append(obj1.y[i]) sliced_data_err2.append(obj1.var_y[i]) len_fit = len(sliced_data) value = utils.weighted_average(sliced_data, sliced_data_err2, 0, len_fit - 1) so.y[i] = value[0] so.var_y[i] = value[1] hlr_utils.result_insert(result, res_descr, so, None, "all") return result
def rebin_axis_1D_frac(obj, axis_out): """ This function rebins the primary axis for a C{SOM} or a C{SO} based on the given C{NessiList} axis. @param obj: Object to be rebinned @type obj: C{SOM.SOM} or C{SOM.SO} @param axis_out: The axis to rebin the C{SOM} or C{SO} to @type axis_out: C{NessiList} @return: Object that has been rebinned according to the provided axis @rtype: C{SOM.SOM} or C{SOM.SO} @raise TypeError: The rebinning axis given is not a C{NessiList} @raise TypeError: The object being rebinned is not a C{SOM} or a C{SO} """ # import the helper functions import hlr_utils # set up for working through data try: axis_out.__type__ except AttributeError: raise TypeError("Rebinning axis must be a NessiList!") o_descr = hlr_utils.get_descr(obj) if o_descr == "number" or o_descr == "list": raise TypeError("Do not know how to handle given type: %s" % \ o_descr) else: pass (result, res_descr) = hlr_utils.empty_result(obj) result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr) # iterate through the values import array_manip import axis_manip for i in xrange(hlr_utils.get_length(obj)): axis_in = hlr_utils.get_value(obj, i, o_descr, "x", 0) val = hlr_utils.get_value(obj, i, o_descr) err2 = hlr_utils.get_err2(obj, i, o_descr) value = axis_manip.rebin_axis_1D_frac(axis_in, val, err2, axis_out) frac_err = nessi_list.NessiList(len(value[2])) value1 = array_manip.div_ncerr(value[0], value[1], value[2], frac_err) xvals = [] xvals.append(axis_out) map_so = hlr_utils.get_map_so(obj, None, i) hlr_utils.result_insert(result, res_descr, value1, map_so, "all", 0, xvals) return result
def sum_by_rebin_frac(obj, axis_out, **kwargs): """ This function uses the C{axis_manip.rebin_axis_1D_frac} function from the SCL to perform the rebinning. The function tracks the counts and fractional area from all spectra separately. The counts and fractional area are divided after all spectra have been parsed. @param obj: Object to be rebinned and summed @type obj: C{SOM.SOM} or C{SOM.SO} @param axis_out: The axis to rebin the C{SOM} or C{SO} to @type axis_out: C{NessiList} @param kwargs: A list of keyword arguments that the function accepts: @keyword configure: This is the object containing the driver configuration. This will signal the function to write out the counts and fractional area to files. @type configure: C{Configure} @return: Object that has been rebinned and summed according to the provided axis @rtype: C{SOM.SOM} or C{SOM.SO} @raise TypeError: The rebinning axis given is not a C{NessiList} @raise TypeError: The object being rebinned is not a C{SOM} or a C{SO} @raise TypeError: The dimension of the input object is not 1D """ # import the helper functions import hlr_utils # set up for working through data try: axis_out.__type__ except AttributeError: raise TypeError("Rebinning axis must be a NessiList!") o_descr = hlr_utils.get_descr(obj) if o_descr == "number" or o_descr == "list": raise TypeError("Do not know how to handle given type: %s" % \ o_descr) else: pass try: if obj.getDimension() != 1: raise TypeError("The input object must be 1D!. This one is "\ +"%dD." % obj.getDimension()) except AttributeError: # obj is a SO if obj.dim() != 1: raise TypeError("The input object must be 1D!. This one is "\ +"%dD." % obj.dim()) # Check for keywords try: config = kwargs["configure"] except KeyError: config = None (result, res_descr) = hlr_utils.empty_result(obj) result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr) import array_manip import axis_manip len_data = len(axis_out) - 1 counts = nessi_list.NessiList(len_data) counts_err2 = nessi_list.NessiList(len_data) frac_area = nessi_list.NessiList(len_data) frac_area_err2 = nessi_list.NessiList(len_data) for i in xrange(hlr_utils.get_length(obj)): axis_in = hlr_utils.get_value(obj, i, o_descr, "x", 0) val = hlr_utils.get_value(obj, i, o_descr) err2 = hlr_utils.get_err2(obj, i, o_descr) value = axis_manip.rebin_axis_1D_frac(axis_in, val, err2, axis_out) (counts, counts_err2) = array_manip.add_ncerr(counts, counts_err2, value[0], value[1]) (frac_area, frac_area_err2) = array_manip.add_ncerr(frac_area, frac_area_err2, value[2], frac_area_err2) # Divide the total counts by the total fractional area value1 = array_manip.div_ncerr(counts, counts_err2, frac_area, frac_area_err2) xvals = [] xvals.append(axis_out) map_so = hlr_utils.get_map_so(obj, None, 0) hlr_utils.result_insert(result, res_descr, value1, map_so, "all", 0, xvals) if config is not None: if o_descr == "SOM": import SOM o_som = SOM.SOM() o_som.copyAttributes(obj) so = hlr_utils.get_map_so(obj, None, 0) so.axis[0].val = axis_out so.y = counts so.var_y = counts_err2 o_som.append(so) # Write out summed counts into file hlr_utils.write_file(config.output, "text/Spec", o_som, output_ext="cnt", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="summed counts") # Replace counts data with fractional area. The axes remain the # same o_som[0].y = frac_area o_som[0].var_y = frac_area_err2 # Write out summed fractional area into file hlr_utils.write_file(config.output, "text/Spec", o_som, output_ext="fra", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="fractional area") return result
def ref_beamdiv_correct(attrs, pix_id, epsilon, cpix, **kwargs): """ @param attrs: The attribute list of a C{SOM.SOM} @type attrs: C{SOM.AttributeList} @param pix_id: The pixel ID for which the correction will be calculated @type pix_id: C{tuple} @param epsilon: The pixel spatial resolution in units of meters @type epsilon: C{float} @param cpix: The center pixel for the calculation @type cpix: C{float} @param kwargs: A list of keyword arguments that the function accepts: @kwarg det_secondary: The main sample to detector flightpath in meters. @type det_secondary: C{float} @kwarg pix_width: The width of a pixel in the high resolution direction @type pix_width: C{float} @return: The beam divergence correction to the scattering angle @type: float @raise RuntimeError: If the instrument name is not recognized. """ # Set instrument specific strings inst_name = attrs["instrument_name"] if inst_name == "REF_L": first_slit_size = "data-slit1_size" last_slit_size = "data-slit2_size" last_slit_dist = "data-slit2_distance" slit_dist = "data-slit12_distance" elif inst_name == "REF_M": first_slit_size = "data-slit1_size" last_slit_size = "data-slit3_size" last_slit_dist = "data-slit3_distance" slit_dist = "data-slit13_distance" else: raise RuntimeError("Do not know how to handle instrument %s" \ % inst_name) # Get sorting direction, y is True, x is False y_sort = attrs["ref_sort"] # Get keyword arguments det_secondary = kwargs.get("det_secondary") pix_width = kwargs.get("pix_width") # Check keyword arguments if det_secondary is None: det_secondary = attrs.instrument.get_det_secondary()[0] # This is currently set to the same number for both REF_L and REF_M if epsilon is None: epsilon = 0.5 * 1.3 * 1.0e-3 # Set the center pixel to something if cpix is None: cpix = 133.5 gamma_plus = math.atan2(0.5 * (attrs[first_slit_size][0] + \ attrs[last_slit_size][0]), attrs[slit_dist][0]) gamma_minus = math.atan2(0.5 * (attrs[first_slit_size][0] - \ attrs[last_slit_size][0]), attrs[slit_dist][0]) half_last_aperture = 0.5 * attrs[last_slit_size][0] neg_half_last_aperture = -1.0 * half_last_aperture last_slit_to_det = attrs[last_slit_dist][0] + det_secondary dist_last_aper_det_sin_gamma_plus = last_slit_to_det * math.sin(gamma_plus) dist_last_aper_det_sin_gamma_minus = last_slit_to_det * \ math.sin(gamma_minus) # Set the delta theta coordinates of the acceptance polygon accept_poly_x = nessi_list.NessiList() accept_poly_x.append(-1.0 * gamma_minus) accept_poly_x.append(gamma_plus) accept_poly_x.append(gamma_plus) accept_poly_x.append(gamma_minus) accept_poly_x.append(-1.0 * gamma_plus) accept_poly_x.append(-1.0 * gamma_plus) accept_poly_x.append(accept_poly_x[0]) # Set the z coordinates of the acceptance polygon accept_poly_y = nessi_list.NessiList() accept_poly_y.append(half_last_aperture - \ dist_last_aper_det_sin_gamma_minus + epsilon) accept_poly_y.append(half_last_aperture + \ dist_last_aper_det_sin_gamma_plus + epsilon) accept_poly_y.append(half_last_aperture + \ dist_last_aper_det_sin_gamma_plus - epsilon) accept_poly_y.append(neg_half_last_aperture + \ dist_last_aper_det_sin_gamma_minus - epsilon) accept_poly_y.append(neg_half_last_aperture - \ dist_last_aper_det_sin_gamma_plus - epsilon) accept_poly_y.append(neg_half_last_aperture - \ dist_last_aper_det_sin_gamma_plus + epsilon) accept_poly_y.append(accept_poly_y[0]) if y_sort: cur_index = pix_id[1][1] if pix_width is None: cur_offset = attrs.instrument.get_y_pix_offset(pix_id) next_id = (pix_id[0], (pix_id[1][0], pix_id[1][1]+1)) next_offset = attrs.instrument.get_y_pix_offset(next_id) else: cur_index = pix_id[1][0] if pix_width is None: cur_offset = attrs.instrument.get_x_pix_offset(pix_id) next_id = (pix_id[0], (pix_id[1][0]+1, pix_id[1][1])) next_offset = attrs.instrument.get_x_pix_offset(next_id) if pix_width is None: pix_width = math.fabs(next_offset - cur_offset) # Set the z band for the pixel xMinus = (cur_index - cpix - 0.5) * pix_width xPlus = (cur_index - cpix + 0.5) * pix_width # Calculate the intersection yLeftCross = -1 yRightCross = -1 xI = accept_poly_x[0] yI = accept_poly_y[0] int_poly_x = nessi_list.NessiList() int_poly_y = nessi_list.NessiList() for i in xrange(len(accept_poly_x)): xF = accept_poly_y[i] yF = accept_poly_x[i] if xI < xF: if xI < xMinus and xF >= xMinus: yLeftCross = yI + (yF - yI) * (xMinus - xI) / (xF - xI) int_poly_x.append(yLeftCross) int_poly_y.append(xMinus) if xI < xPlus and xF >= xPlus: yRightCross = yI + (yF - yI) * (xPlus - xI) / (xF - xI); int_poly_x.append(yRightCross) int_poly_y.append(xPlus) else: if xF < xPlus and xI >= xPlus: yRightCross = yI + (yF - yI) * (xPlus - xI) / (xF - xI); int_poly_x.append(yRightCross) int_poly_y.append(xPlus) if xF < xMinus and xI >= xMinus: yLeftCross = yI + (yF - yI) * (xMinus - xI) / (xF - xI); int_poly_x.append(yLeftCross) int_poly_y.append(xMinus) # This catches points on the polygon inside the range of interest if xF >= xMinus and xF < xPlus: int_poly_x.append(yF) int_poly_y.append(xF) xI = xF yI = yF if len(int_poly_x) > 2: int_poly_x.append(int_poly_x[0]) int_poly_y.append(int_poly_y[0]) int_poly_x.append(int_poly_x[1]) int_poly_y.append(int_poly_y[1]) else: # Intersection polygon is NULL, point or line, so has no area # Therefore there is no angle correction return None # Calculate intersection polygon aread import utils area = utils.calc_area_2D_polygon(int_poly_x, int_poly_y, len(int_poly_x) - 2, True) return __calc_center_of_mass(int_poly_x, int_poly_y, area)