def process_reflp_data(datalist,
                       conf,
                       roi_file,
                       bkg_roi_file=None,
                       no_bkg=False,
                       **kwargs):
    """
    This function combines Steps 1 through 3 in section 2.4.6.1 of the data
    reduction process for Reduction from TOF to lambda_T as specified by
    the document at
    U{http://neutrons.ornl.gov/asg/projects/SCL/reqspec/DR_Lib_RS.doc}. The
    function takes a list of file names, a L{hlr_utils.Configure} object,
    region-of-interest (ROI) file for the normalization dataset, a background
    region-of-interest (ROI) file and an optional flag about background
    subtractionand processes the data accordingly.

    @param datalist: The filenames of the data to be processed
    @type datalist: C{list} of C{string}s

    @param conf: Object that contains the current setup of the driver
    @type conf: L{hlr_utils.Configure}

    @param roi_file: The file containing the list of pixel IDs for the region
                     of interest. This only applies to normalization data. 
    @type roi_file: C{string}

    @param bkg_roi_file: The file containing the list of pixel IDs for the
                         (possible) background region of interest.
    @type bkg_roi_file: C{string}    
    
    @param no_bkg: (OPTIONAL) Flag which determines if the background will be
                              calculated and subtracted.
    @type no_bkg: C{boolean}    

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

    @keyword inst_geom_dst: File object that contains instrument geometry
                            information.
    @type inst_geom_dst: C{DST.GeomDST}

    @keyword timer:  Timing object so the function can perform timing
                     estimates.
    @type timer: C{sns_timer.DiffTime}


    @return: Object that has undergone all requested processing steps
    @rtype: C{SOM.SOM}
    """
    import hlr_utils
    import common_lib
    import dr_lib

    # Check keywords
    try:
        i_geom_dst = kwargs["inst_geom_dst"]
    except KeyError:
        i_geom_dst = None

    try:
        t = kwargs["timer"]
    except KeyError:
        t = None

    if roi_file is not None:
        # Normalization
        dataset_type = "norm"
    else:
        # Sample data
        dataset_type = "data"

    so_axis = "time_of_flight"

    # Step 0: Open data files and select ROI (if necessary)
    if conf.verbose:
        print "Reading %s file" % dataset_type

    if len(conf.norm_data_paths) and dataset_type == "norm":
        data_path = conf.norm_data_paths.toPath()
    else:
        data_path = conf.data_paths.toPath()

    (d_som1, b_som1) = dr_lib.add_files_bg(datalist,
                                           Data_Paths=data_path,
                                           SO_Axis=so_axis,
                                           dataset_type=dataset_type,
                                           Signal_ROI=roi_file,
                                           Bkg_ROI=bkg_roi_file,
                                           Verbose=conf.verbose,
                                           Timer=t)

    if t is not None:
        t.getTime(msg="After reading %s " % dataset_type)

    # Override geometry if necessary
    if i_geom_dst is not None:
        i_geom_dst.setGeometry(conf.data_paths.toPath(), d_som1)

    if dataset_type == "data":
        # Get TOF bin width
        conf.delta_TOF = d_som1[0].axis[0].val[1] - d_som1[0].axis[0].val[0]

    if conf.mon_norm:
        if conf.verbose:
            print "Reading in monitor data from %s file" % dataset_type

        # The [0] is to get the data SOM and ignore the None background SOM
        dm_som1 = dr_lib.add_files(datalist,
                                   Data_Paths=conf.mon_path.toPath(),
                                   SO_Axis=so_axis,
                                   dataset_type=dataset_type,
                                   Verbose=conf.verbose,
                                   Timer=t)

        if t is not None:
            t.getTime(msg="After reading monitor data ")

    else:
        dm_som1 = None

    # Step 1: Sum all spectra along the low resolution direction
    # Set sorting for REF_L
    if conf.verbose:
        print "Summing over low resolution direction"

    # Set sorting
    (y_sort, cent_pixel) = hlr_utils.get_ref_integration_direction(
        conf.int_dir, conf.inst, d_som1.attr_list.instrument)

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

    d_som2 = dr_lib.sum_all_spectra(d_som1,
                                    y_sort=y_sort,
                                    stripe=True,
                                    pixel_fix=cent_pixel)

    if b_som1 is not None:
        b_som2 = dr_lib.sum_all_spectra(b_som1,
                                        y_sort=y_sort,
                                        stripe=True,
                                        pixel_fix=cent_pixel)
        del b_som1
    else:
        b_som2 = b_som1

    if t is not None:
        t.getTime(msg="After summing low resolution direction ")

    del d_som1

    # Determine background spectrum
    if conf.verbose and not no_bkg:
        print "Determining %s background" % dataset_type

    if b_som2 is not None:
        B = dr_lib.calculate_ref_background(b_som2,
                                            no_bkg,
                                            conf.inst,
                                            None,
                                            aobj=d_som2)
    if t is not None:
        t.getTime(msg="After background determination")

    # Subtract background spectrum from data spectra
    if not no_bkg:
        d_som3 = dr_lib.subtract_bkg_from_data(d_som2,
                                               B,
                                               verbose=conf.verbose,
                                               timer=t,
                                               dataset1="data",
                                               dataset2="background")
    else:
        d_som3 = d_som2

    del d_som2

    # Zero the spectra if necessary
    if roi_file is None and (conf.tof_cut_min is not None or \
                             conf.tof_cut_max is not None):
        import utils
        # Find the indicies for the non zero range
        if conf.tof_cut_min is None:
            conf.TOF_min = d_som3[0].axis[0].val[0]
            start_index = 0
        else:
            start_index = utils.bisect_helper(d_som3[0].axis[0].val,
                                              conf.tof_cut_min)

        if conf.tof_cut_max is None:
            conf.TOF_max = d_som3[0].axis[0].val[-1]
            end_index = len(d_som3[0].axis[0].val) - 1
        else:
            end_index = utils.bisect_helper(d_som3[0].axis[0].val,
                                            conf.tof_cut_max)

        nz_list = []
        for i in xrange(hlr_utils.get_length(d_som3)):
            nz_list.append((start_index, end_index))

        d_som4 = dr_lib.zero_spectra(d_som3, nz_list, use_bin_index=True)
    else:
        conf.TOF_min = d_som3[0].axis[0].val[0]
        conf.TOF_max = d_som3[0].axis[0].val[-1]
        d_som4 = d_som3

    del d_som3

    # Step N: Convert TOF to wavelength
    if conf.verbose:
        print "Converting TOF to wavelength"

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

    d_som5 = common_lib.tof_to_wavelength(d_som4,
                                          inst_param="total",
                                          units="microsecond")
    if dm_som1 is not None:
        dm_som2 = common_lib.tof_to_wavelength(dm_som1, units="microsecond")
    else:
        dm_som2 = None

    del dm_som1

    if t is not None:
        t.getTime(msg="After converting TOF to wavelength ")

    del d_som4

    if conf.mon_norm:
        dm_som3 = dr_lib.rebin_monitor(dm_som2, d_som5, rtype="frac")
    else:
        dm_som3 = None

    del dm_som2

    if not conf.mon_norm:
        # Step 2: Multiply the spectra by the proton charge
        if conf.verbose:
            print "Multiply spectra by proton charge"

        pc_tag = dataset_type + "-proton_charge"
        proton_charge = d_som5.attr_list[pc_tag]

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

        d_som6 = common_lib.div_ncerr(d_som5, (proton_charge.getValue(), 0.0))

        if t is not None:
            t.getTime(msg="After scaling by proton charge ")
    else:
        if conf.verbose:
            print "Normalize by monitor spectrum"

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

        d_som6 = common_lib.div_ncerr(d_som5, dm_som3)

        if t is not None:
            t.getTime(msg="After monitor normalization ")

    del d_som5, dm_som3

    if roi_file is None:
        return d_som6
    else:
        # Step 3: Make one spectrum for normalization dataset
        # Need to create a final rebinning axis
        pathlength = d_som6.attr_list.instrument.get_total_path(
            det_secondary=True)

        delta_lambda = common_lib.tof_to_wavelength((conf.delta_TOF, 0.0),
                                                    pathlength=pathlength)

        lambda_bins = dr_lib.create_axis_from_data(d_som6,
                                                   width=delta_lambda[0])

        return dr_lib.sum_by_rebin_frac(d_som6, lambda_bins.toNessiList())
