def __calc_x3(*args):
    """
    This function calculates the x3 coeffiecient to the S(Q,E) Jacobian

    @param args: A list of parameters used to calculate the x3 coefficient

    The following is a list of the arguments needed in there expected order
      1. Initial Wavevector
      2. Initial Energy
      3. Length Ratio (L_f / L_i)
      4. Final Energy
      5. Final Wavevector
      6. Lambda Constant (2*pi/l_f^2)(dlf/dh)
      7. Time-zero Slope Correction
      8. Vector of Zeros
    @type args: C{list}

    
    @return: The calculated x3 coefficient
    @rtype: (C{nessi_list.NessiList}, C{nessi_list.NessiList})
    """
    # Settle out the arguments to sensible names
    k_i = args[0]
    E_i = args[1]
    len_ratio = args[2]
    E_f = args[3]
    k_f = args[4]
    lam_const = args[5]
    t_0_s_corr = args[6]
    z_vec = args[7]

    # E_f / k_f
    const1 = E_f / k_f
    # (L_f / L_i) * (1 / k_f)^2 * (1 / 1 + ((h / m) * (t0_s / L_i)))
    const2 = (len_ratio * t_0_s_corr) / (k_f * k_f)
    # (4 * pi / l_f^2) * dlf/dh
    const3 = 2.0 * lam_const
    # E_i * k_i
    temp1 = array_manip.mult_ncerr(k_i, z_vec, E_i, z_vec)
    # E_i * k_i * (L_f / L_i) * (1 / k_f)^2
    # * (1 / 1 + ((h / m) * (t0_s / L_i)))
    temp2 = array_manip.mult_ncerr(temp1[0], temp1[1], const2, 0.0)
    # E_i * k_i * (L_f / L_i) * (1 / k_f)^2
    # * (1 / 1 + ((h / m) * (t0_s / L_i)))+ E_f / k_f
    temp3 = array_manip.add_ncerr(temp2[0], temp2[1], const1, 0.0)
    # (4 * pi / l_f^2) * dlf/dh * (E_i * k_i * (L_f / L_i) * (1 / k_f)^2
    # * (1 / 1 + ((h / m) * (t0_s / L_i))) + E_f / k_f)
    return array_manip.mult_ncerr(temp3[0], temp3[1], const3, 0.0)
def __calc_x3(*args):
    """
    This function calculates the x3 coeffiecient to the S(Q,E) Jacobian

    @param args: A list of parameters used to calculate the x3 coefficient

    The following is a list of the arguments needed in there expected order
      1. Initial Wavevector
      2. Initial Energy
      3. Length Ratio (L_f / L_i)
      4. Final Energy
      5. Final Wavevector
      6. Lambda Constant (2*pi/l_f^2)(dlf/dh)
      7. Time-zero Slope Correction
      8. Vector of Zeros
    @type args: C{list}

    
    @return: The calculated x3 coefficient
    @rtype: (C{nessi_list.NessiList}, C{nessi_list.NessiList})
    """
    # Settle out the arguments to sensible names
    k_i = args[0]
    E_i = args[1]
    len_ratio = args[2]
    E_f = args[3]
    k_f = args[4]
    lam_const = args[5]
    t_0_s_corr = args[6]
    z_vec = args[7]

    # E_f / k_f
    const1 = E_f / k_f
    # (L_f / L_i) * (1 / k_f)^2 * (1 / 1 + ((h / m) * (t0_s / L_i)))
    const2 = (len_ratio * t_0_s_corr) / (k_f * k_f)
    # (4 * pi / l_f^2) * dlf/dh
    const3 = 2.0 * lam_const
    # E_i * k_i
    temp1 = array_manip.mult_ncerr(k_i, z_vec, E_i, z_vec)
    # E_i * k_i * (L_f / L_i) * (1 / k_f)^2
    # * (1 / 1 + ((h / m) * (t0_s / L_i)))
    temp2 = array_manip.mult_ncerr(temp1[0], temp1[1], const2, 0.0)
    # E_i * k_i * (L_f / L_i) * (1 / k_f)^2
    # * (1 / 1 + ((h / m) * (t0_s / L_i)))+ E_f / k_f
    temp3 = array_manip.add_ncerr(temp2[0], temp2[1], const1, 0.0)
    # (4 * pi / l_f^2) * dlf/dh * (E_i * k_i * (L_f / L_i) * (1 / k_f)^2
    # * (1 / 1 + ((h / m) * (t0_s / L_i))) + E_f / k_f)
    return array_manip.mult_ncerr(temp3[0], temp3[1], const3, 0.0)
