Exemple #1
0
    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
Exemple #2
0
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
Exemple #3
0
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)
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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.")
Exemple #8
0
    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
Exemple #9
0
    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)
Exemple #10
0
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
Exemple #11
0
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()
Exemple #12
0
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")
Exemple #13
0
        @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
Exemple #14
0
            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 ")
Exemple #16
0
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
Exemple #17
0
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)
Exemple #20
0
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
Exemple #21
0
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
Exemple #22
0
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")
Exemple #24
0
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
Exemple #26
0
    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
Exemple #28
0
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
Exemple #29
0
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
Exemple #30
0
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)