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

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

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

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

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


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

    # import the helper functions
    import hlr_utils

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

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

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

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

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

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

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

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

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return result
Beispiel #2
0
def run(config, tim):
    """
    This method is where the data reduction process gets done.

    @param config: Object containing the data reduction configuration
                   information.
    @type config: L{hlr_utils.Configure}

    @param tim: Object that will allow the method to perform timing
                evaluations.
    @type tim: C{sns_time.DiffTime}
    """
    import DST
    import math
    if config.inst == "REF_M":
        import axis_manip
        import utils

    if tim is not None:
        tim.getTime(False)
        old_time = tim.getOldTime()

    if config.data is None:
        raise RuntimeError("Need to pass a data filename to the driver "\
                           +"script.")

    # Read in sample data geometry if one is provided
    if config.data_inst_geom is not None:
        if config.verbose:
            print "Reading in sample data instrument geometry file"
            
        data_inst_geom_dst = DST.getInstance("application/x-NxsGeom",
                                             config.data_inst_geom)
    else:
        data_inst_geom_dst = None

    # Read in normalization data geometry if one is provided
    if config.norm_inst_geom is not None:
        if config.verbose:
            print "Reading in normalization instrument geometry file"
            
        norm_inst_geom_dst = DST.getInstance("application/x-NxsGeom",
                                        config.norm_inst_geom)
    else:
        norm_inst_geom_dst = None        
    
    # Perform Steps 1-6 on sample data
    d_som1 = dr_lib.process_ref_data(config.data, config,
                                     config.data_roi_file,
                                     config.dbkg_roi_file,
                                     config.no_bkg,
                                     tof_cuts=config.tof_cuts,
                                     inst_geom_dst=data_inst_geom_dst,
                                     timer=tim)

    # Perform Steps 1-6 on normalization data
    if config.norm is not None:
        n_som1 = dr_lib.process_ref_data(config.norm, config,
                                         config.norm_roi_file,
                                         config.nbkg_roi_file,
                                         config.no_norm_bkg,
                                         dataset_type="norm",
                                         tof_cuts=config.tof_cuts,
                                         inst_geom_dst=norm_inst_geom_dst,
                                         timer=tim)
    else:
        n_som1 = None

    if config.Q_bins is None and config.scatt_angle is not None:
        import copy
        tof_axis = copy.deepcopy(d_som1[0].axis[0].val)

    # Closing sample data instrument geometry file
    if data_inst_geom_dst is not None:
        data_inst_geom_dst.release_resource()

    # Closing normalization data instrument geometry file
    if norm_inst_geom_dst is not None:
        norm_inst_geom_dst.release_resource()        

    # Step 7: Sum all normalization spectra together
    if config.norm is not None:
        n_som2 = dr_lib.sum_all_spectra(n_som1)
    else:
        n_som2 = None

    del n_som1

    # Step 8: Divide data by normalization
    if config.verbose and config.norm is not None:
        print "Scale data by normalization"

    if config.norm is not None:
        d_som2 = common_lib.div_ncerr(d_som1, n_som2, length_one_som=True)
    else:
        d_som2 = d_som1

    if tim is not None and config.norm is not None:
        tim.getTime(msg="After normalizing signal spectra")

    del d_som1, n_som2

    if config.dump_rtof_comb:
        d_som2_1 = dr_lib.sum_all_spectra(d_som2)
        d_som2_2 = dr_lib.data_filter(d_som2_1)
        del d_som2_1

        if config.inst == "REF_M":
            tof_bc = utils.calc_bin_centers(d_som2_2[0].axis[0].val)
            d_som2_2[0].axis[0].val = tof_bc[0]
            d_som2_2.setDataSetType("density")
        
        hlr_utils.write_file(config.output, "text/Spec", d_som2_2,
                             output_ext="crtof",
                             verbose=config.verbose,
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             message="combined R(TOF) information")

        del d_som2_2

    if config.dump_rtof:
        if config.inst == "REF_M":
            d_som2_1 = d_som2
        else:
            d_som2_1 = dr_lib.filter_ref_data(d_som2)
        
        hlr_utils.write_file(config.output, "text/Spec", d_som2_1,
                             output_ext="rtof",
                             verbose=config.verbose,
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             message="R(TOF) information")
        del d_som2_1

    if config.inst == "REF_L":
        # Step 9: Convert TOF to scalar Q
        if config.verbose:
            print "Converting TOF to scalar Q"
    
        # Check to see if polar angle offset is necessary
        if config.angle_offset is not None:
            # Check on units, offset must be in radians
            p_temp = config.angle_offset.toFullTuple(True)
            if p_temp[2] == "degrees" or p_temp[2] == "degree":
                deg_to_rad =  (math.pi / 180.0)
                p_off_rads = p_temp[0] * deg_to_rad
                p_off_err2_rads = p_temp[1] * deg_to_rad * deg_to_rad
            else:
                p_off_rads = p_temp[0]
                p_off_err2_rads = p_temp[1]
    
            p_offset = (p_off_rads, p_off_err2_rads)
    
            d_som2.attr_list["angle_offset"] = config.angle_offset
        else:
            p_offset = None
    
        if tim is not None:
            tim.getTime(False)
    
        d_som3 = common_lib.tof_to_scalar_Q(d_som2, units="microsecond",
                                            angle_offset=p_offset,
                                            lojac=False)
    
        del d_som2
            
        if tim is not None:
            tim.getTime(msg="After converting wavelength to scalar Q ")
    
        if config.dump_rq:
            d_som3_1 = dr_lib.data_filter(d_som3, clean_axis=True)
            hlr_utils.write_file(config.output, "text/Spec", d_som3_1,
                                 output_ext="rq",
                                 verbose=config.verbose,
                                 data_ext=config.ext_replacement,
                                 path_replacement=config.path_replacement,
                                 message="pixel R(Q) information")
            del d_som3_1
                    
        if not config.no_filter:
            if config.verbose:
                print "Filtering final data"
            
            if tim is not None:
                tim.getTime(False)
            
            d_som4 = dr_lib.data_filter(d_som3)
    
            if tim is not None:
                tim.getTime(msg="After filtering data")
        else:
            d_som4 = d_som3
    
        del d_som3
    else:
        d_som4 = d_som2

    # Step 10: Rebin all spectra to final Q axis
    if config.Q_bins is None:
        if config.scatt_angle is None:
            config.Q_bins = dr_lib.create_axis_from_data(d_som4)
            rebin_axis = config.Q_bins.toNessiList()
        else:
            # Get scattering angle and make Q conversion from TOF axis
            # Check on units, scattering angle must be in radians
            sa_temp = config.scatt_angle.toFullTuple(True)
            if sa_temp[2] == "degrees" or sa_temp[2] == "degree":
                deg_to_rad =  (math.pi / 180.0)
                sa_rads = sa_temp[0] * deg_to_rad
                sa_err2_rads = sa_temp[1] * deg_to_rad * deg_to_rad
            else:
                sa_rads = sa_temp[0]
                sa_err2_rads = sa_temp[1]

            sa = (sa_rads, sa_err2_rads)

            pl = d_som4.attr_list.instrument.get_total_path(d_som4[0].id,
                                                            det_secondary=True)

            import nessi_list
            tof_axis_err2 = nessi_list.NessiList(len(tof_axis))

            rebin_axis = axis_manip.tof_to_scalar_Q(tof_axis,
                                                    tof_axis_err2,
                                                    pl[0], pl[1],
                                                    sa[0], sa[1])[0]

            axis_manip.reverse_array_nc(rebin_axis)            
    else:
        rebin_axis = config.Q_bins.toNessiList()

    if config.inst == "REF_L":
        if config.verbose:
            print "Rebinning spectra"

        if tim is not None:
            tim.getTime(False)
            
        d_som5 = common_lib.rebin_axis_1D_linint(d_som4, rebin_axis)
    
        if tim is not None:
            tim.getTime(msg="After rebinning spectra")
    
        del d_som4
    
        if config.dump_rqr:
            hlr_utils.write_file(config.output, "text/Spec", d_som5,
                                 output_ext="rqr",
                                 verbose=config.verbose,
                                 data_ext=config.ext_replacement,
                                 path_replacement=config.path_replacement,
                                 message="pixel R(Q) (after rebinning) "\
                                 +"information")
    
        # Step 11: Sum all rebinned spectra
        if config.verbose:
            print "Summing spectra"
    
        if tim is not None:
            tim.getTime(False)
    
        d_som6 = dr_lib.sum_all_spectra(d_som5)
    
        if tim is not None:
            tim.getTime(msg="After summing spectra")
    
        del d_som5
    else:
        d_som5 = d_som4

    if config.inst == "REF_M":
        d_som5A = dr_lib.sum_all_spectra(d_som5)
        del d_som5
        d_som6 = dr_lib.data_filter(d_som5A)
        del d_som5A
        axis_manip.reverse_array_nc(d_som6[0].y)
        axis_manip.reverse_array_nc(d_som6[0].var_y)

        d_som6.setYLabel("Intensity")
        d_som6.setYUnits("Counts/A-1")
        d_som6.setAllAxisLabels(["scalar wavevector transfer"])
        d_som6.setAllAxisUnits(["1/Angstroms"])

        Q_bc = utils.calc_bin_centers(rebin_axis)
        d_som6[0].axis[0].val = Q_bc[0]
        d_som6.setDataSetType("density")

    hlr_utils.write_file(config.output, "text/Spec", d_som6,
                         replace_ext=False,
                         replace_path=False,
                         verbose=config.verbose,
                         message="combined Reflectivity information")

    d_som6.attr_list["config"] = config

    hlr_utils.write_file(config.output, "text/rmd", d_som6,
                         output_ext="rmd", verbose=config.verbose,
                         data_ext=config.ext_replacement,
                         path_replacement=config.path_replacement,
                         message="metadata")

    if tim is not None:
        tim.setOldTime(old_time)
        tim.getTime(msg="Total Running Time")