Example #2
0
def run(config, tim=None):
    """
    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: (OPTIONAL) Object that will allow the method to perform
                           timing evaluations.
    @type tim: C{sns_time.DiffTime}
    """
    import common_lib
    import dr_lib
    import DST

    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 geometry if one is provided
    if config.inst_geom is not None:
        if config.verbose:
            print "Reading in instrument geometry file"
            
        inst_geom_dst = DST.getInstance("application/x-NxsGeom",
                                        config.inst_geom)
    else:
        inst_geom_dst = None

    # Perform early background subtraction if the hwfix flag is used
    if config.hwfix:
        if not config.mc:
            so_axis = "time_of_flight"
        else:
            so_axis = "Time_of_Flight"
        
        bkg_som0 = dr_lib.add_files(config.back,
                                    Data_Paths=config.data_paths.toPath(),
                                    SO_Axis=so_axis,
                                    Signal_ROI=config.roi_file,
                                    dataset_type="background",
                                    Verbose=config.verbose, Timer=tim)

        bkg_som = dr_lib.fix_bin_contents(bkg_som0)
        del bkg_som0
    else:
        bkg_som = None

    # Perform Steps 1-15 on sample data
    d_som1 = dr_lib.process_igs_data(config.data, config, timer=tim,
                                     inst_geom_dst=inst_geom_dst,
                                     tib_const=config.tib_data_const,
                                     bkg_som=bkg_som)

    # Perform Steps 1-15 on empty can data
    if config.ecan is not None:
        e_som1 = dr_lib.process_igs_data(config.ecan, config, timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="empty_can",
                                         tib_const=config.tib_ecan_const,
                                         bkg_som=bkg_som)
    else:
        e_som1 = None

    # Perform Steps 1-15 on normalization data            
    if config.norm is not None:
        n_som1 = dr_lib.process_igs_data(config.norm, config, timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="normalization",
                                         tib_const=config.tib_norm_const,
                                         bkg_som=bkg_som)
    else:
        n_som1 = None

    # Perform Steps 1-15 on background data
    if config.back is not None and not config.hwfix:
        b_som1 = dr_lib.process_igs_data(config.back, config, timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="background",
                                         tib_const=config.tib_back_const)
    else:
        b_som1 = None

    # Perform Step 1-15 on direct scattering background data
    if config.dsback is not None:
        ds_som1 = dr_lib.process_igs_data(config.dsback, config, timer=tim,
                                          inst_geom_dst=inst_geom_dst,
                                          tib_const=config.tib_dsback_const,
                                          dataset_type="dsbackground",
                                          bkg_som=bkg_som)

        # Note: time_zero_slope MUST be a tuple
        if config.time_zero_slope is not None:
            ds_som1.attr_list["Time_zero_slope"] = \
                                      config.time_zero_slope.toValErrTuple()

        # Note: time_zero_offset MUST be a tuple
        if config.time_zero_offset is not None:
            ds_som1.attr_list["Time_zero_offset"] = \
                                      config.time_zero_offset.toValErrTuple()
        
        # Step 16: Linearly interpolate TOF elastic range in direct scattering
        #          background data

        # First convert TOF elastic range to appropriate pixel initial
        # wavelengths
        if config.verbose:
            print "Determining initial wavelength range for elastic line"

        if tim is not None:
            tim.getTime(False)
        
        if config.tof_elastic is None:
            # Units are in microseconds
            tof_elastic_range = (140300, 141300)
        else:
            tof_elastic_range = config.tof_elastic
        
        ctof_elastic_low = dr_lib.convert_single_to_list(\
               "tof_to_initial_wavelength_igs_lin_time_zero",
               (tof_elastic_range[0], 0.0),
               ds_som1)
        
        ctof_elastic_high = dr_lib.convert_single_to_list(\
               "tof_to_initial_wavelength_igs_lin_time_zero",
               (tof_elastic_range[1], 0.0),
               ds_som1)
        
        ctof_elastic_range = [(ctof_elastic_low[i][0], ctof_elastic_high[i][0])
                              for i in xrange(len(ctof_elastic_low))]

        if tim is not None:
            tim.getTime(msg="After calculating initial wavelength range for "\
                        +"elastic line ")

        del ctof_elastic_low, ctof_elastic_high

        # Now interpolate spectra between TOF elastic range (converted to
        # initial wavelength)
        if config.verbose:
            print "Linearly interpolating direct scattering spectra"

        if tim is not None:
            tim.getTime(False)
            
        ds_som2 = dr_lib.lin_interpolate_spectra(ds_som1, ctof_elastic_range)

        if tim is not None:
            tim.getTime(msg="After linearly interpolating direct scattering "\
                        +"spectra ")

        if config.dump_dslin:
            ds_som2_1 = dr_lib.sum_all_spectra(ds_som2,\
                                  rebin_axis=config.lambda_bins.toNessiList())

            hlr_utils.write_file(config.output, "text/Spec", ds_som2_1,
                                 output_ext="lin",
                                 data_ext=config.ext_replacement,    
                                 path_replacement=config.path_replacement,
                                 verbose=config.verbose,
                                 message="dsbackground linear interpolation")
            del ds_som2_1
        
        del ds_som1
    else:
        ds_som2 = None

    if inst_geom_dst is not None:
        inst_geom_dst.release_resource()
        
    # Steps 17-18: Subtract background spectrum from sample spectrum
    if config.dsback is None:
        back_som = b_som1
        bkg_type = "background"
    else:
        back_som = ds_som2
        bkg_type = "dsbackground"
    d_som2 = dr_lib.subtract_bkg_from_data(d_som1, back_som,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="data",
                                           dataset2=bkg_type,
                                           scale=config.scale_bs)

    if config.dsback is not None:
        del ds_som2 

    # Step 19: Zero region outside TOF elastic for background for empty can
    if config.dsback is None:
        bcs_som = b_som1
        cs_som = e_som1
    else:
        if config.verbose and b_som1 is not None:
            print "Zeroing background spectra"

        if tim is not None and b_som1 is not None:
            tim.getTime(False)
            
        bcs_som = dr_lib.zero_spectra(b_som1, ctof_elastic_range)

        if tim is not None and b_som1 is not None:
            tim.getTime(msg="After zeroing background spectra")


        if config.verbose and e_som1 is not None:
            print "Zeroing empty can spectra"

        if tim is not None and e_som1 is not None:
            tim.getTime(False)
            
        cs_som = dr_lib.zero_spectra(e_som1, ctof_elastic_range)

        if tim is not None and e_som1 is not None:
            tim.getTime(msg="After zeroing empty can spectra")
            
        del ctof_elastic_range

    # Steps 20-21: Subtract background spectrum from empty can spectrum    
    e_som2 = dr_lib.subtract_bkg_from_data(cs_som, bcs_som,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="empty_can",
                                           dataset2="background",
                                           scale=config.scale_bcs)

    # Steps 22-23: Subtract background spectrum from empty can spectrum for
    #              normalization
    e_som3 = dr_lib.subtract_bkg_from_data(e_som1, b_som1,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="empty_can",
                                           dataset2="background",
                                           scale=config.scale_bcn)

    # Steps 24-25: Subtract background spectrum from normalization spectrum
    n_som2 = dr_lib.subtract_bkg_from_data(n_som1, b_som1,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="normalization",
                                           dataset2="background",
                                           scale=config.scale_bn)

    del b_som1, e_som1, bcs_som, cs_som

    # Steps 26-27: Subtract empty can spectrum from sample spectrum    
    d_som3 = dr_lib.subtract_bkg_from_data(d_som2, e_som2,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="data",
                                           dataset2="empty_can",
                                           scale=config.scale_cs)

    del d_som2, e_som2
    
    # Steps 28-29: Subtract empty can spectrum from normalization spectrum
    n_som3 = dr_lib.subtract_bkg_from_data(n_som2, e_som3,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="normalization",
                                           dataset2="empty_can",
                                           scale=config.scale_cn)    

    del n_som2, e_som3

    # Step 30-32: Integrate normalization spectra
    if config.verbose and n_som3 is not None:
        print "Integrating normalization spectra"

    norm_int = dr_lib.integrate_spectra(n_som3, start=config.norm_start,
                                        end=config.norm_end, norm=True)

    del n_som3
        
    # Step 33: Normalize data by integrated values
    if config.verbose and norm_int is not None:
        print "Normalizing data by normalization data"

    if norm_int is not None:
        d_som4 = common_lib.div_ncerr(d_som3, norm_int)
    else:
        d_som4 = d_som3

    if norm_int is not None:
        if tim is not None:
            tim.getTime(msg="After normalizing data ")

    del d_som3, norm_int

    # Step 35: Convert initial wavelength to E_initial
    if config.verbose:
        print "Converting initial wavelength to E_initial"
        
    if tim is not None:
        tim.getTime(False)

    d_som6 = common_lib.wavelength_to_energy(d_som4)
        
    if tim is not None:
        tim.getTime(msg="After converting initial wavelength to E_initial ")

    if config.dump_initial_energy:
        hlr_utils.write_file(config.output, "text/Spec", d_som6,
                             output_ext="ixl",
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="pixel initial energy information")
            
    del d_som4

    # Steps 36-37: Calculate energy transfer
    if config.verbose:
        print "Calculating energy transfer"

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

    d_som7 = dr_lib.igs_energy_transfer(d_som6)

    if tim is not None:
        tim.getTime(msg="After calculating energy transfer ")
        
    if config.dump_energy:
        hlr_utils.write_file(config.output, "text/Spec", d_som7,
                             output_ext="exl",
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="pixel energy transfer information")

    # Write 3-column ASCII file for E_t
    d_som7_1 = dr_lib.sum_all_spectra(d_som7,
                                      rebin_axis=config.E_bins.toNessiList())
    hlr_utils.write_file(config.output, "text/Spec", d_som7_1,
                         output_ext="etr",
                         data_ext=config.ext_replacement,
                         path_replacement=config.path_replacement,
                         verbose=config.verbose,
                         message="combined energy transfer information") 
    
    del d_som7_1

    # Steps 34,36-37: Calculate scaled energy transfer
    if config.verbose:
        print "Calculating scaled energy transfer"
        
    d_som9 = dr_lib.igs_energy_transfer(d_som6, scale=True)
    
    if tim is not None:
        tim.getTime(msg="After calculating scaled energy transfer ")

    if config.dump_energy:
        hlr_utils.write_file(config.output, "text/Spec", d_som9,
                             output_ext="sexl",
                             data_ext=config.ext_replacement,    
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="pixel scaled energy transfer "\
                             +"information")

    # Write 3-column ASCII file for scaled E_t
    d_som9_1 = dr_lib.sum_all_spectra(d_som9,
                                      rebin_axis=config.E_bins.toNessiList())
    hlr_utils.write_file(config.output, "text/Spec", d_som9_1,
                         output_ext="setr",
                         data_ext=config.ext_replacement,            
                         path_replacement=config.path_replacement,
                         verbose=config.verbose,
                         message="combined scaled energy transfer "\
                         +"information") 
    
    del d_som9_1
    
    del d_som6, d_som7
        
    d_som9.attr_list["config"] = config
    
    hlr_utils.write_file(config.output, "text/rmd", d_som9,
                         output_ext="rmd",
                         data_ext=config.ext_replacement,         
                         path_replacement=config.path_replacement,
                         verbose=config.verbose,
                         message="metadata")
    
    if tim is not None:
        tim.setOldTime(old_time)
        tim.getTime(msg="Total Running Time")