def calc_substrate_trans(obj, subtrans_coeff, substrate_diam, **kwargs):
    """
    This function calculates substrate transmission via the following formula:
    T = exp[-(A + B * wavelength) * d] where A is a constant with units of
    cm^-1, B is a constant with units of cm^-2 and d is the substrate
    diameter in units of cm.

    @param obj: The data object that contains the TOF axes to calculate the
                transmission from.
    @type obj: C{SOM.SOM} or C{SOM.SO}

    @param subtrans_coeff: The two coefficients for substrate transmission
           calculation.
    @type subtrans_coeff: C{tuple} of two C{float}s

    @param substrate_diam: The diameter of the substrate.
    @type substrate_diam: C{float}

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

    @keyword pathlength: The pathlength and its associated error^2
    @type pathlength: C{tuple} or C{list} of C{tuple}s

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


    @return: The calculate transmission for the given substrate parameters
    @rtype: C{SOM.SOM} or C{SOM.SO}

    
    @raise TypeError: The object used for calculation is not a C{SOM} or a
                      C{SO}

    @raise RuntimeError: The C{SOM} x-axis units are not I{microsecond}
    
    @raise RuntimeError: A C{SOM} does not contain an instrument and no
                         pathlength was provided
                         
    @raise RuntimeError: No C{SOM} is provided and no pathlength given
    """
    # import the helper functions
    import hlr_utils

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

    if o_descr == "number" or o_descr == "list":
        raise TypeError("Do not know how to handle given type: %s" % o_descr)
    else:
        pass

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

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

    # Primary axis for transformation. If a SO is passed, the function, will
    # assume the axis for transformation is at the 0 position
    if o_descr == "SOM":
        axis = hlr_utils.one_d_units(obj, units)
    else:
        axis = 0

    if pathlength is not None:
        p_descr = hlr_utils.get_descr(pathlength)
    else:
        if o_descr == "SOM":
            try:
                obj.attr_list.instrument.get_primary()
                inst = obj.attr_list.instrument
            except RuntimeError:
                raise RuntimeError("A detector was not provided")
        else:
            raise RuntimeError("If no SOM is provided, then pathlength "\
                               +"information must be provided")            

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)
    if res_descr == "SOM":
        result.setYLabel("Transmission")

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

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

        if pathlength is None:
            (pl, pl_err2) = hlr_utils.get_parameter("total", map_so, inst)
        else:
            pl = hlr_utils.get_value(pathlength, i, p_descr)
            pl_err2 = hlr_utils.get_err2(pathlength, i, p_descr)        

        value = axis_manip.tof_to_wavelength(val, err2, pl, pl_err2)

        value1 = utils.calc_bin_centers(value[0])
        del value

        # Convert Angstroms to centimeters
        value2 = array_manip.mult_ncerr(value1[0], value1[1],
                                        subtrans_coeff[1]*1.0e-8, 0.0)
        del value1

        # Calculate the exponential
        value3 = array_manip.add_ncerr(value2[0], value2[1],
                                       subtrans_coeff[0], 0.0)
        del value2

        value4 = array_manip.mult_ncerr(value3[0], value3[1],
                                        -1.0*substrate_diam, 0.0)
        del value3

        # Calculate transmission
        trans = nessi_list.NessiList()
        len_trans = len(value4[0])
        for j in xrange(len_trans):
            trans.append(math.exp(value4[0][j]))

        trans_err2 = nessi_list.NessiList(len(trans))

        hlr_utils.result_insert(result, res_descr, (trans, trans_err2), map_so)

    return result
