Example #1
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 #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

    only_background = False
    data_type = "transmission"

    # Perform Steps 1,6-7 or 1,3,5-7 on sample data
    d_som1 = dr_lib.process_sas_data(config.data,
                                     config,
                                     timer=tim,
                                     inst_geom_dst=inst_geom_dst,
                                     dataset_type=data_type,
                                     transmission=True,
                                     get_background=only_background)

    # Perform Steps 1,6-7 on background data
    if config.back is not None:
        b_som1 = dr_lib.process_sas_data(config.back,
                                         config,
                                         timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="trans_bkg",
                                         transmission=True)
    else:
        b_som1 = None

    # Put the datasets on the same axis
    d_som2 = dr_lib.sum_by_rebin_frac(d_som1, config.lambda_bins.toNessiList())
    del d_som1

    if b_som1 is not None:
        b_som2 = dr_lib.sum_by_rebin_frac(b_som1,
                                          config.lambda_bins.toNessiList())
    else:
        b_som2 = None

    del b_som1

    # Divide the data spectrum by the background spectrum
    if b_som2 is not None:
        d_som3 = common_lib.div_ncerr(d_som2, b_som2)
    else:
        d_som3 = d_som2

    del d_som2, b_som2

    # Reset y units to dimensionless for the tranmission due to ratio
    if config.back is not None:
        d_som3.setYLabel("Ratio")
        d_som3.setYUnits("")
        write_message = "transmission spectrum"
    else:
        write_message = "spectrum for background estimation"

    # Write out the transmission spectrum
    hlr_utils.write_file(config.output,
                         "text/Spec",
                         d_som3,
                         verbose=config.verbose,
                         replace_path=False,
                         replace_ext=False,
                         message=write_message)

    d_som3.attr_list["config"] = config

    hlr_utils.write_file(config.output,
                         "text/rmd",
                         d_som3,
                         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")
Example #3
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

    # Add so_axis to Configure object
    config.so_axis = "time_of_flight"

    dataset_type = "background"

    # Step 0: Open appropriate data files

    # Data
    if config.verbose:
        print "Reading %s file" % dataset_type

    # The [0] is to get the data SOM and ignore the None background SOM
    dp_som = dr_lib.add_files(
        config.data,
        Data_Paths=config.data_paths.toPath(),
        SO_Axis=config.so_axis,
        Signal_ROI=config.roi_file,
        dataset_type=dataset_type,
        Verbose=config.verbose,
        Timer=tim,
    )

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

    dp_som0 = dr_lib.fix_bin_contents(dp_som)

    del dp_som

    if inst_geom_dst is not None:
        inst_geom_dst.setGeometry(config.data_paths.toPath(), dp_som0)

    # Note: time_zero_offset_det MUST be a tuple
    if config.time_zero_offset_det is not None:
        dp_som0.attr_list["Time_zero_offset_det"] = config.time_zero_offset_det.toValErrTuple()

    # Step 2: Convert TOF to wavelength for data
    if config.verbose:
        print "Converting TOF to wavelength"

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

    # Convert detector pixels
    dp_som1 = common_lib.tof_to_wavelength_lin_time_zero(
        dp_som0, units="microsecond", time_zero_offset=config.time_zero_offset_det.toValErrTuple(), inst_param="total"
    )

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

    del dp_som0

    if config.verbose:
        print "Cutting spectra"

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

    dp_som2 = dr_lib.cut_spectra(dp_som1, config.lambda_low_cut, config.lambda_high_cut)

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

    del dp_som1

    rebin_axis = config.lambda_bins.toNessiList()

    # Put the data on the same axis
    if config.verbose:
        print "Rebinning data onto specified wavelength axis"

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

    dp_som3 = dr_lib.sum_by_rebin_frac(dp_som2, rebin_axis)

    if tim is not None:
        tim.getTime(msg="After rebinning data onto specified wavelength axis ")

    del dp_som2

    data_run_time = dp_som3.attr_list["background-duration"]

    # Calculate the accelerator on time
    if config.verbose:
        print "Calculating accelerator on time"

    acc_on_time = hlr_utils.DrParameter(data_run_time.getValue() - config.acc_down_time.getValue(), 0.0, "seconds")

    # Get the number of data bins
    num_wave_bins = len(rebin_axis) - 1

    # Calculate the scaled accelerator uptime
    if config.verbose:
        print "Calculating the scaled accelerator uptime"

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

    final_scale = acc_on_time.toValErrTuple()[0] / num_wave_bins

    if tim is not None:
        tim.getTime(msg="After calculating the scaled accelerator uptime ")

    # Create the final background spectrum
    if config.verbose:
        print "Creating the background spectrum"

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

    dp_som4 = common_lib.div_ncerr(dp_som3, (final_scale, 0))
    dp_som4.attr_list["%s-Scaling" % dataset_type] = final_scale

    if tim is not None:
        tim.getTime(msg="After creating background spectrum ")

    del dp_som3

    # Write out the background spectrum
    hlr_utils.write_file(
        config.output,
        "text/Spec",
        dp_som4,
        verbose=config.verbose,
        output_ext="bkg",
        data_ext=config.ext_replacement,
        replace_path=False,
        replace_ext=True,
        message="background spectrum",
    )

    dp_som4.attr_list["config"] = config

    hlr_utils.write_file(
        config.output,
        "text/rmd",
        dp_som4,
        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 calibrate_dgs_data(datalist, conf, dkcur, **kwargs):
    """
    This function combines Steps 3 through 6 in Section 2.1.1 of the data
    reduction process for Direct Geometry Spectrometers 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 and
    processes the data accordingly.
    
    @param datalist: A list containing 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 dkcur: The object containing the TOF dark current data.
    @type dkcur: C{SOM.SOM}
    
    @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 tib_const: A time-independent background constant to subtract
                        from every pixel.
    @type tib_const: L{hlr_utils.DrParameter}
    
    @keyword dataset_type: The practical name of the dataset being processed.
                           The default value is I{data}.
    @type dataset_type: C{string}

    @keyword cwp: A list of chopper phase corrections in units of microseconds.
    @type cwp: C{list} of C{float}s
    
    @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 common_lib
    import dr_lib
    import hlr_utils

    # Check keywords
    try:
        tib_const = kwargs["tib_const"]
    except KeyError:
        tib_const = None
    
    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"

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

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

    dataset_cwp = kwargs.get("cwp")

    # Open the appropriate datafiles
    if conf.verbose:
        print "Reading %s file" % dataset_type

    data_paths = conf.data_paths.toPath()
    if conf.no_mon_norm:
        mon_paths = None
    else:
        mon_paths = conf.usmon_path.toPath()

    # Check for mask file since normalization drive doesn't understand option
    try:
        mask_file = conf.mask_file
    except AttributeError:
        mask_file = None

    if t is not None:
        oldtime = t.getOldTime()

    (dp_som0, dm_som0) = dr_lib.add_files_dm(datalist, Data_Paths=data_paths,
                                             Mon_Paths=mon_paths,
                                             SO_Axis=conf.so_axis,
                                             Signal_ROI=conf.roi_file,
                                             Signal_MASK=mask_file,
                                             dataset_type=dataset_type,
                                             dataset_cwp=dataset_cwp,
                                             Verbose=conf.verbose, Timer=t)

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

    # Cut the spectra if necessary
    dp_somA = dr_lib.cut_spectra(dp_som0, conf.tof_cut_min, conf.tof_cut_max)

    del dp_som0

    dp_somB = dr_lib.fix_bin_contents(dp_somA)

    del dp_somA

    if dp_somB.attr_list.instrument.get_name() != "CNCS":

        if conf.verbose:
            print "Cutting spectrum at minimum TOF"
        
        if t is not None:
            t.getTime(False)

        # Calculate minimum TOF for physical neutrons
        if conf.initial_energy is not None:
            initial_wavelength = common_lib.energy_to_wavelength(\
            conf.initial_energy.toValErrTuple())
            initial_velocity = common_lib.wavelength_to_velocity(\
            initial_wavelength)
        else:
            # This should actually calculate it, but don't have a way right now
            pass

        if conf.time_zero_offset is not None:
            time_zero_offset = conf.time_zero_offset.toValErrTuple()
        else:
            # This should actually calculate it, but don't have a way right now
            time_zero_offset = (0.0, 0.0)

        ss_length = dp_somB.attr_list.instrument.get_primary()
        
        tof_min = (ss_length[0] / initial_velocity[0]) + time_zero_offset[0]

        # Cut all spectra a the minimum TOF
        dp_som1 = dr_lib.cut_spectra(dp_somB, tof_min, None)

        if t is not None:
            t.getTime(msg="After cutting spectrum at minimum TOF ")
    else:
        dp_som1 = dp_somB

    del dp_somB

    if dm_som0 is not None:
        dm_som1 = dr_lib.fix_bin_contents(dm_som0)
    else:
        dm_som1 = dm_som0

    del dm_som0    

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

    if conf.inst_geom is not None and dm_som1 is not None:
        i_geom_dst.setGeometry(mon_paths, dm_som1)
    
    # Step 3: Integrate the upstream monitor
    if dm_som1 is not None:
        if conf.verbose:
            print "Integrating upstream monitor spectrum"

        if t is not None:
            t.getTime(False)
        
        if conf.mon_int_range is None:
            start_val = float("inf")
            end_val = float("inf")
        else:
            start_val = conf.mon_int_range[0]
            end_val = conf.mon_int_range[1]
        
        dm_som2 = dr_lib.integrate_spectra(dm_som1, start=start_val,
                                           end=end_val,
                                           width=True)
        if t is not None:
            t.getTime(msg="After integrating upstream monitor spectrum ")
    else:
        dm_som2 = dm_som1

    del dm_som1

    tib_norm_const = None
    
    # Step 4: Divide data set by summed monitor spectrum
    if dm_som2 is not None:
        if conf.verbose:
            print "Normalizing %s by monitor sum" % dataset_type

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

        dp_som2 = common_lib.div_ncerr(dp_som1, dm_som2, length_one_som=True)

        tib_norm_const = dm_som2[0].y

        if t is not None:
            t.getTime(msg="After normalizing %s by monitor sum" % dataset_type)

    elif conf.pc_norm:
        if conf.verbose:
            print "Normalizing %s by proton charge" % dataset_type

        pc_tag = dataset_type+"-proton_charge"
        pc = dp_som1.attr_list[pc_tag]

        # Scale the proton charge and then set the scale PC back to attributes
        if conf.scale_pc is not None:
            if conf.verbose:
                print "Scaling %s proton charge" % dataset_type

            pc = hlr_utils.scale_proton_charge(pc, conf.scale_pc)
            dp_som1.attr_list[pc_tag] = pc

        tib_norm_const = pc.getValue()

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

        dp_som2 = common_lib.div_ncerr(dp_som1, (pc.getValue(), 0.0))

        if t is not None:
            t.getTime(msg="After normalizing %s by proton charge" \
                      % dataset_type)

    else:
        dp_som2 = dp_som1

    del dp_som1, dm_som2

    # Step 5: Scale dark current by data set measurement time
    if dkcur is not None:
        if conf.verbose:
            print "Scaling dark current by %s acquisition time" % dataset_type

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

        dstime_tag = dataset_type+"-duration"
        dstime = dp_som2.attr_list[dstime_tag]

        dkcur1 = common_lib.div_ncerr(dkcur, (dstime.getValue(), 0.0))

        if t is not None:
            t.getTime(msg="After scaling dark current by %s acquisition time" \
                      % dataset_type)        
    else:
        dkcur1 = dkcur

    del dkcur

    # Step 6: Subtract scaled dark current from data set
    if dkcur1 is not None:
        if conf.verbose:
            print "Subtracting %s by scaled dark current" % dataset_type

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

        dp_som3 = common_lib.sub_ncerr(dp_som2, dkcur1)

        if t is not None:
            t.getTime(msg="After subtracting %s by scaled dark current" \
                      % dataset_type)
    elif tib_const is not None and dkcur1 is None:
        if conf.verbose:
            print "Subtracting TIB constant from %s" % dataset_type

        # Normalize the TIB constant by dividing by the current normalization
        # the duration (if necessary) and the conversion from seconds to
        # microseconds
        tib_c = tib_const.toValErrTuple()

        conv_sec_to_usec = 1.0e-6

        if tib_norm_const is None:
            tib_norm_const = 1
            duration = 1
        else:
            duration_tag = dataset_type+"-duration"
            duration = dp_som2.attr_list[duration_tag].getValue()

        norm_const = (duration * conv_sec_to_usec) / tib_norm_const

        tib_val = tib_c[0] * norm_const
        tib_err2 = tib_c[1] * (norm_const * norm_const)

        if t is not None:
            t.getTime(False)
  
        dp_som3 = common_lib.sub_ncerr(dp_som2, (tib_val, tib_err2))

        if t is not None:
            t.getTime(msg="After subtracting TIB constant from %s" \
                      % dataset_type)
    elif conf.tib_range is not None and dkcur1 is None:
        if conf.verbose:
            print "Determining TIB constant from %s" % dataset_type

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

        TIB = dr_lib.determine_time_indep_bkg(dp_som2, conf.tib_range,
                                              is_range=True)

        if t is not None:
            t.getTime(msg="After determining TIB constant from %s" \
                      % dataset_type)

        if conf.dump_tib:
            file_comment = "TIB TOF Range: [%d, %d]" % (conf.tib_range[0],
                                                        conf.tib_range[1])
        
            hlr_utils.write_file(conf.output, "text/num-info", TIB,
                                 output_ext="tib",
                                 extra_tag=dataset_type,
                                 verbose=conf.verbose,
                                 data_ext=conf.ext_replacement,
                                 path_replacement=conf.path_replacement,
                                 message="time-independent background "\
                                 +"information",
                                 tag="Average TIB",
                                 units="counts/usec",
                                 comments=[file_comment])
            
        if conf.verbose:
            print "Subtracting TIB constant from %s" % dataset_type

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

        dp_som3 = common_lib.sub_ncerr(dp_som2, TIB)

        if t is not None:
            t.getTime(msg="After subtracting TIB constant from %s" \
                      % dataset_type)

        del TIB
    else:
        dp_som3 = dp_som2

    del dp_som2, dkcur1

    if conf.dump_ctof_comb:
        dp_som3_1 = dr_lib.sum_all_spectra(dp_som3)
        hlr_utils.write_file(conf.output, "text/Spec", dp_som3_1,
                             output_ext="ctof",
                             extra_tag=dataset_type,
                             data_ext=conf.ext_replacement,    
                             path_replacement=conf.path_replacement,
                             verbose=conf.verbose,
                             message="combined calibrated TOF information")
        
        del dp_som3_1
    
    return dp_som3
def process_sas_data(datalist, conf, **kwargs):
    """
    This function combines Steps 1 through 9 of the data reduction process for
    Small-Angle Scattering section 2.5.1 as specified by the documents 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 and
    processes the data accordingly. This function should really only be used in
    the context of I{sas_reduction}.

    @param datalist: A list containing 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 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 dataset_type: The practical name of the dataset being processed.
                           The default value is I{data}.
    @type dataset_type: C{string}

    @keyword trans_data: Alternate data for the transmission spectrum. This is
                         used in the absence of transmission monitors.
    @type trans_data: C{string}

    @keyword transmission: A flag that signals the function to stop after
                           doing the conversion from TOF to wavelength. The
                           default is I{False}.
    @type transmission: C{boolean}

    @keyword bkg_subtract: A list of coefficients that help determine the
                           wavelength dependent background subtraction.
    @type bkg_subtract: C{list}

    @keyword get_background: A flag that signals the function to convert the
                             main data to wavelength and exit before
                             normalizing to the beam monitor.
    @type get_background: C{boolean}

    @keyword acc_down_time: The information for the accelerator downtime.
    @type acc_down_time: C{tuple}

    @keyword bkg_scale: The scaling used for the axis dependent background
                        parameters.
    @type bkg_scale: C{float}

    @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 common_lib
    import dr_lib
    import hlr_utils

    # Check keywords
    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"

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

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

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

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

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

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

    acc_down_time = kwargs.get("acc_down_time")
    bkg_scale = kwargs.get("bkg_scale")

    # Add so_axis to Configure object
    conf.so_axis = "time_of_flight"

    # Step 0: Open appropriate data files

    # Data
    if conf.verbose:
        print "Reading %s file" % dataset_type

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

    dp_som1 = dr_lib.fix_bin_contents(dp_som)

    del dp_som

    if conf.inst_geom is not None:
        i_geom_dst.setGeometry(conf.data_paths.toPath(), dp_som1)

    if conf.dump_tof_r:
        dp_som1_1 = dr_lib.create_param_vs_Y(dp_som1, "radius", "param_array",
                                             conf.r_bins.toNessiList(),
                                             y_label="counts",
                                             y_units="counts / (usec * m)",
                                             x_labels=["Radius", "TOF"], 
                                             x_units=["m", "usec"])

        hlr_utils.write_file(conf.output, "text/Dave2d", dp_som1_1,
                             output_ext="tvr",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="TOF vs radius information")

        del dp_som1_1

    if conf.dump_tof_theta:
        dp_som1_1 = dr_lib.create_param_vs_Y(dp_som1, "polar", "param_array",
                                             conf.theta_bins.toNessiList(),
                                             y_label="counts",
                                             y_units="counts / (usec * rads)",
                                             x_labels=["Polar Angle", "TOF"], 
                                             x_units=["rads", "usec"])

        hlr_utils.write_file(conf.output, "text/Dave2d", dp_som1_1,
                             output_ext="tvt",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="TOF vs polar angle information")        

        del dp_som1_1
        
    # Beam monitor
    if not get_background:
        if conf.beammon_over is None:
            if conf.verbose:
                print "Reading in beam monitor data from %s file" \
                      % dataset_type

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

                if conf.inst_geom is not None:
                    i_geom_dst.setGeometry(conf.bmon_path.toPath(), dbm_som0)
        else:
            if conf.verbose:
                print "Reading in vanadium data"

                dbm_som0 = dr_lib.add_files(datalist,
                                          Data_Paths=conf.data_paths.toPath(),
                                            Signal_ROI=conf.roi_file,
                                            SO_Axis=conf.so_axis,
                                            dataset_type=dataset_type,
                                            Verbose=conf.verbose,
                                            Timer=t)
                if t is not None:
                    t.getTime(msg="After reading vanadium data ")

                if conf.inst_geom is not None:
                    i_geom_dst.setGeometry(conf.data_paths.toPath(), dbm_som0)


        dbm_som1 = dr_lib.fix_bin_contents(dbm_som0)
        
        del dbm_som0
    else:
        dbm_som1 = None

    # Transmission monitor
    if trans_data is None:
        if conf.verbose:
            print "Reading in transmission monitor data from %s file" \
                  % dataset_type
        try:
            dtm_som0 = dr_lib.add_files(datalist,
                                        Data_Paths=conf.tmon_path.toPath(),
                                        SO_Axis=conf.so_axis,
                                        dataset_type=dataset_type,
                                        Verbose=conf.verbose,
                                        Timer=t)
            if t is not None:
                t.getTime(msg="After reading transmission monitor data ")

                if conf.inst_geom is not None:
                    i_geom_dst.setGeometry(conf.tmon_path.toPath(), dtm_som0)
                    
            dtm_som1 = dr_lib.fix_bin_contents(dtm_som0)
                
            del dtm_som0
        # Transmission monitor cannot be found
        except KeyError:
            if conf.verbose:
                print "Transmission monitor not found"
            dtm_som1 = None
    else:
        dtm_som1 = None

    # Note: time_zero_offset_det MUST be a tuple
    if conf.time_zero_offset_det is not None:
        dp_som1.attr_list["Time_zero_offset_det"] = \
                                     conf.time_zero_offset_det.toValErrTuple()
    # Note: time_zero_offset_mon MUST be a tuple
    if conf.time_zero_offset_mon is not None and not get_background and \
           conf.beammon_over is None:
        dbm_som1.attr_list["Time_zero_offset_mon"] = \
                                     conf.time_zero_offset_mon.toValErrTuple()
    if conf.beammon_over is not None:
        dbm_som1.attr_list["Time_zero_offset_det"] = \
                                     conf.time_zero_offset_det.toValErrTuple()
    if trans_data is None and dtm_som1 is not None:
        dtm_som1.attr_list["Time_zero_offset_mon"] = \
                                     conf.time_zero_offset_mon.toValErrTuple()

    # Step 1: Convert TOF to wavelength for data and monitor
    if conf.verbose:
        print "Converting TOF to wavelength"

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

    if not get_background:
        # Convert beam monitor
        if conf.beammon_over is None:
            dbm_som2 = common_lib.tof_to_wavelength_lin_time_zero(
                dbm_som1,
                units="microsecond",
                time_zero_offset=conf.time_zero_offset_mon.toValErrTuple())
        else:
            dbm_som2 = common_lib.tof_to_wavelength_lin_time_zero(
                dbm_som1,
                units="microsecond",
                time_zero_offset=conf.time_zero_offset_det.toValErrTuple(),
                inst_param="total")
    else:
        dbm_som2 = None

    # Convert detector pixels
    dp_som2 = common_lib.tof_to_wavelength_lin_time_zero(
        dp_som1,
        units="microsecond",
        time_zero_offset=conf.time_zero_offset_det.toValErrTuple(),
        inst_param="total")

    if get_background:
        return dp_som2

    if dtm_som1 is not None:
        # Convert transmission  monitor
        dtm_som2 = common_lib.tof_to_wavelength_lin_time_zero(
            dtm_som1,
            units="microsecond",
            time_zero_offset=conf.time_zero_offset_mon.toValErrTuple())
    else:
        dtm_som2 = dtm_som1
        
    if t is not None:
        t.getTime(msg="After converting TOF to wavelength ")

    del dp_som1, dbm_som1, dtm_som1

    if conf.verbose and (conf.lambda_low_cut is not None or \
                         conf.lambda_high_cut is not None):
        print "Cutting data spectra"

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

    dp_som3 = dr_lib.cut_spectra(dp_som2, conf.lambda_low_cut,
                                 conf.lambda_high_cut)

    if t is not None:
        t.getTime(msg="After cutting data spectra ")

    del dp_som2

    if conf.beammon_over is not None:
        dbm_som2 = dr_lib.cut_spectra(dbm_som2, conf.lambda_low_cut,
                                       conf.lambda_high_cut)
        
    if conf.dump_wave:
        hlr_utils.write_file(conf.output, "text/Spec", dp_som3,
                             output_ext="pxl",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="pixel wavelength information")
    if conf.dump_bmon_wave:
        if conf.beammon_over is None:
            hlr_utils.write_file(conf.output, "text/Spec", dbm_som2,
                                 output_ext="bmxl",
                                 extra_tag=dataset_type,
                                 verbose=conf.verbose,
                                 data_ext=conf.ext_replacement,
                                 path_replacement=conf.path_replacement,
                                 message="beam monitor wavelength information")
        else:
            
            dbm_som2_1 = dr_lib.sum_by_rebin_frac(dbm_som2,
                                               conf.lambda_bins.toNessiList())
            hlr_utils.write_file(conf.output, "text/Spec", dbm_som2_1,
                                 output_ext="bmxl",
                                 extra_tag=dataset_type,
                                 verbose=conf.verbose,
                                 data_ext=conf.ext_replacement,
                                 path_replacement=conf.path_replacement,
                                 message="beam monitor override wavelength "\
                                 +"information")
            del dbm_som2_1

    # Step 2: Subtract wavelength dependent background if necessary
    if conf.verbose and bkg_subtract is not None:
        print "Subtracting wavelength dependent background"
        
    if bkg_subtract is not None:
        if t is not None:
            t.getTime(False)

        duration = dp_som3.attr_list["%s-duration" % dataset_type]
        scale = duration.getValue() - acc_down_time[0]
            
        dp_som4 = dr_lib.subtract_axis_dep_bkg(dp_som3, bkg_subtract,
                                               old_scale=bkg_scale,
                                               new_scale=scale)

        if t is not None:
            t.getTime(msg="After subtracting wavelength dependent background ")
    else:
        dp_som4 = dp_som3

    del dp_som3

    # Step 3: Efficiency correct beam monitor
    if conf.verbose and conf.mon_effc:
        print "Efficiency correct beam monitor data"

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

    if conf.mon_effc:
        dbm_som3 = dr_lib.feff_correct_mon(dbm_som2, inst_name=conf.inst,
                                           eff_const=conf.mon_eff_const)
    else:
        dbm_som3 = dbm_som2

    if t is not None and conf.mon_effc:
        t.getTime(msg="After efficiency correcting beam monitor ")

    if conf.dump_bmon_effc and conf.mon_effc:   
        hlr_utils.write_file(conf.output, "text/Spec", dbm_som3,
                             output_ext="bmel",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="beam monitor wavelength information "\
                             +"(efficiency)")

    del dbm_som2

    # Step 4: Efficiency correct transmission monitor    
    if dtm_som2 is not None:
        if conf.verbose and conf.mon_effc:
            print "Efficiency correct transmission monitor data"

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

        if conf.mon_effc:
            dtm_som3 = dr_lib.feff_correct_mon(dtm_som2)
        else:
            dtm_som3 = dtm_som2
    else:
        dtm_som3 = dtm_som2            

    if t is not None and conf.mon_effc and dtm_som2 is not None:
        t.getTime(msg="After efficiency correcting beam monitor ")

    # Step 5: Efficiency correct detector pixels
    if conf.det_effc:
        if conf.verbose:
            print "Calculating detector efficiency"

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

        det_eff = dr_lib.create_det_eff(dp_som4, inst_name=conf.inst,
                                      eff_scale_const=conf.det_eff_scale_const,
                                      eff_atten_const=conf.det_eff_atten_const)

        if t is not None:
            t.getTime(msg="After calculating detector efficiency")

        if conf.verbose:
            print "Applying detector efficiency"

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

        dp_som5 = common_lib.div_ncerr(dp_som4, det_eff)

        if t is not None:
            t.getTime(msg="After spplying detector efficiency")

    else:
        dp_som5 = dp_som4

    del dp_som4

    # Step 6: Rebin beam monitor axis onto detector pixel axis
    if conf.beammon_over is None:
        if not conf.no_bmon_norm:
            if conf.verbose:
                print "Rebin beam monitor axis to detector pixel axis"

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

            dbm_som4 = dr_lib.rebin_monitor(dbm_som3, dp_som5, rtype="frac")

            if t is not None:
                t.getTime(msg="After rebinning beam monitor ")
        else:
            dbm_som4 = dbm_som3
    else:
        dbm_som4 = dbm_som3

    del dbm_som3

    if conf.dump_bmon_rebin:
        hlr_utils.write_file(conf.output, "text/Spec", dbm_som4,
                             output_ext="bmrl",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="beam monitor wavelength information "\
                             +"(rebinned)")

    # Step 7: Normalize data by beam monitor
    if not conf.no_bmon_norm:
        if conf.verbose:
            print "Normalizing data by beam monitor"

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

        dp_som6 = common_lib.div_ncerr(dp_som5, dbm_som4)

        if t is not None:
            t.getTime(msg="After normalizing data by beam monitor ")
    else:
        dp_som6 = dp_som5

    del dp_som5

    if transmission:
        return dp_som6

    if conf.dump_wave_bmnorm:
        dp_som6_1 = dr_lib.sum_by_rebin_frac(dp_som6,
                                             conf.lambda_bins.toNessiList())

        write_message = "combined pixel wavelength information"
        write_message += " (beam monitor normalized)"
        
        hlr_utils.write_file(conf.output, "text/Spec", dp_som6_1,
                             output_ext="pbml",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message=write_message)
        del dp_som6_1

    if conf.dump_wave_r:
        dp_som6_1 = dr_lib.create_param_vs_Y(dp_som6, "radius", "param_array",
                                   conf.r_bins.toNessiList(),
                                   rebin_axis=conf.lambda_bins.toNessiList(),
                                   y_label="counts",
                                   y_units="counts / (Angstrom * m)",
                                   x_labels=["Radius", "Wavelength"], 
                                   x_units=["m", "Angstrom"])

        hlr_utils.write_file(conf.output, "text/Dave2d", dp_som6_1,
                             output_ext="lvr",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="wavelength vs radius information")

        del dp_som6_1

    if conf.dump_wave_theta:
        dp_som6_1 = dr_lib.create_param_vs_Y(dp_som6, "polar", "param_array",
                                   conf.theta_bins.toNessiList(),
                                   rebin_axis=conf.lambda_bins.toNessiList(),
                                   y_label="counts",
                                   y_units="counts / (Angstrom * rads)",
                                   x_labels=["Polar Angle", "Wavelength"], 
                                   x_units=["rads", "Angstrom"])

        hlr_utils.write_file(conf.output, "text/Dave2d", dp_som6_1,
                             output_ext="lvt",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="wavelength vs polar angle information") 

        del dp_som6_1

    # Step 8: Rebin transmission monitor axis onto detector pixel axis
    if trans_data is not None:
        print "Reading in transmission monitor data from file"

        dtm_som3 = dr_lib.add_files([trans_data],
                                    dataset_type=dataset_type,
                                    dst_type="text/Spec",
                                    Verbose=conf.verbose,
                                    Timer=t)

    
    if conf.verbose and dtm_som3 is not None:
        print "Rebin transmission monitor axis to detector pixel axis"
        
    if t is not None:
        t.getTime(False)

    dtm_som4 = dr_lib.rebin_monitor(dtm_som3, dp_som6, rtype="frac")

    if t is not None and dtm_som3 is not None:
        t.getTime(msg="After rebinning transmission monitor ")

    del dtm_som3

    # Step 9: Normalize data by transmission monitor    
    if conf.verbose and dtm_som4 is not None:
        print "Normalizing data by transmission monitor"

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

    if dtm_som4 is not None:
        # The transmission spectra derived from sas_tranmission does not have
        # the same y information by convention as sample data or a
        # tranmission monitor. Therefore, we'll fake it by setting the
        # y information from the sample data into the transmission
        if trans_data is not None:
            dtm_som4.setYLabel(dp_som6.getYLabel())
            dtm_som4.setYUnits(dp_som6.getYUnits())
        dp_som7 = common_lib.div_ncerr(dp_som6, dtm_som4)
    else:
        dp_som7 = dp_som6

    if t is not None and dtm_som4 is not None:
        t.getTime(msg="After normalizing data by transmission monitor ")

    del dp_som6

    # Step 10: Convert wavelength to Q for data
    if conf.verbose:
        print "Converting data from wavelength to scalar Q"
    
    if t is not None:
        t.getTime(False)

    dp_som8 = common_lib.wavelength_to_scalar_Q(dp_som7)

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

    if conf.facility == "LENS":
        # Step 11: Apply SAS correction factor to data
        if conf.verbose:
            print "Applying geometrical correction"

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

        dp_som9 = dr_lib.apply_sas_correct(dp_som8)

        if t is not None:
            t.getTime(msg="After applying geometrical correction ")

        return dp_som9
    else:
        return dp_som8
Example #6
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 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 #8
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

    config.so_axis = "time_of_flight"

    try:
        if type(config.mask_file) == type([]):
            if len(config.mask_file) > 1:
                if config.verbose:
                    print "Creating combined mask file"

                if tim is not None:
                    tim.getTime(False)
        
                config.mask_file = hlr_utils.merge_roi_files(\
                        config.mask_file,
                        config)

                if tim is not None:
                    tim.getTime(msg="After creating combined mask file")
            else:
                config.mask_file = config.mask_file[0]
        else:
            # Do nothing since it's already a string
            pass
    except TypeError:
        # No mask files provided, do nothing
        pass

    # Steps 1-3: Produce a scaled summed dark current dataset
    dc_som = dr_lib.scaled_summed_data(config.dkcur, config,
                                       dataset_type="dark_current",
                                       timer=tim)

    # Perform Steps 3-6 on black can data
    if config.bcan is not None:
        b_som1 = dr_lib.calibrate_dgs_data(config.bcan, config, dc_som,
                                           dataset_type="black_can",
                                           inst_geom_dst=inst_geom_dst,
                                           tib_const=config.tib_const,
                                           cwp=config.cwp_bcan,
                                           timer=tim)
    else:
        b_som1 = None

    # Perform Steps 3-6 on empty can data    
    if config.ecan is not None:
        e_som1 = dr_lib.calibrate_dgs_data(config.ecan, config, dc_som,
                                           dataset_type="empty_can",
                                           inst_geom_dst=inst_geom_dst,
                                           tib_const=config.tib_const,
                                           cwp=config.cwp_ecan,
                                           timer=tim)
    else:
        e_som1 = None

    # Perform Steps 3-6 on sample data
    d_som1 = dr_lib.calibrate_dgs_data(config.data, config, dc_som,
                                       inst_geom_dst=inst_geom_dst,
                                       tib_const=config.tib_const,
                                       cwp=config.cwp_data,
                                       timer=tim)

    # Perform Steps 7-16 on sample data
    if config.data_trans_coeff is None:
        data_trans_coeff = None
    else:
        data_trans_coeff = config.data_trans_coeff.toValErrTuple()

    # Determine if we need to rebin the empty or black can data
    if config.ecan is not None and e_som1 is not None:
        ecan_cwp = True
    else:
        ecan_cwp = False

    if config.bcan is not None and b_som1 is not None:
        bcan_cwp = True
    else:
        bcan_cwp = False        

    cwp_used = ecan_cwp or bcan_cwp
    
    d_som2 = dr_lib.process_dgs_data(d_som1, config, b_som1, e_som1,
                                     data_trans_coeff, cwp_used=cwp_used,
                                     timer=tim)

    del d_som1

    del b_som1, e_som1

    # Step 18: Normalize sample data by integrated values
    if config.norm is not None:
        if config.verbose:
            print "Reading normalization information"

        norm_int = dr_lib.add_files(config.norm, Signal_ROI=config.roi_file,
                                    Signal_MASK=config.mask_file,
                                    dataset_type="normalization",
                                    dst_type="text/num-info",
                                    Verbose=config.verbose,
                                    Timer=tim)
        
        # Make the labels and units compatible with a NeXus file based SOM
        norm_int.setAllAxisLabels(["wavelength"])
        norm_int.setAllAxisUnits(["Angstroms"])
        norm_int.setYLabel("Intensity")
        norm_int.setYUnits("Counts/Angstroms")
        
        if config.verbose:
            print "Normalizing data by normalization data"

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

        d_som3 = common_lib.div_ncerr(d_som2, norm_int)            

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

        del norm_int
    else:
        d_som3 = d_som2

    del d_som2

    # Step 19: Calculate the initial energy
    if config.initial_energy is not None:
        d_som3.attr_list["Initial_Energy"] = config.initial_energy

    # Steps 20-21: Calculate the energy transfer
    if config.verbose:
        print "Calculating energy transfer"

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

    d_som4 = dr_lib.energy_transfer(d_som3, "DGS", "Initial_Energy",
                                    lojac=True, scale=config.lambda_ratio)
    
    if tim is not None:
        tim.getTime(msg="After calculating energy transfer ")

    del d_som3

    # Step 22: Rebin energy transfer spectra
    if config.verbose:
        print "Rebinning to final energy transfer axis"

    if tim is not None:
        tim.getTime(False)
        
    d_som5 = common_lib.rebin_axis_1D_frac(d_som4, config.E_bins.toNessiList())

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

    del d_som4

    if config.dump_et_comb:
        d_som5_1 = dr_lib.sum_all_spectra(d_som5)
        hlr_utils.write_file(config.output, "text/Spec", d_som5_1,
                             output_ext="et",
                             data_ext=config.ext_replacement,    
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="combined energy transfer information")

        del d_som5_1

    # Get the corner geometry information
    if config.verbose:
        print "Reading in corner geometry information"
        
    if tim is not None:
        tim.getTime(False)
        
    corner_angles = hlr_utils.get_corner_geometry(config.corner_geom)

    if tim is not None:
        tim.getTime(msg="After reading in corner geometry information ")

    if config.make_spe:
        d_som5.attr_list["corner_geom"] = corner_angles

        hlr_utils.write_file(config.output, "text/PHX", d_som5,
                             output_ext="phx",
                             data_ext=config.ext_replacement,    
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="PHX information")

        hlr_utils.write_file(config.output, "text/PAR", d_som5,
                             output_ext="par",
                             data_ext=config.ext_replacement,    
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="PAR information")

        hlr_utils.write_file(config.output, "text/SPE", d_som5,
                             output_ext="spe",
                             data_ext=config.ext_replacement,    
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="SPE information")

    # Steps 23-34: Create S(Q, E) distribution
    if config.verbose:
        print "Creating S(Q, E)"

    if tim is not None:
        tim.getTime(False)
        
    d_som5_2 = dr_lib.create_E_vs_Q_dgs(d_som5,
                                        config.initial_energy.toValErrTuple(),
                                        config.Q_bins.toNessiList(),
                                        corner_angles=corner_angles,
                                        split=config.split,
                                        configure=config,
                                        timer=tim)

    # Writing 2D DAVE file
    if not config.split:
        hlr_utils.write_file(config.output, "text/Dave2d", d_som5_2,
                             output_ext="sqe",
                             data_ext=config.ext_replacement,    
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="S(Q,E)")

        hlr_utils.write_file(config.output, "application/x-RedNxs", d_som5_2,
                             output_ext="nxs",
                             data_ext=config.ext_replacement,    
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             extra_tag="sqe",
                             getsom_kwargs={"entry_name": "sqe"},
                             message="NeXus S(Q,E)")
                                               
    if tim is not None:
        tim.getTime(msg="After calculating S(Q,E) spectrum ")    

    del d_som5_2

    if config.qmesh:
        # Steps 23-27,35-36: Create S(Qvec, E) distribution
        if config.verbose:
            print "Creating S(Qvec, E)"

        if tim is not None:
            tim.getTime(False)
        
        dr_lib.create_Qvec_vs_E_dgs(d_som5,
                                    config.initial_energy.toValErrTuple(),
                                    config, corner_angles=corner_angles,
                                    make_fixed=config.fixed,
                                    output=config.output,
                                    timer=tim)
        
        if tim is not None:
            tim.getTime(msg="After calculating final spectrum ")    

    # Write out RMD file
    d_som5.attr_list["config"] = config

    hlr_utils.write_file(config.output, "text/rmd", d_som5,
                         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 scaled_summed_data(datalist, conf, **kwargs):
    """
    This function takes a list of TOF datafiles, creates the dataset
    representation, integrates each pixel spectrum and then scales those
    integrations with the acquisition time.

    @param datalist: A list containing 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 kwargs: A list of keyword arguments that the function accepts:

    @keyword dataset_type: The practical name of the dataset being processed.
                           The default value is I{data}.
    @type dataset_type: C{string}

    @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}
    """
    # Kick-out is no data list is present
    if datalist is None:
        return None

    import common_lib
    import dr_lib

    # Check keywords
    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"
    
    try:
        t = kwargs["timer"]
    except KeyError:
        t = None

    # Open the appropriate datafiles
    if conf.verbose:
        print "Reading %s file" % dataset_type

    dst_type = "application/x-NeXus"
    data_paths = conf.data_paths.toPath()

    dp_som0 = dr_lib.add_files(datalist, Data_Paths=data_paths,
                               SO_Axis=conf.so_axis, Signal_ROI=conf.roi_file,
                               Signal_MASK=conf.mask_file,
                               dataset_type=dataset_type,
                               dst_type=dst_type,
                               Verbose=conf.verbose, Timer=t)

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

    dp_som1 = dr_lib.fix_bin_contents(dp_som0)

    del dp_som0    

    if conf.verbose:
        print "Integrating %s data" % dataset_type
        
    if t is not None:
        t.getTime(False)

    dp_som2 = dr_lib.integrate_spectra(dp_som1, width=True)

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

    del dp_som1

    # Make dataset duration tag
    duration_tag = dataset_type+"-duration"
    duration = dp_som2.attr_list[duration_tag]

    if conf.verbose:
        print "Scaling %s integration by acquisition duration " % dataset_type

    if t is not None:
        t.getTime(False)
 
    dp_som3 = common_lib.div_ncerr(dp_som2, (duration.getValue(), 0.0))

    if t is not None:
        t.getTime("After scaling %s integration by acquisition duration " \
                  % dataset_type)

    del dp_som2

    return dp_som3
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 #11
0
def process_igs_data(datalist, conf, **kwargs):
    """
    This function combines Steps 1 through 8 of the data reduction process for
    Inverse Geometry Spectrometers as specified by the documents 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 and
    processes the data accordingly. This function should really only be used in
    the context of I{amorphous_reduction} and I{calc_norm_eff}.

    @param datalist: A list containing 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 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 dataset_type: The practical name of the dataset being processed.
    The default value is I{data}.
    @type dataset_type: C{string}
    
    @keyword tib_const: Object providing the time-independent background
    constant to subtract.
    @type tib_const: L{hlr_utils.DrParameter}

    @keyword bkg_som: Object that will be used for early background subtraction
    @type bkg_som: C{SOM.SOM}
    
    @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

    # Check keywords
    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"

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

    try:
        if kwargs["tib_const"] is not None:
            tib_const = kwargs["tib_const"].toValErrTuple()
        else:
            tib_const = None
    except KeyError:
        tib_const = None

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

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

    # Step 1: Open appropriate data files
    if not conf.mc:
        so_axis = "time_of_flight"
    else:
        so_axis = "Time_of_Flight"

    # Add so_axis to Configure object
    conf.so_axis = so_axis

    if conf.verbose:
        print "Reading %s file" % dataset_type

    # Special case handling for normalization data. Dynamically trying to
    # determine if incoming file is a previously calculated one.
    if dataset_type == "normalization":
        try:
            # Check the first incoming file
            dst_type = hlr_utils.file_peeker(datalist[0])
            # If file_peeker succeeds, the DST is different than the function
            # returns
            dst_type = "text/num-info"
            # Let ROI file handle filtering
            data_paths = None
        except RuntimeError:
            # It's a NeXus file
            dst_type = "application/x-NeXus"
            data_paths = conf.data_paths.toPath()
    else:
        dst_type = "application/x-NeXus"
        data_paths = conf.data_paths.toPath()

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

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

    if dst_type == "text/num-info":
        # Since we have a pre-calculated normalization dataset, set the flag
        # and return the SOM now
        conf.pre_norm = True
        # Make the labels and units compatible with a NeXus file based SOM
        dp_som0.setAxisLabel(0, "wavelength")
        dp_som0.setAxisUnits(0, "Angstroms")
        dp_som0.setYUnits("Counts/A")
        return dp_som0
    else:
        if dataset_type == "normalization":
            # Since we have a NeXus file, we need to continue
            conf.pre_norm = False

    # Cut the spectra if necessary
    dp_somA = dr_lib.cut_spectra(dp_som0, conf.tof_cut_min, conf.tof_cut_max)

    del dp_som0

    dp_som1 = dr_lib.fix_bin_contents(dp_somA)

    del dp_somA

    if conf.inst_geom is not None:
        i_geom_dst.setGeometry(conf.data_paths.toPath(), dp_som1)

    if conf.no_mon_norm:
        dm_som1 = None
    else:
        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_som0 = 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 ")

        dm_som1 = dr_lib.fix_bin_contents(dm_som0)

        del dm_som0

        if conf.inst_geom is not None:
            i_geom_dst.setGeometry(conf.mon_path.toPath(), dm_som1)

    if bkg_som is not None:
        bkg_pcharge = bkg_som.attr_list["background-proton_charge"].getValue()
        data_pcharge = dp_som1.attr_list[dataset_type + "-proton_charge"].getValue()

        ratio = data_pcharge / bkg_pcharge

        bkg_som1 = common_lib.mult_ncerr(bkg_som, (ratio, 0.0))

        del bkg_som

        dp_som2 = dr_lib.subtract_bkg_from_data(
            dp_som1, bkg_som1, verbose=conf.verbose, timer=t, dataset1=dataset_type, dataset2="background"
        )

    else:
        dp_som2 = dp_som1

    del dp_som1

    # Step 2: Dead Time Correction
    # No dead time correction is being applied to the data yet

    # Step 3: Time-independent background determination
    if conf.verbose and conf.tib_tofs is not None:
        print "Determining time-independent background from data"

    if t is not None and conf.tib_tofs is not None:
        t.getTime(False)

    B = dr_lib.determine_time_indep_bkg(dp_som2, conf.tib_tofs)

    if t is not None and B is not None:
        t.getTime(msg="After determining time-independent background ")

    if conf.dump_tib and B is not None:
        file_comment = "TOFs: %s" % conf.tib_tofs

        hlr_utils.write_file(
            conf.output,
            "text/num-info",
            B,
            output_ext="tib",
            extra_tag=dataset_type,
            verbose=conf.verbose,
            data_ext=conf.ext_replacement,
            path_replacement=conf.path_replacement,
            message="time-independent background " + "information",
            tag="Average",
            units="counts",
            comments=[file_comment],
        )

    # Step 4: Subtract time-independent background
    if conf.verbose and B is not None:
        print "Subtracting time-independent background from data"

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

    if B is not None:
        dp_som3 = common_lib.sub_ncerr(dp_som2, B)
    else:
        dp_som3 = dp_som2

    if B is not None and t is not None:
        t.getTime(msg="After subtracting time-independent background ")

    del dp_som2, B

    # Step 5: Subtract time-independent background constant
    if conf.verbose and tib_const is not None:
        print "Subtracting time-independent background constant from data"

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

    if tib_const is not None:
        dp_som4 = common_lib.sub_ncerr(dp_som3, tib_const)
    else:
        dp_som4 = dp_som3

    if t is not None and tib_const is not None:
        t.getTime(msg="After subtracting time-independent background " + "constant ")

    del dp_som3

    # Provide override capability for final wavelength, time-zero slope and
    # time-zero offset

    if conf.wavelength_final is not None:
        dp_som4.attr_list["Wavelength_final"] = conf.wavelength_final.toValErrTuple()

    # Note: time_zero_slope MUST be a tuple
    if conf.time_zero_slope is not None:
        dp_som4.attr_list["Time_zero_slope"] = conf.time_zero_slope.toValErrTuple()
        if dm_som1 is not None:
            dm_som1.attr_list["Time_zero_slope"] = conf.time_zero_slope.toValErrTuple()

    # Note: time_zero_offset MUST be a tuple
    if conf.time_zero_offset is not None:
        dp_som4.attr_list["Time_zero_offset"] = conf.time_zero_offset.toValErrTuple()
        if dm_som1 is not None:
            dm_som1.attr_list["Time_zero_offset"] = conf.time_zero_offset.toValErrTuple()

    # Step 6: Convert TOF to wavelength for data and monitor
    if conf.verbose:
        print "Converting TOF to wavelength"

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

    # Convert monitor
    if dm_som1 is not None:
        dm_som2 = common_lib.tof_to_wavelength_lin_time_zero(dm_som1, units="microsecond")
    else:
        dm_som2 = None

    # Convert detector pixels
    dp_som5 = common_lib.tof_to_initial_wavelength_igs_lin_time_zero(
        dp_som4, units="microsecond", run_filter=conf.filter
    )

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

    if conf.dump_wave:
        hlr_utils.write_file(
            conf.output,
            "text/Spec",
            dp_som5,
            output_ext="pxl",
            extra_tag=dataset_type,
            verbose=conf.verbose,
            data_ext=conf.ext_replacement,
            path_replacement=conf.path_replacement,
            message="pixel wavelength information",
        )
    if conf.dump_mon_wave and dm_som2 is not None:
        hlr_utils.write_file(
            conf.output,
            "text/Spec",
            dm_som2,
            output_ext="mxl",
            extra_tag=dataset_type,
            verbose=conf.verbose,
            data_ext=conf.ext_replacement,
            path_replacement=conf.path_replacement,
            message="monitor wavelength information",
        )

    del dp_som4, dm_som1

    # Step 7: Efficiency correct monitor
    if conf.verbose and dm_som2 is not None and not conf.no_mon_effc:
        print "Efficiency correct monitor data"

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

    if not conf.no_mon_effc:
        dm_som3 = dr_lib.feff_correct_mon(dm_som2)
    else:
        dm_som3 = dm_som2

    if t is not None and dm_som2 is not None and not conf.no_mon_effc:
        t.getTime(msg="After efficiency correcting monitor ")

    if conf.dump_mon_effc and not conf.no_mon_effc and dm_som3 is not None:
        hlr_utils.write_file(
            conf.output,
            "text/Spec",
            dm_som3,
            output_ext="mel",
            extra_tag=dataset_type,
            verbose=conf.verbose,
            data_ext=conf.ext_replacement,
            path_replacement=conf.path_replacement,
            message="monitor wavelength information " + "(efficiency)",
        )

    del dm_som2

    # Step 8: Rebin monitor axis onto detector pixel axis
    if conf.verbose and dm_som3 is not None:
        print "Rebin monitor axis to detector pixel axis"

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

    dm_som4 = dr_lib.rebin_monitor(dm_som3, dp_som5)

    if t is not None and dm_som4 is not None:
        t.getTime(msg="After rebinning monitor ")

    del dm_som3

    if conf.dump_mon_rebin and dm_som4 is not None:
        hlr_utils.write_file(
            conf.output,
            "text/Spec",
            dm_som4,
            output_ext="mrl",
            extra_tag=dataset_type,
            verbose=conf.verbose,
            data_ext=conf.ext_replacement,
            path_replacement=conf.path_replacement,
            message="monitor wavelength information " + "(rebinned)",
        )

    # The lambda-dependent background is only done on sample data (aka data)
    # for the BSS instrument at the SNS
    if conf.inst == "BSS" and conf.ldb_const is not None and dataset_type == "data":
        # Step 9: Convert chopper center wavelength to TOF center
        if conf.verbose:
            print "Converting chopper center wavelength to TOF"

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

        tof_center = dr_lib.convert_single_to_list(
            "initial_wavelength_igs_lin_time_zero_to_tof", conf.chopper_lambda_cent.toValErrTuple(), dp_som5
        )

        # Step 10: Calculate beginning and end of detector TOF spectrum
        if conf.verbose:
            print "Calculating beginning and ending TOF ranges"

        half_inv_chop_freq = 0.5 / conf.chopper_freq.toValErrTuple()[0]
        # Above is in seconds, need microseconds
        half_inv_chop_freq *= 1.0e6

        tof_begin = common_lib.sub_ncerr(tof_center, (half_inv_chop_freq, 0.0))
        tof_end = common_lib.add_ncerr(tof_center, (half_inv_chop_freq, 0.0))

        # Step 11: Convert TOF_begin and TOF_end to wavelength
        if conf.verbose:
            print "Converting TOF_begin and TOF_end to wavelength"

        # Check for time-zero slope information
        try:
            tz_slope = conf.time_zero_slope.toValErrTuple()
        except AttributeError:
            tz_slope = (0.0, 0.0)

        # Check for time-zero offset information
        try:
            tz_offset = conf.time_zero_offset.toValErrTuple()
        except AttributeError:
            tz_offset = (0.0, 0.0)

        l_begin = common_lib.tof_to_initial_wavelength_igs_lin_time_zero(
            tof_begin, time_zero_slope=tz_slope, time_zero_offset=tz_offset, iobj=dp_som5, run_filter=False
        )
        l_end = common_lib.tof_to_initial_wavelength_igs_lin_time_zero(
            tof_end, time_zero_slope=tz_slope, time_zero_offset=tz_offset, iobj=dp_som5, run_filter=False
        )

        # Step 12: tof-least-bkg to lambda-least-bkg
        if conf.verbose:
            print "Converting TOF least background to wavelength"

        lambda_least_bkg = dr_lib.convert_single_to_list(
            "tof_to_initial_wavelength_igs_lin_time_zero", conf.tof_least_bkg.toValErrTuple(), dp_som5
        )

        if t is not None:
            t.getTime(msg="After converting boundary positions ")

        # Step 13: Create lambda-dependent background spectrum
        if conf.verbose:
            print "Creating lambda-dependent background spectra"

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

        ldb_som = dr_lib.shift_spectrum(dm_som4, lambda_least_bkg, l_begin, l_end, conf.ldb_const.getValue())

        if t is not None:
            t.getTime(msg="After creating lambda-dependent background " + "spectra ")

        # Step 14: Subtract lambda-dependent background from sample data
        if conf.verbose:
            print "Subtracting lambda-dependent background from data"

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

        dp_som6 = common_lib.sub_ncerr(dp_som5, ldb_som)

        if t is not None:
            t.getTime(msg="After subtracting lambda-dependent background " + "from data ")
    else:
        dp_som6 = dp_som5

    del dp_som5

    # Step 15: Normalize data by monitor
    if conf.verbose and dm_som4 is not None:
        print "Normalizing data by monitor"

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

    if dm_som4 is not None:
        dp_som7 = common_lib.div_ncerr(dp_som6, dm_som4)

        if t is not None:
            t.getTime(msg="After normalizing data by monitor ")
    else:
        dp_som7 = dp_som6

    if conf.dump_wave_mnorm:
        dp_som7_1 = dr_lib.sum_all_spectra(dp_som7, rebin_axis=conf.lambda_bins.toNessiList())

        write_message = "combined pixel wavelength information"
        if dm_som4 is not None:
            write_message += " (monitor normalized)"

        hlr_utils.write_file(
            conf.output,
            "text/Spec",
            dp_som7_1,
            output_ext="pml",
            extra_tag=dataset_type,
            verbose=conf.verbose,
            data_ext=conf.ext_replacement,
            path_replacement=conf.path_replacement,
            message=write_message,
        )
        del dp_som7_1

    del dm_som4, dp_som6

    return dp_som7
Example #12
0
def process_ref_data(datalist,
                     conf,
                     signal_roi_file,
                     bkg_roi_file=None,
                     no_bkg=False,
                     **kwargs):
    """
    This function combines Steps 1 through 6 in section 2.4.5 of the data
    reduction process for Reflectometers (without Monitors) 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,
    signal and background region-of-interest (ROI) files and an optional flag
    about background subtraction and 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 signal_roi_file: The file containing the list of pixel IDs for the
                            signal region of interest.
    @type signal_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: Object that contains the instrument geometry
                            information.
    @type inst_geom_dst: C{DST.getInstance()}
    
    @keyword dataset_type: The practical name of the dataset being processed.
                           The default value is I{data}.
    @type dataset_type: C{string}

    @keyword tof_cuts: Time-of-flight bins to remove (zero) from the data
    @type tof_cuts: C{list} of C{string}s

    @keyword no_tof_cuts: Flag to stop application of the TOF cuts
    @type no_tof_cuts: C{boolean}
    
    @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 common_lib
    import dr_lib
    import hlr_utils

    # Check keywords
    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"

    if dataset_type != "data" and dataset_type != "norm":
        raise RuntimeError("Please use data or norm to specify the dataset "\
                           +"type. Do not understand how to handle %s." \
                           % dataset_type)

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

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

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

    no_tof_cuts = kwargs.get("no_tof_cuts", False)

    so_axis = "time_of_flight"

    # Step 0: Open data files and select signal (and possible background) ROIs
    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=signal_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)

    if i_geom_dst is not None:
        i_geom_dst.setGeometry(conf.data_paths.toPath(), d_som1)

    # Calculate delta t over t
    if conf.verbose:
        print "Calculating delta t over t"

    dtot = dr_lib.calc_deltat_over_t(d_som1[0].axis[0].val)

    # Calculate delta theta over theta
    if conf.verbose:
        print "Calculating delta theta over theta"

    dr_lib.calc_delta_theta_over_theta(d_som1, dataset_type)

    # Step 1: Sum all spectra along the 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 dataset_type == "data":
        d_som1.attr_list["ref_sort"] = y_sort

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

    del d_som1

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

    # Set the TOF cuts
    if no_tof_cuts:
        tof_cut_min = None
        tof_cut_max = None
    else:
        tof_cut_min = conf.tof_cut_min
        tof_cut_max = conf.tof_cut_max

    # Cut the spectra if necessary
    d_som2 = dr_lib.cut_spectra(d_som1A, tof_cut_min, tof_cut_max)

    del d_som1A

    if b_som1A is not None:
        b_som2 = dr_lib.cut_spectra(b_som1A, tof_cut_min, tof_cut_max)
        del b_som1A
    else:
        b_som2 = b_som1A

    # Fix TOF cuts to make them list of integers
    try:
        tof_cuts = [int(x) for x in tof_cuts]
    # This will trigger if tof_cuts is None
    except TypeError:
        pass

    d_som3 = dr_lib.zero_bins(d_som2, tof_cuts)

    del d_som2

    if b_som2 is not None:
        b_som3 = dr_lib.zero_bins(b_som2, tof_cuts)

        del b_som2
    else:
        b_som3 = b_som2

    if conf.dump_specular:
        if no_tof_cuts:
            d_som3_1 = dr_lib.cut_spectra(d_som3, conf.tof_cut_min,
                                          conf.tof_cut_max)
        else:
            d_som3_1 = d_som3
        hlr_utils.write_file(conf.output,
                             "text/Spec",
                             d_som3_1,
                             output_ext="sdc",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="specular TOF information")
        del d_som3_1

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

    if dataset_type == "data":
        peak_excl = conf.data_peak_excl
    elif dataset_type == "norm":
        peak_excl = conf.norm_peak_excl

    if b_som3 is not None:
        B = dr_lib.calculate_ref_background(b_som3,
                                            no_bkg,
                                            conf.inst,
                                            None,
                                            aobj=d_som3)
    else:
        B = dr_lib.calculate_ref_background(d_som3, no_bkg, conf.inst,
                                            peak_excl)

    if t is not None:
        t.getTime(msg="After background determination")

    if not no_bkg and conf.dump_bkg:
        if no_tof_cuts:
            B_1 = dr_lib.cut_spectra(B, conf.tof_cut_min, conf.tof_cut_max)
        else:
            B_1 = B
        hlr_utils.write_file(conf.output,
                             "text/Spec",
                             B_1,
                             output_ext="bkg",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="background TOF information")
        del B_1

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

    del d_som3

    if not no_bkg and conf.dump_sub:
        if no_tof_cuts:
            d_som4_1 = dr_lib.cut_spectra(d_som4, conf.tof_cut_min,
                                          conf.tof_cut_max)
        else:
            d_som4_1 = d_som4
        hlr_utils.write_file(conf.output,
                             "text/Spec",
                             d_som4_1,
                             output_ext="sub",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="subtracted TOF information")
        del d_som4_1

    dtot_int = dr_lib.integrate_axis_py(dtot, avg=True)
    param_key = dataset_type + "-dt_over_t"
    d_som4.attr_list[param_key] = dtot_int[0]

    if conf.store_dtot:
        d_som4.attr_list["extra_som"] = dtot

    # Step 6: Scale by proton charge
    pc = d_som4.attr_list[dataset_type + "-proton_charge"]
    pc_new = hlr_utils.scale_proton_charge(pc, "C")
    d_som5 = common_lib.div_ncerr(d_som4, (pc_new.getValue(), 0.0))

    del d_som4

    return d_som5
Example #13
0
def scaled_summed_data(datalist, conf, **kwargs):
    """
    This function takes a list of TOF datafiles, creates the dataset
    representation, integrates each pixel spectrum and then scales those
    integrations with the acquisition time.

    @param datalist: A list containing 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 kwargs: A list of keyword arguments that the function accepts:

    @keyword dataset_type: The practical name of the dataset being processed.
                           The default value is I{data}.
    @type dataset_type: C{string}

    @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}
    """
    # Kick-out is no data list is present
    if datalist is None:
        return None

    import common_lib
    import dr_lib

    # Check keywords
    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"

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

    # Open the appropriate datafiles
    if conf.verbose:
        print "Reading %s file" % dataset_type

    dst_type = "application/x-NeXus"
    data_paths = conf.data_paths.toPath()

    dp_som0 = dr_lib.add_files(datalist,
                               Data_Paths=data_paths,
                               SO_Axis=conf.so_axis,
                               Signal_ROI=conf.roi_file,
                               Signal_MASK=conf.mask_file,
                               dataset_type=dataset_type,
                               dst_type=dst_type,
                               Verbose=conf.verbose,
                               Timer=t)

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

    dp_som1 = dr_lib.fix_bin_contents(dp_som0)

    del dp_som0

    if conf.verbose:
        print "Integrating %s data" % dataset_type

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

    dp_som2 = dr_lib.integrate_spectra(dp_som1, width=True)

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

    del dp_som1

    # Make dataset duration tag
    duration_tag = dataset_type + "-duration"
    duration = dp_som2.attr_list[duration_tag]

    if conf.verbose:
        print "Scaling %s integration by acquisition duration " % dataset_type

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

    dp_som3 = common_lib.div_ncerr(dp_som2, (duration.getValue(), 0.0))

    if t is not None:
        t.getTime("After scaling %s integration by acquisition duration " \
                  % dataset_type)

    del dp_som2

    return dp_som3
Example #14
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

    # Add so_axis to Configure object
    config.so_axis = "time_of_flight"

    dataset_type = "background"

    # Step 0: Open appropriate data files

    # Data
    if config.verbose:
        print "Reading %s file" % dataset_type

    # The [0] is to get the data SOM and ignore the None background SOM
    dp_som = dr_lib.add_files(config.data,
                              Data_Paths=config.data_paths.toPath(),
                              SO_Axis=config.so_axis,
                              Signal_ROI=config.roi_file,
                              dataset_type=dataset_type,
                              Verbose=config.verbose,
                              Timer=tim)

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

    dp_som0 = dr_lib.fix_bin_contents(dp_som)

    del dp_som

    if inst_geom_dst is not None:
        inst_geom_dst.setGeometry(config.data_paths.toPath(), dp_som0)

    # Note: time_zero_offset_det MUST be a tuple
    if config.time_zero_offset_det is not None:
        dp_som0.attr_list["Time_zero_offset_det"] = \
                                   config.time_zero_offset_det.toValErrTuple()

    # Step 2: Convert TOF to wavelength for data
    if config.verbose:
        print "Converting TOF to wavelength"

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

    # Convert detector pixels
    dp_som1 = common_lib.tof_to_wavelength_lin_time_zero(
        dp_som0,
        units="microsecond",
        time_zero_offset=config.time_zero_offset_det.toValErrTuple(),
        inst_param="total")

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

    del dp_som0

    if config.verbose:
        print "Cutting spectra"

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

    dp_som2 = dr_lib.cut_spectra(dp_som1, config.lambda_low_cut,
                                 config.lambda_high_cut)

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

    del dp_som1

    rebin_axis = config.lambda_bins.toNessiList()

    # Put the data on the same axis
    if config.verbose:
        print "Rebinning data onto specified wavelength axis"

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

    dp_som3 = dr_lib.sum_by_rebin_frac(dp_som2, rebin_axis)

    if tim is not None:
        tim.getTime(msg="After rebinning data onto specified wavelength axis ")

    del dp_som2

    data_run_time = dp_som3.attr_list["background-duration"]

    # Calculate the accelerator on time
    if config.verbose:
        print "Calculating accelerator on time"

    acc_on_time = hlr_utils.DrParameter(
        data_run_time.getValue() - config.acc_down_time.getValue(), 0.0,
        "seconds")

    # Get the number of data bins
    num_wave_bins = len(rebin_axis) - 1

    # Calculate the scaled accelerator uptime
    if config.verbose:
        print "Calculating the scaled accelerator uptime"

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

    final_scale = acc_on_time.toValErrTuple()[0] / num_wave_bins

    if tim is not None:
        tim.getTime(msg="After calculating the scaled accelerator uptime ")

    # Create the final background spectrum
    if config.verbose:
        print "Creating the background spectrum"

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

    dp_som4 = common_lib.div_ncerr(dp_som3, (final_scale, 0))
    dp_som4.attr_list["%s-Scaling" % dataset_type] = final_scale

    if tim is not None:
        tim.getTime(msg="After creating background spectrum ")

    del dp_som3

    # Write out the background spectrum
    hlr_utils.write_file(config.output,
                         "text/Spec",
                         dp_som4,
                         verbose=config.verbose,
                         output_ext="bkg",
                         data_ext=config.ext_replacement,
                         replace_path=False,
                         replace_ext=True,
                         message="background spectrum")

    dp_som4.attr_list["config"] = config

    hlr_utils.write_file(config.output,
                         "text/rmd",
                         dp_som4,
                         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")
Example #15
0
def process_igs_data(datalist, conf, **kwargs):
    """
    This function combines Steps 1 through 8 of the data reduction process for
    Inverse Geometry Spectrometers as specified by the documents 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 and
    processes the data accordingly. This function should really only be used in
    the context of I{amorphous_reduction} and I{calc_norm_eff}.

    @param datalist: A list containing 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 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 dataset_type: The practical name of the dataset being processed.
    The default value is I{data}.
    @type dataset_type: C{string}
    
    @keyword tib_const: Object providing the time-independent background
    constant to subtract.
    @type tib_const: L{hlr_utils.DrParameter}

    @keyword bkg_som: Object that will be used for early background subtraction
    @type bkg_som: C{SOM.SOM}
    
    @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

    # Check keywords
    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"

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

    try:
        if kwargs["tib_const"] is not None:
            tib_const = kwargs["tib_const"].toValErrTuple()
        else:
            tib_const = None
    except KeyError:
        tib_const = None

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

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

    # Step 1: Open appropriate data files
    if not conf.mc:
        so_axis = "time_of_flight"
    else:
        so_axis = "Time_of_Flight"

    # Add so_axis to Configure object
    conf.so_axis = so_axis

    if conf.verbose:
        print "Reading %s file" % dataset_type

    # Special case handling for normalization data. Dynamically trying to
    # determine if incoming file is a previously calculated one.
    if dataset_type == "normalization":
        try:
            # Check the first incoming file
            dst_type = hlr_utils.file_peeker(datalist[0])
            # If file_peeker succeeds, the DST is different than the function
            # returns
            dst_type = "text/num-info"
            # Let ROI file handle filtering
            data_paths = None
        except RuntimeError:
            # It's a NeXus file
            dst_type = "application/x-NeXus"
            data_paths = conf.data_paths.toPath()
    else:
        dst_type = "application/x-NeXus"
        data_paths = conf.data_paths.toPath()

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

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

    if dst_type == "text/num-info":
        # Since we have a pre-calculated normalization dataset, set the flag
        # and return the SOM now
        conf.pre_norm = True
        # Make the labels and units compatible with a NeXus file based SOM
        dp_som0.setAxisLabel(0, "wavelength")
        dp_som0.setAxisUnits(0, "Angstroms")
        dp_som0.setYUnits("Counts/A")
        return dp_som0
    else:
        if dataset_type == "normalization":
            # Since we have a NeXus file, we need to continue
            conf.pre_norm = False

    # Cut the spectra if necessary
    dp_somA = dr_lib.cut_spectra(dp_som0, conf.tof_cut_min, conf.tof_cut_max)

    del dp_som0

    dp_som1 = dr_lib.fix_bin_contents(dp_somA)

    del dp_somA

    if conf.inst_geom is not None:
        i_geom_dst.setGeometry(conf.data_paths.toPath(), dp_som1)

    if conf.no_mon_norm:
        dm_som1 = None
    else:
        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_som0 = 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 ")

        dm_som1 = dr_lib.fix_bin_contents(dm_som0)

        del dm_som0

        if conf.inst_geom is not None:
            i_geom_dst.setGeometry(conf.mon_path.toPath(), dm_som1)

    if bkg_som is not None:
        bkg_pcharge = bkg_som.attr_list["background-proton_charge"].getValue()
        data_pcharge = dp_som1.attr_list[dataset_type +
                                         "-proton_charge"].getValue()

        ratio = data_pcharge / bkg_pcharge

        bkg_som1 = common_lib.mult_ncerr(bkg_som, (ratio, 0.0))

        del bkg_som

        dp_som2 = dr_lib.subtract_bkg_from_data(dp_som1,
                                                bkg_som1,
                                                verbose=conf.verbose,
                                                timer=t,
                                                dataset1=dataset_type,
                                                dataset2="background")

    else:
        dp_som2 = dp_som1

    del dp_som1

    # Step 2: Dead Time Correction
    # No dead time correction is being applied to the data yet

    # Step 3: Time-independent background determination
    if conf.verbose and conf.tib_tofs is not None:
        print "Determining time-independent background from data"

    if t is not None and conf.tib_tofs is not None:
        t.getTime(False)

    B = dr_lib.determine_time_indep_bkg(dp_som2, conf.tib_tofs)

    if t is not None and B is not None:
        t.getTime(msg="After determining time-independent background ")

    if conf.dump_tib and B is not None:
        file_comment = "TOFs: %s" % conf.tib_tofs

        hlr_utils.write_file(conf.output, "text/num-info", B,
                             output_ext="tib",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="time-independent background "\
                             +"information",
                             tag="Average",
                             units="counts",
                             comments=[file_comment])

    # Step 4: Subtract time-independent background
    if conf.verbose and B is not None:
        print "Subtracting time-independent background from data"

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

    if B is not None:
        dp_som3 = common_lib.sub_ncerr(dp_som2, B)
    else:
        dp_som3 = dp_som2

    if B is not None and t is not None:
        t.getTime(msg="After subtracting time-independent background ")

    del dp_som2, B

    # Step 5: Subtract time-independent background constant
    if conf.verbose and tib_const is not None:
        print "Subtracting time-independent background constant from data"

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

    if tib_const is not None:
        dp_som4 = common_lib.sub_ncerr(dp_som3, tib_const)
    else:
        dp_som4 = dp_som3

    if t is not None and tib_const is not None:
        t.getTime(msg="After subtracting time-independent background "\
                  +"constant ")

    del dp_som3

    # Provide override capability for final wavelength, time-zero slope and
    # time-zero offset

    if conf.wavelength_final is not None:
        dp_som4.attr_list["Wavelength_final"] = \
                                     conf.wavelength_final.toValErrTuple()

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

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

    # Step 6: Convert TOF to wavelength for data and monitor
    if conf.verbose:
        print "Converting TOF to wavelength"

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

    # Convert monitor
    if dm_som1 is not None:
        dm_som2 = common_lib.tof_to_wavelength_lin_time_zero(
            dm_som1, units="microsecond")
    else:
        dm_som2 = None

    # Convert detector pixels
    dp_som5 = common_lib.tof_to_initial_wavelength_igs_lin_time_zero(
        dp_som4, units="microsecond", run_filter=conf.filter)

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

    if conf.dump_wave:
        hlr_utils.write_file(conf.output,
                             "text/Spec",
                             dp_som5,
                             output_ext="pxl",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="pixel wavelength information")
    if conf.dump_mon_wave and dm_som2 is not None:
        hlr_utils.write_file(conf.output,
                             "text/Spec",
                             dm_som2,
                             output_ext="mxl",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="monitor wavelength information")

    del dp_som4, dm_som1

    # Step 7: Efficiency correct monitor
    if conf.verbose and dm_som2 is not None and not conf.no_mon_effc:
        print "Efficiency correct monitor data"

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

    if not conf.no_mon_effc:
        dm_som3 = dr_lib.feff_correct_mon(dm_som2)
    else:
        dm_som3 = dm_som2

    if t is not None and dm_som2 is not None and not conf.no_mon_effc:
        t.getTime(msg="After efficiency correcting monitor ")

    if conf.dump_mon_effc and not conf.no_mon_effc and dm_som3 is not None:
        hlr_utils.write_file(conf.output, "text/Spec", dm_som3,
                             output_ext="mel",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="monitor wavelength information "\
                             +"(efficiency)")

    del dm_som2

    # Step 8: Rebin monitor axis onto detector pixel axis
    if conf.verbose and dm_som3 is not None:
        print "Rebin monitor axis to detector pixel axis"

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

    dm_som4 = dr_lib.rebin_monitor(dm_som3, dp_som5)

    if t is not None and dm_som4 is not None:
        t.getTime(msg="After rebinning monitor ")

    del dm_som3

    if conf.dump_mon_rebin and dm_som4 is not None:
        hlr_utils.write_file(conf.output, "text/Spec", dm_som4,
                             output_ext="mrl",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message="monitor wavelength information "\
                             +"(rebinned)")

    # The lambda-dependent background is only done on sample data (aka data)
    # for the BSS instrument at the SNS
    if conf.inst == "BSS" and conf.ldb_const is not None and \
           dataset_type == "data":
        # Step 9: Convert chopper center wavelength to TOF center
        if conf.verbose:
            print "Converting chopper center wavelength to TOF"

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

        tof_center = dr_lib.convert_single_to_list(\
            "initial_wavelength_igs_lin_time_zero_to_tof",
            conf.chopper_lambda_cent.toValErrTuple(), dp_som5)

        # Step 10: Calculate beginning and end of detector TOF spectrum
        if conf.verbose:
            print "Calculating beginning and ending TOF ranges"

        half_inv_chop_freq = 0.5 / conf.chopper_freq.toValErrTuple()[0]
        # Above is in seconds, need microseconds
        half_inv_chop_freq *= 1.0e6

        tof_begin = common_lib.sub_ncerr(tof_center, (half_inv_chop_freq, 0.0))
        tof_end = common_lib.add_ncerr(tof_center, (half_inv_chop_freq, 0.0))

        # Step 11: Convert TOF_begin and TOF_end to wavelength
        if conf.verbose:
            print "Converting TOF_begin and TOF_end to wavelength"

        # Check for time-zero slope information
        try:
            tz_slope = conf.time_zero_slope.toValErrTuple()
        except AttributeError:
            tz_slope = (0.0, 0.0)

        # Check for time-zero offset information
        try:
            tz_offset = conf.time_zero_offset.toValErrTuple()
        except AttributeError:
            tz_offset = (0.0, 0.0)

        l_begin = common_lib.tof_to_initial_wavelength_igs_lin_time_zero(\
            tof_begin, time_zero_slope=tz_slope, time_zero_offset=tz_offset,
            iobj=dp_som5, run_filter=False)
        l_end = common_lib.tof_to_initial_wavelength_igs_lin_time_zero(\
            tof_end, time_zero_slope=tz_slope, time_zero_offset=tz_offset,
            iobj=dp_som5, run_filter=False)

        # Step 12: tof-least-bkg to lambda-least-bkg
        if conf.verbose:
            print "Converting TOF least background to wavelength"

        lambda_least_bkg = dr_lib.convert_single_to_list(\
            "tof_to_initial_wavelength_igs_lin_time_zero",
            conf.tof_least_bkg.toValErrTuple(), dp_som5)

        if t is not None:
            t.getTime(msg="After converting boundary positions ")

        # Step 13: Create lambda-dependent background spectrum
        if conf.verbose:
            print "Creating lambda-dependent background spectra"

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

        ldb_som = dr_lib.shift_spectrum(dm_som4, lambda_least_bkg, l_begin,
                                        l_end, conf.ldb_const.getValue())

        if t is not None:
            t.getTime(msg="After creating lambda-dependent background "\
                      +"spectra ")

        # Step 14: Subtract lambda-dependent background from sample data
        if conf.verbose:
            print "Subtracting lambda-dependent background from data"

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

        dp_som6 = common_lib.sub_ncerr(dp_som5, ldb_som)

        if t is not None:
            t.getTime(msg="After subtracting lambda-dependent background "\
                      +"from data ")
    else:
        dp_som6 = dp_som5

    del dp_som5

    # Step 15: Normalize data by monitor
    if conf.verbose and dm_som4 is not None:
        print "Normalizing data by monitor"

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

    if dm_som4 is not None:
        dp_som7 = common_lib.div_ncerr(dp_som6, dm_som4)

        if t is not None:
            t.getTime(msg="After normalizing data by monitor ")
    else:
        dp_som7 = dp_som6

    if conf.dump_wave_mnorm:
        dp_som7_1 = dr_lib.sum_all_spectra(dp_som7,\
                                   rebin_axis=conf.lambda_bins.toNessiList())

        write_message = "combined pixel wavelength information"
        if dm_som4 is not None:
            write_message += " (monitor normalized)"

        hlr_utils.write_file(conf.output,
                             "text/Spec",
                             dp_som7_1,
                             output_ext="pml",
                             extra_tag=dataset_type,
                             verbose=conf.verbose,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             message=write_message)
        del dp_som7_1

    del dm_som4, dp_som6

    return dp_som7
Example #16
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

    only_background = False
    data_type = "transmission"
        
    # Perform Steps 1,6-7 or 1,3,5-7 on sample data
    d_som1 = dr_lib.process_sas_data(config.data, config, timer=tim,
                                     inst_geom_dst=inst_geom_dst,
                                     dataset_type=data_type,
                                     transmission=True,
                                     get_background=only_background)

    # Perform Steps 1,6-7 on background data
    if config.back is not None:
        b_som1 = dr_lib.process_sas_data(config.back, config, timer=tim,
                                         inst_geom_dst=inst_geom_dst,
                                         dataset_type="trans_bkg",
                                         transmission=True)
    else:
        b_som1 = None

    # Put the datasets on the same axis
    d_som2 = dr_lib.sum_by_rebin_frac(d_som1, config.lambda_bins.toNessiList())
    del d_som1

    if b_som1 is not None:
        b_som2 = dr_lib.sum_by_rebin_frac(b_som1,
                                          config.lambda_bins.toNessiList())
    else:
        b_som2 = None
        
    del b_som1    
    
    # Divide the data spectrum by the background spectrum
    if b_som2 is not None:
        d_som3 = common_lib.div_ncerr(d_som2, b_som2)
    else:
        d_som3 = d_som2

    del d_som2, b_som2

    # Reset y units to dimensionless for the tranmission due to ratio
    if config.back is not None:
        d_som3.setYLabel("Ratio")
        d_som3.setYUnits("")
        write_message = "transmission spectrum"
    else:
        write_message = "spectrum for background estimation"

    # Write out the transmission spectrum
    hlr_utils.write_file(config.output, "text/Spec", d_som3,
                         verbose=config.verbose,
                         replace_path=False,
                         replace_ext=False,
                         message=write_message)

    d_som3.attr_list["config"] = config

    hlr_utils.write_file(config.output, "text/rmd", d_som3,
                         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")    
Example #17
0
def calibrate_dgs_data(datalist, conf, dkcur, **kwargs):
    """
    This function combines Steps 3 through 6 in Section 2.1.1 of the data
    reduction process for Direct Geometry Spectrometers 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 and
    processes the data accordingly.
    
    @param datalist: A list containing 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 dkcur: The object containing the TOF dark current data.
    @type dkcur: C{SOM.SOM}
    
    @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 tib_const: A time-independent background constant to subtract
                        from every pixel.
    @type tib_const: L{hlr_utils.DrParameter}
    
    @keyword dataset_type: The practical name of the dataset being processed.
                           The default value is I{data}.
    @type dataset_type: C{string}

    @keyword cwp: A list of chopper phase corrections in units of microseconds.
    @type cwp: C{list} of C{float}s
    
    @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 common_lib
    import dr_lib
    import hlr_utils

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

    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"

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

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

    dataset_cwp = kwargs.get("cwp")

    # Open the appropriate datafiles
    if conf.verbose:
        print "Reading %s file" % dataset_type

    data_paths = conf.data_paths.toPath()
    if conf.no_mon_norm:
        mon_paths = None
    else:
        mon_paths = conf.usmon_path.toPath()

    # Check for mask file since normalization drive doesn't understand option
    try:
        mask_file = conf.mask_file
    except AttributeError:
        mask_file = None

    if t is not None:
        oldtime = t.getOldTime()

    (dp_som0, dm_som0) = dr_lib.add_files_dm(datalist,
                                             Data_Paths=data_paths,
                                             Mon_Paths=mon_paths,
                                             SO_Axis=conf.so_axis,
                                             Signal_ROI=conf.roi_file,
                                             Signal_MASK=mask_file,
                                             dataset_type=dataset_type,
                                             dataset_cwp=dataset_cwp,
                                             Verbose=conf.verbose,
                                             Timer=t)

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

    # Cut the spectra if necessary
    dp_somA = dr_lib.cut_spectra(dp_som0, conf.tof_cut_min, conf.tof_cut_max)

    del dp_som0

    dp_somB = dr_lib.fix_bin_contents(dp_somA)

    del dp_somA

    if dp_somB.attr_list.instrument.get_name() != "CNCS":

        if conf.verbose:
            print "Cutting spectrum at minimum TOF"

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

        # Calculate minimum TOF for physical neutrons
        if conf.initial_energy is not None:
            initial_wavelength = common_lib.energy_to_wavelength(\
            conf.initial_energy.toValErrTuple())
            initial_velocity = common_lib.wavelength_to_velocity(\
            initial_wavelength)
        else:
            # This should actually calculate it, but don't have a way right now
            pass

        if conf.time_zero_offset is not None:
            time_zero_offset = conf.time_zero_offset.toValErrTuple()
        else:
            # This should actually calculate it, but don't have a way right now
            time_zero_offset = (0.0, 0.0)

        ss_length = dp_somB.attr_list.instrument.get_primary()

        tof_min = (ss_length[0] / initial_velocity[0]) + time_zero_offset[0]

        # Cut all spectra a the minimum TOF
        dp_som1 = dr_lib.cut_spectra(dp_somB, tof_min, None)

        if t is not None:
            t.getTime(msg="After cutting spectrum at minimum TOF ")
    else:
        dp_som1 = dp_somB

    del dp_somB

    if dm_som0 is not None:
        dm_som1 = dr_lib.fix_bin_contents(dm_som0)
    else:
        dm_som1 = dm_som0

    del dm_som0

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

    if conf.inst_geom is not None and dm_som1 is not None:
        i_geom_dst.setGeometry(mon_paths, dm_som1)

    # Step 3: Integrate the upstream monitor
    if dm_som1 is not None:
        if conf.verbose:
            print "Integrating upstream monitor spectrum"

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

        if conf.mon_int_range is None:
            start_val = float("inf")
            end_val = float("inf")
        else:
            start_val = conf.mon_int_range[0]
            end_val = conf.mon_int_range[1]

        dm_som2 = dr_lib.integrate_spectra(dm_som1,
                                           start=start_val,
                                           end=end_val,
                                           width=True)
        if t is not None:
            t.getTime(msg="After integrating upstream monitor spectrum ")
    else:
        dm_som2 = dm_som1

    del dm_som1

    tib_norm_const = None

    # Step 4: Divide data set by summed monitor spectrum
    if dm_som2 is not None:
        if conf.verbose:
            print "Normalizing %s by monitor sum" % dataset_type

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

        dp_som2 = common_lib.div_ncerr(dp_som1, dm_som2, length_one_som=True)

        tib_norm_const = dm_som2[0].y

        if t is not None:
            t.getTime(msg="After normalizing %s by monitor sum" % dataset_type)

    elif conf.pc_norm:
        if conf.verbose:
            print "Normalizing %s by proton charge" % dataset_type

        pc_tag = dataset_type + "-proton_charge"
        pc = dp_som1.attr_list[pc_tag]

        # Scale the proton charge and then set the scale PC back to attributes
        if conf.scale_pc is not None:
            if conf.verbose:
                print "Scaling %s proton charge" % dataset_type

            pc = hlr_utils.scale_proton_charge(pc, conf.scale_pc)
            dp_som1.attr_list[pc_tag] = pc

        tib_norm_const = pc.getValue()

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

        dp_som2 = common_lib.div_ncerr(dp_som1, (pc.getValue(), 0.0))

        if t is not None:
            t.getTime(msg="After normalizing %s by proton charge" \
                      % dataset_type)

    else:
        dp_som2 = dp_som1

    del dp_som1, dm_som2

    # Step 5: Scale dark current by data set measurement time
    if dkcur is not None:
        if conf.verbose:
            print "Scaling dark current by %s acquisition time" % dataset_type

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

        dstime_tag = dataset_type + "-duration"
        dstime = dp_som2.attr_list[dstime_tag]

        dkcur1 = common_lib.div_ncerr(dkcur, (dstime.getValue(), 0.0))

        if t is not None:
            t.getTime(msg="After scaling dark current by %s acquisition time" \
                      % dataset_type)
    else:
        dkcur1 = dkcur

    del dkcur

    # Step 6: Subtract scaled dark current from data set
    if dkcur1 is not None:
        if conf.verbose:
            print "Subtracting %s by scaled dark current" % dataset_type

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

        dp_som3 = common_lib.sub_ncerr(dp_som2, dkcur1)

        if t is not None:
            t.getTime(msg="After subtracting %s by scaled dark current" \
                      % dataset_type)
    elif tib_const is not None and dkcur1 is None:
        if conf.verbose:
            print "Subtracting TIB constant from %s" % dataset_type

        # Normalize the TIB constant by dividing by the current normalization
        # the duration (if necessary) and the conversion from seconds to
        # microseconds
        tib_c = tib_const.toValErrTuple()

        conv_sec_to_usec = 1.0e-6

        if tib_norm_const is None:
            tib_norm_const = 1
            duration = 1
        else:
            duration_tag = dataset_type + "-duration"
            duration = dp_som2.attr_list[duration_tag].getValue()

        norm_const = (duration * conv_sec_to_usec) / tib_norm_const

        tib_val = tib_c[0] * norm_const
        tib_err2 = tib_c[1] * (norm_const * norm_const)

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

        dp_som3 = common_lib.sub_ncerr(dp_som2, (tib_val, tib_err2))

        if t is not None:
            t.getTime(msg="After subtracting TIB constant from %s" \
                      % dataset_type)
    elif conf.tib_range is not None and dkcur1 is None:
        if conf.verbose:
            print "Determining TIB constant from %s" % dataset_type

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

        TIB = dr_lib.determine_time_indep_bkg(dp_som2,
                                              conf.tib_range,
                                              is_range=True)

        if t is not None:
            t.getTime(msg="After determining TIB constant from %s" \
                      % dataset_type)

        if conf.dump_tib:
            file_comment = "TIB TOF Range: [%d, %d]" % (conf.tib_range[0],
                                                        conf.tib_range[1])

            hlr_utils.write_file(conf.output, "text/num-info", TIB,
                                 output_ext="tib",
                                 extra_tag=dataset_type,
                                 verbose=conf.verbose,
                                 data_ext=conf.ext_replacement,
                                 path_replacement=conf.path_replacement,
                                 message="time-independent background "\
                                 +"information",
                                 tag="Average TIB",
                                 units="counts/usec",
                                 comments=[file_comment])

        if conf.verbose:
            print "Subtracting TIB constant from %s" % dataset_type

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

        dp_som3 = common_lib.sub_ncerr(dp_som2, TIB)

        if t is not None:
            t.getTime(msg="After subtracting TIB constant from %s" \
                      % dataset_type)

        del TIB
    else:
        dp_som3 = dp_som2

    del dp_som2, dkcur1

    if conf.dump_ctof_comb:
        dp_som3_1 = dr_lib.sum_all_spectra(dp_som3)
        hlr_utils.write_file(conf.output,
                             "text/Spec",
                             dp_som3_1,
                             output_ext="ctof",
                             extra_tag=dataset_type,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             verbose=conf.verbose,
                             message="combined calibrated TOF information")

        del dp_som3_1

    return dp_som3
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 #19
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())
Example #21
0
def process_dgs_data(obj, conf, bcan, ecan, tcoeff, **kwargs):
    """
    This function combines Steps 7 through 16 in Section 2.1.1 of the data
    reduction process for Direct Geometry Spectrometers as specified by the
    document at 
    U{http://neutrons.ornl.gov/asg/projects/SCL/reqspec/DR_Lib_RS.doc}. The
    function takes a calibrated dataset, a L{hlr_utils.Configure} object and
    processes the data accordingly.

    @param obj: A calibrated dataset object.
    @type obj: C{SOM.SOM}

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

    @param bcan: The object containing the black can data.
    @type bcan: C{SOM.SOM}

    @param ecan: The object containing the empty can data.
    @type ecan: C{SOM.SOM}

    @param tcoeff: The transmission coefficient appropriate to the given data
                   set.
    @type tcoeff: C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword dataset_type: The practical name of the dataset being processed.
                           The default value is I{data}.
    @type dataset_type: C{string}

    @keyword cwp_used: A flag signalling the use of the chopper phase
                       corrections.
    @type cwp_used: C{bool}

    @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 array_manip
    import common_lib
    import dr_lib
    import hlr_utils

    # Check keywords
    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"

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

    cwp_used = kwargs.get("cwp_used", False)

    if conf.verbose:
        print "Processing %s information" % dataset_type

    # Step 7: Create black can background contribution
    if bcan is not None:
        if conf.verbose:
            print "Creating black can background contribution for %s" \
                  % dataset_type

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

        bccoeff = array_manip.sub_ncerr(1.0, 0.0, tcoeff[0], tcoeff[1])
        bcan1 = common_lib.mult_ncerr(bcan, bccoeff)

        if t is not None:
            t.getTime(msg="After creating black can background contribution ")

        del bcan
    else:
        bcan1 = None

    # Step 8: Create empty can background contribution
    if ecan is not None:
        if conf.verbose:
            print "Creating empty can background contribution for %s" \
                  % dataset_type

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

        ecan1 = common_lib.mult_ncerr(ecan, tcoeff)

        if t is not None:
            t.getTime(msg="After creating empty can background contribution ")

        del ecan
    else:
        ecan1 = None

    # Step 9: Create background spectra
    if bcan1 is not None or ecan1 is not None and conf.verbose:
        print "Creating background spectra for %s" % dataset_type

    if bcan1 is not None and ecan1 is not None:
        if cwp_used:
            if conf.verbose:
                print "Rebinning empty can to black can axis."

            ecan2 = common_lib.rebin_axis_1D_frac(ecan1, bcan1[0].axis[0].val)
        else:
            ecan2 = ecan1

        del ecan1

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

        b_som = common_lib.add_ncerr(bcan1, ecan2)

        if t is not None:
            t.getTime(msg="After creating background spectra ")
    elif bcan1 is not None and ecan1 is None:
        b_som = bcan1
    elif bcan1 is None and ecan1 is not None:
        b_som = ecan1
    else:
        b_som = None

    del bcan1, ecan1

    if cwp_used:
        if conf.verbose:
            print "Rebinning background spectra to %s" % dataset_type

        b_som1 = common_lib.rebin_axis_1D_frac(b_som, obj[0].axis[0].val)
    else:
        b_som1 = b_som

    del b_som

    if conf.dump_ctof_comb and b_som1 is not None:
        b_som_1 = dr_lib.sum_all_spectra(b_som1)
        hlr_utils.write_file(conf.output,
                             "text/Spec",
                             b_som_1,
                             output_ext="ctof",
                             extra_tag="background",
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             verbose=conf.verbose,
                             message="combined background TOF information")
        del b_som_1

    # Step 10: Subtract background from data
    obj1 = dr_lib.subtract_bkg_from_data(obj,
                                         b_som1,
                                         verbose=conf.verbose,
                                         timer=t,
                                         dataset1=dataset_type,
                                         dataset2="background")

    del obj, b_som1

    # Step 11: Calculate initial velocity
    if conf.verbose:
        print "Calculating initial velocity"

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

    if conf.initial_energy is not None:
        initial_wavelength = common_lib.energy_to_wavelength(\
            conf.initial_energy.toValErrTuple())
        initial_velocity = common_lib.wavelength_to_velocity(\
            initial_wavelength)
    else:
        # This should actually calculate it, but don't have a way right now
        pass

    if t is not None:
        t.getTime(msg="After calculating initial velocity ")

    # Step 12: Calculate the time-zero offset
    if conf.time_zero_offset is not None:
        time_zero_offset = conf.time_zero_offset.toValErrTuple()
    else:
        # This should actually calculate it, but don't have a way right now
        time_zero_offset = (0.0, 0.0)

    # Step 13: Convert time-of-flight to final velocity
    if conf.verbose:
        print "Converting TOF to final velocity DGS"

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

    obj2 = common_lib.tof_to_final_velocity_dgs(obj1,
                                                initial_velocity,
                                                time_zero_offset,
                                                units="microsecond")

    if t is not None:
        t.getTime(msg="After calculating TOF to final velocity DGS ")

    del obj1

    # Step 14: Convert final velocity to final wavelength
    if conf.verbose:
        print "Converting final velocity DGS to final wavelength"

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

    obj3 = common_lib.velocity_to_wavelength(obj2)

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

    del obj2

    if conf.dump_wave_comb:
        obj3_1 = dr_lib.sum_all_spectra(
            obj3, rebin_axis=conf.lambda_bins.toNessiList())
        hlr_utils.write_file(conf.output,
                             "text/Spec",
                             obj3_1,
                             output_ext="fwv",
                             extra_tag=dataset_type,
                             data_ext=conf.ext_replacement,
                             path_replacement=conf.path_replacement,
                             verbose=conf.verbose,
                             message="combined final wavelength information")

        del obj3_1

    # Step 15: Create the detector efficiency
    if conf.det_eff is not None:
        if conf.verbose:
            print "Creating detector efficiency spectra"

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

        det_eff = dr_lib.create_det_eff(obj3)

        if t is not None:
            t.getTime(msg="After creating detector efficiency spectra ")
    else:
        det_eff = None

    # Step 16: Divide the detector pixel spectra by the detector efficiency
    if det_eff is not None:
        if conf.verbose:
            print "Correcting %s for detector efficiency" % dataset_type

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

        obj4 = common_lib.div_ncerr(obj3, det_eff)

        if t is not None:
            t.getTime(msg="After correcting %s for detector efficiency" \
                      % dataset_type)
    else:
        obj4 = obj3

    del obj3, det_eff

    return obj4
Example #22
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

    config.so_axis = "time_of_flight"

    try:
        if type(config.mask_file) == type([]):
            if len(config.mask_file) > 1:
                if config.verbose:
                    print "Creating combined mask file"

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

                config.mask_file = hlr_utils.merge_roi_files(\
                        config.mask_file,
                        config)

                if tim is not None:
                    tim.getTime(msg="After creating combined mask file")
            else:
                config.mask_file = config.mask_file[0]
        else:
            # Do nothing since it's already a string
            pass
    except TypeError:
        # No mask files provided, do nothing
        pass

    # Steps 1-3: Produce a scaled summed dark current dataset
    dc_som = dr_lib.scaled_summed_data(config.dkcur,
                                       config,
                                       dataset_type="dark_current",
                                       timer=tim)

    # Perform Steps 3-6 on black can data
    if config.bcan is not None:
        b_som1 = dr_lib.calibrate_dgs_data(config.bcan,
                                           config,
                                           dc_som,
                                           dataset_type="black_can",
                                           inst_geom_dst=inst_geom_dst,
                                           tib_const=config.tib_const,
                                           cwp=config.cwp_bcan,
                                           timer=tim)
    else:
        b_som1 = None

    # Perform Steps 3-6 on empty can data
    if config.ecan is not None:
        e_som1 = dr_lib.calibrate_dgs_data(config.ecan,
                                           config,
                                           dc_som,
                                           dataset_type="empty_can",
                                           inst_geom_dst=inst_geom_dst,
                                           tib_const=config.tib_const,
                                           cwp=config.cwp_ecan,
                                           timer=tim)
    else:
        e_som1 = None

    # Perform Steps 3-6 on sample data
    d_som1 = dr_lib.calibrate_dgs_data(config.data,
                                       config,
                                       dc_som,
                                       inst_geom_dst=inst_geom_dst,
                                       tib_const=config.tib_const,
                                       cwp=config.cwp_data,
                                       timer=tim)

    # Perform Steps 7-16 on sample data
    if config.data_trans_coeff is None:
        data_trans_coeff = None
    else:
        data_trans_coeff = config.data_trans_coeff.toValErrTuple()

    # Determine if we need to rebin the empty or black can data
    if config.ecan is not None and e_som1 is not None:
        ecan_cwp = True
    else:
        ecan_cwp = False

    if config.bcan is not None and b_som1 is not None:
        bcan_cwp = True
    else:
        bcan_cwp = False

    cwp_used = ecan_cwp or bcan_cwp

    d_som2 = dr_lib.process_dgs_data(d_som1,
                                     config,
                                     b_som1,
                                     e_som1,
                                     data_trans_coeff,
                                     cwp_used=cwp_used,
                                     timer=tim)

    del d_som1

    del b_som1, e_som1

    # Step 18: Normalize sample data by integrated values
    if config.norm is not None:
        if config.verbose:
            print "Reading normalization information"

        norm_int = dr_lib.add_files(config.norm,
                                    Signal_ROI=config.roi_file,
                                    Signal_MASK=config.mask_file,
                                    dataset_type="normalization",
                                    dst_type="text/num-info",
                                    Verbose=config.verbose,
                                    Timer=tim)

        # Make the labels and units compatible with a NeXus file based SOM
        norm_int.setAllAxisLabels(["wavelength"])
        norm_int.setAllAxisUnits(["Angstroms"])
        norm_int.setYLabel("Intensity")
        norm_int.setYUnits("Counts/Angstroms")

        if config.verbose:
            print "Normalizing data by normalization data"

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

        d_som3 = common_lib.div_ncerr(d_som2, norm_int)

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

        del norm_int
    else:
        d_som3 = d_som2

    del d_som2

    # Step 19: Calculate the initial energy
    if config.initial_energy is not None:
        d_som3.attr_list["Initial_Energy"] = config.initial_energy

    # Steps 20-21: Calculate the energy transfer
    if config.verbose:
        print "Calculating energy transfer"

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

    d_som4 = dr_lib.energy_transfer(d_som3,
                                    "DGS",
                                    "Initial_Energy",
                                    lojac=True,
                                    scale=config.lambda_ratio)

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

    del d_som3

    # Step 22: Rebin energy transfer spectra
    if config.verbose:
        print "Rebinning to final energy transfer axis"

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

    d_som5 = common_lib.rebin_axis_1D_frac(d_som4, config.E_bins.toNessiList())

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

    del d_som4

    if config.dump_et_comb:
        d_som5_1 = dr_lib.sum_all_spectra(d_som5)
        hlr_utils.write_file(config.output,
                             "text/Spec",
                             d_som5_1,
                             output_ext="et",
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="combined energy transfer information")

        del d_som5_1

    # Get the corner geometry information
    if config.verbose:
        print "Reading in corner geometry information"

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

    corner_angles = hlr_utils.get_corner_geometry(config.corner_geom)

    if tim is not None:
        tim.getTime(msg="After reading in corner geometry information ")

    if config.make_spe:
        d_som5.attr_list["corner_geom"] = corner_angles

        hlr_utils.write_file(config.output,
                             "text/PHX",
                             d_som5,
                             output_ext="phx",
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="PHX information")

        hlr_utils.write_file(config.output,
                             "text/PAR",
                             d_som5,
                             output_ext="par",
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="PAR information")

        hlr_utils.write_file(config.output,
                             "text/SPE",
                             d_som5,
                             output_ext="spe",
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="SPE information")

    # Steps 23-34: Create S(Q, E) distribution
    if config.verbose:
        print "Creating S(Q, E)"

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

    d_som5_2 = dr_lib.create_E_vs_Q_dgs(d_som5,
                                        config.initial_energy.toValErrTuple(),
                                        config.Q_bins.toNessiList(),
                                        corner_angles=corner_angles,
                                        split=config.split,
                                        configure=config,
                                        timer=tim)

    # Writing 2D DAVE file
    if not config.split:
        hlr_utils.write_file(config.output,
                             "text/Dave2d",
                             d_som5_2,
                             output_ext="sqe",
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             message="S(Q,E)")

        hlr_utils.write_file(config.output,
                             "application/x-RedNxs",
                             d_som5_2,
                             output_ext="nxs",
                             data_ext=config.ext_replacement,
                             path_replacement=config.path_replacement,
                             verbose=config.verbose,
                             extra_tag="sqe",
                             getsom_kwargs={"entry_name": "sqe"},
                             message="NeXus S(Q,E)")

    if tim is not None:
        tim.getTime(msg="After calculating S(Q,E) spectrum ")

    del d_som5_2

    if config.qmesh:
        # Steps 23-27,35-36: Create S(Qvec, E) distribution
        if config.verbose:
            print "Creating S(Qvec, E)"

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

        dr_lib.create_Qvec_vs_E_dgs(d_som5,
                                    config.initial_energy.toValErrTuple(),
                                    config,
                                    corner_angles=corner_angles,
                                    make_fixed=config.fixed,
                                    output=config.output,
                                    timer=tim)

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

    # Write out RMD file
    d_som5.attr_list["config"] = config

    hlr_utils.write_file(config.output,
                         "text/rmd",
                         d_som5,
                         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")
Example #23
0
def process_dgs_data(obj, conf, bcan, ecan, tcoeff, **kwargs):
    """
    This function combines Steps 7 through 16 in Section 2.1.1 of the data
    reduction process for Direct Geometry Spectrometers as specified by the
    document at 
    U{http://neutrons.ornl.gov/asg/projects/SCL/reqspec/DR_Lib_RS.doc}. The
    function takes a calibrated dataset, a L{hlr_utils.Configure} object and
    processes the data accordingly.

    @param obj: A calibrated dataset object.
    @type obj: C{SOM.SOM}

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

    @param bcan: The object containing the black can data.
    @type bcan: C{SOM.SOM}

    @param ecan: The object containing the empty can data.
    @type ecan: C{SOM.SOM}

    @param tcoeff: The transmission coefficient appropriate to the given data
                   set.
    @type tcoeff: C{tuple}
    
    @param kwargs: A list of keyword arguments that the function accepts:

    @keyword dataset_type: The practical name of the dataset being processed.
                           The default value is I{data}.
    @type dataset_type: C{string}

    @keyword cwp_used: A flag signalling the use of the chopper phase
                       corrections.
    @type cwp_used: C{bool}

    @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 array_manip
    import common_lib
    import dr_lib
    import hlr_utils

    # Check keywords
    try:
        dataset_type = kwargs["dataset_type"]
    except KeyError:
        dataset_type = "data"

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

    cwp_used = kwargs.get("cwp_used", False)
        
    if conf.verbose:
        print "Processing %s information" % dataset_type

    # Step 7: Create black can background contribution
    if bcan is not None:
        if conf.verbose:
            print "Creating black can background contribution for %s" \
                  % dataset_type

        if t is not None:
            t.getTime(False)
            
        bccoeff = array_manip.sub_ncerr(1.0, 0.0, tcoeff[0], tcoeff[1])
        bcan1 = common_lib.mult_ncerr(bcan, bccoeff)

        if t is not None:
            t.getTime(msg="After creating black can background contribution ")
        
        del bcan
    else:
        bcan1 = None

    # Step 8: Create empty can background contribution
    if ecan is not None:
        if conf.verbose:
            print "Creating empty can background contribution for %s" \
                  % dataset_type

        if t is not None:
            t.getTime(False)
        
        ecan1 = common_lib.mult_ncerr(ecan, tcoeff)

        if t is not None:
            t.getTime(msg="After creating empty can background contribution ")
        
        del ecan
    else:
        ecan1 = None

    # Step 9: Create background spectra
    if bcan1 is not None or ecan1 is not None and conf.verbose:
        print "Creating background spectra for %s" % dataset_type
    
    if bcan1 is not None and ecan1 is not None:
        if cwp_used:
            if conf.verbose:
                print "Rebinning empty can to black can axis."
                
            ecan2 = common_lib.rebin_axis_1D_frac(ecan1, bcan1[0].axis[0].val)
        else:
            ecan2 = ecan1

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

        b_som = common_lib.add_ncerr(bcan1, ecan2)

        if t is not None:
            t.getTime(msg="After creating background spectra ")
    elif bcan1 is not None and ecan1 is None:
        b_som = bcan1
    elif bcan1 is None and ecan1 is not None:
        b_som = ecan1
    else:
        b_som = None

    del bcan1, ecan1

    if cwp_used:
        if conf.verbose:
            print "Rebinning background spectra to %s" % dataset_type

        b_som1 = common_lib.rebin_axis_1D_frac(b_som, obj[0].axis[0].val)
    else:
        b_som1 = b_som

    del b_som

    if conf.dump_ctof_comb and b_som1 is not None:
        b_som_1 = dr_lib.sum_all_spectra(b_som1)
        hlr_utils.write_file(conf.output, "text/Spec", b_som_1,
                             output_ext="ctof",
                             extra_tag="background",
                             data_ext=conf.ext_replacement,    
                             path_replacement=conf.path_replacement,
                             verbose=conf.verbose,
                             message="combined background TOF information")
        del b_som_1
        
    # Step 10: Subtract background from data
    obj1 = dr_lib.subtract_bkg_from_data(obj, b_som1, verbose=conf.verbose,
                                         timer=t,
                                         dataset1=dataset_type,
                                         dataset2="background")

    del obj, b_som1

    # Step 11: Calculate initial velocity
    if conf.verbose:
        print "Calculating initial velocity"

    if t is not None:
        t.getTime(False)
        
    if conf.initial_energy is not None:
        initial_wavelength = common_lib.energy_to_wavelength(\
            conf.initial_energy.toValErrTuple())
        initial_velocity = common_lib.wavelength_to_velocity(\
            initial_wavelength)
    else:
        # This should actually calculate it, but don't have a way right now
        pass

    if t is not None:
        t.getTime(msg="After calculating initial velocity ")

    # Step 12: Calculate the time-zero offset
    if conf.time_zero_offset is not None:
        time_zero_offset = conf.time_zero_offset.toValErrTuple()
    else:
        # This should actually calculate it, but don't have a way right now
        time_zero_offset = (0.0, 0.0)

    # Step 13: Convert time-of-flight to final velocity
    if conf.verbose:
        print "Converting TOF to final velocity DGS"

    if t is not None:
        t.getTime(False)
        
    obj2 = common_lib.tof_to_final_velocity_dgs(obj1, initial_velocity,
                                                time_zero_offset,
                                                units="microsecond")

    if t is not None:
        t.getTime(msg="After calculating TOF to final velocity DGS ")
        
    del obj1
    
    # Step 14: Convert final velocity to final wavelength
    if conf.verbose:
        print "Converting final velocity DGS to final wavelength"

    if t is not None:
        t.getTime(False)
        
    obj3 = common_lib.velocity_to_wavelength(obj2)

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

    del obj2

    if conf.dump_wave_comb:
        obj3_1 = dr_lib.sum_all_spectra(obj3,
                                     rebin_axis=conf.lambda_bins.toNessiList())
        hlr_utils.write_file(conf.output, "text/Spec", obj3_1,
                             output_ext="fwv",
                             extra_tag=dataset_type,
                             data_ext=conf.ext_replacement,    
                             path_replacement=conf.path_replacement,
                             verbose=conf.verbose,
                             message="combined final wavelength information")

        del obj3_1

    # Step 15: Create the detector efficiency
    if conf.det_eff is not None:
        if conf.verbose:
            print "Creating detector efficiency spectra"

        if t is not None:
            t.getTime(False)
            
        det_eff = dr_lib.create_det_eff(obj3)

        if t is not None:
            t.getTime(msg="After creating detector efficiency spectra ")
    else:
        det_eff = None

    # Step 16: Divide the detector pixel spectra by the detector efficiency
    if det_eff is not None:
        if conf.verbose:
            print "Correcting %s for detector efficiency" % dataset_type

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

        obj4 = common_lib.div_ncerr(obj3, det_eff)

        if t is not None:
            t.getTime(msg="After correcting %s for detector efficiency" \
                      % dataset_type)
    else:
        obj4 = obj3

    del obj3, det_eff

    return obj4