def run(config, tim=None):
    """
    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: (OPTIONAL) Object that will allow the method to perform
                           timing evaluations.
    @type tim: C{sns_time.DiffTime}
    """
    import common_lib
    import dr_lib
    import DST

    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 geometry if one is provided
    if config.inst_geom is not None:
        if config.verbose:
            print "Reading in instrument geometry file"
            
        inst_geom_dst = DST.getInstance("application/x-NxsGeom",
                                        config.inst_geom)
    else:
        inst_geom_dst = None

    # Perform early background subtraction if the hwfix flag is used
    if config.hwfix:
        if not config.mc:
            so_axis = "time_of_flight"
        else:
            so_axis = "Time_of_Flight"
        
        bkg_som0 = dr_lib.add_files(config.back,
                                    Data_Paths=config.data_paths.toPath(),
                                    SO_Axis=so_axis,
                                    Signal_ROI=config.roi_file,
                                    dataset_type="background",
                                    Verbose=config.verbose, Timer=tim)

        bkg_som = dr_lib.fix_bin_contents(bkg_som0)
        del bkg_som0
    else:
        bkg_som = None

    # Perform Steps 1-15 on sample data
    d_som1 = dr_lib.process_igs_data(config.data, config, timer=tim,
                                     inst_geom_dst=inst_geom_dst,
                                     tib_const=config.tib_data_const,
                                     bkg_som=bkg_som)

    # Perform Steps 1-15 on empty can data
    if config.ecan is not None:
        e_som1 = dr_lib.process_igs_data(config.ecan, config, timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="empty_can",
                                         tib_const=config.tib_ecan_const,
                                         bkg_som=bkg_som)
    else:
        e_som1 = None

    # Perform Steps 1-15 on normalization data            
    if config.norm is not None:
        n_som1 = dr_lib.process_igs_data(config.norm, config, timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="normalization",
                                         tib_const=config.tib_norm_const,
                                         bkg_som=bkg_som)
    else:
        n_som1 = None

    # Perform Steps 1-15 on background data
    if config.back is not None:
        b_som1 = dr_lib.process_igs_data(config.back, config, timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="background",
                                         tib_const=config.tib_back_const,
                                         bkg_som=bkg_som)
    else:
        b_som1 = None

    # Perform Step 1-15 on direct scattering background data
    if config.dsback is not None:
        ds_som1 = dr_lib.process_igs_data(config.dsback, config, timer=tim,
                                          inst_geom_dst=inst_geom_dst,
                                          tib_const=config.tib_dsback_const,
                                          dataset_type="dsbackground",
                                          bkg_som=bkg_som)

        # Note: time_zero_slope MUST be a tuple
        if config.time_zero_slope is not None:
            ds_som1.attr_list["Time_zero_slope"] = \
                                      config.time_zero_slope.toValErrTuple()

        # Note: time_zero_offset MUST be a tuple
        if config.time_zero_offset is not None:
            ds_som1.attr_list["Time_zero_offset"] = \
                                      config.time_zero_offset.toValErrTuple()
        
        # Step 16: Linearly interpolate TOF elastic range in direct scattering
        #          background data

        # First convert TOF elastic range to appropriate pixel initial
        # wavelengths
        if config.verbose:
            print "Determining initial wavelength range for elastic line"

        if tim is not None:
            tim.getTime(False)
        
        if config.tof_elastic is None:
            # Units are in microseconds
            tof_elastic_range = (140300, 141300)
        else:
            tof_elastic_range = config.tof_elastic
        
        ctof_elastic_low = dr_lib.convert_single_to_list(\
               "tof_to_initial_wavelength_igs_lin_time_zero",
               (tof_elastic_range[0], 0.0),
               ds_som1)
        
        ctof_elastic_high = dr_lib.convert_single_to_list(\
               "tof_to_initial_wavelength_igs_lin_time_zero",
               (tof_elastic_range[1], 0.0),
               ds_som1)
        
        ctof_elastic_range = [(ctof_elastic_low[i][0], ctof_elastic_high[i][0])
                              for i in xrange(len(ctof_elastic_low))]

        if tim is not None:
            tim.getTime(msg="After calculating initial wavelength range for "\
                        +"elastic line ")

        del ctof_elastic_low, ctof_elastic_high

        if config.split:
            lambda_filter = [(d_som1[i].axis[0].val[0],
                              d_som1[i].axis[0].val[-1])
                             for i in xrange(len(d_som1))]
        else:
            lambda_filter = None

        # Now interpolate spectra between TOF elastic range (converted to
        # initial wavelength)
        if config.verbose:
            print "Linearly interpolating direct scattering spectra"

        if tim is not None:
            tim.getTime(False)
            
        ds_som2 = dr_lib.lin_interpolate_spectra(ds_som1, ctof_elastic_range,
                                                 filter_axis=lambda_filter)

        if tim is not None:
            tim.getTime(msg="After linearly interpolating direct scattering "\
                        +"spectra ")

        if config.dump_dslin:
            ds_som2_1 = dr_lib.sum_all_spectra(ds_som2,\
                                  rebin_axis=config.lambda_bins.toNessiList())

            hlr_utils.write_file(config.output, "text/Spec", ds_som2_1,
                                 output_ext="lin",
                                 data_ext=config.ext_replacement,    
                                 path_replacement=config.path_replacement,
                                 verbose=config.verbose,
                                 message="dsbackground linear interpolation")
            del ds_som2_1
        
        del ds_som1
    else:
        ds_som2 = None

    if inst_geom_dst is not None:
        inst_geom_dst.release_resource()

    # Steps 17-18: Subtract background spectrum from sample spectrum
    if config.dsback is None:
        back_som = b_som1
        bkg_type = "background"
    else:
        back_som = ds_som2
        bkg_type = "dsbackground"
    d_som2 = dr_lib.subtract_bkg_from_data(d_som1, back_som,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="data",
                                           dataset2=bkg_type,
                                           scale=config.scale_bs)

    if config.dsback is not None:
        del ds_som2 

    # Step 19: Zero region outside TOF elastic for background for empty can
    if config.dsback is None:
        bcs_som = b_som1
        cs_som = e_som1
    else:
        if config.verbose and b_som1 is not None:
            print "Zeroing background spectra"

        if tim is not None and b_som1 is not None:
            tim.getTime(False)
            
        bcs_som = dr_lib.zero_spectra(b_som1, ctof_elastic_range)

        if tim is not None and b_som1 is not None:
            tim.getTime(msg="After zeroing background spectra")


        if config.verbose and e_som1 is not None:
            print "Zeroing empty can spectra"

        if tim is not None and e_som1 is not None:
            tim.getTime(False)
            
        cs_som = dr_lib.zero_spectra(e_som1, ctof_elastic_range)

        if tim is not None and e_som1 is not None:
            tim.getTime(msg="After zeroing empty can spectra")
            
        del ctof_elastic_range

    # Steps 20-21: Subtract background spectrum from empty can spectrum    
    e_som2 = dr_lib.subtract_bkg_from_data(cs_som, bcs_som,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="data-empty_can",
                                           dataset2="background",
                                           scale=config.scale_bcs)

    # Steps 22-23: Subtract background spectrum from empty can spectrum for
    #              normalization

    try:
        config.pre_norm
    except AttributeError:
        config.pre_norm = False

    if not config.pre_norm:
        e_som3 = dr_lib.subtract_bkg_from_data(e_som1, b_som1,
                                               verbose=config.verbose,
                                               timer=tim,
                                               dataset1="norm-empty_can",
                                               dataset2="background",
                                               scale=config.scale_bcn)
    else:
        e_som3 = None

    # Steps 24-25: Subtract background spectrum from normalization spectrum
    if not config.pre_norm:
        n_som2 = dr_lib.subtract_bkg_from_data(n_som1, b_som1,
                                               verbose=config.verbose,
                                               timer=tim,
                                               dataset1="normalization",
                                               dataset2="background",
                                               scale=config.scale_bn)
    else:
        n_som2 = n_som1

    del b_som1, e_som1, bcs_som, cs_som

    # Steps 26-27: Subtract empty can spectrum from sample spectrum    
    d_som3 = dr_lib.subtract_bkg_from_data(d_som2, e_som2,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="data",
                                           dataset2="empty_can",
                                           scale=config.scale_cs)

    del d_som2, e_som2
    
    # Steps 28-29: Subtract empty can spectrum from normalization spectrum
    if not config.pre_norm:
        n_som3 = dr_lib.subtract_bkg_from_data(n_som2, e_som3,
                                               verbose=config.verbose,
                                               timer=tim,
                                               dataset1="normalization",
                                               dataset2="empty_can",
                                               scale=config.scale_cn)
    else:
        n_som3 = n_som2

    del n_som2, e_som3

    # Step 30-31: Integrate normalization spectra
    if config.verbose and n_som3 is not None and not config.pre_norm:
        print "Integrating normalization spectra"

    if not config.pre_norm:
        norm_int = dr_lib.integrate_spectra(n_som3, start=config.norm_start,
                                            end=config.norm_end, norm=True)
    else:
        norm_int = n_som3

    del n_som3
        
    # Step 32: Normalize data by integrated values
    if config.verbose and norm_int is not None:
        print "Normalizing data by normalization data"

    if norm_int is not None:
        d_som4 = common_lib.div_ncerr(d_som3, norm_int)
    else:
        d_som4 = d_som3

    if norm_int is not None:
        if tim is not None:
            tim.getTime(msg="After normalizing data ")

    del d_som3, norm_int

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

        hlr_utils.write_file(config.output, "text/Spec", d_som4,
                             output_ext="wvn",
                             data_ext=config.ext_replacement,    
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="wavelength (vanadium norm) information")

        if tim is not None:
            tim.getTime(msg="After writing wavelength (vanadium norm) info ")

    # Steps 33 to end: Creating S(Q,E)
    if config.Q_bins is not None:
        if config.verbose:
            print "Creating 2D spectrum"

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

        d_som5 = dr_lib.create_E_vs_Q_igs(d_som4,
                                          config.E_bins.toNessiList(),
                                          config.Q_bins.toNessiList(),
                                          so_id="Full Detector",
                                          y_label="counts",
                                          y_units="counts / (ueV * A^-1)",
                                          x_labels=["Q transfer",
                                                    "energy transfer"],
                                          x_units=["1/Angstroms","ueV"],
                                          split=config.split,
                                          Q_filter=False,
                                          configure=config)
        if tim is not None:
            tim.getTime(msg="After creation of final spectrum ")

        del d_som4
        
    # Steps 33 to 36: Create S(-cos(polar), E)
    elif config.ncospol_bins is not None:
        if config.verbose:
            print "Convert wavelength to energy transfer"

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

        d_som4a = dr_lib.energy_transfer(d_som4, "IGS", "Wavelength_final",
                                         sa_norm=True, scale=True,
                                         change_units=True)

        if tim is not None:
            tim.getTime(msg="After wavelength to energy transfer conversion ")

        del d_som4

        if config.verbose:
            print "Creating 2D spectrum"

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

        d_som5 = dr_lib.create_param_vs_Y(d_som4a, "polar",
                                        "negcos_param_array",
                                        config.ncospol_bins.toNessiList(),
                                        rebin_axis=config.E_bins.toNessiList(),
                                        y_label="counts",
                                        y_units="counts / ueV",
                                        x_labels=["-cos(polar)",
                                                  "Energy Transfer"], 
                                        x_units=["", "ueV"])

        if tim is not None:
            tim.getTime(msg="After creation of final spectrum ")        
    
    # If rescaling factor present, rescale the data
    if config.rescale_final is not None and not config.split:
        d_som6 = common_lib.mult_ncerr(d_som5, (config.rescale_final, 0.0))
    else:
        d_som6 = d_som5

    if tim is None:
        old_time = None

    if not __name__ == "amorphous_reduction_sqe":
        del d_som5
        __write_output(d_som6, config, tim, old_time)
    else:
        if config.create_output:
            del d_som5
            __write_output(d_som6, config, tim, old_time)
        else:
            return d_som6