Beispiel #3
0
def tof_to_ref_scalar_Q(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to reflectometer scalar Q. This means that a single angle
    and a single flightpath is used. The time-of-flight axis for a C{SOM} must
    be in units of I{microseconds}. The primary axis of a C{SO} is assumed to
    be in units of I{microseconds}. A C{tuple} of C{(time-of-flight,
    time-of-flight_err2)} (assumed to be in units of I{microseconds}) can be
    converted to C{(scalar_Q, scalar_Q_err2)}.

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

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

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

    @keyword configure: This is the object containing the driver configuration.
                        This will signal the function to write out the counts
                        and fractional area to files.
    @type configure: C{Configure}


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


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

    # import the helper functions
    import hlr_utils

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

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

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

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

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

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

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

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

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

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

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

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

    if beamdiv_corr:
        import dr_lib

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

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

        if beamdiv_corr:
            dangle = dr_lib.ref_beamdiv_correct(obj.attr_list, map_so.id,
                                                config.det_spat_res,
                                                config.center_pix)
            # We subtract due to the inversion of the z coordinates from the
            # mirror reflection of the beam at the sample.
            if dangle is not None:
                pangle = angle - (2.0 * dangle)
            else:
                pangle = angle
                skip_pixel = True
        else:
            pangle = angle

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

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

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

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

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

    return result
Beispiel #4
0
def run(config, tim):
    """
    This method is where the data reduction process gets done.

    @param config: Object containing the data reduction configuration
                   information.
    @type config: L{hlr_utils.Configure}

    @param tim: Object that will allow the method to perform timing
                evaluations.
    @type tim: C{sns_time.DiffTime}
    """
    import DST
    import math

    if config.inst == "REF_M":
        import axis_manip
        import utils

    if tim is not None:
        tim.getTime(False)
        old_time = tim.getOldTime()

    if config.data is None:
        raise RuntimeError("Need to pass a data filename to the driver " + "script.")

    # Read in sample data geometry if one is provided
    if config.data_inst_geom is not None:
        if config.verbose:
            print "Reading in sample data instrument geometry file"

        data_inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.data_inst_geom)
    else:
        data_inst_geom_dst = None

    # Read in normalization data geometry if one is provided
    if config.norm_inst_geom is not None:
        if config.verbose:
            print "Reading in normalization instrument geometry file"

        norm_inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.norm_inst_geom)
    else:
        norm_inst_geom_dst = None

    # Perform Steps 1-6 on sample data
    d_som1 = dr_lib.process_ref_data(
        config.data,
        config,
        config.data_roi_file,
        config.dbkg_roi_file,
        config.no_bkg,
        tof_cuts=config.tof_cuts,
        inst_geom_dst=data_inst_geom_dst,
        timer=tim,
    )

    # Perform Steps 1-6 on normalization data
    if config.norm is not None:
        n_som1 = dr_lib.process_ref_data(
            config.norm,
            config,
            config.norm_roi_file,
            config.nbkg_roi_file,
            config.no_norm_bkg,
            dataset_type="norm",
            tof_cuts=config.tof_cuts,
            inst_geom_dst=norm_inst_geom_dst,
            timer=tim,
        )
    else:
        n_som1 = None

    if config.Q_bins is None and config.scatt_angle is not None:
        import copy

        tof_axis = copy.deepcopy(d_som1[0].axis[0].val)

    # Closing sample data instrument geometry file
    if data_inst_geom_dst is not None:
        data_inst_geom_dst.release_resource()

    # Closing normalization data instrument geometry file
    if norm_inst_geom_dst is not None:
        norm_inst_geom_dst.release_resource()

    # Step 7: Sum all normalization spectra together
    if config.norm is not None:
        n_som2 = dr_lib.sum_all_spectra(n_som1)
    else:
        n_som2 = None

    del n_som1

    # Step 8: Divide data by normalization
    if config.verbose and config.norm is not None:
        print "Scale data by normalization"

    if config.norm is not None:
        d_som2 = common_lib.div_ncerr(d_som1, n_som2, length_one_som=True)
    else:
        d_som2 = d_som1

    if tim is not None and config.norm is not None:
        tim.getTime(msg="After normalizing signal spectra")

    del d_som1, n_som2

    if config.dump_rtof_comb:
        d_som2_1 = dr_lib.sum_all_spectra(d_som2)
        d_som2_2 = dr_lib.data_filter(d_som2_1)
        del d_som2_1

        if config.inst == "REF_M":
            tof_bc = utils.calc_bin_centers(d_som2_2[0].axis[0].val)
            d_som2_2[0].axis[0].val = tof_bc[0]
            d_som2_2.setDataSetType("density")

        hlr_utils.write_file(
            config.output,
            "text/Spec",
            d_som2_2,
            output_ext="crtof",
            verbose=config.verbose,
            data_ext=config.ext_replacement,
            path_replacement=config.path_replacement,
            message="combined R(TOF) information",
        )

        del d_som2_2

    if config.dump_rtof:
        if config.inst == "REF_M":
            d_som2_1 = d_som2
        else:
            d_som2_1 = dr_lib.filter_ref_data(d_som2)

        hlr_utils.write_file(
            config.output,
            "text/Spec",
            d_som2_1,
            output_ext="rtof",
            verbose=config.verbose,
            data_ext=config.ext_replacement,
            path_replacement=config.path_replacement,
            message="R(TOF) information",
        )
        del d_som2_1

    if config.inst == "REF_L":
        # Step 9: Convert TOF to scalar Q
        if config.verbose:
            print "Converting TOF to scalar Q"

        # Check to see if polar angle offset is necessary
        if config.angle_offset is not None:
            # Check on units, offset must be in radians
            p_temp = config.angle_offset.toFullTuple(True)
            if p_temp[2] == "degrees" or p_temp[2] == "degree":
                deg_to_rad = math.pi / 180.0
                p_off_rads = p_temp[0] * deg_to_rad
                p_off_err2_rads = p_temp[1] * deg_to_rad * deg_to_rad
            else:
                p_off_rads = p_temp[0]
                p_off_err2_rads = p_temp[1]

            p_offset = (p_off_rads, p_off_err2_rads)

            d_som2.attr_list["angle_offset"] = config.angle_offset
        else:
            p_offset = None

        if tim is not None:
            tim.getTime(False)

        d_som3 = common_lib.tof_to_scalar_Q(d_som2, units="microsecond", angle_offset=p_offset, lojac=False)

        del d_som2

        if tim is not None:
            tim.getTime(msg="After converting wavelength to scalar Q ")

        if config.dump_rq:
            d_som3_1 = dr_lib.data_filter(d_som3, clean_axis=True)
            hlr_utils.write_file(
                config.output,
                "text/Spec",
                d_som3_1,
                output_ext="rq",
                verbose=config.verbose,
                data_ext=config.ext_replacement,
                path_replacement=config.path_replacement,
                message="pixel R(Q) information",
            )
            del d_som3_1

        if not config.no_filter:
            if config.verbose:
                print "Filtering final data"

            if tim is not None:
                tim.getTime(False)

            d_som4 = dr_lib.data_filter(d_som3)

            if tim is not None:
                tim.getTime(msg="After filtering data")
        else:
            d_som4 = d_som3

        del d_som3
    else:
        d_som4 = d_som2

    # Step 10: Rebin all spectra to final Q axis
    if config.Q_bins is None:
        if config.scatt_angle is None:
            config.Q_bins = dr_lib.create_axis_from_data(d_som4)
            rebin_axis = config.Q_bins.toNessiList()
        else:
            # Get scattering angle and make Q conversion from TOF axis
            # Check on units, scattering angle must be in radians
            sa_temp = config.scatt_angle.toFullTuple(True)
            if sa_temp[2] == "degrees" or sa_temp[2] == "degree":
                deg_to_rad = math.pi / 180.0
                sa_rads = sa_temp[0] * deg_to_rad
                sa_err2_rads = sa_temp[1] * deg_to_rad * deg_to_rad
            else:
                sa_rads = sa_temp[0]
                sa_err2_rads = sa_temp[1]

            sa = (sa_rads, sa_err2_rads)

            pl = d_som4.attr_list.instrument.get_total_path(d_som4[0].id, det_secondary=True)

            import nessi_list

            tof_axis_err2 = nessi_list.NessiList(len(tof_axis))

            rebin_axis = axis_manip.tof_to_scalar_Q(tof_axis, tof_axis_err2, pl[0], pl[1], sa[0], sa[1])[0]

            axis_manip.reverse_array_nc(rebin_axis)
    else:
        rebin_axis = config.Q_bins.toNessiList()

    if config.inst == "REF_L":
        if config.verbose:
            print "Rebinning spectra"

        if tim is not None:
            tim.getTime(False)

        d_som5 = common_lib.rebin_axis_1D_linint(d_som4, rebin_axis)

        if tim is not None:
            tim.getTime(msg="After rebinning spectra")

        del d_som4

        if config.dump_rqr:
            hlr_utils.write_file(
                config.output,
                "text/Spec",
                d_som5,
                output_ext="rqr",
                verbose=config.verbose,
                data_ext=config.ext_replacement,
                path_replacement=config.path_replacement,
                message="pixel R(Q) (after rebinning) " + "information",
            )

        # Step 11: Sum all rebinned spectra
        if config.verbose:
            print "Summing spectra"

        if tim is not None:
            tim.getTime(False)

        d_som6 = dr_lib.sum_all_spectra(d_som5)

        if tim is not None:
            tim.getTime(msg="After summing spectra")

        del d_som5
    else:
        d_som5 = d_som4

    if config.inst == "REF_M":
        d_som5A = dr_lib.sum_all_spectra(d_som5)
        del d_som5
        d_som6 = dr_lib.data_filter(d_som5A)
        del d_som5A
        axis_manip.reverse_array_nc(d_som6[0].y)
        axis_manip.reverse_array_nc(d_som6[0].var_y)

        d_som6.setYLabel("Intensity")
        d_som6.setYUnits("Counts/A-1")
        d_som6.setAllAxisLabels(["scalar wavevector transfer"])
        d_som6.setAllAxisUnits(["1/Angstroms"])

        Q_bc = utils.calc_bin_centers(rebin_axis)
        d_som6[0].axis[0].val = Q_bc[0]
        d_som6.setDataSetType("density")

    hlr_utils.write_file(
        config.output,
        "text/Spec",
        d_som6,
        replace_ext=False,
        replace_path=False,
        verbose=config.verbose,
        message="combined Reflectivity information",
    )

    d_som6.attr_list["config"] = config

    hlr_utils.write_file(
        config.output,
        "text/rmd",
        d_som6,
        output_ext="rmd",
        verbose=config.verbose,
        data_ext=config.ext_replacement,
        path_replacement=config.path_replacement,
        message="metadata",
    )

    if tim is not None:
        tim.setOldTime(old_time)
        tim.getTime(msg="Total Running Time")