def create_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
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
def calc_BSS_EQ_verticies(*args):
    """
    This function calculates the S(Q,E) bin verticies for BSS. It uses the
    x_i coefficients, dT, dh and the E and Q bin centers for the calculation.

    @param args: A list of parameters (C{tuple}s with value and err^2) used to
    calculate the x_i coefficients

    The following is a list of the arguments needed in there expected order
      1. Energy Transfer
      2. Momentum Transfer
      3. x_1 coefficient
      4. x_2 coefficient
      5. x_3 coefficient
      6. x_4 coefficient
      7. dT (Time-of-flight bin widths)
      8. dh (Height of detector pixel)
      9. Vector of Zeros
    @type args: C{list}


    @return: The calculated Q and E verticies ((Q_1, E_1), (Q_2, E_2),
             (Q_3, E_3), (Q_4, E_4))
    @rtype: C{tuple} of 4 C{tuple}s of 2 C{nessi_list.NessiList}s
    """
    # Settle out the arguments to sensible names
    E_t = args[0][0]
    E_t_err2 = args[0][1]
    Q = args[1][0]
    Q_err2 = args[1][1]
    x_1 = args[2]
    x_2 = args[3]
    x_3 = args[4]
    x_4 = args[5]
    dT = args[6]
    dh = args[7]
    zero_vec = args[8]

    # Calculate bin centric values
    (E_t_bc, E_t_bc_err2) = utils.calc_bin_centers(E_t, E_t_err2)
    (Q_bc, Q_bc_err2) = utils.calc_bin_centers(Q, Q_err2)

    (x1dh, x1dh_err2) = array_manip.mult_ncerr(x_1, zero_vec, dh, 0.0)
    (x3dh, x3dh_err2) = array_manip.mult_ncerr(x_3, zero_vec, dh, 0.0)
    (x2dT, x2dT_err2) = array_manip.mult_ncerr(x_2, zero_vec, dT, zero_vec)
    (x4dT, x4dT_err2) = array_manip.mult_ncerr(x_4, zero_vec, dT, zero_vec)

    (x1dh_p_x2dT,
     x1dh_p_x2dT_err2) = array_manip.add_ncerr(x1dh, x1dh_err2, x2dT,
                                               x2dT_err2)
    (x3dh_p_x4dT,
     x3dh_p_x4dT_err2) = array_manip.add_ncerr(x3dh, x3dh_err2, x4dT,
                                               x4dT_err2)
    (x1dh_m_x2dT,
     x1dh_m_x2dT_err2) = array_manip.sub_ncerr(x1dh, x1dh_err2, x2dT,
                                               x2dT_err2)
    (x3dh_m_x4dT,
     x3dh_m_x4dT_err2) = array_manip.sub_ncerr(x3dh, x3dh_err2, x4dT,
                                               x4dT_err2)

    (dQ_1, dQ_1_err2) = array_manip.mult_ncerr(x1dh_p_x2dT, x1dh_p_x2dT_err2,
                                               -0.5, 0.0)
    (dE_1, dE_1_err2) = array_manip.mult_ncerr(x3dh_p_x4dT, x3dh_p_x4dT_err2,
                                               -0.5, 0.0)
    (dQ_2, dQ_2_err2) = array_manip.mult_ncerr(x1dh_m_x2dT, x1dh_m_x2dT_err2,
                                               -0.5, 0.0)
    (dE_2, dE_2_err2) = array_manip.mult_ncerr(x3dh_m_x4dT, x3dh_m_x4dT_err2,
                                               -0.5, 0.0)

    (dQ_3, dQ_3_err2) = array_manip.mult_ncerr(dQ_1, dQ_1_err2, -1.0, 0.0)
    (dE_3, dE_3_err2) = array_manip.mult_ncerr(dE_1, dE_1_err2, -1.0, 0.0)
    (dQ_4, dQ_4_err2) = array_manip.mult_ncerr(dQ_2, dQ_2_err2, -1.0, 0.0)
    (dE_4, dE_4_err2) = array_manip.mult_ncerr(dE_2, dE_2_err2, -1.0, 0.0)

    Q_1 = array_manip.add_ncerr(Q_bc, Q_bc_err2, dQ_1, dQ_1_err2)
    E_t_1 = array_manip.add_ncerr(E_t_bc, E_t_bc_err2, dE_1, dE_1_err2)

    Q_2 = array_manip.add_ncerr(Q_bc, Q_bc_err2, dQ_2, dQ_2_err2)
    E_t_2 = array_manip.add_ncerr(E_t_bc, E_t_bc_err2, dE_2, dE_2_err2)

    Q_3 = array_manip.add_ncerr(Q_bc, Q_bc_err2, dQ_3, dQ_3_err2)
    E_t_3 = array_manip.add_ncerr(E_t_bc, E_t_bc_err2, dE_3, dE_3_err2)

    Q_4 = array_manip.add_ncerr(Q_bc, Q_bc_err2, dQ_4, dQ_4_err2)
    E_t_4 = array_manip.add_ncerr(E_t_bc, E_t_bc_err2, dE_4, dE_4_err2)

    return ((Q_1[0], E_t_1[0]), (Q_2[0], E_t_2[0]), (Q_3[0], E_t_3[0]),
            (Q_4[0], E_t_4[0]))