Example #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 array_manip
    import common_lib
    import dr_lib
    import DST
    import SOM

    import math

    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-2 on sample data
    d_som1 = dr_lib.process_reflp_data(config.data,
                                       config,
                                       None,
                                       config.dbkg_roi_file,
                                       config.no_bkg,
                                       inst_geom_dst=data_inst_geom_dst,
                                       timer=tim)

    # Get the detector angle
    if config.omega is None:
        # Make a fake SO
        so = SOM.SO()
        try:
            theta = hlr_utils.get_special(d_som1.attr_list["Theta"], so)
        except KeyError:
            theta = (float('nan'), float('nan'))
    else:
        theta = config.omega.toFullTuple()

    if theta[0] is not None:
        if theta[2] == "degrees" or theta[2] == "degree":
            theta_rads = (theta[0] * (math.pi / 180.0), 0.0)
        else:
            theta_rads = (theta[0], 0.0)
    else:
        theta_rads = (float('nan'), float('nan'))

    d_som1.attr_list["data-theta"] = (theta_rads[0], theta_rads[1], "radians")

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

    # 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 4: Divide data by normalization
    if config.verbose and config.norm is not None:
        print "Scale data by normalization"

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

    if config.norm is not None:
        # Need to rebin the normalization spectra to the data pixel spectra
        n_som2 = dr_lib.rebin_monitor(n_som1, d_som1, rtype="frac")
        # Now divide the spectra
        d_som2 = common_lib.div_ncerr(d_som1, n_som2)
        del n_som2
    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_som1

    sin_theta_rads = (math.sin(theta_rads[0]), math.sin(theta_rads[1]))
    if sin_theta_rads[0] < 0.0:
        sin_theta_rads = (math.fabs(sin_theta_rads[0]),
                          math.fabs(sin_theta_rads[1]))

    # Step 6: Scale wavelength axis by sin(theta) to make lambda_T
    if config.verbose:
        print "Scaling wavelength axis by sin(theta)"

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

    d_som3 = common_lib.div_ncerr(d_som2, sin_theta_rads, axis="x")

    if tim is not None:
        tim.getTime(msg="After scaling wavelength axis ")

    del d_som2

    d_som3.setAxisLabel(0, "lambda_T")

    # Step 7: Rebin to lambda_T axis
    if config.verbose:
        print "Rebinning spectra"

    if config.lambdap_bins is None:
        # Create a binning scheme
        pathlength = d_som3.attr_list.instrument.get_total_path(
            det_secondary=True)

        delta_lambda = common_lib.tof_to_wavelength((config.delta_TOF, 0.0),
                                                    pathlength=pathlength)

        delta_lambdap = array_manip.div_ncerr(delta_lambda[0], delta_lambda[1],
                                              sin_theta_rads[0], 0.0)

        config.lambdap_bins = dr_lib.create_axis_from_data(
            d_som3, width=delta_lambdap[0])
    else:
        # Do nothing, got the binning scheme
        pass

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

    d_som4 = common_lib.rebin_axis_1D_frac(d_som3,
                                           config.lambdap_bins.toNessiList())

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

    del d_som3

    if config.inst == "REF_M":
        # Clean up spectrum
        if config.tof_cut_min is not None:
            tof_cut_min = float(config.tof_cut_min)
        else:
            tof_cut_min = config.TOF_min

        if config.tof_cut_max is not None:
            tof_cut_max = float(config.tof_cut_max)
        else:
            tof_cut_max = config.TOF_max

        pathlength = d_som4.attr_list.instrument.get_total_path(
            det_secondary=True)

        lambda_min = common_lib.tof_to_wavelength((tof_cut_min, 0.0),
                                                  pathlength=pathlength)

        lambda_T_min = common_lib.div_ncerr(lambda_min, sin_theta_rads)

        lambda_max = common_lib.tof_to_wavelength((tof_cut_max, 0.0),
                                                  pathlength=pathlength)

        lambda_T_max = common_lib.div_ncerr(lambda_max, sin_theta_rads)

        nz_list = []
        for i in xrange(hlr_utils.get_length(d_som4)):
            nz_list.append((lambda_T_min[0], lambda_T_max[0]))

        d_som4A = dr_lib.zero_spectra(d_som4, nz_list)
    else:
        d_som4A = d_som4

    del d_som4

    # Step 8: Write out all spectra to a file
    hlr_utils.write_file(config.output,
                         "text/Spec",
                         d_som4A,
                         replace_ext=False,
                         replace_path=False,
                         verbose=config.verbose,
                         message="Reflectivity information")

    if config.dump_twod:
        d_som5 = dr_lib.create_X_vs_pixpos(d_som4A,
                                           config.lambdap_bins.toNessiList(),
                                           rebin=False,
                                           y_label="R",
                                           y_units="",
                                           x_label="$\lambda_T$",
                                           x_units="$\AA$")

        hlr_utils.write_file(config.output,
                             "text/Dave2d",
                             d_som5,
                             output_ext="plp",
                             verbose=config.verbose,
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             message="2D Reflectivity information")

    d_som4A.attr_list["config"] = config

    hlr_utils.write_file(config.output,
                         "text/rmd",
                         d_som4A,
                         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")
Example #5
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 array_manip
    import common_lib
    import dr_lib
    import DST
    import SOM

    import math

    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-2 on sample data
    d_som1 = dr_lib.process_reflp_data(config.data, config, None,
                                       config.dbkg_roi_file,
                                       config.no_bkg,
                                       inst_geom_dst=data_inst_geom_dst,
                                       timer=tim)

    # Get the detector angle
    if config.omega is None:
        # Make a fake SO
        so = SOM.SO()
        try: 
            theta = hlr_utils.get_special(d_som1.attr_list["Theta"], so)
        except KeyError: 
            theta = (float('nan'), float('nan'))
    else:
        theta = config.omega.toFullTuple()
        
    if theta[0] is not None: 
        if theta[2] == "degrees" or theta[2] == "degree": 
            theta_rads = (theta[0] * (math.pi / 180.0), 0.0)
        else: 
            theta_rads = (theta[0], 0.0)
    else: 
        theta_rads = (float('nan'), float('nan'))

    d_som1.attr_list["data-theta"] = (theta_rads[0], theta_rads[1], "radians")

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

    # 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 4: Divide data by normalization
    if config.verbose and config.norm is not None:
        print "Scale data by normalization"

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

    if config.norm is not None:
        # Need to rebin the normalization spectra to the data pixel spectra
        n_som2 = dr_lib.rebin_monitor(n_som1, d_som1, rtype="frac")
        # Now divide the spectra
        d_som2 = common_lib.div_ncerr(d_som1, n_som2)
        del n_som2
    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_som1

    sin_theta_rads = (math.sin(theta_rads[0]), math.sin(theta_rads[1]))
    if sin_theta_rads[0] < 0.0:
        sin_theta_rads = (math.fabs(sin_theta_rads[0]),
                          math.fabs(sin_theta_rads[1]))

    # Step 6: Scale wavelength axis by sin(theta) to make lambda_T
    if config.verbose:
        print "Scaling wavelength axis by sin(theta)"
    
    if tim is not None:
        tim.getTime(False)
        
    d_som3 = common_lib.div_ncerr(d_som2, sin_theta_rads, axis="x")

    if tim is not None:
        tim.getTime(msg="After scaling wavelength axis ")

    del d_som2

    d_som3.setAxisLabel(0, "lambda_T")

    # Step 7: Rebin to lambda_T axis
    if config.verbose:
        print "Rebinning spectra"

    if config.lambdap_bins is None:
        # Create a binning scheme
        pathlength = d_som3.attr_list.instrument.get_total_path(
            det_secondary=True)

        delta_lambda = common_lib.tof_to_wavelength((config.delta_TOF, 0.0),
                                                    pathlength=pathlength)
 
        delta_lambdap = array_manip.div_ncerr(delta_lambda[0], delta_lambda[1],
                                              sin_theta_rads[0], 0.0)

        config.lambdap_bins = dr_lib.create_axis_from_data(d_som3,
                                                       width=delta_lambdap[0])
    else:
        # Do nothing, got the binning scheme
        pass

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

    d_som4 = common_lib.rebin_axis_1D_frac(d_som3,
                                           config.lambdap_bins.toNessiList())

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

    del d_som3

    if config.inst == "REF_M":
        # Clean up spectrum
        if config.tof_cut_min is not None:
            tof_cut_min = float(config.tof_cut_min)
        else:
            tof_cut_min = config.TOF_min

        if config.tof_cut_max is not None:
            tof_cut_max = float(config.tof_cut_max)
        else:
            tof_cut_max = config.TOF_max

        pathlength = d_som4.attr_list.instrument.get_total_path(
            det_secondary=True)

        lambda_min = common_lib.tof_to_wavelength((tof_cut_min, 0.0),
                                                  pathlength=pathlength)

        lambda_T_min = common_lib.div_ncerr(lambda_min, sin_theta_rads)
        
        lambda_max = common_lib.tof_to_wavelength((tof_cut_max, 0.0),
                                                  pathlength=pathlength)

        lambda_T_max = common_lib.div_ncerr(lambda_max, sin_theta_rads)

        nz_list = []
        for i in xrange(hlr_utils.get_length(d_som4)):
            nz_list.append((lambda_T_min[0], lambda_T_max[0]))
        
        d_som4A = dr_lib.zero_spectra(d_som4, nz_list)
    else:
        d_som4A = d_som4

    del d_som4

    # Step 8: Write out all spectra to a file
    hlr_utils.write_file(config.output, "text/Spec", d_som4A,
                         replace_ext=False,
                         replace_path=False,
                         verbose=config.verbose,
                         message="Reflectivity information")

    if config.dump_twod:
        d_som5 = dr_lib.create_X_vs_pixpos(d_som4A,
                                           config.lambdap_bins.toNessiList(),
                                           rebin=False,
                                           y_label="R",
                                           y_units="",
                                           x_label="$\lambda_T$",
                                           x_units="$\AA$")

        hlr_utils.write_file(config.output, "text/Dave2d", d_som5,
                             output_ext="plp", verbose=config.verbose,
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             message="2D Reflectivity information")

    d_som4A.attr_list["config"] = config

    hlr_utils.write_file(config.output, "text/rmd", d_som4A,
                         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 process_reflp_data(datalist, conf, roi_file, bkg_roi_file=None,
                     no_bkg=False, **kwargs):
    """
    This function combines Steps 1 through 3 in section 2.4.6.1 of the data
    reduction process for Reduction from TOF to lambda_T as specified by
    the document at
    U{http://neutrons.ornl.gov/asg/projects/SCL/reqspec/DR_Lib_RS.doc}. The
    function takes a list of file names, a L{hlr_utils.Configure} object,
    region-of-interest (ROI) file for the normalization dataset, a background
    region-of-interest (ROI) file and an optional flag about background
    subtractionand processes the data accordingly.

    @param datalist: The filenames of the data to be processed
    @type datalist: C{list} of C{string}s

    @param conf: Object that contains the current setup of the driver
    @type conf: L{hlr_utils.Configure}

    @param roi_file: The file containing the list of pixel IDs for the region
                     of interest. This only applies to normalization data. 
    @type roi_file: C{string}

    @param bkg_roi_file: The file containing the list of pixel IDs for the
                         (possible) background region of interest.
    @type bkg_roi_file: C{string}    
    
    @param no_bkg: (OPTIONAL) Flag which determines if the background will be
                              calculated and subtracted.
    @type no_bkg: C{boolean}    

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

    @keyword inst_geom_dst: File object that contains instrument geometry
                            information.
    @type inst_geom_dst: C{DST.GeomDST}

    @keyword timer:  Timing object so the function can perform timing
                     estimates.
    @type timer: C{sns_timer.DiffTime}


    @return: Object that has undergone all requested processing steps
    @rtype: C{SOM.SOM}
    """
    import hlr_utils
    import common_lib
    import dr_lib

    # Check keywords
    try:
        i_geom_dst = kwargs["inst_geom_dst"]
    except KeyError:
        i_geom_dst = None
    
    try:
        t = kwargs["timer"]
    except KeyError:
        t = None

    if roi_file is not None:
        # Normalization
        dataset_type = "norm"
    else:
        # Sample data
        dataset_type = "data"

    so_axis = "time_of_flight"

    # Step 0: Open data files and select ROI (if necessary)
    if conf.verbose:
        print "Reading %s file" % dataset_type

    if len(conf.norm_data_paths) and dataset_type == "norm":
        data_path = conf.norm_data_paths.toPath()
    else:
        data_path = conf.data_paths.toPath()

    (d_som1, b_som1) = dr_lib.add_files_bg(datalist,
                                           Data_Paths=data_path,
                                           SO_Axis=so_axis,
                                           dataset_type=dataset_type,
                                           Signal_ROI=roi_file,
                                           Bkg_ROI=bkg_roi_file,
                                           Verbose=conf.verbose,
                                           Timer=t)

    if t is not None:
        t.getTime(msg="After reading %s " % dataset_type)

    # Override geometry if necessary
    if i_geom_dst is not None:
        i_geom_dst.setGeometry(conf.data_paths.toPath(), d_som1)

    if dataset_type == "data":
        # Get TOF bin width
        conf.delta_TOF = d_som1[0].axis[0].val[1] - d_som1[0].axis[0].val[0]

    if conf.mon_norm:
        if conf.verbose:
            print "Reading in monitor data from %s file" % dataset_type

        # The [0] is to get the data SOM and ignore the None background SOM
        dm_som1 = dr_lib.add_files(datalist, Data_Paths=conf.mon_path.toPath(),
                                   SO_Axis=so_axis,
                                   dataset_type=dataset_type,
                                   Verbose=conf.verbose,
                                   Timer=t)
        
        if t is not None:
            t.getTime(msg="After reading monitor data ")
            
    else:
        dm_som1 = None

    # Step 1: Sum all spectra along the low resolution direction
    # Set sorting for REF_L
    if conf.verbose:
        print "Summing over low resolution direction"

    # Set sorting
    (y_sort,
     cent_pixel) = hlr_utils.get_ref_integration_direction(conf.int_dir,
                                                           conf.inst,
                                                  d_som1.attr_list.instrument)
    
    if t is not None:
        t.getTime(False)

    d_som2 = dr_lib.sum_all_spectra(d_som1, y_sort=y_sort, stripe=True,
                                    pixel_fix=cent_pixel)

    if b_som1 is not None:
        b_som2 = dr_lib.sum_all_spectra(b_som1, y_sort=y_sort, stripe=True,
                                        pixel_fix=cent_pixel)
        del b_som1
    else:
        b_som2 = b_som1

    if t is not None:
        t.getTime(msg="After summing low resolution direction ")
        
    del d_som1

    # Determine background spectrum
    if conf.verbose and not no_bkg:
        print "Determining %s background" % dataset_type

    if b_som2 is not None:
        B = dr_lib.calculate_ref_background(b_som2, no_bkg, conf.inst, None,
                                            aobj=d_som2)
    if t is not None:
        t.getTime(msg="After background determination")

    # Subtract background spectrum from data spectra
    if not no_bkg:
        d_som3 = dr_lib.subtract_bkg_from_data(d_som2, B,
                                               verbose=conf.verbose,
                                               timer=t,
                                               dataset1="data",
                                               dataset2="background")
    else:
        d_som3 = d_som2

    del d_som2

    # Zero the spectra if necessary
    if roi_file is None and (conf.tof_cut_min is not None or \
                             conf.tof_cut_max is not None):
        import utils
        # Find the indicies for the non zero range
        if conf.tof_cut_min is None:
            conf.TOF_min = d_som3[0].axis[0].val[0]
            start_index = 0
        else:
            start_index = utils.bisect_helper(d_som3[0].axis[0].val,
                                              conf.tof_cut_min)

        if conf.tof_cut_max is None:
            conf.TOF_max = d_som3[0].axis[0].val[-1]
            end_index = len(d_som3[0].axis[0].val) - 1
        else:
            end_index = utils.bisect_helper(d_som3[0].axis[0].val,
                                            conf.tof_cut_max)

        nz_list = []
        for i in xrange(hlr_utils.get_length(d_som3)):
            nz_list.append((start_index, end_index))
        
        d_som4 = dr_lib.zero_spectra(d_som3, nz_list, use_bin_index=True)
    else:
        conf.TOF_min = d_som3[0].axis[0].val[0]
        conf.TOF_max = d_som3[0].axis[0].val[-1]
        d_som4 = d_som3

    del d_som3

    # Step N: Convert TOF to wavelength
    if conf.verbose:
        print "Converting TOF to wavelength"

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

    d_som5 = common_lib.tof_to_wavelength(d_som4, inst_param="total",
                                          units="microsecond")
    if dm_som1 is not None:
        dm_som2 = common_lib.tof_to_wavelength(dm_som1, units="microsecond")
    else:
        dm_som2 = None

    del dm_som1

    if t is not None:
        t.getTime(msg="After converting TOF to wavelength ")

    del d_som4

    if conf.mon_norm:
        dm_som3 = dr_lib.rebin_monitor(dm_som2, d_som5, rtype="frac")
    else:
        dm_som3 = None

    del dm_som2

    if not conf.mon_norm:
        # Step 2: Multiply the spectra by the proton charge
        if conf.verbose:
            print "Multiply spectra by proton charge"

        pc_tag = dataset_type + "-proton_charge"
        proton_charge = d_som5.attr_list[pc_tag]

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

        d_som6 = common_lib.div_ncerr(d_som5, (proton_charge.getValue(), 0.0))

        if t is not None:
            t.getTime(msg="After scaling by proton charge ")
    else:
        if conf.verbose:
            print "Normalize by monitor spectrum"

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

        d_som6 = common_lib.div_ncerr(d_som5, dm_som3)

        if t is not None:
            t.getTime(msg="After monitor normalization ")

    del d_som5, dm_som3

    if roi_file is None:
        return d_som6
    else:
        # Step 3: Make one spectrum for normalization dataset
        # Need to create a final rebinning axis
        pathlength = d_som6.attr_list.instrument.get_total_path(
            det_secondary=True)
        
        delta_lambda = common_lib.tof_to_wavelength((conf.delta_TOF, 0.0),
                                                    pathlength=pathlength)

        lambda_bins = dr_lib.create_axis_from_data(d_som6,
                                                   width=delta_lambda[0])

        return dr_lib.sum_by_rebin_frac(d_som6, lambda_bins.toNessiList())
def run(config, tim=None):
    """
    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: (OPTIONAL) Object that will allow the method to perform
                           timing evaluations.
    @type tim: C{sns_time.DiffTime}
    """
    import common_lib
    import dr_lib
    import DST

    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 geometry if one is provided
    if config.inst_geom is not None:
        if config.verbose:
            print "Reading in instrument geometry file"

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

    # Perform early background subtraction if the hwfix flag is used
    if config.hwfix:
        if not config.mc:
            so_axis = "time_of_flight"
        else:
            so_axis = "Time_of_Flight"

        bkg_som0 = dr_lib.add_files(config.back,
                                    Data_Paths=config.data_paths.toPath(),
                                    SO_Axis=so_axis,
                                    Signal_ROI=config.roi_file,
                                    dataset_type="background",
                                    Verbose=config.verbose,
                                    Timer=tim)

        bkg_som = dr_lib.fix_bin_contents(bkg_som0)
        del bkg_som0
    else:
        bkg_som = None

    # Perform Steps 1-15 on sample data
    d_som1 = dr_lib.process_igs_data(config.data,
                                     config,
                                     timer=tim,
                                     inst_geom_dst=inst_geom_dst,
                                     tib_const=config.tib_data_const,
                                     bkg_som=bkg_som)

    # Perform Steps 1-15 on empty can data
    if config.ecan is not None:
        e_som1 = dr_lib.process_igs_data(config.ecan,
                                         config,
                                         timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="empty_can",
                                         tib_const=config.tib_ecan_const,
                                         bkg_som=bkg_som)
    else:
        e_som1 = None

    # Perform Steps 1-15 on normalization data
    if config.norm is not None:
        n_som1 = dr_lib.process_igs_data(config.norm,
                                         config,
                                         timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="normalization",
                                         tib_const=config.tib_norm_const,
                                         bkg_som=bkg_som)
    else:
        n_som1 = None

    # Perform Steps 1-15 on background data
    if config.back is not None:
        b_som1 = dr_lib.process_igs_data(config.back,
                                         config,
                                         timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="background",
                                         tib_const=config.tib_back_const,
                                         bkg_som=bkg_som)
    else:
        b_som1 = None

    # Perform Step 1-15 on direct scattering background data
    if config.dsback is not None:
        ds_som1 = dr_lib.process_igs_data(config.dsback,
                                          config,
                                          timer=tim,
                                          inst_geom_dst=inst_geom_dst,
                                          tib_const=config.tib_dsback_const,
                                          dataset_type="dsbackground",
                                          bkg_som=bkg_som)

        # Note: time_zero_slope MUST be a tuple
        if config.time_zero_slope is not None:
            ds_som1.attr_list["Time_zero_slope"] = \
                                      config.time_zero_slope.toValErrTuple()

        # Note: time_zero_offset MUST be a tuple
        if config.time_zero_offset is not None:
            ds_som1.attr_list["Time_zero_offset"] = \
                                      config.time_zero_offset.toValErrTuple()

        # Step 16: Linearly interpolate TOF elastic range in direct scattering
        #          background data

        # First convert TOF elastic range to appropriate pixel initial
        # wavelengths
        if config.verbose:
            print "Determining initial wavelength range for elastic line"

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

        if config.tof_elastic is None:
            # Units are in microseconds
            tof_elastic_range = (140300, 141300)
        else:
            tof_elastic_range = config.tof_elastic

        ctof_elastic_low = dr_lib.convert_single_to_list(\
               "tof_to_initial_wavelength_igs_lin_time_zero",
               (tof_elastic_range[0], 0.0),
               ds_som1)

        ctof_elastic_high = dr_lib.convert_single_to_list(\
               "tof_to_initial_wavelength_igs_lin_time_zero",
               (tof_elastic_range[1], 0.0),
               ds_som1)

        ctof_elastic_range = [(ctof_elastic_low[i][0], ctof_elastic_high[i][0])
                              for i in xrange(len(ctof_elastic_low))]

        if tim is not None:
            tim.getTime(msg="After calculating initial wavelength range for "\
                        +"elastic line ")

        del ctof_elastic_low, ctof_elastic_high

        if config.split:
            lambda_filter = [(d_som1[i].axis[0].val[0],
                              d_som1[i].axis[0].val[-1])
                             for i in xrange(len(d_som1))]
        else:
            lambda_filter = None

        # Now interpolate spectra between TOF elastic range (converted to
        # initial wavelength)
        if config.verbose:
            print "Linearly interpolating direct scattering spectra"

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

        ds_som2 = dr_lib.lin_interpolate_spectra(ds_som1,
                                                 ctof_elastic_range,
                                                 filter_axis=lambda_filter)

        if tim is not None:
            tim.getTime(msg="After linearly interpolating direct scattering "\
                        +"spectra ")

        if config.dump_dslin:
            ds_som2_1 = dr_lib.sum_all_spectra(ds_som2,\
                                  rebin_axis=config.lambda_bins.toNessiList())

            hlr_utils.write_file(config.output,
                                 "text/Spec",
                                 ds_som2_1,
                                 output_ext="lin",
                                 data_ext=config.ext_replacement,
                                 path_replacement=config.path_replacement,
                                 verbose=config.verbose,
                                 message="dsbackground linear interpolation")
            del ds_som2_1

        del ds_som1
    else:
        ds_som2 = None

    if inst_geom_dst is not None:
        inst_geom_dst.release_resource()

    # Steps 17-18: Subtract background spectrum from sample spectrum
    if config.dsback is None:
        back_som = b_som1
        bkg_type = "background"
    else:
        back_som = ds_som2
        bkg_type = "dsbackground"
    d_som2 = dr_lib.subtract_bkg_from_data(d_som1,
                                           back_som,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="data",
                                           dataset2=bkg_type,
                                           scale=config.scale_bs)

    if config.dsback is not None:
        del ds_som2

    # Step 19: Zero region outside TOF elastic for background for empty can
    if config.dsback is None:
        bcs_som = b_som1
        cs_som = e_som1
    else:
        if config.verbose and b_som1 is not None:
            print "Zeroing background spectra"

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

        bcs_som = dr_lib.zero_spectra(b_som1, ctof_elastic_range)

        if tim is not None and b_som1 is not None:
            tim.getTime(msg="After zeroing background spectra")

        if config.verbose and e_som1 is not None:
            print "Zeroing empty can spectra"

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

        cs_som = dr_lib.zero_spectra(e_som1, ctof_elastic_range)

        if tim is not None and e_som1 is not None:
            tim.getTime(msg="After zeroing empty can spectra")

        del ctof_elastic_range

    # Steps 20-21: Subtract background spectrum from empty can spectrum
    e_som2 = dr_lib.subtract_bkg_from_data(cs_som,
                                           bcs_som,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="data-empty_can",
                                           dataset2="background",
                                           scale=config.scale_bcs)

    # Steps 22-23: Subtract background spectrum from empty can spectrum for
    #              normalization

    try:
        config.pre_norm
    except AttributeError:
        config.pre_norm = False

    if not config.pre_norm:
        e_som3 = dr_lib.subtract_bkg_from_data(e_som1,
                                               b_som1,
                                               verbose=config.verbose,
                                               timer=tim,
                                               dataset1="norm-empty_can",
                                               dataset2="background",
                                               scale=config.scale_bcn)
    else:
        e_som3 = None

    # Steps 24-25: Subtract background spectrum from normalization spectrum
    if not config.pre_norm:
        n_som2 = dr_lib.subtract_bkg_from_data(n_som1,
                                               b_som1,
                                               verbose=config.verbose,
                                               timer=tim,
                                               dataset1="normalization",
                                               dataset2="background",
                                               scale=config.scale_bn)
    else:
        n_som2 = n_som1

    del b_som1, e_som1, bcs_som, cs_som

    # Steps 26-27: Subtract empty can spectrum from sample spectrum
    d_som3 = dr_lib.subtract_bkg_from_data(d_som2,
                                           e_som2,
                                           verbose=config.verbose,
                                           timer=tim,
                                           dataset1="data",
                                           dataset2="empty_can",
                                           scale=config.scale_cs)

    del d_som2, e_som2

    # Steps 28-29: Subtract empty can spectrum from normalization spectrum
    if not config.pre_norm:
        n_som3 = dr_lib.subtract_bkg_from_data(n_som2,
                                               e_som3,
                                               verbose=config.verbose,
                                               timer=tim,
                                               dataset1="normalization",
                                               dataset2="empty_can",
                                               scale=config.scale_cn)
    else:
        n_som3 = n_som2

    del n_som2, e_som3

    # Step 30-31: Integrate normalization spectra
    if config.verbose and n_som3 is not None and not config.pre_norm:
        print "Integrating normalization spectra"

    if not config.pre_norm:
        norm_int = dr_lib.integrate_spectra(n_som3,
                                            start=config.norm_start,
                                            end=config.norm_end,
                                            norm=True)
    else:
        norm_int = n_som3

    del n_som3

    # Step 32: Normalize data by integrated values
    if config.verbose and norm_int is not None:
        print "Normalizing data by normalization data"

    if norm_int is not None:
        d_som4 = common_lib.div_ncerr(d_som3, norm_int)
    else:
        d_som4 = d_som3

    if norm_int is not None:
        if tim is not None:
            tim.getTime(msg="After normalizing data ")

    del d_som3, norm_int

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

        hlr_utils.write_file(config.output,
                             "text/Spec",
                             d_som4,
                             output_ext="wvn",
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="wavelength (vanadium norm) information")

        if tim is not None:
            tim.getTime(msg="After writing wavelength (vanadium norm) info ")

    # Steps 33 to end: Creating S(Q,E)
    if config.Q_bins is not None:
        if config.verbose:
            print "Creating 2D spectrum"

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

        d_som5 = dr_lib.create_E_vs_Q_igs(
            d_som4,
            config.E_bins.toNessiList(),
            config.Q_bins.toNessiList(),
            so_id="Full Detector",
            y_label="counts",
            y_units="counts / (ueV * A^-1)",
            x_labels=["Q transfer", "energy transfer"],
            x_units=["1/Angstroms", "ueV"],
            split=config.split,
            Q_filter=False,
            configure=config)
        if tim is not None:
            tim.getTime(msg="After creation of final spectrum ")

        del d_som4

    # Steps 33 to 36: Create S(-cos(polar), E)
    elif config.ncospol_bins is not None:
        if config.verbose:
            print "Convert wavelength to energy transfer"

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

        d_som4a = dr_lib.energy_transfer(d_som4,
                                         "IGS",
                                         "Wavelength_final",
                                         sa_norm=True,
                                         scale=True,
                                         change_units=True)

        if tim is not None:
            tim.getTime(msg="After wavelength to energy transfer conversion ")

        del d_som4

        if config.verbose:
            print "Creating 2D spectrum"

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

        d_som5 = dr_lib.create_param_vs_Y(
            d_som4a,
            "polar",
            "negcos_param_array",
            config.ncospol_bins.toNessiList(),
            rebin_axis=config.E_bins.toNessiList(),
            y_label="counts",
            y_units="counts / ueV",
            x_labels=["-cos(polar)", "Energy Transfer"],
            x_units=["", "ueV"])

        if tim is not None:
            tim.getTime(msg="After creation of final spectrum ")

    # If rescaling factor present, rescale the data
    if config.rescale_final is not None and not config.split:
        d_som6 = common_lib.mult_ncerr(d_som5, (config.rescale_final, 0.0))
    else:
        d_som6 = d_som5

    if tim is None:
        old_time = None

    if not __name__ == "amorphous_reduction_sqe":
        del d_som5
        __write_output(d_som6, config, tim, old_time)
    else:
        if config.create_output:
            del d_som5
            __write_output(d_som6, config, tim, old_time)
        else:
            return d_som6