def tof_to_ref_scalar_Q(obj, **kwargs):
    """
    This function converts a primary axis of a C{SOM} or C{SO} from
    time-of-flight to reflectometer scalar Q. This means that a single angle
    and a single flightpath is used. The time-of-flight axis for a C{SOM} must
    be in units of I{microseconds}. The primary axis of a C{SO} is assumed to
    be in units of I{microseconds}. A C{tuple} of C{(time-of-flight,
    time-of-flight_err2)} (assumed to be in units of I{microseconds}) can be
    converted to C{(scalar_Q, scalar_Q_err2)}.

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

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

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

    @keyword configure: This is the object containing the driver configuration.
                        This will signal the function to write out the counts
                        and fractional area to files.
    @type configure: C{Configure}


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


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

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

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

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

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

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

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

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

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

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

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

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

    if beamdiv_corr:
        import dr_lib

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

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

        if beamdiv_corr:
            dangle = dr_lib.ref_beamdiv_correct(obj.attr_list, map_so.id,
                                                config.det_spat_res,
                                                config.center_pix)
            # We subtract due to the inversion of the z coordinates from the
            # mirror reflection of the beam at the sample.
            if dangle is not None:
                pangle = angle - (2.0 * dangle)
            else:
                pangle = angle
                skip_pixel = True
        else:
            pangle = angle

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

    result = hlr_utils.copy_som_attr(result, res_descr, obj, o_descr)
    if res_descr == "SOM":
        result = hlr_utils.force_units(result, "1/Angstroms", axis)
        result.setAxisLabel(axis, "scalar wavevector transfer")
        result.setYUnits("Counts/A-1")
        result.setYLabel("Intensity")
    else:
        pass

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return result