Esempio n. 7
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
Esempio n. 8
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)
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
Esempio n. 10
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)
Esempio n. 11
0
def run(config):
    """
    This method is where the processing is done.

    @param config: Object containing the driver configuration information.
    @type config: L{hlr_utils.Configure}
    """
    if config.data is None:
        raise RuntimeError("Need to pass a data filename to the driver "\
                           +"script.")

    dst_type = hlr_utils.file_peeker(config.data[0])
    if dst_type != "text/Dave2d":
        raise TypeError("Only Dave2D ASCII files can be handled. Do not "\
                        +"know how to handle %s." % dst_type)

    spectra = []

    # Read in all data files
    for datafile in config.data:
        spectra.append(dr_lib.add_files([datafile], dst_type=dst_type,
                                        Verbose=config.verbose))

    # Sort spectra on slowest axis (Q for BSS files)
    spectra.sort(lambda x, y: cmp(x[0].axis[0].val[0], y[0].axis[0].val[0]))

    # Create placeholder for combined spectrum
    Ny = len(spectra)
    Nx = len(spectra[0][0].axis[1].val)

    import nessi_list
    import SOM

    result = SOM.SOM()
    result = hlr_utils.copy_som_attr(result, "SOM", spectra[0], "SOM")
    
    so = SOM.SO(2)
    so.id = 0
    so.y = nessi_list.NessiList(Nx * Ny)
    so.var_y = nessi_list.NessiList(Nx * Ny)
    so.axis[1].val = spectra[0][0].axis[1].val

    # Make the slowest axis
    slow_axis = [x[0].axis[0].val[0] for x in spectra]
    so.axis[0].val = nessi_list.NessiList()
    so.axis[0].val.extend(slow_axis)

    # Create combined spectrum
    import array_manip
    
    for i in xrange(Ny):
        value = hlr_utils.get_value(spectra[i], 0, "SOM", "y")
        err2 = hlr_utils.get_err2(spectra[i], 0, "SOM", "y")
        
        start = i * Nx

        (so.y, so.var_y) = array_manip.add_ncerr(so.y, so.var_y, value, err2,
                                                a_start=start)

    result.append(so)

    # Rescale data if necessary
    if config.rescale is not None:
        import common_lib
        result2 = common_lib.mult_ncerr(result, (config.rescale, 0.0))
    else:
        result2 = result

    del result

    hlr_utils.write_file(config.output, dst_type, result2,
                         verbose=config.verbose,
                         replace_ext=False,
                         path_replacement=config.path_replacement,
                         axis_ok=True,
                         message="combined file")
