예제 #1
0
def rebin_axis_1D(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 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(axis_in, val, err2, axis_out)
        xvals = []
        xvals.append(axis_out)

        map_so = hlr_utils.get_map_so(obj, None, i)
        hlr_utils.result_insert(result, res_descr, value, map_so, "all",
                                0, xvals)

    return result
예제 #2
0
def reverse_array_cp(obj):
    """
    This function reverses the y and var_y values of all the C{SO}s in a
    C{SOM} or an individual C{SO}. This is assuming that there was a previous
    transformation on the x-axis of the C{SO} or C{SOM}.


    @param obj: Object that needs to have its y and var_y values reversed
    @type obj: C{SOM.SOM} or C{SOM.SO}


    @return: Object containing the results of the reversal process
    @rtype: C{SOM.SOM} or C{SOM.SO}

    
    @raise TypeError: A C{tuple} or C{list} of C{tuple}s is presented to the
                      function
    """

    # 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

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    # iterate through the values
    import axis_manip

    for i in xrange(hlr_utils.get_length(obj)):
        val = hlr_utils.get_value(obj, i, o_descr)
        err2 = hlr_utils.get_err2(obj, i, o_descr)

        value1 = axis_manip.reverse_array_cp(val)
        value2 = axis_manip.reverse_array_cp(err2)

        map_so = hlr_utils.get_map_so(obj, None, i)
        hlr_utils.result_insert(result, res_descr, (value1, value2), map_so)

    return result
예제 #3
0
def reverse_array_cp(obj):
    """
    This function reverses the y and var_y values of all the C{SO}s in a
    C{SOM} or an individual C{SO}. This is assuming that there was a previous
    transformation on the x-axis of the C{SO} or C{SOM}.


    @param obj: Object that needs to have its y and var_y values reversed
    @type obj: C{SOM.SOM} or C{SOM.SO}


    @return: Object containing the results of the reversal process
    @rtype: C{SOM.SOM} or C{SOM.SO}

    
    @raise TypeError: A C{tuple} or C{list} of C{tuple}s is presented to the
                      function
    """

    # 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

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    # iterate through the values
    import axis_manip
    
    for i in xrange(hlr_utils.get_length(obj)):
        val = hlr_utils.get_value(obj, i, o_descr)
        err2 = hlr_utils.get_err2(obj, i, o_descr)

        value1 = axis_manip.reverse_array_cp(val)
        value2 = axis_manip.reverse_array_cp(err2)

        map_so = hlr_utils.get_map_so(obj, None, i)
        hlr_utils.result_insert(result, res_descr, (value1, value2), map_so)

    return result
예제 #4
0
def apply_sas_correct(obj):
    """
    This function applies the following corrections to SAS TOF data:
      - Multiply counts by the following formula:
            (sin(polar) * cos(polar)) / (1 + tan^2(polar))

    @param obj: The data to apply the corrections to
    @type obj: C{SOM.SOM} or C{SOM.SO}


    @return: The data after corrections have been applied
    @rtype: C{SOM.SOM} or C{SOM.SO}


    @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

    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

    if o_descr == "SOM":
        inst = obj.attr_list.instrument
    else:
        inst = None

    (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 math

    len_obj = hlr_utils.get_length(obj)
    for i in xrange(len_obj):
        val = hlr_utils.get_value(obj, i, o_descr, "y")
        err2 = hlr_utils.get_err2(obj, i, o_descr, "y")

        map_so = hlr_utils.get_map_so(obj, None, i)

        polar = hlr_utils.get_parameter("polar", map_so, inst)

        sin_pol = math.sin(polar[0])
        cos_pol = math.cos(polar[0])
        tan_pol = math.tan(polar[0])

        scale = (sin_pol * cos_pol) / (1.0 + (tan_pol * tan_pol))

        value = array_manip.mult_ncerr(val, err2, scale, 0.0)

        hlr_utils.result_insert(result, res_descr, value, map_so, "y")

    return result
예제 #5
0
def tof_to_wavelength(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to wavelength. The wavelength axis for a C{SOM} must be in
    units of I{microseconds}. The primary axis of a C{SO} is assumed to be in
    units of I{microseconds}. A C{tuple} of C{(tof, tof_err2)} (assumed to be
    in units of I{microseconds}) can be converted to C{(wavelength,
    wavelength_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @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 inst_param: The type of parameter requested from an associated
                         instrument. For this function the acceptable
                         parameters are I{primary}, I{secondary} and I{total}.
                         Default is I{primary}.
    @type inst_param: C{string}

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is I{True} for
                    histogram data.
    @type lojac: C{boolean}

    @keyword units: The expected units for this function. The default for this
                    function is I{microseconds}.
    @type units: C{string}
 

    @return: Object with a primary axis in time-of-flight converted to
             wavelength
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{microseconds}
    
    @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)

    # Setup keyword arguments
    try:
        inst_param = kwargs["inst_param"]
    except KeyError:
        inst_param = "primary"

    try:
        pathlength = kwargs["pathlength"]
    except KeyError:
        pathlength = None

    try:
        units = kwargs["units"]
    except KeyError:
        units = "microseconds"

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "Angstroms", axis)
        result.setAxisLabel(axis, "wavelength")
        result.setYUnits("Counts/A")
        result.setYLabel("Intensity")
    else:
        pass

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

    # iterate through the values
    import axis_manip
    if lojac:
        import utils
    
    for i in xrange(hlr_utils.get_length(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(inst_param, 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)

        if lojac:
            y_val = hlr_utils.get_value(obj, i, o_descr, "y")
            y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
            counts = utils.linear_order_jacobian(val, value[0],
                                                 y_val, y_err2)
            hlr_utils.result_insert(result, res_descr, counts, map_so,
                                    "all", axis, [value[0]])

        else:
            hlr_utils.result_insert(result, res_descr, value, map_so,
                                    "x", axis)

    return result
예제 #6
0
def tof_to_scalar_Q(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to scalarQ. The time-of-flight axis for a C{SOM} must be in
    units of I{microseconds}. The primary axis of a C{SO} is assumed to be in
    units of I{microseconds}. A C{tuple} of C{(time-of-flight,
    time-of-flight_err2)} (assumed to be in units of I{microseconds}) can be
    converted to C{(scalar_Q, scalar_Q_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword polar: The polar angle and its associated error^2
    @type polar: C{tuple} or C{list} of C{tuple}s
    
    @keyword pathlength: The pathlength and its associated error^2
    @type pathlength: C{tuple} or C{list} of C{tuple}s

    @keyword angle_offset: A constant offset for the polar angle and its
                           associated error^2. The units of the offset should
                           be in radians.
    @type angle_offset: C{tuple}

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is True for
                    histogram data.
    @type lojac: C{boolean}    
    
    @keyword units: The expected units for this function. The default for this
                    function is I{microseconds}.
    @type units: C{string}
 

    @return: Object with a primary axis in time-of-flight converted to scalar Q
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: A C{SOM} is not passed and no polar angle is provided
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{microseconds}
    """

    # 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 == "list":
        raise TypeError("Do not know how to handle given type: %s" % \
                        o_descr)
    else:
        pass

    # Setup keyword arguments
    try:
        polar = kwargs["polar"]
    except KeyError:
        polar = None

    try:
        pathlength = kwargs["pathlength"]
    except KeyError:
        pathlength = None

    try:
        units = kwargs["units"]
    except KeyError:
        units = "microseconds"

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    try:
        angle_offset = kwargs["angle_offset"]
    except KeyError:
        angle_offset = None

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

    if pathlength is None or polar is None:
        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:
            if pathlength is None and polar is None:
                raise RuntimeError("If no SOM is provided, then pathlength "\
                                   +"and polar angle information must be "\
                                   +"provided")
            elif pathlength is None:
                raise RuntimeError("If no SOM is provided, then pathlength "\
                                   +"information must be provided")
            elif polar is None:
                raise RuntimeError("If no SOM is provided, then polar angle "\
                                   +"information must be provided")
            else:
                raise RuntimeError("If you get here, see Steve Miller for "\
                                   +"your mug.")
    else:
        pass

    if pathlength is not None:
        p_descr = hlr_utils.get_descr(pathlength)
    else:
        pass

    if polar is not None:
        a_descr = hlr_utils.get_descr(polar)
    else:
        pass

    # iterate through the values
    import axis_manip
    if lojac:
        import utils

    for i in xrange(hlr_utils.get_length(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)

        if polar is None:
            (angle,
             angle_err2) = hlr_utils.get_parameter("polar", map_so, inst)
        else:
            angle = hlr_utils.get_value(polar, i, a_descr)
            angle_err2 = hlr_utils.get_err2(polar, i, a_descr)

        if angle_offset is not None:
            angle += angle_offset[0]
            angle_err2 += angle_offset[1]

        value = axis_manip.tof_to_scalar_Q(val, err2, pl, pl_err2, angle,
                                           angle_err2)

        if lojac:
            y_val = hlr_utils.get_value(obj, i, o_descr, "y")
            y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
            counts = utils.linear_order_jacobian(val, value[0], y_val, y_err2)
        else:
            pass

        if o_descr != "number":
            value1 = axis_manip.reverse_array_cp(value[0])
            value2 = axis_manip.reverse_array_cp(value[1])
            rev_value = (value1, value2)
        else:
            rev_value = value

        if map_so is not None:
            if not lojac:
                map_so.y = axis_manip.reverse_array_cp(map_so.y)
                map_so.var_y = axis_manip.reverse_array_cp(map_so.var_y)
            else:
                map_so.y = axis_manip.reverse_array_cp(counts[0])
                map_so.var_y = axis_manip.reverse_array_cp(counts[1])
        else:
            pass

        hlr_utils.result_insert(result, res_descr, rev_value, map_so, "x",
                                axis)

    return result
예제 #7
0
def zero_spectra(obj, nz_range, **kwargs):
    """
    This function takes spectra and a corrsponding range and zeros the values
    in the spectra outside the given range.

    @param obj: The object containing the spectra to be zeroed
    @type obj: C{SOM.SOM}

    @param nz_range: Range pairs where the spectra will not be zeroed
    @type nz_range: C{list} of C{tuple}s

    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword use_bin_index: A flag that tells the function to use the
                            information in C{nz_range} as the range index.
    @type use_bin_index: C{boolean}
    
    
    @return: Object containing the zeroed spectra
    @rtype: C{SOM.SOM}


    @raise RuntimeError: If I{obj} and I{nz_range} do not have the same length
    """
    # import the helper functions
    import hlr_utils

    # Kickout if incoming object is NoneType
    if obj is None:
        return obj

    # Get keyword arguments
    use_bin_index = kwargs.get("use_bin_index", False)

    # Length cross-check
    if len(obj) != len(nz_range):
        raise RuntimeError("The SOM and the range pair list must be the same "\
                           +"length")

    # 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)

    # iterate through the values
    import bisect

    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")
        x_axis = hlr_utils.get_value(obj, i, o_descr, "x", 0)
        
        y_new = nessi_list.NessiList(len(y_val))
        var_y_new = nessi_list.NessiList(len(y_err2))

        if not use_bin_index:
            # Find the bins for the range to not zero
            i_start = bisect.bisect(x_axis, nz_range[i][0]) - 1
            i_end = bisect.bisect(x_axis, nz_range[i][1]) - 1
        else:
            i_start = nz_range[i][0]
            i_end = nz_range[i][1]
        
        for j in xrange(i_start, i_end+1):
            try:
                y_new[j] = y_val[j]
                var_y_new[j] = y_err2[j]
            except IndexError:
                continue

        hlr_utils.result_insert(result, res_descr, (y_new, var_y_new),
                                map_so, "y")

    return result
예제 #8
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    
예제 #9
0
def shift_spectrum(obj, shift_point, min_ext, max_ext, scale_const=None):
    """
    This function takes a given spectrum and a central value and creates
    a spectrum that is shifted about that point. Values greater than the point
    are moved to the beginning of the new spectrum and values less than the
    point are move towards the end of the new spectrum.
    
    @param obj: Monitor object that will be shifted
    @type obj: C{SOM.SOM} or C{SOM.SO}

    @param shift_point: The point in the spectrum about which to shift the
    data.
    @type shift_point: C{list} of C{floats}

    @param min_ext: The minimum extent of the axis to shift.
    @type min_ext: C{list} of C{floats}

    @param max_ext: The maximum extent of the axis to shift.
    @type max_ext: C{list} of C{floats}
    
    @param scale_const: A scaling constant to apply (multiply) to the newly
                        shifted spectrum. The default is I{None}.
    @type scale_const: C{float}


    @return: Monitor spectrum that have been shifted
    @rtype: C{SOM.SOM} or C{SOM.SO}
    """
    # 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)
    s_descr = hlr_utils.get_descr(shift_point)
    ie_descr = hlr_utils.get_descr(min_ext)
    ae_descr = hlr_utils.get_descr(max_ext)

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    import array_manip
    import utils

    len_obj = hlr_utils.get_length(obj)
    for i in xrange(len_obj):
        val = hlr_utils.get_value(obj, i, o_descr, "y")
        err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
        x_axis = hlr_utils.get_value(obj, i, o_descr, "x", 0)
        x_err2 = hlr_utils.get_err2(obj, i, o_descr, "x", 0)
        map_so = hlr_utils.get_map_so(obj, None, i)

        bin_center = utils.calc_bin_centers(x_axis, x_err2)

        # Get shift point and extents
        sp = hlr_utils.get_value(shift_point, i, s_descr, "y")
        ie = hlr_utils.get_value(min_ext, i, ie_descr, "y")
        ae = hlr_utils.get_value(max_ext, i, ae_descr, "y")

        # Make shifted spectrum
        value0 = utils.shift_spectrum(val, err2, x_axis, bin_center[0],
                                      sp, ie, ae)

        # Scale spectrum if necessary
        if scale_const is not None:
            value1 = array_manip.mult_ncerr(value0[0], value0[1],
                                            scale_const, 0.0)
        else:
            value1 = value0

        hlr_utils.result_insert(result, res_descr, value1, map_so, "y")

    return result
예제 #10
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
예제 #11
0
def sumw_ncerr(obj1, obj2, **kwargs):
    """
    This function sums by weighting errors of two objects (C{SOM} or C{SO}) and
    returns the result of that action in an C{SOM}. The function does not
    handle the cases of C{SOM}+C{tuple}, C{SO}+C{tuple} or C{tuple}+C{tuple}.

    @param obj1:  First object in the weighted sum
    @type obj1: C{SOM.SOM} or C{SOM.SO} or C{tuple}
    
    @param obj2: Second object in the the weighted sum
    @type obj2: C{SOM.SOM} or C{SOM.SO} or C{tuple}

    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword axis: This is the axis one wishes to manipulate. If no argument
                   is given the default value is y
    @type axis: C{string}=<y or x>
    
    @keyword axis_pos: This is position of the axis in the axis array. If no
                       argument is given, the default value is 0
    @type axis_pos: C{int}
    
    @keyword length_one_som: This is a flag that lets the function know it is
                             dealing with a length 1 C{SOM} so that attributes
                             may be passed along. The length 1 C{SOM} will be
                             turned into a C{SO}. The default value is False.
    @type length_one_som: C{boolean}
    
    @keyword length_one_som_pos: This is the argument position of the
                                 length 1 C{SOM} since the check is done
                                 before the arguments are swapped. The default
                                 value is 2.
    @type length_one_som_pos: C{int}=<1 or 2>
    

    @return: Object containing the results of the addition
    @rtype: C{SOM.SOM} or C{SOM.SO}


    @raise TypeError: The C{SOM}+C{tuple}, C{SO}+C{tuple} or C{tuple}+C{tuple}
                      cases are presented to the function
    
    @raise IndexError: The two C{SOM}s do not contain the same number of
                       spectra
                       
    @raise RunTimeError: The x-axis units of the C{SOM}s do not match
    
    @raise RunTimeError: The y-axis units of the C{SOM}s do not match
    
    @raise RunTimeError: The x-axes of the two C{SO}s are not equal
    """
    
    # import the helper functions
    import hlr_utils

    # Check to see if we are working with a length 1 SOM
    try:
        length_one_som = kwargs["length_one_som"]
    except KeyError:
        length_one_som = False

    try:
        length_one_som_pos = kwargs["length_one_som_pos"]
        if length_one_som_pos != 1 or length_one_som_pos != 2:
            raise RuntimeError("length_one_som_pos must be either 1 or 2 and "\
                               +"%d" % length_one_som_pos)
    except KeyError:
        length_one_som_pos = 2

    if length_one_som:
        if length_one_som_pos == 1:
            som_copy = obj1
            obj1 = obj1[0]
        else:
            som_copy = obj2
            obj2 = obj2[0]
    else:
        # Not working with a length 1 SOM, do nothing
        pass

    # set up for working through data
    (result, res_descr) = hlr_utils.empty_result(obj1, obj2)
    (o1_descr, o2_descr) = hlr_utils.get_descr(obj1, obj2)

    # error check information
    if o1_descr == "number" or o2_descr == "number":
        raise RuntimeError("Operations with tuples are not supported!")
    elif o2_descr == "SOM" and o1_descr == "SO":
        (obj1, obj2) = hlr_utils.swap_args(obj1, obj2)
        (o1_descr, o2_descr) = hlr_utils.swap_args(o1_descr, o2_descr)
    elif o2_descr == "SOM" and o1_descr == "SOM":
        hlr_utils.math_compatible(obj1, o1_descr, obj2, o2_descr)
    else:
        pass

    # Check for axis keyword argument
    try:
        axis = kwargs["axis"]
    except KeyError:
        axis = "y"
        
    # Check for axis_pos keyword argument
    try:
        axis_pos = kwargs["axis_pos"]
    except KeyError:
        axis_pos = 0
        
    if length_one_som:
        if length_one_som_pos == 1:
            result = hlr_utils.copy_som_attr(result, res_descr,
                                             som_copy, "SOM",
                                             obj2, o2_descr)
        else:
            result = hlr_utils.copy_som_attr(result, res_descr, obj1, o1_descr,
                                             som_copy, "SOM")            
    else:
        result = hlr_utils.copy_som_attr(result, res_descr, obj1, o1_descr,
                                         obj2, o2_descr)
    
    # iterate through the values
    import array_manip
    
    for i in xrange(hlr_utils.get_length(obj1, obj2)):
        val1 = hlr_utils.get_value(obj1, i, o1_descr, axis, axis_pos)
        err2_1 = hlr_utils.get_err2(obj1, i, o1_descr, axis, axis_pos)

        val2 = hlr_utils.get_value(obj2, i, o2_descr, axis, axis_pos)
        err2_2 = hlr_utils.get_err2(obj2, i, o2_descr, axis, axis_pos)
        
        (descr_1, descr_2) = hlr_utils.get_descr(val1, val2)

        hlr_utils.math_compatible(val1, descr_1, val2, descr_2)

        value = array_manip.sumw_ncerr(val1, err2_1, val2, err2_2)
        
        map_so = hlr_utils.get_map_so(obj1, None, i)
        hlr_utils.result_insert(result, res_descr, value, map_so, axis,
                                axis_pos)

    return result
예제 #12
0
def init_scatt_wavevector_to_scalar_Q(initk, scattk, **kwargs):
    """
    This function takes an initial wavevector and a scattered wavevector as a
    C{tuple} and a C{SOM}, a C{tuple} and a C{SO} or two C{tuple}s and
    calculates the quantity scalar Q units of I{1/Angstroms}. The C{SOM}
    principle axis must be in units of I{1/Angstroms}. The C{SO}s and
    C{tuple}(s) is(are) assumed to be in units of I{1/Angstroms}. The polar
    angle must be provided if one of the initial arguments is not a C{SOM}. If
    a C{SOM} is passed, by providing the polar angle at the function call time,
    the polar angle carried in the C{SOM} instrument will be overridden.

    @param initk: Object holding the initial wavevector
    @type initk: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param scattk: Object holding the scattered wavevector
    @type scattk: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword polar: The polar angle and its associated error^2
    @type polar: C{tuple} or C{list} of C{tuple}s

    @keyword units: The expected units for this function. The default for this
                    function is I{1/Angstroms}.
    @type units: C{string}


    @return: Object converted to scalar Q
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The C{SOM}-C{SOM} operation is attempted
    
    @raise TypeError: The C{SOM}-C{SO} operation is attempted
    
    @raise TypeError: The C{SO}-C{SOM} operation is attempted
    
    @raise TypeError: The C{SO}-C{SO} operation is attempted
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{1/Angstroms}
    
    @raise RuntimeError: A C{SOM} is not passed and no polar angle is provided
    
    @raise RuntimeError: No C{SOM.Instrument} is provided in a C{SOM}
    """

    # import the helper functions
    import hlr_utils

    # set up for working through data
    (result, res_descr) = hlr_utils.empty_result(initk, scattk)
    (i_descr, s_descr) = hlr_utils.get_descr(initk, scattk)

    # error checking for types
    if i_descr == "SOM" and s_descr == "SOM":
        raise TypeError("SOM-SOM operation not supported")
    elif i_descr == "SOM" and s_descr == "SO":
        raise TypeError("SOM-SO operation not supported")
    elif i_descr == "SO" and s_descr == "SOM":
        raise TypeError("SO-SOM operation not supported")
    elif i_descr == "SO" and s_descr == "SO":
        raise TypeError("SO-SO operation not supported")
    else:
        pass

    # Setup keyword arguments
    try:
        polar = kwargs["polar"]
    except KeyError:
        polar = None

    try:
        units = kwargs["units"]
    except KeyError:
        units = "1/Angstroms"

    result = hlr_utils.copy_som_attr(result, res_descr, initk, i_descr, scattk,
                                     s_descr)
    if res_descr == "SOM":
        index = hlr_utils.one_d_units(result, units)
        result = hlr_utils.force_units(result, units, index)
        result.setAxisLabel(index, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

    if polar is None:
        if i_descr == "SOM":
            try:
                initk.attr_list.instrument.get_primary()
                inst = initk.attr_list.instrument
            except RuntimeError:
                raise RuntimeError("A detector was not provided!")

        elif s_descr == "SOM":
            try:
                scattk.attr_list.instrument.get_primary()
                inst = scattk.attr_list.instrument
            except RuntimeError:
                raise RuntimeError("A detector was not provided!")

        else:
            raise RuntimeError("If no SOM is provided, then polar "\
                               +"information must be given.")
    else:
        p_descr = hlr_utils.get_descr(polar)

    # iterate through the values
    import axis_manip

    for i in xrange(hlr_utils.get_length(initk, scattk)):
        val1 = hlr_utils.get_value(initk, i, i_descr, "x")
        err2_1 = hlr_utils.get_err2(initk, i, i_descr, "x")

        val2 = hlr_utils.get_value(scattk, i, s_descr, "x")
        err2_2 = hlr_utils.get_err2(scattk, i, s_descr, "x")

        map_so = hlr_utils.get_map_so(initk, scattk, i)

        if polar is None:
            (angle,
             angle_err2) = hlr_utils.get_parameter("polar", map_so, inst)
        else:
            angle = hlr_utils.get_value(polar, i, p_descr)
            angle_err2 = hlr_utils.get_err2(polar, i, p_descr)

        value = axis_manip.init_scatt_wavevector_to_scalar_Q(
            val1, err2_1, val2, err2_2, angle, angle_err2)

        hlr_utils.result_insert(result, res_descr, value, map_so, "x")

    return result
예제 #13
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
예제 #14
0
def igs_energy_transfer(obj, **kwargs):
    """
    @depricated: This function will eventually disappear when the full S(Q,E)
                 transformation for IGS detectors is completed and verified.
                 
    This function takes a SOM or a SO and calculates the energy transfer for
    the IGS class of instruments. It is different from
    common_lib.energy_transfer in that the final wavelength is provided in a
    SOM.Information, SOM.CompositeInformation or a tuple, then converted to
    energy in place before being given to the common_lib.energy_transfer
    function.

    Parameters:
    ----------
    -> obj
    -> kwargs is a list of key word arguments that the function accepts:
          units= a string containing the expected units for this function.
                 The default for this function is meV
          lambda_f= a SOM.Information, SOM.CompositeInformation or a tuple
                    containing the final wavelength information
          offset= a SOM.Information or SOM.CompositeInformation containing
                  the final energy offsets
          scale=<boolean> is a flag that determines if the energy transfer
                          results are scaled by the ratio of lambda_f/lambda_i.
                          The default is False

    Returns:
    -------
    <- A SOM or SO with the energy transfer calculated in units of THz

    Exceptions:
    ----------
    <- RuntimeError is raised if the x-axis units are not meV
    <- RuntimeError is raised if a SOM or SO is not given to the function
    <- RuntimeError is raised if the final wavelength is not provided to the
       function
    """

    # 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 RuntimeError, "Must provide a SOM of a SO to the function."
    # Go on
    else:
        pass

    # Setup keyword arguments
    try:
        units = kwargs["units"]
    except KeyError:
        units = "meV"

    try:
        lambda_f = kwargs["lambda_f"]
    except KeyError:
        lambda_f = None

    try:
        offset = kwargs["offset"]
    except KeyError:
        offset = None

    try:
        scale = kwargs["scale"]
    except KeyError:
        scale = False

        
    # 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 lambda_f is None:
        if o_descr == "SOM":
            try:
                lambda_f = obj.attr_list["Wavelength_final"]
            except KeyError:
                raise RuntimeError("Must provide a final wavelength via the "\
                                   +"incoming SOM or the lambda_f keyword")
        else:
            raise RuntimeError("Must provide a final wavelength via the "\
                                   +"lambda_f keyword")
    else:
        pass
    

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "ueV", axis)
        result.setAxisLabel(axis, "energy_transfer")
        result.setYUnits("Counts/ueV")
        result.setYLabel("Intensity")
    else:
        pass

    # iterate through the values
    import array_manip
    import axis_manip
    import utils

    for i in xrange(hlr_utils.get_length(obj)):
        val = hlr_utils.get_value(obj, i, o_descr, "x", axis)
        err2 = hlr_utils.get_err2(obj, i, o_descr, "x", axis)

        y_val = hlr_utils.get_value(obj, i, o_descr, "y", axis)
        y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y", axis)
        
        map_so = hlr_utils.get_map_so(obj, None, i)
        
        l_f = hlr_utils.get_special(lambda_f, map_so)

        (E_f, E_f_err2) = axis_manip.wavelength_to_energy(l_f[0], l_f[1])

        if offset is not None:
            info = hlr_utils.get_special(offset, map_so)
            try:
                E_f_new = array_manip.add_ncerr(E_f, E_f_err2,
                                                info[0], info[1])
            except TypeError:
                # Have to do this since add_ncerr does not support
                # scalar-scalar operations
                value1 = E_f + info[0]
                value2 = E_f_err2 + info[1]
                E_f_new = (value1, value2)
        else:
            E_f_new = (E_f, E_f_err2)

        # Scale counts by lambda_f / lambda_i
        if scale:
            l_i = axis_manip.energy_to_wavelength(val, err2)

            l_i_bc = utils.calc_bin_centers(l_i[0], l_i[1])

            ratio = array_manip.div_ncerr(l_f[0], l_f[1],
                                          l_i_bc[0], l_i_bc[1])

            scale_y = array_manip.mult_ncerr(y_val, y_err2, ratio[0], ratio[1])
        else:
            scale_y = (y_val, y_err2)

        value = array_manip.sub_ncerr(val, err2, E_f_new[0], E_f_new[1])
            
        # Convert from meV to ueV
        value2 = array_manip.mult_ncerr(value[0], value[1], 1000.0, 0.0)
        value3 = array_manip.mult_ncerr(scale_y[0], scale_y[1],
                                        1.0/1000.0, 0.0)

        hlr_utils.result_insert(result, res_descr, value3, map_so, "all",
                                0, [value2[0]])

    return result
예제 #15
0
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
예제 #16
0
def integrate_axis(obj, **kwargs):
    """
    This function takes a spectrum and integrates the given axis. The function
    assumes that the incoming data is in the histogram form.

    @param obj: Spectrum to be integrated
    @type obj: C{SOM.SOM} or C{SOM.SO}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword start: Value for the start range of the integration.
    @type start: C{float}
    
    @keyword end: Value for the end range of the integration.
    @type end: C{float}
    
    @keyword width: This is a flag to turn on the multiplication of the
                    individual bin contents with the bins corresponding width.
    @type width: C{boolean}

    @keyword width_pos: This is the position of the x-axis in the axis array
                        from which to calculate the bin widths in support of
                        the width flag. If no argument is given, the default
                        value is I{0}.
    @type width_pos: C{int}

    
    @return: The integration value and its associated error
    @rtype: C{tuple}

    
    @raise RuntimError: A C{SOM} or C{SO} is not given to the function.
    """

    # import the helper functions
    import hlr_utils

    # set up for working through data
    o_descr = hlr_utils.get_descr(obj)

    if o_descr == "number" or o_descr == "list":
        raise RuntimeError("Must provide a SOM of a SO to the function.")
    # Go on
    else:
        pass

    # Check for starting bin
    try:
        start = kwargs["start"]
    except KeyError:
        start = float("inf")

    # Check for ending bin
    try:
        end = kwargs["end"]
    except KeyError:
        end = float("inf")

    # Check for width keyword argument
    try:
        width = kwargs["width"]
    except KeyError:
        width = False

    if width:
        # Check for width_pos keyword argument
        try:
            width_pos = kwargs["width_pos"]
        except KeyError:
            width_pos = 0
    else:
        width_pos = 0

    import array_manip
    import utils

    integration = float(0)
    integration_error2 = float(0)

    len_obj = hlr_utils.get_length(obj)
    for i in xrange(len_obj):
        value = hlr_utils.get_value(obj, i, o_descr, "y")
        error = hlr_utils.get_err2(obj, i, o_descr, "y")
        x_axis = hlr_utils.get_value(obj, i, o_descr, "x", width_pos)

        (int_val) = utils.integrate_1D_hist(value,
                                            error,
                                            x_axis,
                                            width=width,
                                            min_int=start,
                                            max_int=end)
        (integration,
         integration_error2) = array_manip.add_ncerr(int_val[0], int_val[1],
                                                     integration,
                                                     integration_error2)

    return (integration, integration_error2)
예제 #17
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
예제 #18
0
def energy_transfer(left, right, **kwargs):
    """
    This function takes a C{tuple} and a C{SOM}, a C{tuple} and a C{SO} or two
    C{tuple}s and calculates the energy transfer in units of I{THz}. The C{SOM}
    principle axis must be in units of I{meV}. The C{SO} and C{tuple}s are
    assumed to be in units of I{meV}.

    @param left: Object on the left side of the subtraction
    @type left: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param right: Object on the right side of the subtraction
    @type right: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @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{meV}
    @type units: C{string}


    @return: Object based on left - right in units of I{THz}
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise RuntimeError: The x-axis units are not I{meV}

    @raise TypeError: C{SOM}-C{SOM} operation not supported

    @raise TypeError: C{SOM}-C{SO} operation not supported

    @raise TypeError: C{SO}-C{SOM} operation not supported

    @raise TypeError: C{SO}-C{SO} operation not supported
    """

    # import the helper functions
    import hlr_utils

    # set up for working through data
    (result, res_descr) = hlr_utils.empty_result(left, right)
    (l_descr, r_descr) = hlr_utils.get_descr(left, right)

    # error checking for types
    if l_descr == "SOM" and r_descr == "SOM":
        raise TypeError("SOM-SOM operation not supported")
    elif l_descr == "SOM" and r_descr == "SO":
        raise TypeError("SOM-SO operation not supported")
    elif l_descr == "SO" and r_descr == "SOM":
        raise TypeError("SO-SOM operation not supported")
    elif l_descr == "SO" and r_descr == "SO":
        raise TypeError("SO-SO operation not supported")
    else:
        pass

    # Setup keyword arguments
    try:
        units = kwargs["units"]
    except KeyError:
        units = "meV"
    
    result = hlr_utils.copy_som_attr(result, res_descr, left, l_descr,
                                     right, r_descr)
    if res_descr == "SOM":
        index = hlr_utils.one_d_units(result, units)
        result = hlr_utils.force_units(result, "THz", index)
        result.setAxisLabel(index, "energy transfer")
        result.setYUnits("Counts/THz")
        result.setYLabel("Intensity")
    else:
        pass

    # iterate through the values
    import axis_manip
    
    for i in xrange(hlr_utils.get_length(left, right)):

        val1 = hlr_utils.get_value(left, i, l_descr, "x")
        err2_1 = hlr_utils.get_err2(left, i, l_descr, "x")
        
        val2 = hlr_utils.get_value(right, i, r_descr, "x")
        err2_2 = hlr_utils.get_err2(right, i, r_descr, "x")

        value = axis_manip.energy_transfer(val1, err2_1, val2, err2_2)

        map_so = hlr_utils.get_map_so(left, right, i)
        hlr_utils.result_insert(result, res_descr, value, map_so, "x")

    return result
def initial_wavelength_igs_lin_time_zero_to_tof(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    initial_wavelength_igs_lin_time_zero to time-of-flight. The
    initial_wavelength_igs_lin_time_zero axis for a C{SOM} must be in units of
    I{Angstroms}. The primary axis of a C{SO} is assumed to be in units of
    I{Angstroms}. A C{tuple} of C{(initial_wavelength_igs_lin_time_zero,
    initial_wavelength_igs_lin_time_zero_err2)} (assumed to be in units of
    I{Angstroms}) can be converted to C{(tof, tof_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}

    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword lambda_f:The final wavelength and its associated error^2
    @type lambda_f: C{tuple}

    @keyword time_zero_slope: The time zero slope and its associated error^2
    @type time_zero_slope: C{tuple}

    @keyword time_zero_offset: The time zero offset and its associated error^2
    @type time_zero_offset: C{tuple}

    @keyword dist_source_sample: The source to sample distance information and
                                 its associated error^2
    @type dist_source_sample: C{tuple} or C{list} of C{tuple}s

    @keyword dist_sample_detector: The sample to detector distance information
                                   and its associated error^2
    @type dist_sample_detector: C{tuple} or C{list} of C{tuple}s

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is True for
                    histogram data.
    @type lojac: C{boolean}

    @keyword units: The expected units for this function. The default for this
                    function is I{Angstroms}
    @type units: C{string}


    @return: Object with a primary axis in initial_wavelength_igs converted to
             time-of-flight
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes

    @raise RuntimeError: The C{SOM} x-axis units are not I{Angstroms}
    """
    # 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)

    # Setup keyword arguments
    try:
        lambda_f = kwargs["lambda_f"]
    except KeyError:
        lambda_f = None

    try:
        time_zero_slope = kwargs["time_zero_slope"]
    except KeyError:
        time_zero_slope = None

    # Current constants for Time Zero Slope
    TIME_ZERO_SLOPE = (float(0.0), float(0.0))

    try:
        time_zero_offset = kwargs["time_zero_offset"]
    except KeyError:
        time_zero_offset = None        

    # Current constants for Time Zero Offset
    TIME_ZERO_OFFSET = (float(0.0), float(0.0))

    try:
        dist_source_sample = kwargs["dist_source_sample"]
    except KeyError:
        dist_source_sample = None

    try:
        dist_sample_detector = kwargs["dist_sample_detector"]
    except KeyError:
        dist_sample_detector = None

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    try:
        units = kwargs["units"]
    except KeyError:
        units = "Angstroms"

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "Microseconds", axis)
        result.setAxisLabel(axis, "time-of-flight")
        result.setYUnits("Counts/uS")
        result.setYLabel("Intensity")
    else:
        pass

    # Where to get instrument information
    if dist_source_sample is None or dist_sample_detector is None:
        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:
            if dist_source_sample is None and dist_sample_detector is None:
                raise RuntimeError("If a SOM is not passed, the "\
                                   +"source-sample and sample-detector "\
                                   +"distances must be provided.")
            elif dist_source_sample is None:
                raise RuntimeError("If a SOM is not passed, the "\
                                   +"source-sample distance must be provided.")
            elif dist_sample_detector is None:
                raise RuntimeError("If a SOM is not passed, the "\
                                   +"sample-detector distance must be "\
                                   +"provided.")
            else:
                raise RuntimeError("If you get here, see Steve Miller for "\
                                   +"your mug.")
    else:
        pass
        
    if lambda_f is not None:
        l_descr = hlr_utils.get_descr(lambda_f)
    else:
        if o_descr == "SOM":
            try:
                som_l_f = obj.attr_list["Wavelength_final"]
            except KeyError:
                raise RuntimeError("Please provide a final wavelength "\
                                   +"parameter either via the function call "\
                                   +"or the SOM")
        else:
            raise RuntimeError("You need to provide a final wavelength")
            

    if time_zero_slope is not None:
        t_0_slope_descr = hlr_utils.get_descr(time_zero_slope)
    else:
        if o_descr == "SOM":
            try:
                t_0_slope = obj.attr_list["Time_zero_slope"][0]
                t_0_slope_err2 = obj.attr_list["Time_zero_slope"][1]
            except KeyError:
                t_0_slope = TIME_ZERO_SLOPE[0]
                t_0_slope_err2 = TIME_ZERO_SLOPE[1]
        else:
            t_0_slope = TIME_ZERO_SLOPE[0]
            t_0_slope_err2 = TIME_ZERO_SLOPE[1]


    if time_zero_offset is not None:
        t_0_offset_descr = hlr_utils.get_descr(time_zero_offset)
    else:
        if o_descr == "SOM":
            try:
                t_0_offset = obj.attr_list["Time_zero_offset"][0]
                t_0_offset_err2 = obj.attr_list["Time_zero_offset"][1]
            except KeyError:
                t_0_offset = TIME_ZERO_OFFSET[0]
                t_0_offset_err2 = TIME_ZERO_OFFSET[1]
        else:
            t_0_offset = TIME_ZERO_OFFSET[0]
            t_0_offset_err2 = TIME_ZERO_OFFSET[1]
            
    if dist_source_sample is not None:
        ls_descr = hlr_utils.get_descr(dist_source_sample)
    # Do nothing, go on
    else:
        pass

    if dist_sample_detector is not None:
        ld_descr = hlr_utils.get_descr(dist_sample_detector)
    # Do nothing, go on
    else:
        pass

    # iterate through the values
    len_obj = hlr_utils.get_length(obj)

    MNEUT_OVER_H = 1.0 / 0.003956034
    MNEUT_OVER_H2 = MNEUT_OVER_H * MNEUT_OVER_H

    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 dist_source_sample is None:
            (L_s, L_s_err2) = hlr_utils.get_parameter("primary", map_so, inst)
        else:
            L_s = hlr_utils.get_value(dist_source_sample, i, ls_descr)
            L_s_err2 = hlr_utils.get_err2(dist_source_sample, i, ls_descr)

        if dist_sample_detector is None:
            (L_d, L_d_err2) = hlr_utils.get_parameter("secondary", map_so,
                                                      inst)
        else:
            L_d = hlr_utils.get_value(dist_sample_detector, i, ld_descr)
            L_d_err2 = hlr_utils.get_err2(dist_sample_detector, i, ld_descr)

        if lambda_f is not None:
            l_f = hlr_utils.get_value(lambda_f, i, l_descr)
            l_f_err2 = hlr_utils.get_err2(lambda_f, i, l_descr)
        else:
            l_f_tuple = hlr_utils.get_special(som_l_f, map_so)
            l_f = l_f_tuple[0]
            l_f_err2 = l_f_tuple[1]

        if time_zero_slope is not None:
            t_0_slope = hlr_utils.get_value(time_zero_slope, i,
                                            t_0_slope_descr)
            t_0_slope_err2 = hlr_utils.get_err2(time_zero_slope, i,
                                                t_0_slope_descr)
        else:
            pass

        if time_zero_offset is not None:
            t_0_offset = hlr_utils.get_value(time_zero_offset, i,
                                             t_0_offset_descr)
            t_0_offset_err2 = hlr_utils.get_err2(time_zero_offset, i,
                                                 t_0_offset_descr)
        else:
            pass

        # Going to violate rules since the current usage is with a single
        # number. When an SCL equivalent function arises, this code can be
        # fixed. 
        front_const = MNEUT_OVER_H * L_s + t_0_slope
        term2 = MNEUT_OVER_H * l_f * L_d

        tof = (front_const * val) + term2 + t_0_offset
        
        front_const2 = front_const * front_const

        eterm1 = l_f * l_f * L_d_err2
        eterm2 = L_d * L_d * l_f_err2
        eterm3 = MNEUT_OVER_H2 * L_s_err2

        tof_err2 = (front_const2 * err2) + (val * val) * \
                   (eterm3 + t_0_slope_err2) + (MNEUT_OVER_H2 * \
                                                (eterm1 + eterm2)) + \
                                                t_0_offset_err2

        hlr_utils.result_insert(result, res_descr, (tof, tof_err2), None,
                                "all")

    return result
예제 #20
0
def fix_bin_contents(obj, **kwargs):
    """
    This function takes a SOM or SO and goes through the individual spectra
    adjusting the bin contents by either multiplying or dividing by the
    bin widths or the bin centers taken from the individual spectra.

    @param obj: The data object to be scaled
    @type obj: C{SOM.SOM} or C{SOM.SO}

    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword scale: A flag that signals multiplication by the required bin
                    quantity. The default is I{False} (divide).
    @type scale: C{bool}

    @keyword width: A flag that signals that the adjusting quantity is the
                    bin width. The default is I{True}. If I{False}, the bin
                    center is used.
    @type width: C{bool}

    @keyword units: The expected units for this function. The default for this
                    function is I{microsecond}.
    @type units: C{string}


    @return: The object with the individual spectrum scaled
    @rtype: C{SOM.SOM} or C{SOM.SO}
    """
    import hlr_utils

    # 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:
        scale = kwargs["scale"]
    except KeyError:
        scale = False

    try:
        width = kwargs["width"]
    except KeyError:
        width = True

    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_pos = hlr_utils.one_d_units(obj, units)
    else:
        axis_pos = 0

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    # iterate through the values
    import array_manip
    import utils

    for i in xrange(hlr_utils.get_length(obj)):
        val = hlr_utils.get_value(obj, i, o_descr, "y")
        err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
        axis = hlr_utils.get_value(obj, i, o_descr, "x", axis_pos)
        axis_err2 = hlr_utils.get_err2(obj, i, o_descr, "x", axis_pos)

        map_so = hlr_utils.get_map_so(obj, None, i)

        if width:
            (bin_const,
             bin_const_err2) = utils.calc_bin_widths(axis, axis_err2)
        else:
            (bin_const,
             bin_const_err2) = utils.calc_bin_centers(axis, axis_err2)

        if scale:
            value = array_manip.mult_ncerr(val, err2, bin_const,
                                           bin_const_err2)
        else:
            value = array_manip.div_ncerr(val, err2, bin_const, bin_const_err2)

        hlr_utils.result_insert(result, res_descr, value, map_so, "y")

    return result
예제 #21
0
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 ")
예제 #22
0
def weighted_average(obj, **kwargs):
    """
    This function takes a C{SOM} or C{SO} and calculates the weighted average
    for the primary axis.

    @param obj: Object that will have the weighted average calculated from it
    @type obj: C{SOM.SOM} or C{SOM.SO}

    @param kwargs: A list of keyword arguments that the function accepts:    

    @keyword start: The index of starting bin
    @type start: C{int}

    @keyword end: The index of ending bin
    @type end: C{int}    
    
    
    @return: Object containing the weighted average and the uncertainty
             squared associated with the weighted average
    @rtype: C{tuple} (for a C{SO}) or a C{list} of C{tuple}s (for a C{SOM})


    @raise TypeError: A C{tuple} or another construct (besides a C{SOM} or
                      C{SO}) is passed to the function
    """

    # import the helper functions
    import hlr_utils

    # set up for working through data
    # This time highest object in the hierarchy is NOT what we need
    result = []
    if (hlr_utils.get_length(obj) > 1):
        res_descr = "list"
    else:
        res_descr = "number"

    o_descr = hlr_utils.get_descr(obj)

    try:
        start = int(kwargs["start"])
    except KeyError:
        start = 0

    try:
        end = int(kwargs["end"])
    except KeyError:
        end = hlr_utils.get_length(obj) - 1

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    # iterate through the values
    import utils

    for i in xrange(hlr_utils.get_length(obj)):
        val = hlr_utils.get_value(obj, i, o_descr, "y")
        err2 = hlr_utils.get_err2(obj, i, o_descr, "y")

        value = utils.weighted_average(val, err2, start, end)

        hlr_utils.result_insert(result, res_descr, value, None, "all")

    import copy
    return copy.deepcopy(result)
예제 #23
0
def energy_transfer(obj, itype, axis_const, **kwargs):
    """
    This function takes a SOM with a wavelength axis (initial for IGS and
    final for DGS) and calculates the energy transfer.  

    @param obj: The object containing the wavelength axis
    @type obj: C{SOM.SOM}

    @param itype: The instrument class type. The choices are either I{IGS} or
                  I{DGS}.
    @type itype: C{string}

    @param axis_const: The attribute name for the axis constant which is the 
                         final wavelength for I{IGS} and the initial energy for
                         I{DGS}.
    @type axis_const: C{string}

    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword units: The units for the incoming axis. The default is
                    I{Angstroms}.
    @type units: C{string}

    @keyword change_units: A flag that signals the function to convert from
                           I{meV} to I{ueV}. The default is I{False}.
    @type change_units: C{boolean}

    @keyword scale: A flag to scale the y-axis by lambda_f/lambda_i for I{IGS}
                    and lambda_i/lambda_f for I{DGS}. The default is I{False}.
    @type scale: C{boolean}

    @keyword lojac: A flag that turns on the calculation and application of
                    the linear-order Jacobian. The default is I{False}.
    @type lojac: C{boolean}

    @keyword sa_norm: A flag to turn on solid angle normlaization.
    @type sa_norm: C{boolean}

    @return: Object with the energy transfer calculated in units of I{meV} or
             I{ueV}. The default is I{meV}.
    @rtype: C{SOM.SOM}


    @raise RuntimeError: The instrument class type is not recognized
    @raise RuntimeError: The x-axis units are not Angstroms
    @raise RuntimeError: A SOM is not given to the function
    """
    # Check the instrument class type to make sure its allowed
    allowed_types = ["DGS", "IGS"]

    if itype not in allowed_types:
        raise RuntimeError("The instrument class type %s is not known. "\
                           +"Please use DGS or IGS" % itype)

    # 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 != "SOM":
        raise RuntimeError("Must provide a SOM to the function.")
    # Go on
    else:
        pass

    # Setup keyword arguments
    try:
        units = kwargs["units"]
    except KeyError:
        units = "Angstroms"

    try:
        change_units = kwargs["change_units"]
    except KeyError:
        change_units = False       

    try:
        scale = kwargs["scale"]
    except KeyError:
        scale = False

    try:
        sa_norm = kwargs["sa_norm"]
    except KeyError:
        sa_norm = False

    if sa_norm:
        inst = obj.attr_list.instrument

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = False
    
    # Primary axis for transformation. 
    axis = hlr_utils.one_d_units(obj, units)

    # Get the subtraction constant
    try:
        axis_c = obj.attr_list[axis_const]
    except KeyError:
        raise RuntimeError("Must provide a final wavelength (IGS) or initial "\
                           +"energy (DGS) via the incoming SOM")
    
    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)
    if change_units:
        unit_str = "ueV"
    else:
        unit_str = "meV"
    result = hlr_utils.force_units(result, unit_str, axis)
    result.setAxisLabel(axis, "energy_transfer")
    result.setYUnits("Counts/" + unit_str)
    result.setYLabel("Intensity")

    # iterate through the values
    import array_manip
    import axis_manip
    import dr_lib
    import utils

    for i in xrange(hlr_utils.get_length(obj)):
        if itype == "IGS":
            l_i = hlr_utils.get_value(obj, i, o_descr, "x", axis)
            l_i_err2 = hlr_utils.get_err2(obj, i, o_descr, "x", axis)
        else:
            l_f = hlr_utils.get_value(obj, i, o_descr, "x", axis)
            l_f_err2 = hlr_utils.get_err2(obj, i, o_descr, "x", axis)
            
        y_val = hlr_utils.get_value(obj, i, o_descr, "y", axis)
        y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y", axis)
        
        map_so = hlr_utils.get_map_so(obj, None, i)

        if itype == "IGS":
            (E_i, E_i_err2) = axis_manip.wavelength_to_energy(l_i, l_i_err2)
            l_f = hlr_utils.get_special(axis_c, map_so)[:2]
            (E_f, E_f_err2) = axis_manip.wavelength_to_energy(l_f[0], l_f[1])
            if lojac:
                (y_val, y_err2) = utils.linear_order_jacobian(l_i, E_i, 
                                                              y_val, y_err2)  
        else:
            (E_i, E_i_err2) = axis_c.toValErrTuple()
            (E_f, E_f_err2) = axis_manip.wavelength_to_energy(l_f, l_f_err2)
            if lojac:
                (y_val, y_err2) = utils.linear_order_jacobian(l_f, E_f, 
                                                              y_val, y_err2)

        if scale:
            # Scale counts by lambda_f / lambda_i
            if itype == "IGS":
                (l_n, l_n_err2) = l_f
                (l_d, l_d_err2) = utils.calc_bin_centers(l_i, l_i_err2)
            else:
                (l_n, l_n_err2) = utils.calc_bin_centers(l_f, l_f_err2)
                (l_d, l_d_err2) = axis_manip.energy_to_wavelength(E_i,
                                                                  E_i_err2)
                
            ratio = array_manip.div_ncerr(l_n, l_n_err2, l_d, l_d_err2)
            scale_y = array_manip.mult_ncerr(y_val, y_err2, ratio[0], ratio[1])
        else:
            scale_y = (y_val, y_err2)

        value = array_manip.sub_ncerr(E_i, E_i_err2, E_f, E_f_err2)

        if change_units:
            # Convert from meV to ueV
            value2 = array_manip.mult_ncerr(value[0], value[1], 1000.0, 0.0)
            scale_y = array_manip.mult_ncerr(scale_y[0], scale_y[1],
                                             1.0/1000.0, 0.0)
        else:
            value2 = value

        if sa_norm:
            if inst.get_name() == "BSS":
                dOmega = dr_lib.calc_BSS_solid_angle(map_so, inst)
                scale_y = array_manip.div_ncerr(scale_y[0], scale_y[1],
                                                dOmega, 0.0)
            else:
                raise RuntimeError("Do not know how to get solid angle from "\
                                   +"%s" % inst.get_name())
            
        if itype == "IGS":
            # Reverse the values due to the conversion
            value_y = axis_manip.reverse_array_cp(scale_y[0])
            value_var_y = axis_manip.reverse_array_cp(scale_y[1])
            value_x = axis_manip.reverse_array_cp(value2[0])
        else:
            value_y = scale_y[0]
            value_var_y = scale_y[1]
            value_x = value2[0]

        hlr_utils.result_insert(result, res_descr, (value_y, value_var_y),
                                map_so, "all", 0, [value_x])

    return result
예제 #24
0
def initial_wavelength_igs_lin_time_zero_to_tof(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    initial_wavelength_igs_lin_time_zero to time-of-flight. The
    initial_wavelength_igs_lin_time_zero axis for a C{SOM} must be in units of
    I{Angstroms}. The primary axis of a C{SO} is assumed to be in units of
    I{Angstroms}. A C{tuple} of C{(initial_wavelength_igs_lin_time_zero,
    initial_wavelength_igs_lin_time_zero_err2)} (assumed to be in units of
    I{Angstroms}) can be converted to C{(tof, tof_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}

    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword lambda_f:The final wavelength and its associated error^2
    @type lambda_f: C{tuple}

    @keyword time_zero_slope: The time zero slope and its associated error^2
    @type time_zero_slope: C{tuple}

    @keyword time_zero_offset: The time zero offset and its associated error^2
    @type time_zero_offset: C{tuple}

    @keyword dist_source_sample: The source to sample distance information and
                                 its associated error^2
    @type dist_source_sample: C{tuple} or C{list} of C{tuple}s

    @keyword dist_sample_detector: The sample to detector distance information
                                   and its associated error^2
    @type dist_sample_detector: C{tuple} or C{list} of C{tuple}s

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is True for
                    histogram data.
    @type lojac: C{boolean}

    @keyword units: The expected units for this function. The default for this
                    function is I{Angstroms}
    @type units: C{string}


    @return: Object with a primary axis in initial_wavelength_igs converted to
             time-of-flight
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes

    @raise RuntimeError: The C{SOM} x-axis units are not I{Angstroms}
    """
    # 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)

    # Setup keyword arguments
    try:
        lambda_f = kwargs["lambda_f"]
    except KeyError:
        lambda_f = None

    try:
        time_zero_slope = kwargs["time_zero_slope"]
    except KeyError:
        time_zero_slope = None

    # Current constants for Time Zero Slope
    TIME_ZERO_SLOPE = (float(0.0), float(0.0))

    try:
        time_zero_offset = kwargs["time_zero_offset"]
    except KeyError:
        time_zero_offset = None

    # Current constants for Time Zero Offset
    TIME_ZERO_OFFSET = (float(0.0), float(0.0))

    try:
        dist_source_sample = kwargs["dist_source_sample"]
    except KeyError:
        dist_source_sample = None

    try:
        dist_sample_detector = kwargs["dist_sample_detector"]
    except KeyError:
        dist_sample_detector = None

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    try:
        units = kwargs["units"]
    except KeyError:
        units = "Angstroms"

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "Microseconds", axis)
        result.setAxisLabel(axis, "time-of-flight")
        result.setYUnits("Counts/uS")
        result.setYLabel("Intensity")
    else:
        pass

    # Where to get instrument information
    if dist_source_sample is None or dist_sample_detector is None:
        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:
            if dist_source_sample is None and dist_sample_detector is None:
                raise RuntimeError("If a SOM is not passed, the "\
                                   +"source-sample and sample-detector "\
                                   +"distances must be provided.")
            elif dist_source_sample is None:
                raise RuntimeError("If a SOM is not passed, the "\
                                   +"source-sample distance must be provided.")
            elif dist_sample_detector is None:
                raise RuntimeError("If a SOM is not passed, the "\
                                   +"sample-detector distance must be "\
                                   +"provided.")
            else:
                raise RuntimeError("If you get here, see Steve Miller for "\
                                   +"your mug.")
    else:
        pass

    if lambda_f is not None:
        l_descr = hlr_utils.get_descr(lambda_f)
    else:
        if o_descr == "SOM":
            try:
                som_l_f = obj.attr_list["Wavelength_final"]
            except KeyError:
                raise RuntimeError("Please provide a final wavelength "\
                                   +"parameter either via the function call "\
                                   +"or the SOM")
        else:
            raise RuntimeError("You need to provide a final wavelength")

    if time_zero_slope is not None:
        t_0_slope_descr = hlr_utils.get_descr(time_zero_slope)
    else:
        if o_descr == "SOM":
            try:
                t_0_slope = obj.attr_list["Time_zero_slope"][0]
                t_0_slope_err2 = obj.attr_list["Time_zero_slope"][1]
            except KeyError:
                t_0_slope = TIME_ZERO_SLOPE[0]
                t_0_slope_err2 = TIME_ZERO_SLOPE[1]
        else:
            t_0_slope = TIME_ZERO_SLOPE[0]
            t_0_slope_err2 = TIME_ZERO_SLOPE[1]

    if time_zero_offset is not None:
        t_0_offset_descr = hlr_utils.get_descr(time_zero_offset)
    else:
        if o_descr == "SOM":
            try:
                t_0_offset = obj.attr_list["Time_zero_offset"][0]
                t_0_offset_err2 = obj.attr_list["Time_zero_offset"][1]
            except KeyError:
                t_0_offset = TIME_ZERO_OFFSET[0]
                t_0_offset_err2 = TIME_ZERO_OFFSET[1]
        else:
            t_0_offset = TIME_ZERO_OFFSET[0]
            t_0_offset_err2 = TIME_ZERO_OFFSET[1]

    if dist_source_sample is not None:
        ls_descr = hlr_utils.get_descr(dist_source_sample)
    # Do nothing, go on
    else:
        pass

    if dist_sample_detector is not None:
        ld_descr = hlr_utils.get_descr(dist_sample_detector)
    # Do nothing, go on
    else:
        pass

    # iterate through the values
    len_obj = hlr_utils.get_length(obj)

    MNEUT_OVER_H = 1.0 / 0.003956034
    MNEUT_OVER_H2 = MNEUT_OVER_H * MNEUT_OVER_H

    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 dist_source_sample is None:
            (L_s, L_s_err2) = hlr_utils.get_parameter("primary", map_so, inst)
        else:
            L_s = hlr_utils.get_value(dist_source_sample, i, ls_descr)
            L_s_err2 = hlr_utils.get_err2(dist_source_sample, i, ls_descr)

        if dist_sample_detector is None:
            (L_d, L_d_err2) = hlr_utils.get_parameter("secondary", map_so,
                                                      inst)
        else:
            L_d = hlr_utils.get_value(dist_sample_detector, i, ld_descr)
            L_d_err2 = hlr_utils.get_err2(dist_sample_detector, i, ld_descr)

        if lambda_f is not None:
            l_f = hlr_utils.get_value(lambda_f, i, l_descr)
            l_f_err2 = hlr_utils.get_err2(lambda_f, i, l_descr)
        else:
            l_f_tuple = hlr_utils.get_special(som_l_f, map_so)
            l_f = l_f_tuple[0]
            l_f_err2 = l_f_tuple[1]

        if time_zero_slope is not None:
            t_0_slope = hlr_utils.get_value(time_zero_slope, i,
                                            t_0_slope_descr)
            t_0_slope_err2 = hlr_utils.get_err2(time_zero_slope, i,
                                                t_0_slope_descr)
        else:
            pass

        if time_zero_offset is not None:
            t_0_offset = hlr_utils.get_value(time_zero_offset, i,
                                             t_0_offset_descr)
            t_0_offset_err2 = hlr_utils.get_err2(time_zero_offset, i,
                                                 t_0_offset_descr)
        else:
            pass

        # Going to violate rules since the current usage is with a single
        # number. When an SCL equivalent function arises, this code can be
        # fixed.
        front_const = MNEUT_OVER_H * L_s + t_0_slope
        term2 = MNEUT_OVER_H * l_f * L_d

        tof = (front_const * val) + term2 + t_0_offset

        front_const2 = front_const * front_const

        eterm1 = l_f * l_f * L_d_err2
        eterm2 = L_d * L_d * l_f_err2
        eterm3 = MNEUT_OVER_H2 * L_s_err2

        tof_err2 = (front_const2 * err2) + (val * val) * \
                   (eterm3 + t_0_slope_err2) + (MNEUT_OVER_H2 * \
                                                (eterm1 + eterm2)) + \
                                                t_0_offset_err2

        hlr_utils.result_insert(result, res_descr, (tof, tof_err2), None,
                                "all")

    return result
예제 #25
0
def tof_to_wavelength_lin_time_zero(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to wavelength incorporating a linear time zero which is a
    described as a linear function of the wavelength. The time-of-flight axis
    for a C{SOM} must be in units of I{microseconds}. The primary axis of a
    C{SO} is assumed to be in units of I{microseconds}. A C{tuple} of C{(tof,
    tof_err2)} (assumed to be in units of I{microseconds}) can be converted to
    C{(wavelength, wavelength_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @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 time_zero_slope: The time zero slope and its associated error^2
    @type time_zero_slope: C{tuple}

    @keyword time_zero_offset: The time zero offset and its associated error^2
    @type time_zero_offset: C{tuple}

    @keyword inst_param: The type of parameter requested from an associated
                         instrument. For this function the acceptable
                         parameters are I{primary}, I{secondary} and I{total}.
                         Default is I{primary}.
    @type inst_param: C{string}

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is I{True} for
                    histogram data.
    @type lojac: C{boolean}

    @keyword units: The expected units for this function. The default for this
                    function is I{microseconds}.
    @type units: C{string}

    @keyword cut_val: Specify a wavelength to cut the spectra at.
    @type cut_val: C{float}

    @keyword cut_less: A flag that specifies cutting the spectra less than
                       C{cut_val}. The default is C{True}.
    @type cut_less: C{boolean}


    @return: Object with a primary axis in time-of-flight converted to
             wavelength
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{microseconds}
    
    @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)

    # Setup keyword arguments
    try:
        inst_param = kwargs["inst_param"]
    except KeyError:
        inst_param = "primary"

    try:
        pathlength = kwargs["pathlength"]
    except KeyError:
        pathlength = None

    try:
        time_zero_slope = kwargs["time_zero_slope"]
    except KeyError:
        time_zero_slope = None

    # Current constants for Time Zero Slope
    TIME_ZERO_SLOPE = (float(0.0), float(0.0))

    try:
        time_zero_offset = kwargs["time_zero_offset"]
    except KeyError:
        time_zero_offset = None

    # Current constants for Time Zero Offset
    TIME_ZERO_OFFSET = (float(0.0), float(0.0))

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    try:
        units = kwargs["units"]
    except KeyError:
        units = "microseconds"

    try:
        cut_val = kwargs["cut_val"]
    except KeyError:
        cut_val = None

    try:
        cut_less = kwargs["cut_less"]
    except KeyError:
        cut_less = True

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "Angstroms", axis)
        result.setAxisLabel(axis, "wavelength")
        result.setYUnits("Counts/A")
        result.setYLabel("Intensity")
    else:
        pass

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

    if time_zero_slope is not None:
        t_0_slope_descr = hlr_utils.get_descr(time_zero_slope)
    else:
        if o_descr == "SOM":
            try:
                t_0_slope = obj.attr_list["Time_zero_slope"][0]
                t_0_slope_err2 = obj.attr_list["Time_zero_slope"][1]
            except KeyError:
                t_0_slope = TIME_ZERO_SLOPE[0]
                t_0_slope_err2 = TIME_ZERO_SLOPE[1]
        else:
            t_0_slope = TIME_ZERO_SLOPE[0]
            t_0_slope_err2 = TIME_ZERO_SLOPE[1]

    if time_zero_offset is not None:
        t_0_offset_descr = hlr_utils.get_descr(time_zero_offset)
    else:
        if o_descr == "SOM":
            try:
                t_0_offset = obj.attr_list["Time_zero_offset"][0]
                t_0_offset_err2 = obj.attr_list["Time_zero_offset"][1]
            except KeyError:
                t_0_offset = TIME_ZERO_OFFSET[0]
                t_0_offset_err2 = TIME_ZERO_OFFSET[1]
        else:
            t_0_offset = TIME_ZERO_OFFSET[0]
            t_0_offset_err2 = TIME_ZERO_OFFSET[1]

    # iterate through the values
    import axis_manip
    if lojac or cut_val is not None:
        import utils

    for i in xrange(hlr_utils.get_length(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(inst_param, map_so, inst)
        else:
            pl = hlr_utils.get_value(pathlength, i, p_descr)
            pl_err2 = hlr_utils.get_err2(pathlength, i, p_descr)

        if time_zero_slope is not None:
            t_0_slope = hlr_utils.get_value(time_zero_slope, i,
                                            t_0_slope_descr)
            t_0_slope_err2 = hlr_utils.get_err2(time_zero_slope, i,
                                                t_0_slope_descr)
        else:
            pass

        if time_zero_offset is not None:
            t_0_offset = hlr_utils.get_value(time_zero_offset, i,
                                             t_0_offset_descr)
            t_0_offset_err2 = hlr_utils.get_err2(time_zero_offset, i,
                                                 t_0_offset_descr)
        else:
            pass

        value = axis_manip.tof_to_wavelength_lin_time_zero(
            val, err2, pl, pl_err2, t_0_slope, t_0_slope_err2, t_0_offset,
            t_0_offset_err2)

        if cut_val is not None:
            index = utils.bisect_helper(value[0], cut_val)
            if cut_less:
                # Need to cut at this index, so increment by one
                index += 1
                value[0].__delslice__(0, index)
                value[1].__delslice__(0, index)
                map_so.y.__delslice__(0, index)
                map_so.var_y.__delslice__(0, index)
                if lojac:
                    val.__delslice__(0, index)
                    err2.__delslice__(0, index)
            else:
                len_data = len(value[0])
                # All axis arrays need starting index adjusted by one since
                # they always carry one more bin than the data
                value[0].__delslice__(index + 1, len_data)
                value[1].__delslice__(index + 1, len_data)
                map_so.y.__delslice__(index, len_data)
                map_so.var_y.__delslice__(index, len_data)
                if lojac:
                    val.__delslice__(index + 1, len_data)
                    err2.__delslice__(index + 1, len_data)

        if lojac:
            counts = utils.linear_order_jacobian(val, value[0], map_so.y,
                                                 map_so.var_y)
            hlr_utils.result_insert(result, res_descr, counts, map_so, "all",
                                    axis, [value[0]])

        else:
            hlr_utils.result_insert(result, res_descr, value, map_so, "x",
                                    axis)

    return result
예제 #26
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
예제 #27
0
def create_X_vs_pixpos(som, *args, **kwargs):
    """
    This function takes a group of single spectrum with any given axes
    (wavelength, energy etc.) and rebins those axes to the given axis and
    converts the spectra into a single I{I(X, pixel)} spectrum.

    @param som: The input object with arbitrary (but same) axis spectra
    @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. Axis
                 With errors
                   1. Axis
                   2. Axis error^2
    @type args: C{nessi_list.NessiList}s
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword withXVar: A 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: 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 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_label: The second primary axis label
    @type x_label: C{string}
    
    @keyword x_units: The second primary axis units
    @type x_units: C{string}

    @keyword rebin: A flag for turning rebin on or off. The default is I{True}.
    @type rebin: C{boolean}


    @return: Object with a single 2D C{SO} with the given axis and global pixel
             position
    @rtype: C{SOM.SOM}


    @raise RuntimeError: The parameter given to the keyword argument withXVar
                         is not I{True} or I{False}
                         
    @raise RuntimeError: The parameter given to the keyword argument data_type
                         is not I{histogram} or I{density} or I{coordinate}.
                         
    @raise RuntimeError: The number of given arguments (x-axes) is not either 2
                         (no errors) or 4 (with errors)
    """

    import common_lib
    import nessi_list

    # Setup some variables 
    dim = 2
    N_y = []
    N_tot = 1
    N_args = len(args)

    # 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 != 2:
                raise RuntimeError("Since you have requested x errors, 2 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 != 1:
            raise RuntimeError("Since you did not requested x errors, 1 "\
                               +"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

    so_dim = SOM.SO(dim)

    arb_axis = 1
    pixel_axis = 0

    # Set the x-axis arguments from the *args list into the new SO
    if not xvar:
        so_dim.axis[arb_axis].val = args[0]
    else:
        so_dim.axis[arb_axis].val = args[0]
        so_dim.axis[arb_axis].var = args[1]

    # Set individual value axis sizes (not x-axis size)
    N_y.append(len(args[0]) - offset)

    # Calculate total 2D array size
    N_som = len(som)
    N_tot = N_som * N_y[-1]

    # Make second axis on total number of pixels
    so_dim.axis[pixel_axis].val = hlr_utils.make_axis(0, N_som, 1)
    if xvar:
        so_dim.axis[pixel_axis].var = nessi_list.NessiList(N_som+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)

    # Check for rebinning
    try:
        rebin = kwargs["rebin"]
    except KeyError:
        rebin = True

    # Rebin data to X axis
    if rebin:
        som_1 = common_lib.rebin_axis_1D(som, args[0])
    else:
        som_1 = som

    del som

    import array_manip
    
    for i in xrange(hlr_utils.get_length(som_1)):

        val = hlr_utils.get_value(som_1, i, "SOM", "y")
        err2 = hlr_utils.get_err2(som_1, i, "SOM", "y")

        start = i * N_y[0]

        (so_dim.y, so_dim.var_y) = array_manip.add_ncerr(so_dim.y,
                                                         so_dim.var_y,
                                                         val,
                                                         err2,
                                                         a_start=start)

        
    # Check for so_id keyword argument
    try:
        so_dim.id = kwargs["so_id"]
    except KeyError:
        so_dim.id = 0

    comb_som = SOM.SOM()
    comb_som.copyAttributes(som_1)

    del som_1

    # 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(["Pixel Number", kwargs["x_label"]])
    except KeyError:
        comb_som.setAllAxisLabels(["Pixel Number", "Arbitrary"])

    # Check for x_units keyword argument
    try:
        comb_som.setAllAxisUnits(["Pixel#", kwargs["x_units"]])
    except KeyError:
        comb_som.setAllAxisUnits(["Pixel#", "Arb"])

    comb_som.append(so_dim)

    del so_dim

    return comb_som
예제 #28
0
def integrate_spectra(obj, **kwargs):
    """
    This function takes a set of spectra and calculates the integration for the
    primary axis. If the integration range for a spectrum cannot be found, an
    error report will be generated with the following information:

    Range not found: pixel ID, start bin, end bin, length of data array
       
    A failing pixel will have the integration tuple set to C{(nan, nan)}.

    @param obj: Object containing spectra that will have the integration
                calculated from them.
    @type obj: C{SOM.SOM} or C{SOM.SO}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword start: The start range for the integration.
    @type start: C{int}
    
    @keyword end: The end range for the integration. 
                  function.
    @type end: C{int}
    
    @keyword axis_pos: This is position of the axis in the axis array. If no
                       argument is given, the default value is I{0}.
    @type axis_pos: C{int}

    @keyword norm: This is a flag to turn on the division of the individual
                   spectrum integrations by the solid angle of the
                   corresponding pixel. This also activates the multiplication
                   of the individual spectrum bin values by their
                   corresponding bin width via the I{width} flag in
                   L{integrate_axis}. The default value of the flag is
                   I{False}.
    @type norm: C{boolean}

    @keyword total: This is a flag to turn on the summation of all individual
                    spectrum integrations. The default value of the flag is
                    I{False}.
    @type total: C{boolean}

    @keyword width: This is a flag to turn on the removal of the individual bin
                    width in the L{integrate_axis} function while doing the
                    integrations. The default value of the flag is I{False}. 
    @type width: C{boolean}
    
    
    @return: Object containing the integration and the uncertainty squared
             associated with the integration
    @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)
    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    # Check for axis_pos keyword argument
    try:
        axis_pos = kwargs["axis_pos"]
    except KeyError:
        axis_pos = 0

    # Check for norm keyword argument
    try:
        norm = kwargs["norm"]
        if norm:
            if o_descr == "SO":
                raise RuntimeError("Cannot use norm keyword with SO!")

            width = True
            inst = obj.attr_list.instrument
        else:
            width = False
    except KeyError:
        norm = False
        width = False

    # Check for total keyword argument
    try:
        total = kwargs["total"]
    except KeyError:
        total = False

    # Check for width keyword argument only if norm isn't present
    if not norm:
        try:
            width = kwargs["width"]
        except KeyError:
            width = False

    # If the integration start bound is not given, set to infinity
    try:
        i_start = kwargs["start"]
    except KeyError:
        i_start = float("inf")

    # If the integration end bound is not given, set to infinity
    try:
        i_end = kwargs["end"]
    except KeyError:
        i_end = float("inf")

    # iterate through the values
    import dr_lib

    len_obj = hlr_utils.get_length(obj)
    for i in xrange(len_obj):
        obj1 = hlr_utils.get_value(obj, i, o_descr, "all")

        # If there's a NaN at the front and back, there are NaN's everywhere
        if str(obj1.axis[axis_pos].val[0]) == "nan" and \
               str(obj1.axis[axis_pos].val[-1]) == "nan":
            print "Range not found:", obj1.id, i_start, i_end, len(obj1)
            value = (float('nan'), float('nan'))
        else:
            value = dr_lib.integrate_axis(obj1,
                                          start=i_start,
                                          end=i_end,
                                          width=width)
        if norm:
            if inst.get_name() == "BSS":
                map_so = hlr_utils.get_map_so(obj, None, i)
                dOmega = dr_lib.calc_BSS_solid_angle(map_so, inst)

                value1 = (value[0] / dOmega, value[1] / (dOmega * dOmega))
            else:
                raise RuntimeError("Do not know how to get solid angle from "\
                                   +"%s" % inst.get_name())
        else:
            value1 = value

        hlr_utils.result_insert(result, res_descr, value1, obj1, "yonly")

    if not total:
        return result
    else:
        # Sum all integration counts
        total_counts = 0
        total_err2 = 0

        for j in xrange(hlr_utils.get_length(result)):
            total_counts += hlr_utils.get_value(result, j, res_descr, "y")
            total_err2 += hlr_utils.get_err2(result, j, res_descr, "y")

        # Create new result object
        (result2, res2_descr) = hlr_utils.empty_result(result)

        result2 = hlr_utils.copy_som_attr(result2, res2_descr, result,
                                          res_descr)

        res1 = hlr_utils.get_value(result, 0, res_descr, "all")
        hlr_utils.result_insert(result2, res2_descr,
                                (total_counts, total_err2), res1, "yonly")
        return result2
예제 #29
0
def tof_to_initial_wavelength_igs_lin_time_zero(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to initial_wavelength_igs_lin_time_zero. The time-of-flight
    axis for a C{SOM} must be in units of I{microseconds}. The primary axis of
    a C{SO} is assumed to be in units of I{microseconds}. A C{tuple} of
    C{(tof, tof_err2)} (assumed to be in units of I{microseconds}) can be
    converted to C{(initial_wavelength_igs, initial_wavelength_igs_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword lambda_f:The final wavelength and its associated error^2
    @type lambda_f: C{tuple}
    
    @keyword time_zero_slope: The time zero slope and its associated error^2
    @type time_zero_slope: C{tuple}

    @keyword time_zero_offset: The time zero offset and its associated error^2
    @type time_zero_offset: C{tuple}
    
    @keyword dist_source_sample: The source to sample distance information and
                                 its associated error^2
    @type dist_source_sample: C{tuple} or C{list} of C{tuple}s 

    @keyword dist_sample_detector: The sample to detector distance information
                                   and its associated error^2
    @type dist_sample_detector: C{tuple} or C{list} of C{tuple}s
    
    @keyword run_filter: This determines if the filter on the negative
                         wavelengths is run. The default setting is True.
    @type run_filter: C{boolean}

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is True for
                    histogram data.
    @type lojac: C{boolean}
    
    @keyword units: The expected units for this function. The default for this
                    function is I{microseconds}
    @type units: C{string}


    @return: Object with a primary axis in time-of-flight converted to
             initial_wavelength_igs
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{microseconds}
    """

    # 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)

    # Setup keyword arguments
    try:
        lambda_f = kwargs["lambda_f"]
    except KeyError:
        lambda_f = None

    try:
        time_zero_slope = kwargs["time_zero_slope"]
    except KeyError:
        time_zero_slope = None

    # Current constants for Time Zero Slope
    TIME_ZERO_SLOPE = (float(0.0), float(0.0))

    try:
        time_zero_offset = kwargs["time_zero_offset"]
    except KeyError:
        time_zero_offset = None

    # Current constants for Time Zero Offset
    TIME_ZERO_OFFSET = (float(0.0), float(0.0))

    try:
        dist_source_sample = kwargs["dist_source_sample"]
    except KeyError:
        dist_source_sample = None

    try:
        dist_sample_detector = kwargs["dist_sample_detector"]
    except KeyError:
        dist_sample_detector = None

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    try:
        units = kwargs["units"]
    except KeyError:
        units = "microseconds"

    try:
        run_filter = kwargs["run_filter"]
    except KeyError:
        run_filter = True

    try:
        iobj = kwargs["iobj"]
    except KeyError:
        iobj = None

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "Angstroms", axis)
        result.setAxisLabel(axis, "wavelength")
        result.setYUnits("Counts/A")
        result.setYLabel("Intensity")
    else:
        pass

    # Where to get instrument information
    if dist_source_sample is None or dist_sample_detector is None:
        if o_descr == "SOM":
            try:
                obj.attr_list.instrument.get_primary()
                inst = obj.attr_list.instrument
                mobj = obj
            except RuntimeError:
                raise RuntimeError("A detector was not provided!")
        else:
            if iobj is None:
                if dist_source_sample is None and dist_sample_detector is None:
                    raise RuntimeError("If a SOM is not passed, the "\
                                       +"source-sample and sample-detector "\
                                       +"distances must be provided.")
                elif dist_source_sample is None:
                    raise RuntimeError("If a SOM is not passed, the "\
                                       +"source-sample distance must be "\
                                       +"provided.")
                elif dist_sample_detector is None:
                    raise RuntimeError("If a SOM is not passed, the "\
                                       +"sample-detector distance must be "\
                                       +"provided.")
                else:
                    raise RuntimeError("If you get here, see Steve Miller "\
                                       +"for your mug.")
            else:
                inst = iobj.attr_list.instrument
                mobj = iobj
    else:
        mobj = obj

    if lambda_f is not None:
        l_descr = hlr_utils.get_descr(lambda_f)
    else:
        if o_descr == "SOM":
            try:
                som_l_f = obj.attr_list["Wavelength_final"]
            except KeyError:
                raise RuntimeError("Please provide a final wavelength "\
                                   +"parameter either via the function call "\
                                   +"or the SOM")
        else:
            if iobj is None:
                raise RuntimeError("You need to provide a final wavelength")
            else:
                som_l_f = iobj.attr_list["Wavelength_final"]

    if time_zero_slope is not None:
        t_0_slope_descr = hlr_utils.get_descr(time_zero_slope)
    else:
        if o_descr == "SOM":
            try:
                t_0_slope = obj.attr_list["Time_zero_slope"][0]
                t_0_slope_err2 = obj.attr_list["Time_zero_slope"][1]
            except KeyError:
                t_0_slope = TIME_ZERO_SLOPE[0]
                t_0_slope_err2 = TIME_ZERO_SLOPE[1]
        else:
            t_0_slope = TIME_ZERO_SLOPE[0]
            t_0_slope_err2 = TIME_ZERO_SLOPE[1]

    if time_zero_offset is not None:
        t_0_offset_descr = hlr_utils.get_descr(time_zero_offset)
    else:
        if o_descr == "SOM":
            try:
                t_0_offset = obj.attr_list["Time_zero_offset"][0]
                t_0_offset_err2 = obj.attr_list["Time_zero_offset"][1]
            except KeyError:
                t_0_offset = TIME_ZERO_OFFSET[0]
                t_0_offset_err2 = TIME_ZERO_OFFSET[1]
        else:
            t_0_offset = TIME_ZERO_OFFSET[0]
            t_0_offset_err2 = TIME_ZERO_OFFSET[1]

    if dist_source_sample is not None:
        ls_descr = hlr_utils.get_descr(dist_source_sample)
    # Do nothing, go on
    else:
        pass

    if dist_sample_detector is not None:
        ld_descr = hlr_utils.get_descr(dist_sample_detector)
    # Do nothing, go on
    else:
        pass

    # iterate through the values
    import axis_manip
    if lojac:
        import utils

    for i in xrange(hlr_utils.get_length(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(mobj, None, i)

        if dist_source_sample is None:
            (L_s, L_s_err2) = hlr_utils.get_parameter("primary", map_so, inst)
        else:
            L_s = hlr_utils.get_value(dist_source_sample, i, ls_descr)
            L_s_err2 = hlr_utils.get_err2(dist_source_sample, i, ls_descr)

        if dist_sample_detector is None:
            (L_d, L_d_err2) = hlr_utils.get_parameter("secondary", map_so,
                                                      inst)
        else:
            L_d = hlr_utils.get_value(dist_sample_detector, i, ld_descr)
            L_d_err2 = hlr_utils.get_err2(dist_sample_detector, i, ld_descr)

        if lambda_f is not None:
            l_f = hlr_utils.get_value(lambda_f, i, l_descr)
            l_f_err2 = hlr_utils.get_err2(lambda_f, i, l_descr)
        else:
            l_f_tuple = hlr_utils.get_special(som_l_f, map_so)
            l_f = l_f_tuple[0]
            l_f_err2 = l_f_tuple[1]

        if time_zero_slope is not None:
            t_0_slope = hlr_utils.get_value(time_zero_slope, i,
                                            t_0_slope_descr)
            t_0_slope_err2 = hlr_utils.get_err2(time_zero_slope, i,
                                                t_0_slope_descr)
        else:
            pass

        if time_zero_offset is not None:
            t_0_offset = hlr_utils.get_value(time_zero_offset, i,
                                             t_0_offset_descr)
            t_0_offset_err2 = hlr_utils.get_err2(time_zero_offset, i,
                                                 t_0_offset_descr)
        else:
            pass

        value = axis_manip.tof_to_initial_wavelength_igs_lin_time_zero(
            val, err2, l_f, l_f_err2, t_0_slope, t_0_slope_err2, t_0_offset,
            t_0_offset_err2, L_s, L_s_err2, L_d, L_d_err2)

        # Remove all wavelengths < 0
        if run_filter:
            index = 0
            for valx in value[0]:
                if valx >= 0:
                    break
                index += 1

            value[0].__delslice__(0, index)
            value[1].__delslice__(0, index)
            map_so.y.__delslice__(0, index)
            map_so.var_y.__delslice__(0, index)
            if lojac:
                val.__delslice__(0, index)
                err2.__delslice__(0, index)
        else:
            pass

        if lojac:
            try:
                counts = utils.linear_order_jacobian(val, value[0], map_so.y,
                                                     map_so.var_y)
            except Exception, e:
                # Lets us know offending pixel ID
                raise Exception(str(map_so.id) + " " + str(e))

            hlr_utils.result_insert(result, res_descr, counts, map_so, "all",
                                    axis, [value[0]])

        else:
            hlr_utils.result_insert(result, res_descr, value, map_so, "x",
                                    axis)
def wavelength_to_scalar_Q(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from wavelength
    to scalar Q. The wavelength axis for a C{SOM} must be in units of
    I{Angstroms}. The primary axis of a C{SO} is assumed to be in units of
    I{Angstroms}. A C{tuple} of C{(wavelength, wavelength_err2)} (assumed to
    be in units of I{Angstroms}) can be converted to C{(scalar_Q,
    scalar_Q_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword polar: The polar angle and its associated error^2
    @type polar: C{tuple} or C{list} of C{tuple}s
    
    @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{Angstroms}.
    @type units: C{string}
 

    @return: Object with a primary axis in wavelength converted to scalar Q
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: A C{SOM} is not passed and no polar angle is provided
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{Angstroms}
    """
    
    # 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 == "list":
        raise TypeError("Do not know how to handle given type: %s" % \
                        o_descr)
    else:
        pass

    # Setup keyword arguments
    try:
        polar = kwargs["polar"]
    except KeyError:
        polar = None

    try:
        units = kwargs["units"]
    except KeyError:
        units = "Angstroms"

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

    if polar is None:
        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 polar "\
                               +"information must be given.")
    else:
        p_descr = hlr_utils.get_descr(polar)

    # iterate through the values
    import axis_manip
    if lojac:
        import utils
    
    for i in xrange(hlr_utils.get_length(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 polar is None:
            (angle, angle_err2) = hlr_utils.get_parameter("polar", map_so,
                                                          inst)
        else:
            angle = hlr_utils.get_value(polar, i, p_descr)
            angle_err2 = hlr_utils.get_err2(polar, i, p_descr) 

        value = axis_manip.wavelength_to_scalar_Q(val, err2, angle, angle_err2)

        if lojac:
            y_val = hlr_utils.get_value(obj, i, o_descr, "y")
            y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
            counts = utils.linear_order_jacobian(val, value[0],
                                                 y_val, y_err2)
        else:
            pass

        if o_descr != "number":
            value1 = axis_manip.reverse_array_cp(value[0])
            value2 = axis_manip.reverse_array_cp(value[1])
            rev_value = (value1, value2)
        else:
            rev_value = value

        if map_so is not None:
            if not lojac:
                map_so.y = axis_manip.reverse_array_cp(map_so.y)
                map_so.var_y = axis_manip.reverse_array_cp(map_so.var_y)
            else:
                map_so.y = axis_manip.reverse_array_cp(counts[0])
                map_so.var_y = axis_manip.reverse_array_cp(counts[1])
        else:
            pass
        
        hlr_utils.result_insert(result, res_descr, rev_value, map_so, "x",
                                axis)

    return result
예제 #31
0
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
예제 #32
0
def shift_spectrum(obj, shift_point, min_ext, max_ext, scale_const=None):
    """
    This function takes a given spectrum and a central value and creates
    a spectrum that is shifted about that point. Values greater than the point
    are moved to the beginning of the new spectrum and values less than the
    point are move towards the end of the new spectrum.
    
    @param obj: Monitor object that will be shifted
    @type obj: C{SOM.SOM} or C{SOM.SO}

    @param shift_point: The point in the spectrum about which to shift the
    data.
    @type shift_point: C{list} of C{floats}

    @param min_ext: The minimum extent of the axis to shift.
    @type min_ext: C{list} of C{floats}

    @param max_ext: The maximum extent of the axis to shift.
    @type max_ext: C{list} of C{floats}
    
    @param scale_const: A scaling constant to apply (multiply) to the newly
                        shifted spectrum. The default is I{None}.
    @type scale_const: C{float}


    @return: Monitor spectrum that have been shifted
    @rtype: C{SOM.SOM} or C{SOM.SO}
    """
    # 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)
    s_descr = hlr_utils.get_descr(shift_point)
    ie_descr = hlr_utils.get_descr(min_ext)
    ae_descr = hlr_utils.get_descr(max_ext)

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    import array_manip
    import utils

    len_obj = hlr_utils.get_length(obj)
    for i in xrange(len_obj):
        val = hlr_utils.get_value(obj, i, o_descr, "y")
        err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
        x_axis = hlr_utils.get_value(obj, i, o_descr, "x", 0)
        x_err2 = hlr_utils.get_err2(obj, i, o_descr, "x", 0)
        map_so = hlr_utils.get_map_so(obj, None, i)

        bin_center = utils.calc_bin_centers(x_axis, x_err2)

        # Get shift point and extents
        sp = hlr_utils.get_value(shift_point, i, s_descr, "y")
        ie = hlr_utils.get_value(min_ext, i, ie_descr, "y")
        ae = hlr_utils.get_value(max_ext, i, ae_descr, "y")

        # Make shifted spectrum
        value0 = utils.shift_spectrum(val, err2, x_axis, bin_center[0], sp, ie,
                                      ae)

        # Scale spectrum if necessary
        if scale_const is not None:
            value1 = array_manip.mult_ncerr(value0[0], value0[1], scale_const,
                                            0.0)
        else:
            value1 = value0

        hlr_utils.result_insert(result, res_descr, value1, map_so, "y")

    return result
예제 #33
0
def tof_to_ref_scalar_Q(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to reflectometer scalar Q. This means that a single angle
    and a single flightpath is used. The time-of-flight axis for a C{SOM} must
    be in units of I{microseconds}. The primary axis of a C{SO} is assumed to
    be in units of I{microseconds}. A C{tuple} of C{(time-of-flight,
    time-of-flight_err2)} (assumed to be in units of I{microseconds}) can be
    converted to C{(scalar_Q, scalar_Q_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword polar: The polar angle and its associated error^2
    @type polar: C{tuple}
    
    @keyword pathlength: The pathlength and its associated error^2
    @type pathlength: C{tuple}

    @keyword angle_offset: A constant offset for the polar angle and its
                           associated error^2. The units of the offset should
                           be in radians.
    @type angle_offset: C{tuple}

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is True for
                    histogram data.
    @type lojac: C{boolean}    
    
    @keyword units: The expected units for this function. The default for this
                    function is I{microseconds}.
    @type units: C{string}

    @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 with a primary axis in time-of-flight converted to
             reflectometer scalar Q
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: A C{SOM} is not passed and no polar angle is provided
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{microseconds}
    """

    # 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 == "list":
        raise TypeError("Do not know how to handle given type: %s" % \
                        o_descr)
    else:
        pass

    # Setup keyword arguments
    polar = kwargs.get("polar")
    pathlength = kwargs.get("pathlength")
    units = kwargs.get("units", "microseconds")
    lojac = kwargs.get("lojac", hlr_utils.check_lojac(obj))
    angle_offset = kwargs.get("angle_offset")
    config = kwargs.get("configure")

    if config is None:
        beamdiv_corr = False
    else:
        beamdiv_corr = config.beamdiv_corr

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

    if pathlength is None or polar is None:
        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:
            if pathlength is None and polar is None:
                raise RuntimeError("If no SOM is provided, then pathlength "\
                                   +"and polar angle information must be "\
                                   +"provided")
            elif pathlength is None:
                raise RuntimeError("If no SOM is provided, then pathlength "\
                                   +"information must be provided")
            elif polar is None:
                raise RuntimeError("If no SOM is provided, then polar angle "\
                                   +"information must be provided")
            else:
                raise RuntimeError("If you get here, see Steve Miller for "\
                                   +"your mug.")
    else:
        pass

    if pathlength is None:
        (pl,
         pl_err2) = obj.attr_list.instrument.get_total_path(obj[0].id,
                                                            det_secondary=True)
    else:
        (pl, pl_err2) = pathlength

    if polar is None:
        angle = hlr_utils.get_special(obj.attr_list["data-theta"], obj[0])[0]
        angle_err2 = 0.0
    else:
        (angle, angle_err2) = polar

    if angle_offset is not None:
        angle += angle_offset[0]
        angle_err2 += angle_offset[1]

    # Need to multiply angle by 2.0 in order to make it be Theta to
    # underlying conversion function
    angle *= 2.0
    angle_err2 *= 4.0

    # iterate through the values
    import axis_manip
    if lojac:
        import utils

    if beamdiv_corr:
        import dr_lib

    for i in xrange(hlr_utils.get_length(obj)):
        skip_pixel = False
        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 beamdiv_corr:
            dangle = dr_lib.ref_beamdiv_correct(obj.attr_list, map_so.id,
                                                config.det_spat_res,
                                                config.center_pix)
            # We subtract due to the inversion of the z coordinates from the
            # mirror reflection of the beam at the sample.
            if dangle is not None:
                pangle = angle - (2.0 * dangle)
            else:
                pangle = angle
                skip_pixel = True
        else:
            pangle = angle

        value = axis_manip.tof_to_scalar_Q(val, err2, pl, pl_err2, pangle,
                                           angle_err2)

        if lojac:
            y_val = hlr_utils.get_value(obj, i, o_descr, "y")
            y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
            counts = utils.linear_order_jacobian(val, value[0], y_val, y_err2)
        else:
            pass

        if o_descr != "number":
            value1 = axis_manip.reverse_array_cp(value[0])
            value2 = axis_manip.reverse_array_cp(value[1])
            rev_value = (value1, value2)
        else:
            rev_value = value

        if map_so is not None:
            if not lojac:
                map_so.y = axis_manip.reverse_array_cp(map_so.y)
                map_so.var_y = axis_manip.reverse_array_cp(map_so.var_y)
            else:
                map_so.y = axis_manip.reverse_array_cp(counts[0])
                map_so.var_y = axis_manip.reverse_array_cp(counts[1])
        else:
            pass

        if not skip_pixel:
            hlr_utils.result_insert(result, res_descr, rev_value, map_so, "x",
                                    axis)

    return result
예제 #34
0
def integrate_spectra(obj, **kwargs):
    """
    This function takes a set of spectra and calculates the integration for the
    primary axis. If the integration range for a spectrum cannot be found, an
    error report will be generated with the following information:

    Range not found: pixel ID, start bin, end bin, length of data array
       
    A failing pixel will have the integration tuple set to C{(nan, nan)}.

    @param obj: Object containing spectra that will have the integration
                calculated from them.
    @type obj: C{SOM.SOM} or C{SOM.SO}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword start: The start range for the integration.
    @type start: C{int}
    
    @keyword end: The end range for the integration. 
                  function.
    @type end: C{int}
    
    @keyword axis_pos: This is position of the axis in the axis array. If no
                       argument is given, the default value is I{0}.
    @type axis_pos: C{int}

    @keyword norm: This is a flag to turn on the division of the individual
                   spectrum integrations by the solid angle of the
                   corresponding pixel. This also activates the multiplication
                   of the individual spectrum bin values by their
                   corresponding bin width via the I{width} flag in
                   L{integrate_axis}. The default value of the flag is
                   I{False}.
    @type norm: C{boolean}

    @keyword total: This is a flag to turn on the summation of all individual
                    spectrum integrations. The default value of the flag is
                    I{False}.
    @type total: C{boolean}

    @keyword width: This is a flag to turn on the removal of the individual bin
                    width in the L{integrate_axis} function while doing the
                    integrations. The default value of the flag is I{False}. 
    @type width: C{boolean}
    
    
    @return: Object containing the integration and the uncertainty squared
             associated with the integration
    @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)
    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    # Check for axis_pos keyword argument
    try:
        axis_pos = kwargs["axis_pos"]
    except KeyError:
        axis_pos = 0

    # Check for norm keyword argument
    try:
        norm = kwargs["norm"]
        if norm:
            if o_descr == "SO":
                raise RuntimeError("Cannot use norm keyword with SO!")
            
            width = True
            inst = obj.attr_list.instrument
        else:
            width = False
    except KeyError:
        norm = False
        width = False

    # Check for total keyword argument
    try:
        total = kwargs["total"]
    except KeyError:
        total = False

    # Check for width keyword argument only if norm isn't present
    if not norm:
        try:
            width = kwargs["width"]
        except KeyError:
            width = False

    # If the integration start bound is not given, set to infinity
    try:
        i_start = kwargs["start"]
    except KeyError:
        i_start = float("inf")

    # If the integration end bound is not given, set to infinity
    try:
        i_end = kwargs["end"]
    except KeyError:
        i_end = float("inf")
    
    # iterate through the values
    import dr_lib

    len_obj = hlr_utils.get_length(obj)
    for i in xrange(len_obj):
        obj1 = hlr_utils.get_value(obj, i, o_descr, "all")

        # If there's a NaN at the front and back, there are NaN's everywhere
        if str(obj1.axis[axis_pos].val[0]) == "nan" and \
               str(obj1.axis[axis_pos].val[-1]) == "nan":
            print "Range not found:", obj1.id, i_start, i_end, len(obj1)
            value = (float('nan'), float('nan'))
        else:
            value = dr_lib.integrate_axis(obj1, start=i_start, end=i_end,
                                          width=width)
        if norm:
            if inst.get_name() == "BSS":
                map_so = hlr_utils.get_map_so(obj, None, i)
                dOmega = dr_lib.calc_BSS_solid_angle(map_so, inst)
        
                value1 = (value[0] / dOmega, value[1] / (dOmega * dOmega))
            else:
                raise RuntimeError("Do not know how to get solid angle from "\
                                   +"%s" % inst.get_name())
        else:
            value1 = value

        hlr_utils.result_insert(result, res_descr, value1, obj1, "yonly")

    if not total:
        return result
    else:
        # Sum all integration counts
        total_counts = 0
        total_err2 = 0

        for j in xrange(hlr_utils.get_length(result)):
            total_counts += hlr_utils.get_value(result, j, res_descr, "y")
            total_err2 += hlr_utils.get_err2(result, j, res_descr, "y")

        # Create new result object
        (result2, res2_descr) = hlr_utils.empty_result(result)

        result2 = hlr_utils.copy_som_attr(result2, res2_descr,
                                          result, res_descr)

        res1 = hlr_utils.get_value(result, 0, res_descr, "all")
        hlr_utils.result_insert(result2, res2_descr,
                                (total_counts, total_err2),
                                res1, "yonly")
        return result2
예제 #35
0
def add_ncerr(left, right, **kwargs):
    """
    This function adds two objects (C{SOM}, C{SO} or C{tuple(val,val_err2)})
    and returns the result of the addition in an C{SOM}, C{SO} or C{tuple}. 

    @param left:  Object on the left of the addition sign
    @type left: C{SOM.SOM} or C{SOM.SO} or C{tuple}
    
    @param right: Object on the right of the addition sign
    @type right: C{SOM.SOM} or C{SOM.SO} or C{tuple}

    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword axis: This is the axis one wishes to manipulate. If no argument
                   is given the default value is y
    @type axis: C{string}=<y or x>
    
    @keyword axis_pos: This is position of the axis in the axis array. If no
                       argument is given, the default value is 0
    @type axis_pos: C{int}
    
    @keyword length_one_som: This is a flag that lets the function know it is
                             dealing with a length 1 C{SOM} so that attributes
                             may be passed along. The length 1 C{SOM} will be
                             turned into a C{SO}. The default value is False.
    @type length_one_som: C{boolean}
    
    @keyword length_one_som_pos: This is the argument position of the
                                 length 1 C{SOM} since the check is done
                                 before the arguments are swapped. The default
                                 value is 2.
    @type length_one_som_pos: C{int}=<1 or 2>
    
    @keyword add_nxpars: This is a flag that will turn on code to add
                         C{SOM.NxParameters} in the two C{SOM}'s attribute
                         lists.
    @type add_nxpars: C{boolean} 


    @return: Object containing the results of the addition
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise IndexError: The two C{SOM}s do not contain the same number of
                       spectra
                       
    @raise RunTimeError: The x-axis units of the C{SOM}s do not match
    
    @raise RunTimeError: The y-axis units of the C{SOM}s do not match
    
    @raise RunTimeError: The x-axes of the two C{SO}s are not equal
    """
    
    # import the helper functions
    import hlr_utils

    # Check to see if we are working with a length 1 SOM
    try:
        length_one_som = kwargs["length_one_som"]
    except KeyError:
        length_one_som = False

    try:
        length_one_som_pos = kwargs["length_one_som_pos"]
        if length_one_som_pos != 1 or length_one_som_pos != 2:
            raise RuntimeError("length_one_som_pos must be either 1 or 2 and "\
                               +"%d" % length_one_som_pos)
    except KeyError:
        length_one_som_pos = 2

    if length_one_som:
        if length_one_som_pos == 1:
            som_copy = left
            left = left[0]
        else:
            som_copy = right
            right = right[0]
    else:
        # Not working with a length 1 SOM, do nothing
        pass

    # set up for working through data
    (result, res_descr) = hlr_utils.empty_result(left, right)
    (l_descr, r_descr) = hlr_utils.get_descr(left, right)

    is_number = False

    # error check information
    if (r_descr == "SOM" and l_descr != "SOM") \
           or (r_descr == "SO" and l_descr == "number"):
        left, right = hlr_utils.swap_args(left, right)
        (l_descr, r_descr) = hlr_utils.swap_args(l_descr, r_descr)
    elif r_descr == "SOM" and l_descr == "SOM":
        hlr_utils.math_compatible(left, l_descr, right, r_descr)
    elif l_descr == "number" and r_descr == "number":
        is_number = True
    else:
        pass

    # Check for axis keyword argument
    try:
        axis = kwargs["axis"]
    except KeyError:
        axis = "y"
        
    # Check for axis_pos keyword argument
    try:
        axis_pos = kwargs["axis_pos"]
    except KeyError:
        axis_pos = 0

    # Check for add_nxpars keyword argument
    try:
        add_nxpars_val = kwargs["add_nxpars"]
    except KeyError:
        add_nxpars_val = False

    if length_one_som:
        if length_one_som_pos == 1:
            result = hlr_utils.copy_som_attr(result, res_descr,
                                             som_copy, "SOM",
                                             right, r_descr)
        else:
            result = hlr_utils.copy_som_attr(result, res_descr, left, l_descr,
                                             som_copy, "SOM")            
    else:
        result = hlr_utils.copy_som_attr(result, res_descr, left, l_descr,
                                         right, r_descr,
                                         add_nxpars=add_nxpars_val)

    # iterate through the values
    import array_manip
    
    for i in xrange(hlr_utils.get_length(left, right)):
        val1 = hlr_utils.get_value(left, i, l_descr, axis, axis_pos)
        err2_1 = hlr_utils.get_err2(left, i, l_descr, axis, axis_pos)

        val2 = hlr_utils.get_value(right, i, r_descr, axis, axis_pos)
        err2_2 = hlr_utils.get_err2(right, i, r_descr, axis, axis_pos)
        
        (descr_1, descr_2) = hlr_utils.get_descr(val1, val2)

        hlr_utils.math_compatible(val1, descr_1, val2, descr_2)

        value = array_manip.add_ncerr(val1, err2_1, val2, err2_2)

        map_so = hlr_utils.get_map_so(left, None, i)
        hlr_utils.result_insert(result, res_descr, value, map_so, axis,
                                axis_pos)

    if is_number:
        return tuple(result)
    else:
        return result
예제 #36
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: Two objects that have been rebinned according to the provided
             axis. The first object contains the rebinned counts and the second
             contains the fractional area.
    @rtype: C{tuple} of two C{SOM.SOM}s or C{SOM.SO}s


    @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

    (result1, res1_descr) = hlr_utils.empty_result(obj)
    result1 = hlr_utils.copy_som_attr(result1, res1_descr, obj, o_descr)

    (result2, res2_descr) = hlr_utils.empty_result(obj)
    result2 = hlr_utils.copy_som_attr(result2, res2_descr, obj, o_descr)

    # iterate through the values
    import axis_manip

    len_obj = hlr_utils.get_length(obj)
    for i in xrange(len_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]))

        xvals = []
        xvals.append(axis_out)

        map_so = hlr_utils.get_map_so(obj, None, i)

        hlr_utils.result_insert(result1, res1_descr, (value[0], value[1]),
                                map_so, "all", 0, xvals)
        hlr_utils.result_insert(result2, res2_descr, (value[2], frac_err),
                                map_so, "all", 0, xvals)        

    return (result1, result2)
예제 #37
0
def d_spacing_to_tof_focused_det(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from d-spacing
    to a focused time-of-flight. The focusing is done using the geometry
    information from a single detector pixel. The d-spacing axis for a C{SOM}
    must be in units of I{Angstroms}. The primary axis of a C{SO} is assumed
    to be in units of I{Angstroms}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM} or C{SOM.SO}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword polar: The polar angle and its associated error^2
    @type polar: C{tuple} or C{list} of C{tuple}s
    
    @keyword pathlength: The total pathlength and its associated error^2
    @type pathlength: C{tuple} or C{list} of C{tuple}s
    
    @keyword pixel_id: The pixel ID from which the geometry information will
                       be retrieved from the instrument
    @type pixel_id: C{tuple}=(\"bankN\", (x, y))
    
    @keyword verbose: This determines if the pixel geometry information is
                      printed. The default is False
    @type verbose: C{boolean}
    
    @keyword units: The expected units for this function. The default for
                    this function is I{microseconds}.
    @type units: C{string}


    @return: Object with a primary axis in d-spacing converted to
             time-of-flight
    @rtype: C{SOM.SOM} or C{SOM.SO}

 
    @raise RuntimeError: A C{SOM} or C{SO} is not provided to the function
    
    @raise RuntimeError: No C{SOM.Instrument} is provided in a C{SOM}
    
    @raise RuntimeError: No C{SOM} is given and both the pathlength and polar
                         angle are not provided
                         
    @raise RuntimeError: No C{SOM} is given and the pathlength is not provided
    
    @raise RuntimeError: No C{SOM} is given and the polar angle is not provided
    """

    # 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 RuntimeError("Must provide a SOM of a SO to the function.")
    # Go on
    else:
        pass

    # Setup keyword arguments
    try:
        polar = kwargs["polar"]
    except KeyError:
        polar = None
    
    try:
        pathlength = kwargs["pathlength"]
    except KeyError:
        pathlength = None

    try:
        pixel_id = kwargs["pixel_id"]
    except KeyError:
        pixel_id = None

    try:
        verbose = kwargs["verbose"]
    except KeyError:
        verbose = False

    try:
        units = kwargs["units"]
    except KeyError:
        units = "Angstroms"

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "microseconds", axis)
        result.setAxisLabel(axis, "time-of-flight")
        result.setYUnits("Counts/usec")
        result.setYLabel("Intensity")
    else:
        pass

    if pathlength is None or polar is None:
        if o_descr == "SOM":
            try:
                obj.attr_list.instrument.get_primary()
                inst = obj.attr_list.instrument
            except RuntimeError:
                raise RuntimeError("An instrument was not provided")
        else:
            if pathlength is None and polar is None:
                raise RuntimeError("If no SOM is provided, then pathlength "\
                +"and polar angle information must be provided")
            elif pathlength is None:
                raise RuntimeError("If no SOM is provided, then pathlength "\
                +"information must be provided")
            elif polar is None:
                raise RuntimeError("If no SOM is provided, then polar angle "\
                +"information must be provided")
            else:
                raise RuntimeError("If you get here, see Steve Miller for "\
                      +"your mug.")
    else:
        pass

    if pathlength is not None:
        p_descr = hlr_utils.get_descr(pathlength)

    if polar is not None:
        a_descr = hlr_utils.get_descr(polar)

    # iterate through the values
    if pixel_id is not None:
        tmp_so = SOM.SO()
        tmp_so.id = pixel_id
        (pl, pl_err2) = hlr_utils.get_parameter("total", tmp_so, inst)
        (angle, angle_err2) = hlr_utils.get_parameter("polar", tmp_so, inst)

        if verbose:
            format_str = "Pixel ID %s has polar angle: (%f,%f) and "
            format_str += "pathlength: (%f,%f)"
            print format_str % (str(pixel_id), angle, angle_err2, pl, pl_err2)
        else:
            pass
    else:
        pl = hlr_utils.get_value(pathlength, 0, p_descr)
        pl_err2 = hlr_utils.get_err2(pathlength, 0, p_descr)
        angle = hlr_utils.get_value(polar, 0, a_descr)
        angle_err2 = hlr_utils.get_err2(polar, 0, a_descr)

    # iterate through the values
    import axis_manip
    
    for i in xrange(hlr_utils.get_length(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)

        value = axis_manip.d_spacing_to_tof_focused_det(val, err2, pl, pl_err2,
                                                        angle, angle_err2)
                                                        
        hlr_utils.result_insert(result, res_descr, value, map_so, "x", axis)

    return result
def wavelength_to_scalar_k(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from wavelength
    to scalar k. The wavelength axis for a C{SOM} must be in units of
    I{Angstroms}. The primary axis of a C{SO} is assumed to be in units of
    I{Angstroms}. A C{tuple} of C{(wavelength, wavelength_err2)} (assumed to
    be in units of I{Angstroms}) can be converted to C{(scalar_k,
    scalar_k_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @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}
 

    @return: Object with a primary axis in wavelength converted to scalar k
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{Angstroms}
    """

    # 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 == "list":
        raise TypeError("Do not know how to handle given type: %s" % \
                        o_descr)
    else:
        pass

    # Setup keyword arguments
    try:
        units = kwargs["units"]
    except KeyError:
        units = "Angstroms"

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

    # iterate through the values
    import axis_manip

    for i in xrange(hlr_utils.get_length(obj)):
        val = hlr_utils.get_value(obj, i, o_descr, "x", axis)
        err2 = hlr_utils.get_err2(obj, i, o_descr, "x", axis)

        value = axis_manip.wavelength_to_scalar_k(val, err2)
        if o_descr != "number":
            value1 = axis_manip.reverse_array_cp(value[0])
            value2 = axis_manip.reverse_array_cp(value[1])
            rev_value = (value1, value2)
        else:
            rev_value = value

        map_so = hlr_utils.get_map_so(obj, None, i)
        if map_so is not None:
            map_so.y = axis_manip.reverse_array_cp(map_so.y)
            map_so.var_y = axis_manip.reverse_array_cp(map_so.var_y)
        else:
            pass

        hlr_utils.result_insert(result, res_descr, rev_value, map_so, "x",
                                axis)

    return result
def wavelength_to_velocity(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from wavelength
    to velocity. The wavelength axis for a C{SOM} must be in units of
    I{Angstroms}. The primary axis of a C{SO} is assumed to be in
    units of I{Angstroms}. A C{tuple} of C{(wavelength, wavelength_err2)}
    (assumed to be in units of I{Angstroms}) can be converted to
    C{(velocity, velocity_err)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is True for
                    histogram data.
    @type lojac: C{boolean}
    
    @keyword units: The expected units for this function. The default for this
                    function is I{Angstroms}
    @type units: C{string}


    @return: Object with a primary axis in wavelength converted to velocity
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    @raise RuntimeError: The C{SOM} x-axis units are not I{Angstroms}
    """
    # 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 == "list":
        raise TypeError("Do not know how to handle given type: %s" % \
                        o_descr)
    else:
        pass

    # Setup keyword arguments
    try:
        units = kwargs["units"]
    except KeyError:
        units = "Angstroms"

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "meters/microseconds", axis)
        result.setAxisLabel(axis, "velocity")
        result.setYUnits("Counts/meters/microseconds")
        result.setYLabel("Intensity")
    else:
        pass

    # iterate through the values
    import axis_manip
    if lojac:
        import utils

    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)

        value = axis_manip.wavelength_to_velocity(val, err2)

        if lojac:
            y_val = hlr_utils.get_value(obj, i, o_descr, "y")
            y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
            counts = utils.linear_order_jacobian(val, value[0],
                                                 y_val, y_err2)
        else:
            pass

        if o_descr != "number":
            value1 = axis_manip.reverse_array_cp(value[0])
            value2 = axis_manip.reverse_array_cp(value[1])
            rev_value = (value1, value2)
        else:
            rev_value = value
        
        if map_so is not None:
            if not lojac:
                map_so.y = axis_manip.reverse_array_cp(map_so.y)
                map_so.var_y = axis_manip.reverse_array_cp(map_so.var_y)
            else:
                map_so.y = axis_manip.reverse_array_cp(counts[0])
                map_so.var_y = axis_manip.reverse_array_cp(counts[1])
        else:
            pass

        hlr_utils.result_insert(result, res_descr, rev_value, map_so, "x",
                                axis)

    return result
예제 #40
0
def energy_transfer(left, right, **kwargs):
    """
    This function takes a C{tuple} and a C{SOM}, a C{tuple} and a C{SO} or two
    C{tuple}s and calculates the energy transfer in units of I{THz}. The C{SOM}
    principle axis must be in units of I{meV}. The C{SO} and C{tuple}s are
    assumed to be in units of I{meV}.

    @param left: Object on the left side of the subtraction
    @type left: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param right: Object on the right side of the subtraction
    @type right: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @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{meV}
    @type units: C{string}


    @return: Object based on left - right in units of I{THz}
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise RuntimeError: The x-axis units are not I{meV}

    @raise TypeError: C{SOM}-C{SOM} operation not supported

    @raise TypeError: C{SOM}-C{SO} operation not supported

    @raise TypeError: C{SO}-C{SOM} operation not supported

    @raise TypeError: C{SO}-C{SO} operation not supported
    """

    # import the helper functions
    import hlr_utils

    # set up for working through data
    (result, res_descr) = hlr_utils.empty_result(left, right)
    (l_descr, r_descr) = hlr_utils.get_descr(left, right)

    # error checking for types
    if l_descr == "SOM" and r_descr == "SOM":
        raise TypeError("SOM-SOM operation not supported")
    elif l_descr == "SOM" and r_descr == "SO":
        raise TypeError("SOM-SO operation not supported")
    elif l_descr == "SO" and r_descr == "SOM":
        raise TypeError("SO-SOM operation not supported")
    elif l_descr == "SO" and r_descr == "SO":
        raise TypeError("SO-SO operation not supported")
    else:
        pass

    # Setup keyword arguments
    try:
        units = kwargs["units"]
    except KeyError:
        units = "meV"

    result = hlr_utils.copy_som_attr(result, res_descr, left, l_descr, right,
                                     r_descr)
    if res_descr == "SOM":
        index = hlr_utils.one_d_units(result, units)
        result = hlr_utils.force_units(result, "THz", index)
        result.setAxisLabel(index, "energy transfer")
        result.setYUnits("Counts/THz")
        result.setYLabel("Intensity")
    else:
        pass

    # iterate through the values
    import axis_manip

    for i in xrange(hlr_utils.get_length(left, right)):

        val1 = hlr_utils.get_value(left, i, l_descr, "x")
        err2_1 = hlr_utils.get_err2(left, i, l_descr, "x")

        val2 = hlr_utils.get_value(right, i, r_descr, "x")
        err2_2 = hlr_utils.get_err2(right, i, r_descr, "x")

        value = axis_manip.energy_transfer(val1, err2_1, val2, err2_2)

        map_so = hlr_utils.get_map_so(left, right, i)
        hlr_utils.result_insert(result, res_descr, value, map_so, "x")

    return result
def init_scatt_wavevector_to_scalar_Q(initk, scattk, **kwargs):
    """
    This function takes an initial wavevector and a scattered wavevector as a
    C{tuple} and a C{SOM}, a C{tuple} and a C{SO} or two C{tuple}s and
    calculates the quantity scalar Q units of I{1/Angstroms}. The C{SOM}
    principle axis must be in units of I{1/Angstroms}. The C{SO}s and
    C{tuple}(s) is(are) assumed to be in units of I{1/Angstroms}. The polar
    angle must be provided if one of the initial arguments is not a C{SOM}. If
    a C{SOM} is passed, by providing the polar angle at the function call time,
    the polar angle carried in the C{SOM} instrument will be overridden.

    @param initk: Object holding the initial wavevector
    @type initk: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param scattk: Object holding the scattered wavevector
    @type scattk: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword polar: The polar angle and its associated error^2
    @type polar: C{tuple} or C{list} of C{tuple}s

    @keyword units: The expected units for this function. The default for this
                    function is I{1/Angstroms}.
    @type units: C{string}


    @return: Object converted to scalar Q
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The C{SOM}-C{SOM} operation is attempted
    
    @raise TypeError: The C{SOM}-C{SO} operation is attempted
    
    @raise TypeError: The C{SO}-C{SOM} operation is attempted
    
    @raise TypeError: The C{SO}-C{SO} operation is attempted
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{1/Angstroms}
    
    @raise RuntimeError: A C{SOM} is not passed and no polar angle is provided
    
    @raise RuntimeError: No C{SOM.Instrument} is provided in a C{SOM}
    """

    # import the helper functions
    import hlr_utils

    # set up for working through data
    (result, res_descr) = hlr_utils.empty_result(initk, scattk)
    (i_descr, s_descr) = hlr_utils.get_descr(initk, scattk)

    # error checking for types
    if i_descr == "SOM" and s_descr == "SOM":
        raise TypeError("SOM-SOM operation not supported")
    elif i_descr == "SOM" and s_descr == "SO":
        raise TypeError("SOM-SO operation not supported")
    elif i_descr == "SO" and s_descr == "SOM":
        raise TypeError("SO-SOM operation not supported")
    elif i_descr == "SO" and s_descr == "SO":
        raise TypeError("SO-SO operation not supported")
    else:
        pass

    # Setup keyword arguments
    try:
        polar = kwargs["polar"]
    except KeyError:
        polar = None

    try:
        units = kwargs["units"]
    except KeyError:
        units = "1/Angstroms"

    result = hlr_utils.copy_som_attr(result, res_descr, initk, i_descr,
                                     scattk, s_descr)
    if res_descr == "SOM":
        index = hlr_utils.one_d_units(result, units)
        result = hlr_utils.force_units(result, units, index)
        result.setAxisLabel(index, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

    if polar is None:
        if i_descr == "SOM":
            try:
                initk.attr_list.instrument.get_primary()
                inst = initk.attr_list.instrument
            except RuntimeError:
                raise RuntimeError("A detector was not provided!")

        elif s_descr == "SOM":
            try:
                scattk.attr_list.instrument.get_primary()
                inst = scattk.attr_list.instrument
            except RuntimeError:
                raise RuntimeError("A detector was not provided!")

        else:
            raise RuntimeError("If no SOM is provided, then polar "\
                               +"information must be given.")
    else:
        p_descr = hlr_utils.get_descr(polar)

    # iterate through the values
    import axis_manip
    
    for i in xrange(hlr_utils.get_length(initk, scattk)):
        val1 = hlr_utils.get_value(initk, i, i_descr, "x")
        err2_1 = hlr_utils.get_err2(initk, i, i_descr, "x")
        
        val2 = hlr_utils.get_value(scattk, i, s_descr, "x")
        err2_2 = hlr_utils.get_err2(scattk, i, s_descr, "x")

        map_so = hlr_utils.get_map_so(initk, scattk, i)

        if polar is None:
            (angle, angle_err2) = hlr_utils.get_parameter("polar", map_so,
                                                          inst)
        else:
            angle = hlr_utils.get_value(polar, i, p_descr)
            angle_err2 = hlr_utils.get_err2(polar, i, p_descr)
            
        value = axis_manip.init_scatt_wavevector_to_scalar_Q(val1, err2_1,
                                                             val2, err2_2,
                                                             angle, angle_err2)

        hlr_utils.result_insert(result, res_descr, value, map_so, "x")

    return result
예제 #42
0
def integrate_axis(obj, **kwargs):
    """
    This function takes a spectrum and integrates the given axis. The function
    assumes that the incoming data is in the histogram form.

    @param obj: Spectrum to be integrated
    @type obj: C{SOM.SOM} or C{SOM.SO}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword start: Value for the start range of the integration.
    @type start: C{float}
    
    @keyword end: Value for the end range of the integration.
    @type end: C{float}
    
    @keyword width: This is a flag to turn on the multiplication of the
                    individual bin contents with the bins corresponding width.
    @type width: C{boolean}

    @keyword width_pos: This is the position of the x-axis in the axis array
                        from which to calculate the bin widths in support of
                        the width flag. If no argument is given, the default
                        value is I{0}.
    @type width_pos: C{int}

    
    @return: The integration value and its associated error
    @rtype: C{tuple}

    
    @raise RuntimError: A C{SOM} or C{SO} is not given to the function.
    """

    # import the helper functions
    import hlr_utils

    # set up for working through data
    o_descr = hlr_utils.get_descr(obj)

    if o_descr == "number" or o_descr == "list":
        raise RuntimeError("Must provide a SOM of a SO to the function.")
    # Go on
    else:
        pass

    # Check for starting bin
    try:
        start = kwargs["start"]
    except KeyError:
        start = float("inf")

    # Check for ending bin
    try: 
        end = kwargs["end"]
    except KeyError:
        end = float("inf")

    # Check for width keyword argument
    try:
        width = kwargs["width"]
    except KeyError:
        width = False        

    if width:
        # Check for width_pos keyword argument
        try:
            width_pos = kwargs["width_pos"]
        except KeyError:
            width_pos = 0
    else:
        width_pos = 0

    import array_manip
    import utils

    integration = float(0)
    integration_error2 = float(0)
    
    len_obj = hlr_utils.get_length(obj)
    for i in xrange(len_obj): 
        value = hlr_utils.get_value(obj, i, o_descr, "y")
        error = hlr_utils.get_err2(obj, i, o_descr, "y")
        x_axis = hlr_utils.get_value(obj, i, o_descr, "x", width_pos)

        (int_val) = utils.integrate_1D_hist(value, error, x_axis,
                                            width=width,
                                            min_int=start,
                                            max_int=end)
        (integration,
         integration_error2) = array_manip.add_ncerr(int_val[0],
                                                     int_val[1],
                                                     integration,
                                                     integration_error2)

    return (integration, integration_error2)
def wavelength_to_scalar_k(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from wavelength
    to scalar k. The wavelength axis for a C{SOM} must be in units of
    I{Angstroms}. The primary axis of a C{SO} is assumed to be in units of
    I{Angstroms}. A C{tuple} of C{(wavelength, wavelength_err2)} (assumed to
    be in units of I{Angstroms}) can be converted to C{(scalar_k,
    scalar_k_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @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}
 

    @return: Object with a primary axis in wavelength converted to scalar k
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{Angstroms}
    """

    # 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 == "list":
        raise TypeError("Do not know how to handle given type: %s" % \
                        o_descr)
    else:
        pass

    # Setup keyword arguments
    try:
        units = kwargs["units"]
    except KeyError:
        units = "Angstroms"

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

    # iterate through the values
    import axis_manip
    
    for i in xrange(hlr_utils.get_length(obj)):
        val = hlr_utils.get_value(obj, i, o_descr, "x", axis)
        err2 = hlr_utils.get_err2(obj, i, o_descr, "x", axis)

        value = axis_manip.wavelength_to_scalar_k(val, err2)
        if o_descr != "number":
            value1 = axis_manip.reverse_array_cp(value[0])
            value2 = axis_manip.reverse_array_cp(value[1])
            rev_value = (value1, value2)
        else:
            rev_value = value
            
        map_so = hlr_utils.get_map_so(obj, None, i)
        if map_so is not None:
            map_so.y = axis_manip.reverse_array_cp(map_so.y)
            map_so.var_y = axis_manip.reverse_array_cp(map_so.var_y)
        else:
            pass
        
        hlr_utils.result_insert(result, res_descr, rev_value, map_so, "x",
                                axis)

    return result
예제 #44
0
def tof_to_ref_scalar_Q(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to reflectometer scalar Q. This means that a single angle
    and a single flightpath is used. The time-of-flight axis for a C{SOM} must
    be in units of I{microseconds}. The primary axis of a C{SO} is assumed to
    be in units of I{microseconds}. A C{tuple} of C{(time-of-flight,
    time-of-flight_err2)} (assumed to be in units of I{microseconds}) can be
    converted to C{(scalar_Q, scalar_Q_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword polar: The polar angle and its associated error^2
    @type polar: C{tuple}
    
    @keyword pathlength: The pathlength and its associated error^2
    @type pathlength: C{tuple}

    @keyword angle_offset: A constant offset for the polar angle and its
                           associated error^2. The units of the offset should
                           be in radians.
    @type angle_offset: C{tuple}

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is True for
                    histogram data.
    @type lojac: C{boolean}    
    
    @keyword units: The expected units for this function. The default for this
                    function is I{microseconds}.
    @type units: C{string}

    @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 with a primary axis in time-of-flight converted to
             reflectometer scalar Q
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: A C{SOM} is not passed and no polar angle is provided
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{microseconds}
    """
    
    # 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 == "list":
        raise TypeError("Do not know how to handle given type: %s" % \
                        o_descr)
    else:
        pass

    # Setup keyword arguments
    polar = kwargs.get("polar")
    pathlength = kwargs.get("pathlength")
    units = kwargs.get("units", "microseconds")
    lojac = kwargs.get("lojac", hlr_utils.check_lojac(obj))
    angle_offset = kwargs.get("angle_offset")
    config = kwargs.get("configure")

    if config is None:
        beamdiv_corr = False
    else:
        beamdiv_corr = config.beamdiv_corr
    
    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

    if pathlength is None or polar is None:
        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:
            if pathlength is None and polar is None:
                raise RuntimeError("If no SOM is provided, then pathlength "\
                                   +"and polar angle information must be "\
                                   +"provided")
            elif pathlength is None:
                raise RuntimeError("If no SOM is provided, then pathlength "\
                                   +"information must be provided")
            elif polar is None:
                raise RuntimeError("If no SOM is provided, then polar angle "\
                                   +"information must be provided")
            else:
                raise RuntimeError("If you get here, see Steve Miller for "\
                                   +"your mug.")
    else:
        pass

    if pathlength is None:
        (pl, pl_err2) = obj.attr_list.instrument.get_total_path(obj[0].id,
                                                             det_secondary=True)
    else:
        (pl, pl_err2) = pathlength

    if polar is None:
        angle = hlr_utils.get_special(obj.attr_list["data-theta"], obj[0])[0]
        angle_err2 = 0.0
    else:
        (angle, angle_err2) = polar

    if angle_offset is not None:
        angle += angle_offset[0]
        angle_err2 += angle_offset[1]

    # Need to multiply angle by 2.0 in order to make it be Theta to
    # underlying conversion function
    angle *= 2.0
    angle_err2 *= 4.0

    # iterate through the values
    import axis_manip
    if lojac:
        import utils

    if beamdiv_corr:
        import dr_lib

    for i in xrange(hlr_utils.get_length(obj)):
        skip_pixel = False
        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 beamdiv_corr:
            dangle = dr_lib.ref_beamdiv_correct(obj.attr_list, map_so.id,
                                                config.det_spat_res,
                                                config.center_pix)
            # We subtract due to the inversion of the z coordinates from the
            # mirror reflection of the beam at the sample.
            if dangle is not None:
                pangle = angle - (2.0 * dangle)
            else:
                pangle = angle
                skip_pixel = True
        else:
            pangle = angle

        value = axis_manip.tof_to_scalar_Q(val, err2, pl, pl_err2, pangle,
                                           angle_err2)

        if lojac:
            y_val = hlr_utils.get_value(obj, i, o_descr, "y")
            y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
            counts = utils.linear_order_jacobian(val, value[0],
                                                 y_val, y_err2)
        else:
            pass

        if o_descr != "number":
            value1 = axis_manip.reverse_array_cp(value[0])
            value2 = axis_manip.reverse_array_cp(value[1])
            rev_value = (value1, value2)
        else:
            rev_value = value

        if map_so is not None:
            if not lojac:
                map_so.y = axis_manip.reverse_array_cp(map_so.y)
                map_so.var_y = axis_manip.reverse_array_cp(map_so.var_y)
            else:
                map_so.y = axis_manip.reverse_array_cp(counts[0])
                map_so.var_y = axis_manip.reverse_array_cp(counts[1])
        else:
            pass

        if not skip_pixel:
            hlr_utils.result_insert(result, res_descr, rev_value, map_so, "x",
                                    axis)

    return result
예제 #45
0
def dimensionless_mon(obj, min_ext, max_ext, **kwargs):
    """
    This function takes monitor spectra and converts them to dimensionless
    spectra by dividing each spectrum by the total number of counts within the
    range [min_ext, max_ext]. Then, each spectrum is multiplied by the quantity
    max_ext - min_ext. The units of min_ext and max_ext are assumed to be the
    same as the monitor spectra axis.

    @param obj: Object containing monitor spectra
    @type obj: C{SOM.SOM} or C{SOM.SO}

    @param min_ext: Minimium range and associated error^2 for integrating total
                    counts.
    @type min_ext: C{tuple}

    @param max_ext: Maximium range and associated error^2 for integrating total
                    counts.
    @type max_ext: C{tuple}

    @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}


    @return: Dimensionless 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"

    # 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)

    import array_manip
    import dr_lib
    import utils

    for i in xrange(hlr_utils.get_length(obj)):
        val = hlr_utils.get_value(obj, i, o_descr, "y")
        err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
        x_axis = hlr_utils.get_value(obj, i, o_descr, "x", axis)
        x_err2 = hlr_utils.get_err2(obj, i, o_descr, "x", axis)
        map_so = hlr_utils.get_map_so(obj, None, i)

        bin_widths = utils.calc_bin_widths(x_axis, x_err2)

        # Scale bin contents by bin width
        value0 = array_manip.mult_ncerr(val, err2,
                                        bin_widths[0], bin_widths[1])

        # Find bin range for extents
        min_index = utils.bisect_helper(x_axis, min_ext[0])
        max_index = utils.bisect_helper(x_axis, max_ext[0])

        # Integrate axis using bin width multiplication
        (asum, asum_err2) = dr_lib.integrate_axis_py(map_so, start=min_index,
                                                     end=max_index, width=True)

        # Get the number of bins in the integration range
        num_bins = max_index - min_index + 1

        asum /= num_bins
        asum_err2 /= (num_bins * num_bins)

        # Divide by sum
        value1 = array_manip.div_ncerr(value0[0], value0[1], asum, asum_err2)

        hlr_utils.result_insert(result, res_descr, value1, map_so, "y")

    return result
def tof_to_initial_wavelength_igs(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to initial_wavelength_igs. The time-of-flight axis for a
    C{SOM} must be in units of I{microseconds}. The primary axis of a C{SO} is
    assumed to be in units of I{microseconds}. A C{tuple} of C{(tof, tof_err2)}
    (assumed to be in units of I{microseconds}) can be converted to
    C{(initial_wavelength_igs, initial_wavelength_igs_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword lambda_f:The final wavelength and its associated error^2
    @type lambda_f: C{tuple}
    
    @keyword time_zero: The time zero offset and its associated error^2
    @type time_zero: C{tuple}
    
    @keyword dist_source_sample: The source to sample distance information and
                                 its associated error^2
    @type dist_source_sample: C{tuple} or C{list} of C{tuple}s 

    @keyword dist_sample_detector: The sample to detector distance information
                                   and its associated error^2
    @type dist_sample_detector: C{tuple} or C{list} of C{tuple}s
    
    @keyword run_filter: This determines if the filter on the negative
                         wavelengths is run. The default setting is True.
    @type run_filter: C{boolean}
    
    @keyword units: The expected units for this function. The default for this
                    function is I{microseconds}
    @type units: C{string}


    @return: Object with a primary axis in time-of-flight converted to
             initial_wavelength_igs
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{microseconds}
    """

    # 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)

    # Setup keyword arguments
    try:
        lambda_f = kwargs["lambda_f"]
    except KeyError:
        lambda_f = None

    try:
        time_zero = kwargs["time_zero"]
    except KeyError:
        time_zero = None

    try:
        dist_source_sample = kwargs["dist_source_sample"]
    except KeyError:
        dist_source_sample = None

    try:
        dist_sample_detector = kwargs["dist_sample_detector"]
    except KeyError:
        dist_sample_detector = None

    try:
        units = kwargs["units"]
    except KeyError:
        units = "microseconds"

    try:
        run_filter = kwargs["run_filter"]
    except KeyError:
        run_filter = True

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "Angstroms", axis)
        result.setAxisLabel(axis, "wavelength")
        result.setYUnits("Counts/A")
        result.setYLabel("Intensity")
    else:
        pass

    # Where to get instrument information
    if dist_source_sample is None or dist_sample_detector is None:
        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:
            if dist_source_sample is None and dist_sample_detector is None:
                raise RuntimeError("If a SOM is not passed, the "\
                                   +"source-sample and sample-detector "\
                                   +"distances must be provided.")
            elif dist_source_sample is None:
                raise RuntimeError("If a SOM is not passed, the "\
                                   +"source-sample distance must be provided.")
            elif dist_sample_detector is None:
                raise RuntimeError("If a SOM is not passed, the "\
                                   +"sample-detector distance must be "\
                                   +"provided.")
            else:
                raise RuntimeError("If you get here, see Steve Miller for "\
                                   +"your mug.")
    else:
        pass

    if lambda_f is not None:
        l_descr = hlr_utils.get_descr(lambda_f)
    else:
        if o_descr == "SOM":
            try:
                som_l_f = obj.attr_list["Wavelength_final"]
            except KeyError:
                raise RuntimeError("Please provide a final wavelength "\
                                   +"parameter either via the function call "\
                                   +"or the SOM")
        else:
            raise RuntimeError("You need to provide a final wavelength")

    if time_zero is not None:
        t_descr = hlr_utils.get_descr(time_zero)
    else:
        if o_descr == "SOM":
            try:
                t_0 = obj.attr_list["Time_zero"][0]
                t_0_err2 = obj.attr_list["Time_zero"][1]
            except KeyError:
                raise RuntimeError("Please provide a time-zero "\
                                   +"parameter either via the function call "\
                                   +"or the SOM")
        else:
            t_0 = 0.0
            t_0_err2 = 0.0

    if dist_source_sample is not None:
        ls_descr = hlr_utils.get_descr(dist_source_sample)
    # Do nothing, go on
    else:
        pass

    if dist_sample_detector is not None:
        ld_descr = hlr_utils.get_descr(dist_sample_detector)
    # Do nothing, go on
    else:
        pass

    # iterate through the values
    import axis_manip

    for i in xrange(hlr_utils.get_length(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 dist_source_sample is None:
            (L_s, L_s_err2) = hlr_utils.get_parameter("primary", map_so, inst)
        else:
            L_s = hlr_utils.get_value(dist_source_sample, i, ls_descr)
            L_s_err2 = hlr_utils.get_err2(dist_source_sample, i, ls_descr)

        if dist_sample_detector is None:
            (L_d, L_d_err2) = hlr_utils.get_parameter("secondary", map_so,
                                                      inst)
        else:
            L_d = hlr_utils.get_value(dist_sample_detector, i, ld_descr)
            L_d_err2 = hlr_utils.get_err2(dist_sample_detector, i, ld_descr)

        if lambda_f is not None:
            l_f = hlr_utils.get_value(lambda_f, i, l_descr)
            l_f_err2 = hlr_utils.get_err2(lambda_f, i, l_descr)
        else:
            l_f_tuple = hlr_utils.get_special(som_l_f, map_so)
            l_f = l_f_tuple[0]
            l_f_err2 = l_f_tuple[1]

        if time_zero is not None:
            t_0 = hlr_utils.get_value(time_zero, i, t_descr)
            t_0_err2 = hlr_utils.get_err2(time_zero, i, t_descr)
        else:
            pass

        value = axis_manip.tof_to_initial_wavelength_igs(
            val, err2, l_f, l_f_err2, t_0, t_0_err2, L_s, L_s_err2, L_d,
            L_d_err2)

        # Remove all wavelengths < 0
        if run_filter:
            index = 0
            for val in value[0]:
                if val >= 0:
                    break
                index += 1

            value[0].__delslice__(0, index)
            value[1].__delslice__(0, index)
            map_so.y.__delslice__(0, index)
            map_so.var_y.__delslice__(0, index)
        else:
            pass

        hlr_utils.result_insert(result, res_descr, value, map_so, "x", axis)

    return result
예제 #47
0
def filter_ref_data(som, **kwargs):
    """
    This function takes in an object containing reflectometer data, scans it
    for bad data and removes that data from the arrays. The following criteria
    are what is considered bad data:

              - R or dR^2 is nan, inf, -inf
              - R < 0
              - dR^2 >= R^2

    @param som: Object containing a single spectrum to be cleaned
    @type som: C{SOM.SOM}

    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword zero_mode: A flag that tells the function to zero the bad values
                        instead of removing them
    @type zero_mode: C{boolean}
    

    @return: Object containing a spectrum that has been cleaned of all bad data
    @rtype: C{SOM.SOM}

    @raise RuntimeError: The incoming object is not a C{SOM}.
    """
    import hlr_utils

    # set up for working through data
    (result, res_descr) = hlr_utils.empty_result(som)
    o_descr = hlr_utils.get_descr(som)

    if o_descr != "SOM":
        raise RuntimeError("Must provide a SOM to the function.")
    # Go on
    else:
        pass

    result = hlr_utils.copy_som_attr(result, res_descr, som, o_descr)

    try:
        dtot = result.attr_list["extra_som"]
    except KeyError:
        dtot = None

    # Check keyword arguments
    try:
        zero_mode = kwargs["zero_mode"]
    except KeyError:
        zero_mode = False

    import copy
    import itertools

    import utils

    index_map = {}

    len_som = hlr_utils.get_length(som)
    if dtot is not None:
        # Deal with delta t / t information
        len_dtot = len(dtot)
        if len_dtot == 1 and len_som > 1:
            # If the delta t / t information has only one spectrum and the som
            # data has more than one, we'll need to clone that delta t / t
            # spectrum
            multiple_dtot = True
            (res_dtot, resd_descr) = hlr_utils.empty_result(dtot)
            res_dtot = hlr_utils.copy_som_attr(res_dtot, resd_descr, dtot,
                                               "SOM")
        else:
            # Everything should be on equal footing with respect to the number
            # of spectra, so we don't have to do anything.
            res_dtot = dtot
            multiple_dtot = False
    else:
        len_dtot = 0
        res_dtot = None
        multiple_dtot = False

    # Parse through the data to find the bad data locations.
    for i in xrange(len_som):
        counter = 0
        indicies = []
        so = hlr_utils.get_value(som, i, o_descr, "all")

        if multiple_dtot:
            if i > 0:
                dso = hlr_utils.get_value(dtot, 0, resd_descr, "all")
                dtot.append(copy.deepcopy(dso))

        for (yval, yerr2) in itertools.izip(so.y, so.var_y):
            tofilter = False

            yval2 = yval * yval
            syval = str(yval)
            syerr2 = str(yerr2)

            if syval == "nan" or syval == "inf" or syval == "-inf":
                tofilter = True

            if syerr2 == "nan" or syerr2 == "inf" or syerr2 == "-inf":
                tofilter = True

            if yval < 0:
                tofilter = True

            if yerr2 > yval2 or not utils.compare(yerr2, yval2):
                tofilter = True

            if tofilter:
                indicies.append(counter)

            counter += 1

        index_map[so.id] = indicies

    # Parse through data to remove bad data at requested indicies
    for j in xrange(len_som):
        map_so = hlr_utils.get_map_so(som, None, j)

        y_val = hlr_utils.get_value(som, j, o_descr, "y")
        y_err2 = hlr_utils.get_err2(som, j, o_descr, "y")

        x_val = hlr_utils.get_value(som, j, o_descr, "x", 0)
        x_err2 = hlr_utils.get_err2(som, j, o_descr, "x", 0)

        y_val_new = copy.deepcopy(y_val)
        y_err2_new = copy.deepcopy(y_err2)

        x_val_new = copy.deepcopy(x_val)
        x_err2_new = copy.deepcopy(x_err2)

        if dtot is not None:
            dso = hlr_utils.get_value(dtot, j, "SOM", "all")
            dso_new = copy.deepcopy(dso)

        offset = 0
        for index in index_map[map_so.id]:
            if not zero_mode:
                # Index arithmetic since list length get shorter with every
                # element deleted
                dindex = index - offset
                del y_val_new[dindex]
                del y_err2_new[dindex]
                del x_val_new[dindex]
                del x_err2_new[dindex]
                if dtot is not None:
                    del dso_new.y[dindex]

                offset += 1
            else:
                y_val_new[index] = 0.0
                y_err2_new[index] = 0.0

        if dtot is not None and multiple_dtot:
            hlr_utils.result_insert(res_dtot, resd_descr, dso_new, None, "all")

        hlr_utils.result_insert(result, res_descr, (y_val_new, y_err2_new),
                                map_so, "all", 0, [x_val_new])

    if dtot is not None:
        result.attr_list["extra_som"] = res_dtot

    return result
예제 #48
0
def data_filter(obj, **kwargs):
    """
    This function takes in an object containing data, scans it for bad data and
    removes that data from the arrays. The criteria is instrument dependent
    and subfunctions will be written that handle the instrument dependent
    criteria. This function will operate in a zeroing mode. This means that
    bins with bad data will have their value and error^2 set to zero. 

    @param obj: Object containing a single spectrum to be cleaned
    @type obj: C{SOM.SOM}

    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword clean_axis: A flag that tells the function to check for I{inf}
    of I{-inf} values (normally at the ends of the axis) and remove those
    bins. The default behavior is I{False}.
    @type clean_axis: C{boolean}

    @keyword axis_index: The index on the axis to check for bad_values. This
    is assumed to be a single value and the default is -1 (last bin)
    @type axis_index: C{int}

    @keyword axis_pos: The position of the axis within the data object. This is
    necessary for greater than 1D spectra. The default value is 0.
    @type axis_pos: C{int}
    

    @return: Object containing a spectrum that has been cleaned of all bad data
    @rtype: C{SOM.SOM}
    

    @raise RuntimeError: The incoming object is not a C{SOM}.

    @raise AttributeError: 1D or 2D data passed is clean_axis is I{True}.

    @raise AttributeError: Axis position not 0 or 1 for 2D data.
    """
    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 != "SOM":
        raise RuntimeError("Must provide a SOM to the function.")
    # Go on
    else:
        pass

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    # See if there is extra information present
    try:
        extra_som = result.attr_list["extra_som"]
    except KeyError:
        extra_som = None

    # Get instrument name
    inst_name = obj.attr_list.instrument.get_name()

    # Get dimension of incoming data
    data_dims = obj.getDimension()

    # Check keyword arguments
    try:
        clean_axis = kwargs["clean_axis"]
    except KeyError:
        clean_axis = False

    try:
        axis_index = kwargs["axis_index"]
    except KeyError:
        axis_index = -1

    try:
        axis_pos = kwargs["axis_pos"]
    except KeyError:
        axis_pos = 0

    if clean_axis:
        # Can only support 1D and 2D data axis cleaning for now
        if data_dims not in [1, 2]:
            raise AttributeError("Do not know how to clean %d-dimensional " +
                                 "data" % data_dims)

        if data_dims == 2:
            if axis_pos not in [0, 1]:
                raise AttributeError("2D data cannot have axis position %d!" \
                                     % axis_pos)
            if axis_pos:
                other_axis = 0
            else:
                other_axis = 1

            axis_lengths = (len(obj[0].axis[0].val) - 1,
                            len(obj[0].axis[1].val) - 1)

        else:
            axis_lengths = None

        if obj[0].axis[0].var is None:
            with_x_var = False
        else:
            with_x_var = True
    else:
        axis_lengths = None

    import copy
    import itertools

    len_som = hlr_utils.get_length(obj)
    if extra_som is not None:
        # Deal with extra information
        len_extra_som = len(extra_som)
        if len_extra_som == 1 and len_som > 1:
            # If the extra information has only one spectrum and the som
            # data has more than one, we'll need to clone that spectrum
            multiple_extra_som = True
            (res_extra_som, resd_descr) = hlr_utils.empty_result(extra_som)
            res_extra_som = hlr_utils.copy_som_attr(res_extra_som, resd_descr,
                                                    extra_som, "SOM")
        else:
            # Everything should be on equal footing with respect to the number
            # of spectra, so we don't have to do anything.
            res_extra_som = extra_som
            multiple_extra_som = False
    else:
        len_extra_som = 0
        res_extra_som = None
        multiple_extra_som = False

    # Parse through the data to find the bad data locations.
    for i in xrange(len_som):
        so = hlr_utils.get_value(obj, i, o_descr, "all")

        map_so = hlr_utils.get_map_so(obj, None, i)

        y_val = hlr_utils.get_value(obj, i, o_descr, "y")
        y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y")

        y_val_new = copy.deepcopy(y_val)
        y_err2_new = copy.deepcopy(y_err2)

        if extra_som is not None:
            eso = hlr_utils.get_value(extra_som, i, "SOM", "all")
            eso_new = copy.deepcopy(eso)
        else:
            eso_new = None

        if multiple_extra_som:
            if i > 0:
                eso = hlr_utils.get_value(extra_som, 0, resd_descr, "all")
                extra_som.append(copy.deepcopy(eso))

        counter = 0
        for (yval, yerr2) in itertools.izip(so.y, so.var_y):
            to_filter = False

            if inst_name == "BSS":
                to_filter = __filter_sns_bss(yval, yerr2)
            elif inst_name == "REF_L" or inst_name == "REF_M":
                to_filter = __filter_sns_ref(yval, yerr2)
            elif inst_name == "SANS":
                to_filter = __filter_ieee(str(yval), str(yerr2))

            if to_filter:
                y_val_new[counter] = 0.0
                y_err2_new[counter] = 0.0

            counter += 1

        if clean_axis:
            x_val = hlr_utils.get_value(obj, i, o_descr, "x", axis_pos)
            x_err2 = hlr_utils.get_err2(obj, i, o_descr, "x", axis_pos)

            x_val_new = copy.deepcopy(x_val)
            x_err2_new = copy.deepcopy(x_err2)

            (y_val_new, y_err2_new, x_val_new, x_err2_new,
             eso_new) = __clean_axis(data_dims,
                                     axis_pos,
                                     axis_index,
                                     x_val_new,
                                     x_err2_new,
                                     y_val_new,
                                     y_err2_new,
                                     ext_so=eso_new,
                                     axis_len=axis_lengths)

        if extra_som is not None and multiple_extra_som:
            hlr_utils.result_insert(res_extra_som, resd_descr, eso_new, None,
                                    "all")

        if not clean_axis:
            hlr_utils.result_insert(result, res_descr, (y_val_new, y_err2_new),
                                    map_so, "y")
        else:
            if data_dims == 1:
                xvals = [x_val_new, x_err2_new]
                if not with_x_var:
                    del xvals[-1]
                hlr_utils.result_insert(result, res_descr,
                                        (y_val_new, y_err2_new), map_so, "all",
                                        axis_pos, xvals)
            elif data_dims == 2:
                ox_val = hlr_utils.get_value(obj, i, o_descr, "x", other_axis)
                ox_err2 = hlr_utils.get_err2(obj, i, o_descr, "x", other_axis)

                if axis_pos == 0:
                    xvals = [
                        x_val_new, x_err2_new,
                        copy.deepcopy(ox_val),
                        copy.deepcopy(ox_err2)
                    ]
                else:
                    xvals = [
                        copy.deepcopy(ox_val),
                        copy.deepcopy(ox_err2), x_val_new, x_err2_new
                    ]

                if not with_x_var:
                    del xvals[1::2]

                hlr_utils.result_insert(result, res_descr,
                                        (y_val_new, y_err2_new), map_so, "all",
                                        axis_pos, xvals)

    if extra_som is not None:
        result.attr_list["extra_som"] = res_extra_som

    return result
예제 #49
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
예제 #50
0
def sumw_ncerr(obj1, obj2, **kwargs):
    """
    This function sums by weighting errors of two objects (C{SOM} or C{SO}) and
    returns the result of that action in an C{SOM}. The function does not
    handle the cases of C{SOM}+C{tuple}, C{SO}+C{tuple} or C{tuple}+C{tuple}.

    @param obj1:  First object in the weighted sum
    @type obj1: C{SOM.SOM} or C{SOM.SO} or C{tuple}
    
    @param obj2: Second object in the the weighted sum
    @type obj2: C{SOM.SOM} or C{SOM.SO} or C{tuple}

    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword axis: This is the axis one wishes to manipulate. If no argument
                   is given the default value is y
    @type axis: C{string}=<y or x>
    
    @keyword axis_pos: This is position of the axis in the axis array. If no
                       argument is given, the default value is 0
    @type axis_pos: C{int}
    
    @keyword length_one_som: This is a flag that lets the function know it is
                             dealing with a length 1 C{SOM} so that attributes
                             may be passed along. The length 1 C{SOM} will be
                             turned into a C{SO}. The default value is False.
    @type length_one_som: C{boolean}
    
    @keyword length_one_som_pos: This is the argument position of the
                                 length 1 C{SOM} since the check is done
                                 before the arguments are swapped. The default
                                 value is 2.
    @type length_one_som_pos: C{int}=<1 or 2>
    

    @return: Object containing the results of the addition
    @rtype: C{SOM.SOM} or C{SOM.SO}


    @raise TypeError: The C{SOM}+C{tuple}, C{SO}+C{tuple} or C{tuple}+C{tuple}
                      cases are presented to the function
    
    @raise IndexError: The two C{SOM}s do not contain the same number of
                       spectra
                       
    @raise RunTimeError: The x-axis units of the C{SOM}s do not match
    
    @raise RunTimeError: The y-axis units of the C{SOM}s do not match
    
    @raise RunTimeError: The x-axes of the two C{SO}s are not equal
    """

    # import the helper functions
    import hlr_utils

    # Check to see if we are working with a length 1 SOM
    try:
        length_one_som = kwargs["length_one_som"]
    except KeyError:
        length_one_som = False

    try:
        length_one_som_pos = kwargs["length_one_som_pos"]
        if length_one_som_pos != 1 or length_one_som_pos != 2:
            raise RuntimeError("length_one_som_pos must be either 1 or 2 and "\
                               +"%d" % length_one_som_pos)
    except KeyError:
        length_one_som_pos = 2

    if length_one_som:
        if length_one_som_pos == 1:
            som_copy = obj1
            obj1 = obj1[0]
        else:
            som_copy = obj2
            obj2 = obj2[0]
    else:
        # Not working with a length 1 SOM, do nothing
        pass

    # set up for working through data
    (result, res_descr) = hlr_utils.empty_result(obj1, obj2)
    (o1_descr, o2_descr) = hlr_utils.get_descr(obj1, obj2)

    # error check information
    if o1_descr == "number" or o2_descr == "number":
        raise RuntimeError("Operations with tuples are not supported!")
    elif o2_descr == "SOM" and o1_descr == "SO":
        (obj1, obj2) = hlr_utils.swap_args(obj1, obj2)
        (o1_descr, o2_descr) = hlr_utils.swap_args(o1_descr, o2_descr)
    elif o2_descr == "SOM" and o1_descr == "SOM":
        hlr_utils.math_compatible(obj1, o1_descr, obj2, o2_descr)
    else:
        pass

    # Check for axis keyword argument
    try:
        axis = kwargs["axis"]
    except KeyError:
        axis = "y"

    # Check for axis_pos keyword argument
    try:
        axis_pos = kwargs["axis_pos"]
    except KeyError:
        axis_pos = 0

    if length_one_som:
        if length_one_som_pos == 1:
            result = hlr_utils.copy_som_attr(result, res_descr, som_copy,
                                             "SOM", obj2, o2_descr)
        else:
            result = hlr_utils.copy_som_attr(result, res_descr, obj1, o1_descr,
                                             som_copy, "SOM")
    else:
        result = hlr_utils.copy_som_attr(result, res_descr, obj1, o1_descr,
                                         obj2, o2_descr)

    # iterate through the values
    import array_manip

    for i in xrange(hlr_utils.get_length(obj1, obj2)):
        val1 = hlr_utils.get_value(obj1, i, o1_descr, axis, axis_pos)
        err2_1 = hlr_utils.get_err2(obj1, i, o1_descr, axis, axis_pos)

        val2 = hlr_utils.get_value(obj2, i, o2_descr, axis, axis_pos)
        err2_2 = hlr_utils.get_err2(obj2, i, o2_descr, axis, axis_pos)

        (descr_1, descr_2) = hlr_utils.get_descr(val1, val2)

        hlr_utils.math_compatible(val1, descr_1, val2, descr_2)

        value = array_manip.sumw_ncerr(val1, err2_1, val2, err2_2)

        map_so = hlr_utils.get_map_so(obj1, None, i)
        hlr_utils.result_insert(result, res_descr, value, map_so, axis,
                                axis_pos)

    return result
예제 #51
0
def div_ncerr(left, right, **kwargs):
    """
    This function divides two objects (C{SOM}, C{SO} or {tuple(val,val_err2)})
    and returns the result of the division in an C{SOM}, C{SO} or C{tuple}.

    @param left: Object on the left of the division sign
    @type left: C{SOM.SOM} or C{SOM.SO} or C{tuple}
    
    @param right: Object on the right of the division sign
    @type right: C{SOM.SOM} or C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:
    
    @keyword axis: This is the axis one wishes to manipulate. If no argument
                   is given the default value is y
    @type axis: C{string}=<y or x>
    
    @keyword axis_pos: This is position of the axis in the axis array. If no
                       argument is given, the default value is 0
    @type axis_pos: C{int}
    
    @keyword length_one_som: This is a flag that lets the function know it is
                             dealing with a length 1 C{SOM} so that attributes
                             may be passed along. The length 1 C{SOM} will be
                             turned into a C{SO}. The default value is False.
    @type length_one_som: C{boolean}
    
    @keyword length_one_som_pos: This is the argument position of the length 1
                                 C{SOM} since division order is not
                                 commutative. The default value is 2.
    @type length_one_som_pos: C{int}=<1 or 2> 


    @return: Object containing the results of the division
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise IndexError: The two C{SOM}s do not contain the same number of
                       spectra
                       
    @raise RunTimeError: The x-axis units of the C{SOM}s do not match
    
    @raise RunTimeError: The y-axis units of the C{SOM}s do not match
    
    @raise RunTimeError: The x-axes of the two C{SO}s are not equal
    """

    # import the helper functions
    import hlr_utils

    # Check to see if we are working with a length 1 SOM
    try:
        length_one_som = kwargs["length_one_som"]
    except KeyError:
        length_one_som = False

    try:
        length_one_som_pos = kwargs["length_one_som_pos"]
        if length_one_som_pos != 1 or length_one_som_pos != 2:
            raise RuntimeError("length_one_som_pos must be either 1 or 2 and "\
                               +"%d" % length_one_som_pos)
    except KeyError:
        length_one_som_pos = 2

    if length_one_som:
        if length_one_som_pos == 1:
            som_copy = left
            left = left[0]
        else:
            som_copy = right
            right = right[0]
    else:
        # Not working with a length 1 SOM, do nothing
        pass

    # set up for working through data
    (result, res_descr) = hlr_utils.empty_result(left, right)
    (l_descr, r_descr) = hlr_utils.get_descr(left, right)

    is_number = False
    
    # error check information
    if r_descr == "SOM" and l_descr == "SOM":
        hlr_utils.math_compatible(left, l_descr, right, r_descr)
    elif l_descr == "number" and r_descr == "number":
        is_number = True
    else:
        pass

    # Check for axis keyword argument
    try:
        axis = kwargs["axis"]
    except KeyError:
        axis = "y"
        
    # Check for axis_pos keyword argument
    try:
        axis_pos = kwargs["axis_pos"]
    except KeyError:
        axis_pos = 0

    if length_one_som:
        if length_one_som_pos == 1:
            result = hlr_utils.copy_som_attr(result, res_descr,
                                             som_copy, "SOM",
                                             right, r_descr)
        else:
            result = hlr_utils.copy_som_attr(result, res_descr, left, l_descr,
                                             som_copy, "SOM")            
    else:
        result = hlr_utils.copy_som_attr(result, res_descr, left, l_descr,
                                         right, r_descr)

    # iterate through the values
    import array_manip
    
    for i in xrange(hlr_utils.get_length(left, right)):
        val1 = hlr_utils.get_value(left, i, l_descr, axis, axis_pos)
        err2_1 = hlr_utils.get_err2(left, i, l_descr, axis, axis_pos)

        val2 = hlr_utils.get_value(right, i, r_descr, axis, axis_pos)
        err2_2 = hlr_utils.get_err2(right, i, r_descr, axis, axis_pos)

        (descr_1, descr_2)=hlr_utils.get_descr(val1, val2)

        hlr_utils.math_compatible(val1, descr_1, val2, descr_2)

        value = array_manip.div_ncerr(val1, err2_1, val2, err2_2)

        map_so = hlr_utils.get_map_so(left, right, i)
        hlr_utils.result_insert(result, res_descr, value, map_so, axis,
                                axis_pos)

    if is_number:
        return tuple(result)
    else:
        return result
예제 #52
0
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)
예제 #53
0
def wavelength_to_velocity(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from wavelength
    to velocity. The wavelength axis for a C{SOM} must be in units of
    I{Angstroms}. The primary axis of a C{SO} is assumed to be in
    units of I{Angstroms}. A C{tuple} of C{(wavelength, wavelength_err2)}
    (assumed to be in units of I{Angstroms}) can be converted to
    C{(velocity, velocity_err)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is True for
                    histogram data.
    @type lojac: C{boolean}
    
    @keyword units: The expected units for this function. The default for this
                    function is I{Angstroms}
    @type units: C{string}


    @return: Object with a primary axis in wavelength converted to velocity
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    @raise RuntimeError: The C{SOM} x-axis units are not I{Angstroms}
    """
    # 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 == "list":
        raise TypeError("Do not know how to handle given type: %s" % \
                        o_descr)
    else:
        pass

    # Setup keyword arguments
    try:
        units = kwargs["units"]
    except KeyError:
        units = "Angstroms"

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "meters/microseconds", axis)
        result.setAxisLabel(axis, "velocity")
        result.setYUnits("Counts/meters/microseconds")
        result.setYLabel("Intensity")
    else:
        pass

    # iterate through the values
    import axis_manip
    if lojac:
        import utils

    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)

        value = axis_manip.wavelength_to_velocity(val, err2)

        if lojac:
            y_val = hlr_utils.get_value(obj, i, o_descr, "y")
            y_err2 = hlr_utils.get_err2(obj, i, o_descr, "y")
            counts = utils.linear_order_jacobian(val, value[0], y_val, y_err2)
        else:
            pass

        if o_descr != "number":
            value1 = axis_manip.reverse_array_cp(value[0])
            value2 = axis_manip.reverse_array_cp(value[1])
            rev_value = (value1, value2)
        else:
            rev_value = value

        if map_so is not None:
            if not lojac:
                map_so.y = axis_manip.reverse_array_cp(map_so.y)
                map_so.var_y = axis_manip.reverse_array_cp(map_so.var_y)
            else:
                map_so.y = axis_manip.reverse_array_cp(counts[0])
                map_so.var_y = axis_manip.reverse_array_cp(counts[1])
        else:
            pass

        hlr_utils.result_insert(result, res_descr, rev_value, map_so, "x",
                                axis)

    return result
def tof_to_wavelength_lin_time_zero(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to wavelength incorporating a linear time zero which is a
    described as a linear function of the wavelength. The time-of-flight axis
    for a C{SOM} must be in units of I{microseconds}. The primary axis of a
    C{SO} is assumed to be in units of I{microseconds}. A C{tuple} of C{(tof,
    tof_err2)} (assumed to be in units of I{microseconds}) can be converted to
    C{(wavelength, wavelength_err2)}.

    @param obj: Object to be converted
    @type obj: C{SOM.SOM}, C{SOM.SO} or C{tuple}
    
    @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 time_zero_slope: The time zero slope and its associated error^2
    @type time_zero_slope: C{tuple}

    @keyword time_zero_offset: The time zero offset and its associated error^2
    @type time_zero_offset: C{tuple}

    @keyword inst_param: The type of parameter requested from an associated
                         instrument. For this function the acceptable
                         parameters are I{primary}, I{secondary} and I{total}.
                         Default is I{primary}.
    @type inst_param: C{string}

    @keyword lojac: A flag that allows one to turn off the calculation of the
                    linear-order Jacobian. The default action is I{True} for
                    histogram data.
    @type lojac: C{boolean}

    @keyword units: The expected units for this function. The default for this
                    function is I{microseconds}.
    @type units: C{string}

    @keyword cut_val: Specify a wavelength to cut the spectra at.
    @type cut_val: C{float}

    @keyword cut_less: A flag that specifies cutting the spectra less than
                       C{cut_val}. The default is C{True}.
    @type cut_less: C{boolean}


    @return: Object with a primary axis in time-of-flight converted to
             wavelength
    @rtype: C{SOM.SOM}, C{SOM.SO} or C{tuple}


    @raise TypeError: The incoming object is not a type the function recognizes
    
    @raise RuntimeError: The C{SOM} x-axis units are not I{microseconds}
    
    @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)

    # Setup keyword arguments
    try:
        inst_param = kwargs["inst_param"]
    except KeyError:
        inst_param = "primary"

    try:
        pathlength = kwargs["pathlength"]
    except KeyError:
        pathlength = None

    try:
        time_zero_slope = kwargs["time_zero_slope"]
    except KeyError:
        time_zero_slope = None

    # Current constants for Time Zero Slope
    TIME_ZERO_SLOPE = (float(0.0), float(0.0))
    
    try:
        time_zero_offset = kwargs["time_zero_offset"]
    except KeyError:
        time_zero_offset = None        

    # Current constants for Time Zero Offset
    TIME_ZERO_OFFSET = (float(0.0), float(0.0))

    try:
        lojac = kwargs["lojac"]
    except KeyError:
        lojac = hlr_utils.check_lojac(obj)

    try:
        units = kwargs["units"]
    except KeyError:
        units = "microseconds"

    try:
        cut_val = kwargs["cut_val"]
    except KeyError:
        cut_val = None

    try:
        cut_less = kwargs["cut_less"]
    except KeyError:
        cut_less = True

    # 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)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "Angstroms", axis)
        result.setAxisLabel(axis, "wavelength")
        result.setYUnits("Counts/A")
        result.setYLabel("Intensity")
    else:
        pass

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

    if time_zero_slope is not None:
        t_0_slope_descr = hlr_utils.get_descr(time_zero_slope)
    else:
        if o_descr == "SOM":
            try:
                t_0_slope = obj.attr_list["Time_zero_slope"][0]
                t_0_slope_err2 = obj.attr_list["Time_zero_slope"][1]
            except KeyError:
                t_0_slope = TIME_ZERO_SLOPE[0]
                t_0_slope_err2 = TIME_ZERO_SLOPE[1]
        else:
            t_0_slope = TIME_ZERO_SLOPE[0]
            t_0_slope_err2 = TIME_ZERO_SLOPE[1]

    if time_zero_offset is not None:
        t_0_offset_descr = hlr_utils.get_descr(time_zero_offset)
    else:
        if o_descr == "SOM":
            try:
                t_0_offset = obj.attr_list["Time_zero_offset"][0]
                t_0_offset_err2 = obj.attr_list["Time_zero_offset"][1]
            except KeyError:
                t_0_offset = TIME_ZERO_OFFSET[0]
                t_0_offset_err2 = TIME_ZERO_OFFSET[1]
        else:
            t_0_offset = TIME_ZERO_OFFSET[0]
            t_0_offset_err2 = TIME_ZERO_OFFSET[1]

    # iterate through the values
    import axis_manip
    if lojac or cut_val is not None:
        import utils
    
    for i in xrange(hlr_utils.get_length(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(inst_param, map_so, inst)
        else:
            pl = hlr_utils.get_value(pathlength, i, p_descr)
            pl_err2 = hlr_utils.get_err2(pathlength, i, p_descr)

        if time_zero_slope is not None:
            t_0_slope = hlr_utils.get_value(time_zero_slope, i,
                                            t_0_slope_descr)
            t_0_slope_err2 = hlr_utils.get_err2(time_zero_slope, i,
                                                t_0_slope_descr)
        else:
            pass

        if time_zero_offset is not None:
            t_0_offset = hlr_utils.get_value(time_zero_offset, i,
                                             t_0_offset_descr)
            t_0_offset_err2 = hlr_utils.get_err2(time_zero_offset, i,
                                                 t_0_offset_descr)
        else:
            pass

        value = axis_manip.tof_to_wavelength_lin_time_zero(val, err2,
                                                           pl, pl_err2,
                                                           t_0_slope,
                                                           t_0_slope_err2,
                                                           t_0_offset,
                                                           t_0_offset_err2)
        
        if cut_val is not None:
            index = utils.bisect_helper(value[0], cut_val)
            if cut_less:
                # Need to cut at this index, so increment by one
                index += 1
                value[0].__delslice__(0, index)
                value[1].__delslice__(0, index)
                map_so.y.__delslice__(0, index)
                map_so.var_y.__delslice__(0, index)
                if lojac:
                    val.__delslice__(0, index)
                    err2.__delslice__(0, index)
            else:
                len_data = len(value[0])
                # All axis arrays need starting index adjusted by one since
                # they always carry one more bin than the data
                value[0].__delslice__(index + 1, len_data)
                value[1].__delslice__(index + 1, len_data)
                map_so.y.__delslice__(index, len_data)
                map_so.var_y.__delslice__(index, len_data)
                if lojac:
                    val.__delslice__(index + 1, len_data)
                    err2.__delslice__(index + 1, len_data)
        
        if lojac:
            counts = utils.linear_order_jacobian(val, value[0],
                                                 map_so.y, map_so.var_y)
            hlr_utils.result_insert(result, res_descr, counts, map_so,
                                    "all", axis, [value[0]])

        else:
            hlr_utils.result_insert(result, res_descr, value, map_so,
                                    "x", axis)

    return result
예제 #55
0
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
예제 #56
0
def subtract_axis_dep_bkg(obj, coeffs, **kwargs):
    """
    This function takes spectrum object(s) and a set of coefficients and
    subtracts an axis dependent background based on a polynomial. The order
    of the polynomial is based on the number of coefficients provided.

    @param obj: Object from which to subtract the individual background numbers
    @type obj: C{SOM.SOM} or C{SOM.SO}

    @param coeffs: The set of coefficients for the polynomial representation
                   of the background to be subtracted.
    @type coeffs: C{list} of C{floats}

    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword old_scale: The scale factor used to obtain the coefficients used
                        in this function.
    @type old_scale: C{float}

    @keyword new_scale: The scale factor for the current data set from which
                        the axis dependent background will be subtracted from.
    @type new_scale: C{float}


    @return: Object with the axis dependent background subtracted
    @rtype: C{SOM.SOM} or C{SOM.SO}


    @raise TypeError: The first argument is not a C{SOM} or C{SO}    
    """
    # Kickout is coeffs is None, or length is zero
    if coeffs is None:
        return obj

    poly_len = len(coeffs)    
    if poly_len == 0:
        return obj

    # Check for keywords
    old_scale = kwargs.get("old_scale", 1.0)
    new_scale = kwargs.get("new_scale", 1.0)

    # Reverse coefficients for __eval_poly function
    coeffs.reverse()

    # import the helper functions
    import hlr_utils

    o_descr = hlr_utils.get_descr(obj)

    if o_descr != "SOM" and o_descr != "SO":
        raise TypeError("Incoming object must be a SOM or a SO")
    # Have a SOM or SO
    else:
        pass

    (result, res_descr) = hlr_utils.empty_result(obj)

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)

    obj_len = hlr_utils.get_length(obj)

    import utils

    # iterate through the values
    for i in xrange(obj_len):
        axis   = hlr_utils.get_value(obj, i, o_descr, "x", 0)
        val    = hlr_utils.get_value(obj, i, o_descr, "y")
        err2   = hlr_utils.get_err2 (obj, i, o_descr, "y")
        map_so = hlr_utils.get_map_so(obj, None, i)

        len_val = len(val)
        new_scale_p = new_scale / len_val
        ratio = old_scale / new_scale_p

        axis_centers = utils.calc_bin_centers(axis)

        for j in xrange(len(val)):
            val[j] -= (ratio * __eval_poly(axis_centers[0][j], coeffs,
                                           poly_len))

        value = (val, err2)

        hlr_utils.result_insert(result, res_descr, value, map_so, "y")

    return result