Esempio n. 12
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
Esempio n. 13
0
def run(config):
    """
    This method is where the processing is done.

    @param config: Object containing the driver configuration information.
    @type config: L{hlr_utils.Configure}
    """
    if config.data is None:
        raise RuntimeError("Need to pass a data filename to the driver "\
                           +"script.")

    dst_type = hlr_utils.file_peeker(config.data[0])
    if dst_type != "text/Dave2d":
        raise TypeError("Only Dave2D ASCII files can be handled. Do not "\
                        +"know how to handle %s." % dst_type)

    spectra = []

    # Read in all data files
    for datafile in config.data:
        spectra.append(
            dr_lib.add_files([datafile],
                             dst_type=dst_type,
                             Verbose=config.verbose))

    # Sort spectra on slowest axis (Q for BSS files)
    spectra.sort(lambda x, y: cmp(x[0].axis[0].val[0], y[0].axis[0].val[0]))

    # Create placeholder for combined spectrum
    Ny = len(spectra)
    Nx = len(spectra[0][0].axis[1].val)

    import nessi_list
    import SOM

    result = SOM.SOM()
    result = hlr_utils.copy_som_attr(result, "SOM", spectra[0], "SOM")

    so = SOM.SO(2)
    so.id = 0
    so.y = nessi_list.NessiList(Nx * Ny)
    so.var_y = nessi_list.NessiList(Nx * Ny)
    so.axis[1].val = spectra[0][0].axis[1].val

    # Make the slowest axis
    slow_axis = [x[0].axis[0].val[0] for x in spectra]
    so.axis[0].val = nessi_list.NessiList()
    so.axis[0].val.extend(slow_axis)

    # Create combined spectrum
    import array_manip

    for i in xrange(Ny):
        value = hlr_utils.get_value(spectra[i], 0, "SOM", "y")
        err2 = hlr_utils.get_err2(spectra[i], 0, "SOM", "y")

        start = i * Nx

        (so.y, so.var_y) = array_manip.add_ncerr(so.y,
                                                 so.var_y,
                                                 value,
                                                 err2,
                                                 a_start=start)

    result.append(so)

    # Rescale data if necessary
    if config.rescale is not None:
        import common_lib
        result2 = common_lib.mult_ncerr(result, (config.rescale, 0.0))
    else:
        result2 = result

    del result

    hlr_utils.write_file(config.output,
                         dst_type,
                         result2,
                         verbose=config.verbose,
                         replace_ext=False,
                         path_replacement=config.path_replacement,
                         axis_ok=True,
                         message="combined file")
Esempio n. 14
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
Esempio n. 15
0
def wavelength_to_energy(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from wavelength
    to energy. 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{(energy, energy_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 offset: Energy offset information
    @type offset: 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 wavelength converted to energy
    @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:
        offset = kwargs["offset"]
    except KeyError:
        offset = None

    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, "meV", axis)
        result.setAxisLabel(axis, "energy")
        result.setYUnits("Counts/meV")
        result.setYLabel("Intensity")
    else:
        pass

    # iterate through the values
    import array_manip
    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)

        value = axis_manip.wavelength_to_energy(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

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

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

    return result
Esempio n. 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)
Esempio n. 17
0
def calc_BSS_EQ_verticies(*args):
    """
    This function calculates the S(Q,E) bin verticies for BSS. It uses the
    x_i coefficients, dT, dh and the E and Q bin centers for the calculation.

    @param args: A list of parameters (C{tuple}s with value and err^2) used to
    calculate the x_i coefficients

    The following is a list of the arguments needed in there expected order
      1. Energy Transfer
      2. Momentum Transfer
      3. x_1 coefficient
      4. x_2 coefficient
      5. x_3 coefficient
      6. x_4 coefficient
      7. dT (Time-of-flight bin widths)
      8. dh (Height of detector pixel)
      9. Vector of Zeros
    @type args: C{list}


    @return: The calculated Q and E verticies ((Q_1, E_1), (Q_2, E_2),
             (Q_3, E_3), (Q_4, E_4))
    @rtype: C{tuple} of 4 C{tuple}s of 2 C{nessi_list.NessiList}s
    """
    # Settle out the arguments to sensible names
    E_t = args[0][0]
    E_t_err2 = args[0][1]
    Q = args[1][0]
    Q_err2 = args[1][1]
    x_1 = args[2]
    x_2 = args[3]
    x_3 = args[4]
    x_4 = args[5]
    dT = args[6]
    dh = args[7]
    zero_vec = args[8]

    # Calculate bin centric values
    (E_t_bc, E_t_bc_err2) = utils.calc_bin_centers(E_t, E_t_err2)
    (Q_bc, Q_bc_err2) = utils.calc_bin_centers(Q, Q_err2)

    (x1dh, x1dh_err2) = array_manip.mult_ncerr(x_1, zero_vec, dh, 0.0)
    (x3dh, x3dh_err2) = array_manip.mult_ncerr(x_3, zero_vec, dh, 0.0)
    (x2dT, x2dT_err2) = array_manip.mult_ncerr(x_2, zero_vec, dT, zero_vec)
    (x4dT, x4dT_err2) = array_manip.mult_ncerr(x_4, zero_vec, dT, zero_vec)

    (x1dh_p_x2dT, x1dh_p_x2dT_err2) = array_manip.add_ncerr(x1dh, x1dh_err2, x2dT, x2dT_err2)
    (x3dh_p_x4dT, x3dh_p_x4dT_err2) = array_manip.add_ncerr(x3dh, x3dh_err2, x4dT, x4dT_err2)
    (x1dh_m_x2dT, x1dh_m_x2dT_err2) = array_manip.sub_ncerr(x1dh, x1dh_err2, x2dT, x2dT_err2)
    (x3dh_m_x4dT, x3dh_m_x4dT_err2) = array_manip.sub_ncerr(x3dh, x3dh_err2, x4dT, x4dT_err2)

    (dQ_1, dQ_1_err2) = array_manip.mult_ncerr(x1dh_p_x2dT, x1dh_p_x2dT_err2, -0.5, 0.0)
    (dE_1, dE_1_err2) = array_manip.mult_ncerr(x3dh_p_x4dT, x3dh_p_x4dT_err2, -0.5, 0.0)
    (dQ_2, dQ_2_err2) = array_manip.mult_ncerr(x1dh_m_x2dT, x1dh_m_x2dT_err2, -0.5, 0.0)
    (dE_2, dE_2_err2) = array_manip.mult_ncerr(x3dh_m_x4dT, x3dh_m_x4dT_err2, -0.5, 0.0)

    (dQ_3, dQ_3_err2) = array_manip.mult_ncerr(dQ_1, dQ_1_err2, -1.0, 0.0)
    (dE_3, dE_3_err2) = array_manip.mult_ncerr(dE_1, dE_1_err2, -1.0, 0.0)
    (dQ_4, dQ_4_err2) = array_manip.mult_ncerr(dQ_2, dQ_2_err2, -1.0, 0.0)
    (dE_4, dE_4_err2) = array_manip.mult_ncerr(dE_2, dE_2_err2, -1.0, 0.0)

    Q_1 = array_manip.add_ncerr(Q_bc, Q_bc_err2, dQ_1, dQ_1_err2)
    E_t_1 = array_manip.add_ncerr(E_t_bc, E_t_bc_err2, dE_1, dE_1_err2)

    Q_2 = array_manip.add_ncerr(Q_bc, Q_bc_err2, dQ_2, dQ_2_err2)
    E_t_2 = array_manip.add_ncerr(E_t_bc, E_t_bc_err2, dE_2, dE_2_err2)

    Q_3 = array_manip.add_ncerr(Q_bc, Q_bc_err2, dQ_3, dQ_3_err2)
    E_t_3 = array_manip.add_ncerr(E_t_bc, E_t_bc_err2, dE_3, dE_3_err2)

    Q_4 = array_manip.add_ncerr(Q_bc, Q_bc_err2, dQ_4, dQ_4_err2)
    E_t_4 = array_manip.add_ncerr(E_t_bc, E_t_bc_err2, dE_4, dE_4_err2)

    return ((Q_1[0], E_t_1[0]), (Q_2[0], E_t_2[0]), (Q_3[0], E_t_3[0]), (Q_4[0], E_t_4[0]))
Esempio n. 18
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
Esempio n. 19
0
def __calc_x1(*args):
    """
    This function calculates the x1 coeffiecient to the S(Q,E) Jacobian

    @param args: A list of parameters used to calculate the x1 coefficient

    The following is a list of the arguments needed in there expected order
      1. Initial Wavevector
      2. Momentum Transfer
      3. Length Ratio (L_f / L_i)
      4. Final Wavevector
      5. Wavevector Final x Cos(polar)
      6. Wavevector Final x Sin(polar)
      7. Lambda Constant (2*pi/l_f^2)(dlf/dh)
      8. Derivative dazi_dh
      9. Derivative dpol_dh
      10. Derivative dpol_dtd
      11. Derivative dazi_dtd
      12. Cos(polar)
      13. Time-zero Slope Correction
      14. Vector of Zeros
    @type args: C{list}

    
    @return: The calculated x1 coefficient
    @rtype: (C{nessi_list.NessiList}, C{nessi_list.NessiList})
    """
    # Settle out the arguments to sensible names
    k_i = args[0]
    Q = args[1]
    len_ratio = args[2]
    k_f = args[3]
    k_f_cos_pol = args[4]
    k_f_sin_pol = args[5]
    lam_const = args[6]
    dpol_dh = args[7]
    dpol_dtd = args[8]
    dtd_over_dh = args[9]
    cos_pol = args[10]
    t_0_s_corr = args[11]
    z_vec = args[12]

    # (L_f / L_i) * (1 / k_f)^2 * (1 / 1 + ((h / m) * (t0_s / L_i)))
    const1 = (len_ratio * t_0_s_corr) / (k_f * k_f)
    # (dpol/dh + (dpol/dtd * dtd/dh)) * k_f * sin(pol)
    const2 = (dpol_dh + (dpol_dtd * dtd_over_dh)) * k_f_sin_pol

    # k_i^2
    temp1 = array_manip.mult_ncerr(k_i, z_vec, k_i, z_vec)
    # (L_f / L_i) * (k_i / k_f)^2 * (1 / 1 + ((h / m) * (t0_s / L_i)))
    temp2 = array_manip.mult_ncerr(temp1[0], temp1[1], const1, 0.0)
    # k_i - k_f * cos(pol)
    temp3 = array_manip.sub_ncerr(k_i, z_vec, k_f_cos_pol, 0.0)
    # (k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2
    temp4 = array_manip.mult_ncerr(temp2[0], temp2[1], temp3[0], temp3[1])

    # k_i * cos(pol)
    temp5 = array_manip.mult_ncerr(k_i, z_vec, cos_pol, 0.0)
    # k_f - k_i * cos(pol)
    temp6 = array_manip.sub_ncerr(k_f, 0.0, temp5[0], temp5[1])

    # (k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2 -
    # (k_f - k_i * cos(pol))
    temp7 = array_manip.sub_ncerr(temp4[0], temp4[1], temp6[0], temp6[1])
    # ((k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2 -
    # (k_f - k_i * cos(pol))) * (2 * pi / l_f^2) * dlf/dh
    temp8 = array_manip.mult_ncerr(temp7[0], temp7[1], lam_const, 0.0)

    # k_i * k_f * sin(pol) * (dpol/dh + (dpol/dtd * dtd/dh))
    temp9 = array_manip.mult_ncerr(k_i, z_vec, const2, 0.0)

    # ((k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2 -
    # (k_f - k_i * cos(pol))) * (2 * pi / l_f^2) * dlf/dh +
    # k_i * k_f * sin(pol) * (dpol/dh + (dpol/dtd * dtd/dh))
    temp10 = array_manip.add_ncerr(temp8[0], temp8[1], temp9[0], temp9[1])

    # (((k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2 -
    # (k_f - k_i * cos(pol))) * (2 * pi / l_f^2) * dlf/dh +
    # k_i * k_f * sin(pol) * (dpol/dh - (dpol/dtd dazi/dh / dazi/dtd))
    return array_manip.div_ncerr(temp10[0], temp10[1], Q, z_vec)
Esempio n. 20
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
Esempio n. 21
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)
Esempio n. 22
0
def __calc_x1(*args):
    """
    This function calculates the x1 coeffiecient to the S(Q,E) Jacobian

    @param args: A list of parameters used to calculate the x1 coefficient

    The following is a list of the arguments needed in there expected order
      1. Initial Wavevector
      2. Momentum Transfer
      3. Length Ratio (L_f / L_i)
      4. Final Wavevector
      5. Wavevector Final x Cos(polar)
      6. Wavevector Final x Sin(polar)
      7. Lambda Constant (2*pi/l_f^2)(dlf/dh)
      8. Derivative dazi_dh
      9. Derivative dpol_dh
      10. Derivative dpol_dtd
      11. Derivative dazi_dtd
      12. Cos(polar)
      13. Time-zero Slope Correction
      14. Vector of Zeros
    @type args: C{list}

    
    @return: The calculated x1 coefficient
    @rtype: (C{nessi_list.NessiList}, C{nessi_list.NessiList})
    """
    # Settle out the arguments to sensible names
    k_i = args[0]
    Q = args[1]
    len_ratio = args[2]
    k_f = args[3]
    k_f_cos_pol = args[4]
    k_f_sin_pol = args[5]
    lam_const = args[6]
    dpol_dh = args[7]
    dpol_dtd = args[8]
    dtd_over_dh = args[9]
    cos_pol = args[10]
    t_0_s_corr = args[11]
    z_vec = args[12]

    # (L_f / L_i) * (1 / k_f)^2 * (1 / 1 + ((h / m) * (t0_s / L_i)))
    const1 = (len_ratio * t_0_s_corr) / (k_f * k_f)
    # (dpol/dh + (dpol/dtd * dtd/dh)) * k_f * sin(pol)
    const2 = (dpol_dh + (dpol_dtd * dtd_over_dh)) * k_f_sin_pol

    # k_i^2
    temp1 = array_manip.mult_ncerr(k_i, z_vec, k_i, z_vec)
    # (L_f / L_i) * (k_i / k_f)^2 * (1 / 1 + ((h / m) * (t0_s / L_i)))
    temp2 = array_manip.mult_ncerr(temp1[0], temp1[1], const1, 0.0)
    # k_i - k_f * cos(pol)
    temp3 = array_manip.sub_ncerr(k_i, z_vec, k_f_cos_pol, 0.0)
    # (k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2
    temp4 = array_manip.mult_ncerr(temp2[0], temp2[1], temp3[0], temp3[1])

    # k_i * cos(pol)
    temp5 = array_manip.mult_ncerr(k_i, z_vec, cos_pol, 0.0)
    # k_f - k_i * cos(pol)
    temp6 = array_manip.sub_ncerr(k_f, 0.0, temp5[0], temp5[1])

    # (k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2 -
    # (k_f - k_i * cos(pol))
    temp7 = array_manip.sub_ncerr(temp4[0], temp4[1], temp6[0], temp6[1])
    # ((k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2 -
    # (k_f - k_i * cos(pol))) * (2 * pi / l_f^2) * dlf/dh
    temp8 = array_manip.mult_ncerr(temp7[0], temp7[1], lam_const, 0.0)

    # k_i * k_f * sin(pol) * (dpol/dh + (dpol/dtd * dtd/dh))
    temp9 = array_manip.mult_ncerr(k_i, z_vec, const2, 0.0)

    # ((k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2 -
    # (k_f - k_i * cos(pol))) * (2 * pi / l_f^2) * dlf/dh +
    # k_i * k_f * sin(pol) * (dpol/dh + (dpol/dtd * dtd/dh))
    temp10 = array_manip.add_ncerr(temp8[0], temp8[1], temp9[0], temp9[1])

    # (((k_i - k_f * cos(pol)) * (L_f / L_i) * (k_i / k_f)^2 -
    # (k_f - k_i * cos(pol))) * (2 * pi / l_f^2) * dlf/dh +
    # k_i * k_f * sin(pol) * (dpol/dh - (dpol/dtd dazi/dh / dazi/dtd))
    return array_manip.div_ncerr(temp10[0], temp10[1], Q, z_vec)
Esempio n. 23
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
Esempio n. 24
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
Esempio n. 25
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
Esempio n. 26
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
def wavelength_to_energy(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from wavelength
    to energy. 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{(energy, energy_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 offset: Energy offset information
    @type offset: 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 wavelength converted to energy
    @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:
        offset = kwargs["offset"]
    except KeyError:
        offset = None

    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, "meV", axis)
        result.setAxisLabel(axis, "energy")
        result.setYUnits("Counts/meV")
        result.setYLabel("Intensity")
    else:
        pass

    # iterate through the values
    import array_manip
    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)

        value = axis_manip.wavelength_to_energy(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

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

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

    return result