def determine_ref_background(obj, no_bkg=False): """ This function takes in a collection of pixels that have been selected as the reflectometer background. The pixels are summed into a single spectrum and then scaled by the total number of pixels present in the selection. @param obj: Object containing reflectometer background information @type obj: C{SOM.SOM} @param no_bkg: (OPTIONAL) Flag which determines if the background will be calculated @type no_bkg: C{boolean} @return: A length object containing a summed background spectrum scaled by the total number of background pixels @rtype: C{SOM.SOM} """ import dr_lib import common_lib import hlr_utils # If user does not desire background subtraction or incoming SOM is None, # return None if no_bkg or obj is None: return None # set up for working through data o_descr = hlr_utils.get_descr(obj) if o_descr != "SOM": raise RuntimeError("Must provide a SOM to the function.") # Go on else: pass # Combine all background spectra into one obj1 = dr_lib.sum_all_spectra(obj) # Determine scaling ratio ratio = (1.0 / float(len(obj)), 0.0) # Scale background spectrum by ratio return common_lib.mult_ncerr(obj1, ratio)
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
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 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
def run(config): """ 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} """ import sys import dr_lib import DST import SOM banks = [("/entry/bank1", 1), ("/entry/bank2", 1)] max_ids = (64, 64) if config.vertical: tag = "v" size = max_ids[1] reps = max_ids[0] / config.pixel_group label = "Integrated pixel" else: tag = "h" size = max_ids[1] / config.pixel_group reps = max_ids[0] / config.sum_tubes label = "Tube Number" try: data_dst = DST.getInstance("application/x-NeXus", config.data) except SystemError: print "ERROR: Failed to data read file %s" % config.data sys.exit(-1) so_axis = "time_of_flight" for path in banks: bank = path[0].split('/')[-1] for i in range(size): tSOM = SOM.SOM() tSO = SOM.SO(construct=True) counter = 1 for j in range(reps): if config.vertical: starting_id = (i, config.pixel_group * j) ending_id = (i + 1, config.pixel_group * (j + 1)) else: if config.sum_tubes == 1: x1 = j x2 = j + 1 else: x1 = j * config.sum_tubes x2 = (j + 1) * config.sum_tubes starting_id = (x1, config.pixel_group * i) ending_id = (x2, config.pixel_group * (i + 1)) d_som1 = data_dst.getSOM(path, so_axis, start_id=starting_id, end_id=ending_id) d_som2 = dr_lib.sum_all_spectra(d_som1) d_som2[0].id = d_som1[0].id d_som1 = None del d_som1 value = dr_lib.integrate_axis(d_som2) if config.verbose: print "Sum", d_som2[0].id, ":", value[0], value[1] tSO.axis[0].val.append(counter) tSO.y.append(value[0]) tSO.var_y.append(value[1]) if counter == 1: tSO.id = d_som2[0].id counter += 1 tSOM.attr_list["filename"] = config.data tSOM.setTitle("TOF Pixel Summation") tSOM.setDataSetType("density") tSOM.setYLabel("Intensity Sum") tSOM.setYUnits("counts") tSOM.setAxisLabel(0, label) tSOM.setAxisUnits(0, "") tSOM.append(tSO) tag1 = str(i + 1) outfile = bank + "_" + tag + "_" + tag1 + ".tof" hlr_utils.write_file(outfile, "text/Spec", tSOM, verbose=config.verbose, message="intensity sum file", replace_ext=False) data_dst.release_resource()
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
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
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_reflp_data(datalist, conf, roi_file, bkg_roi_file=None, no_bkg=False, **kwargs): """ This function combines Steps 1 through 3 in section 2.4.6.1 of the data reduction process for Reduction from TOF to lambda_T as specified by the document at U{http://neutrons.ornl.gov/asg/projects/SCL/reqspec/DR_Lib_RS.doc}. The function takes a list of file names, a L{hlr_utils.Configure} object, region-of-interest (ROI) file for the normalization dataset, a background region-of-interest (ROI) file and an optional flag about background subtractionand processes the data accordingly. @param datalist: The filenames of the data to be processed @type datalist: C{list} of C{string}s @param conf: Object that contains the current setup of the driver @type conf: L{hlr_utils.Configure} @param roi_file: The file containing the list of pixel IDs for the region of interest. This only applies to normalization data. @type roi_file: C{string} @param bkg_roi_file: The file containing the list of pixel IDs for the (possible) background region of interest. @type bkg_roi_file: C{string} @param no_bkg: (OPTIONAL) Flag which determines if the background will be calculated and subtracted. @type no_bkg: C{boolean} @param kwargs: A list of keyword arguments that the function accepts: @keyword inst_geom_dst: File object that contains instrument geometry information. @type inst_geom_dst: C{DST.GeomDST} @keyword timer: Timing object so the function can perform timing estimates. @type timer: C{sns_timer.DiffTime} @return: Object that has undergone all requested processing steps @rtype: C{SOM.SOM} """ import hlr_utils import common_lib import dr_lib # Check keywords try: i_geom_dst = kwargs["inst_geom_dst"] except KeyError: i_geom_dst = None try: t = kwargs["timer"] except KeyError: t = None if roi_file is not None: # Normalization dataset_type = "norm" else: # Sample data dataset_type = "data" so_axis = "time_of_flight" # Step 0: Open data files and select ROI (if necessary) if conf.verbose: print "Reading %s file" % dataset_type if len(conf.norm_data_paths) and dataset_type == "norm": data_path = conf.norm_data_paths.toPath() else: data_path = conf.data_paths.toPath() (d_som1, b_som1) = dr_lib.add_files_bg(datalist, Data_Paths=data_path, SO_Axis=so_axis, dataset_type=dataset_type, Signal_ROI=roi_file, Bkg_ROI=bkg_roi_file, Verbose=conf.verbose, Timer=t) if t is not None: t.getTime(msg="After reading %s " % dataset_type) # Override geometry if necessary if i_geom_dst is not None: i_geom_dst.setGeometry(conf.data_paths.toPath(), d_som1) if dataset_type == "data": # Get TOF bin width conf.delta_TOF = d_som1[0].axis[0].val[1] - d_som1[0].axis[0].val[0] if conf.mon_norm: if conf.verbose: print "Reading in monitor data from %s file" % dataset_type # The [0] is to get the data SOM and ignore the None background SOM dm_som1 = dr_lib.add_files(datalist, Data_Paths=conf.mon_path.toPath(), SO_Axis=so_axis, dataset_type=dataset_type, Verbose=conf.verbose, Timer=t) if t is not None: t.getTime(msg="After reading monitor data ") else: dm_som1 = None # Step 1: Sum all spectra along the low resolution direction # Set sorting for REF_L if conf.verbose: print "Summing over low resolution direction" # Set sorting (y_sort, cent_pixel) = hlr_utils.get_ref_integration_direction(conf.int_dir, conf.inst, d_som1.attr_list.instrument) if t is not None: t.getTime(False) d_som2 = dr_lib.sum_all_spectra(d_som1, y_sort=y_sort, stripe=True, pixel_fix=cent_pixel) if b_som1 is not None: b_som2 = dr_lib.sum_all_spectra(b_som1, y_sort=y_sort, stripe=True, pixel_fix=cent_pixel) del b_som1 else: b_som2 = b_som1 if t is not None: t.getTime(msg="After summing low resolution direction ") del d_som1 # Determine background spectrum if conf.verbose and not no_bkg: print "Determining %s background" % dataset_type if b_som2 is not None: B = dr_lib.calculate_ref_background(b_som2, no_bkg, conf.inst, None, aobj=d_som2) if t is not None: t.getTime(msg="After background determination") # Subtract background spectrum from data spectra if not no_bkg: d_som3 = dr_lib.subtract_bkg_from_data(d_som2, B, verbose=conf.verbose, timer=t, dataset1="data", dataset2="background") else: d_som3 = d_som2 del d_som2 # Zero the spectra if necessary if roi_file is None and (conf.tof_cut_min is not None or \ conf.tof_cut_max is not None): import utils # Find the indicies for the non zero range if conf.tof_cut_min is None: conf.TOF_min = d_som3[0].axis[0].val[0] start_index = 0 else: start_index = utils.bisect_helper(d_som3[0].axis[0].val, conf.tof_cut_min) if conf.tof_cut_max is None: conf.TOF_max = d_som3[0].axis[0].val[-1] end_index = len(d_som3[0].axis[0].val) - 1 else: end_index = utils.bisect_helper(d_som3[0].axis[0].val, conf.tof_cut_max) nz_list = [] for i in xrange(hlr_utils.get_length(d_som3)): nz_list.append((start_index, end_index)) d_som4 = dr_lib.zero_spectra(d_som3, nz_list, use_bin_index=True) else: conf.TOF_min = d_som3[0].axis[0].val[0] conf.TOF_max = d_som3[0].axis[0].val[-1] d_som4 = d_som3 del d_som3 # Step N: Convert TOF to wavelength if conf.verbose: print "Converting TOF to wavelength" if t is not None: t.getTime(False) d_som5 = common_lib.tof_to_wavelength(d_som4, inst_param="total", units="microsecond") if dm_som1 is not None: dm_som2 = common_lib.tof_to_wavelength(dm_som1, units="microsecond") else: dm_som2 = None del dm_som1 if t is not None: t.getTime(msg="After converting TOF to wavelength ") del d_som4 if conf.mon_norm: dm_som3 = dr_lib.rebin_monitor(dm_som2, d_som5, rtype="frac") else: dm_som3 = None del dm_som2 if not conf.mon_norm: # Step 2: Multiply the spectra by the proton charge if conf.verbose: print "Multiply spectra by proton charge" pc_tag = dataset_type + "-proton_charge" proton_charge = d_som5.attr_list[pc_tag] if t is not None: t.getTime(False) d_som6 = common_lib.div_ncerr(d_som5, (proton_charge.getValue(), 0.0)) if t is not None: t.getTime(msg="After scaling by proton charge ") else: if conf.verbose: print "Normalize by monitor spectrum" if t is not None: t.getTime(False) d_som6 = common_lib.div_ncerr(d_som5, dm_som3) if t is not None: t.getTime(msg="After monitor normalization ") del d_som5, dm_som3 if roi_file is None: return d_som6 else: # Step 3: Make one spectrum for normalization dataset # Need to create a final rebinning axis pathlength = d_som6.attr_list.instrument.get_total_path( det_secondary=True) delta_lambda = common_lib.tof_to_wavelength((conf.delta_TOF, 0.0), pathlength=pathlength) lambda_bins = dr_lib.create_axis_from_data(d_som6, width=delta_lambda[0]) return dr_lib.sum_by_rebin_frac(d_som6, lambda_bins.toNessiList())
def run(config, tim=None): """ This method is where the data reduction process gets done. @param config: Object containing the data reduction configuration information. @type config: L{hlr_utils.Configure} @param tim: (OPTIONAL) Object that will allow the method to perform timing evaluations. @type tim: C{sns_time.DiffTime} """ import common_lib import dr_lib import DST if tim is not None: tim.getTime(False) old_time = tim.getOldTime() if config.data is None: raise RuntimeError("Need to pass a data filename to the driver "\ +"script.") # Read in geometry if one is provided if config.inst_geom is not None: if config.verbose: print "Reading in instrument geometry file" inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.inst_geom) else: inst_geom_dst = None # Perform early background subtraction if the hwfix flag is used if config.hwfix: if not config.mc: so_axis = "time_of_flight" else: so_axis = "Time_of_Flight" bkg_som0 = dr_lib.add_files(config.back, Data_Paths=config.data_paths.toPath(), SO_Axis=so_axis, Signal_ROI=config.roi_file, dataset_type="background", Verbose=config.verbose, Timer=tim) bkg_som = dr_lib.fix_bin_contents(bkg_som0) del bkg_som0 else: bkg_som = None # Perform Steps 1-15 on sample data d_som1 = dr_lib.process_igs_data(config.data, config, timer=tim, inst_geom_dst=inst_geom_dst, tib_const=config.tib_data_const, bkg_som=bkg_som) # Perform Steps 1-15 on empty can data if config.ecan is not None: e_som1 = dr_lib.process_igs_data(config.ecan, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="empty_can", tib_const=config.tib_ecan_const, bkg_som=bkg_som) else: e_som1 = None # Perform Steps 1-15 on normalization data if config.norm is not None: n_som1 = dr_lib.process_igs_data(config.norm, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="normalization", tib_const=config.tib_norm_const, bkg_som=bkg_som) else: n_som1 = None # Perform Steps 1-15 on background data if config.back is not None: b_som1 = dr_lib.process_igs_data(config.back, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="background", tib_const=config.tib_back_const, bkg_som=bkg_som) else: b_som1 = None # Perform Step 1-15 on direct scattering background data if config.dsback is not None: ds_som1 = dr_lib.process_igs_data(config.dsback, config, timer=tim, inst_geom_dst=inst_geom_dst, tib_const=config.tib_dsback_const, dataset_type="dsbackground", bkg_som=bkg_som) # Note: time_zero_slope MUST be a tuple if config.time_zero_slope is not None: ds_som1.attr_list["Time_zero_slope"] = \ config.time_zero_slope.toValErrTuple() # Note: time_zero_offset MUST be a tuple if config.time_zero_offset is not None: ds_som1.attr_list["Time_zero_offset"] = \ config.time_zero_offset.toValErrTuple() # Step 16: Linearly interpolate TOF elastic range in direct scattering # background data # First convert TOF elastic range to appropriate pixel initial # wavelengths if config.verbose: print "Determining initial wavelength range for elastic line" if tim is not None: tim.getTime(False) if config.tof_elastic is None: # Units are in microseconds tof_elastic_range = (140300, 141300) else: tof_elastic_range = config.tof_elastic ctof_elastic_low = dr_lib.convert_single_to_list(\ "tof_to_initial_wavelength_igs_lin_time_zero", (tof_elastic_range[0], 0.0), ds_som1) ctof_elastic_high = dr_lib.convert_single_to_list(\ "tof_to_initial_wavelength_igs_lin_time_zero", (tof_elastic_range[1], 0.0), ds_som1) ctof_elastic_range = [(ctof_elastic_low[i][0], ctof_elastic_high[i][0]) for i in xrange(len(ctof_elastic_low))] if tim is not None: tim.getTime(msg="After calculating initial wavelength range for "\ +"elastic line ") del ctof_elastic_low, ctof_elastic_high if config.split: lambda_filter = [(d_som1[i].axis[0].val[0], d_som1[i].axis[0].val[-1]) for i in xrange(len(d_som1))] else: lambda_filter = None # Now interpolate spectra between TOF elastic range (converted to # initial wavelength) if config.verbose: print "Linearly interpolating direct scattering spectra" if tim is not None: tim.getTime(False) ds_som2 = dr_lib.lin_interpolate_spectra(ds_som1, ctof_elastic_range, filter_axis=lambda_filter) if tim is not None: tim.getTime(msg="After linearly interpolating direct scattering "\ +"spectra ") if config.dump_dslin: ds_som2_1 = dr_lib.sum_all_spectra(ds_som2,\ rebin_axis=config.lambda_bins.toNessiList()) hlr_utils.write_file(config.output, "text/Spec", ds_som2_1, output_ext="lin", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="dsbackground linear interpolation") del ds_som2_1 del ds_som1 else: ds_som2 = None if inst_geom_dst is not None: inst_geom_dst.release_resource() # Steps 17-18: Subtract background spectrum from sample spectrum if config.dsback is None: back_som = b_som1 bkg_type = "background" else: back_som = ds_som2 bkg_type = "dsbackground" d_som2 = dr_lib.subtract_bkg_from_data(d_som1, back_som, verbose=config.verbose, timer=tim, dataset1="data", dataset2=bkg_type, scale=config.scale_bs) if config.dsback is not None: del ds_som2 # Step 19: Zero region outside TOF elastic for background for empty can if config.dsback is None: bcs_som = b_som1 cs_som = e_som1 else: if config.verbose and b_som1 is not None: print "Zeroing background spectra" if tim is not None and b_som1 is not None: tim.getTime(False) bcs_som = dr_lib.zero_spectra(b_som1, ctof_elastic_range) if tim is not None and b_som1 is not None: tim.getTime(msg="After zeroing background spectra") if config.verbose and e_som1 is not None: print "Zeroing empty can spectra" if tim is not None and e_som1 is not None: tim.getTime(False) cs_som = dr_lib.zero_spectra(e_som1, ctof_elastic_range) if tim is not None and e_som1 is not None: tim.getTime(msg="After zeroing empty can spectra") del ctof_elastic_range # Steps 20-21: Subtract background spectrum from empty can spectrum e_som2 = dr_lib.subtract_bkg_from_data(cs_som, bcs_som, verbose=config.verbose, timer=tim, dataset1="data-empty_can", dataset2="background", scale=config.scale_bcs) # Steps 22-23: Subtract background spectrum from empty can spectrum for # normalization try: config.pre_norm except AttributeError: config.pre_norm = False if not config.pre_norm: e_som3 = dr_lib.subtract_bkg_from_data(e_som1, b_som1, verbose=config.verbose, timer=tim, dataset1="norm-empty_can", dataset2="background", scale=config.scale_bcn) else: e_som3 = None # Steps 24-25: Subtract background spectrum from normalization spectrum if not config.pre_norm: n_som2 = dr_lib.subtract_bkg_from_data(n_som1, b_som1, verbose=config.verbose, timer=tim, dataset1="normalization", dataset2="background", scale=config.scale_bn) else: n_som2 = n_som1 del b_som1, e_som1, bcs_som, cs_som # Steps 26-27: Subtract empty can spectrum from sample spectrum d_som3 = dr_lib.subtract_bkg_from_data(d_som2, e_som2, verbose=config.verbose, timer=tim, dataset1="data", dataset2="empty_can", scale=config.scale_cs) del d_som2, e_som2 # Steps 28-29: Subtract empty can spectrum from normalization spectrum if not config.pre_norm: n_som3 = dr_lib.subtract_bkg_from_data(n_som2, e_som3, verbose=config.verbose, timer=tim, dataset1="normalization", dataset2="empty_can", scale=config.scale_cn) else: n_som3 = n_som2 del n_som2, e_som3 # Step 30-31: Integrate normalization spectra if config.verbose and n_som3 is not None and not config.pre_norm: print "Integrating normalization spectra" if not config.pre_norm: norm_int = dr_lib.integrate_spectra(n_som3, start=config.norm_start, end=config.norm_end, norm=True) else: norm_int = n_som3 del n_som3 # Step 32: Normalize data by integrated values if config.verbose and norm_int is not None: print "Normalizing data by normalization data" if norm_int is not None: d_som4 = common_lib.div_ncerr(d_som3, norm_int) else: d_som4 = d_som3 if norm_int is not None: if tim is not None: tim.getTime(msg="After normalizing data ") del d_som3, norm_int if config.dump_norm: if tim is not None: tim.getTime(False) hlr_utils.write_file(config.output, "text/Spec", d_som4, output_ext="wvn", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="wavelength (vanadium norm) information") if tim is not None: tim.getTime(msg="After writing wavelength (vanadium norm) info ") # Steps 33 to end: Creating S(Q,E) if config.Q_bins is not None: if config.verbose: print "Creating 2D spectrum" if tim is not None: tim.getTime(False) d_som5 = dr_lib.create_E_vs_Q_igs( d_som4, config.E_bins.toNessiList(), config.Q_bins.toNessiList(), so_id="Full Detector", y_label="counts", y_units="counts / (ueV * A^-1)", x_labels=["Q transfer", "energy transfer"], x_units=["1/Angstroms", "ueV"], split=config.split, Q_filter=False, configure=config) if tim is not None: tim.getTime(msg="After creation of final spectrum ") del d_som4 # Steps 33 to 36: Create S(-cos(polar), E) elif config.ncospol_bins is not None: if config.verbose: print "Convert wavelength to energy transfer" if tim is not None: tim.getTime(False) d_som4a = dr_lib.energy_transfer(d_som4, "IGS", "Wavelength_final", sa_norm=True, scale=True, change_units=True) if tim is not None: tim.getTime(msg="After wavelength to energy transfer conversion ") del d_som4 if config.verbose: print "Creating 2D spectrum" if tim is not None: tim.getTime(False) d_som5 = dr_lib.create_param_vs_Y( d_som4a, "polar", "negcos_param_array", config.ncospol_bins.toNessiList(), rebin_axis=config.E_bins.toNessiList(), y_label="counts", y_units="counts / ueV", x_labels=["-cos(polar)", "Energy Transfer"], x_units=["", "ueV"]) if tim is not None: tim.getTime(msg="After creation of final spectrum ") # If rescaling factor present, rescale the data if config.rescale_final is not None and not config.split: d_som6 = common_lib.mult_ncerr(d_som5, (config.rescale_final, 0.0)) else: d_som6 = d_som5 if tim is None: old_time = None if not __name__ == "amorphous_reduction_sqe": del d_som5 __write_output(d_som6, config, tim, old_time) else: if config.create_output: del d_som5 __write_output(d_som6, config, tim, old_time) else: return d_som6
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
def process_reflp_data(datalist, conf, roi_file, bkg_roi_file=None, no_bkg=False, **kwargs): """ This function combines Steps 1 through 3 in section 2.4.6.1 of the data reduction process for Reduction from TOF to lambda_T as specified by the document at U{http://neutrons.ornl.gov/asg/projects/SCL/reqspec/DR_Lib_RS.doc}. The function takes a list of file names, a L{hlr_utils.Configure} object, region-of-interest (ROI) file for the normalization dataset, a background region-of-interest (ROI) file and an optional flag about background subtractionand processes the data accordingly. @param datalist: The filenames of the data to be processed @type datalist: C{list} of C{string}s @param conf: Object that contains the current setup of the driver @type conf: L{hlr_utils.Configure} @param roi_file: The file containing the list of pixel IDs for the region of interest. This only applies to normalization data. @type roi_file: C{string} @param bkg_roi_file: The file containing the list of pixel IDs for the (possible) background region of interest. @type bkg_roi_file: C{string} @param no_bkg: (OPTIONAL) Flag which determines if the background will be calculated and subtracted. @type no_bkg: C{boolean} @param kwargs: A list of keyword arguments that the function accepts: @keyword inst_geom_dst: File object that contains instrument geometry information. @type inst_geom_dst: C{DST.GeomDST} @keyword timer: Timing object so the function can perform timing estimates. @type timer: C{sns_timer.DiffTime} @return: Object that has undergone all requested processing steps @rtype: C{SOM.SOM} """ import hlr_utils import common_lib import dr_lib # Check keywords try: i_geom_dst = kwargs["inst_geom_dst"] except KeyError: i_geom_dst = None try: t = kwargs["timer"] except KeyError: t = None if roi_file is not None: # Normalization dataset_type = "norm" else: # Sample data dataset_type = "data" so_axis = "time_of_flight" # Step 0: Open data files and select ROI (if necessary) if conf.verbose: print "Reading %s file" % dataset_type if len(conf.norm_data_paths) and dataset_type == "norm": data_path = conf.norm_data_paths.toPath() else: data_path = conf.data_paths.toPath() (d_som1, b_som1) = dr_lib.add_files_bg(datalist, Data_Paths=data_path, SO_Axis=so_axis, dataset_type=dataset_type, Signal_ROI=roi_file, Bkg_ROI=bkg_roi_file, Verbose=conf.verbose, Timer=t) if t is not None: t.getTime(msg="After reading %s " % dataset_type) # Override geometry if necessary if i_geom_dst is not None: i_geom_dst.setGeometry(conf.data_paths.toPath(), d_som1) if dataset_type == "data": # Get TOF bin width conf.delta_TOF = d_som1[0].axis[0].val[1] - d_som1[0].axis[0].val[0] if conf.mon_norm: if conf.verbose: print "Reading in monitor data from %s file" % dataset_type # The [0] is to get the data SOM and ignore the None background SOM dm_som1 = dr_lib.add_files(datalist, Data_Paths=conf.mon_path.toPath(), SO_Axis=so_axis, dataset_type=dataset_type, Verbose=conf.verbose, Timer=t) if t is not None: t.getTime(msg="After reading monitor data ") else: dm_som1 = None # Step 1: Sum all spectra along the low resolution direction # Set sorting for REF_L if conf.verbose: print "Summing over low resolution direction" # Set sorting (y_sort, cent_pixel) = hlr_utils.get_ref_integration_direction( conf.int_dir, conf.inst, d_som1.attr_list.instrument) if t is not None: t.getTime(False) d_som2 = dr_lib.sum_all_spectra(d_som1, y_sort=y_sort, stripe=True, pixel_fix=cent_pixel) if b_som1 is not None: b_som2 = dr_lib.sum_all_spectra(b_som1, y_sort=y_sort, stripe=True, pixel_fix=cent_pixel) del b_som1 else: b_som2 = b_som1 if t is not None: t.getTime(msg="After summing low resolution direction ") del d_som1 # Determine background spectrum if conf.verbose and not no_bkg: print "Determining %s background" % dataset_type if b_som2 is not None: B = dr_lib.calculate_ref_background(b_som2, no_bkg, conf.inst, None, aobj=d_som2) if t is not None: t.getTime(msg="After background determination") # Subtract background spectrum from data spectra if not no_bkg: d_som3 = dr_lib.subtract_bkg_from_data(d_som2, B, verbose=conf.verbose, timer=t, dataset1="data", dataset2="background") else: d_som3 = d_som2 del d_som2 # Zero the spectra if necessary if roi_file is None and (conf.tof_cut_min is not None or \ conf.tof_cut_max is not None): import utils # Find the indicies for the non zero range if conf.tof_cut_min is None: conf.TOF_min = d_som3[0].axis[0].val[0] start_index = 0 else: start_index = utils.bisect_helper(d_som3[0].axis[0].val, conf.tof_cut_min) if conf.tof_cut_max is None: conf.TOF_max = d_som3[0].axis[0].val[-1] end_index = len(d_som3[0].axis[0].val) - 1 else: end_index = utils.bisect_helper(d_som3[0].axis[0].val, conf.tof_cut_max) nz_list = [] for i in xrange(hlr_utils.get_length(d_som3)): nz_list.append((start_index, end_index)) d_som4 = dr_lib.zero_spectra(d_som3, nz_list, use_bin_index=True) else: conf.TOF_min = d_som3[0].axis[0].val[0] conf.TOF_max = d_som3[0].axis[0].val[-1] d_som4 = d_som3 del d_som3 # Step N: Convert TOF to wavelength if conf.verbose: print "Converting TOF to wavelength" if t is not None: t.getTime(False) d_som5 = common_lib.tof_to_wavelength(d_som4, inst_param="total", units="microsecond") if dm_som1 is not None: dm_som2 = common_lib.tof_to_wavelength(dm_som1, units="microsecond") else: dm_som2 = None del dm_som1 if t is not None: t.getTime(msg="After converting TOF to wavelength ") del d_som4 if conf.mon_norm: dm_som3 = dr_lib.rebin_monitor(dm_som2, d_som5, rtype="frac") else: dm_som3 = None del dm_som2 if not conf.mon_norm: # Step 2: Multiply the spectra by the proton charge if conf.verbose: print "Multiply spectra by proton charge" pc_tag = dataset_type + "-proton_charge" proton_charge = d_som5.attr_list[pc_tag] if t is not None: t.getTime(False) d_som6 = common_lib.div_ncerr(d_som5, (proton_charge.getValue(), 0.0)) if t is not None: t.getTime(msg="After scaling by proton charge ") else: if conf.verbose: print "Normalize by monitor spectrum" if t is not None: t.getTime(False) d_som6 = common_lib.div_ncerr(d_som5, dm_som3) if t is not None: t.getTime(msg="After monitor normalization ") del d_som5, dm_som3 if roi_file is None: return d_som6 else: # Step 3: Make one spectrum for normalization dataset # Need to create a final rebinning axis pathlength = d_som6.attr_list.instrument.get_total_path( det_secondary=True) delta_lambda = common_lib.tof_to_wavelength((conf.delta_TOF, 0.0), pathlength=pathlength) lambda_bins = dr_lib.create_axis_from_data(d_som6, width=delta_lambda[0]) return dr_lib.sum_by_rebin_frac(d_som6, lambda_bins.toNessiList())
def 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 and not config.hwfix: b_som1 = dr_lib.process_igs_data(config.back, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="background", tib_const=config.tib_back_const) else: b_som1 = None # Perform Step 1-15 on direct scattering background data if config.dsback is not None: ds_som1 = dr_lib.process_igs_data(config.dsback, config, timer=tim, inst_geom_dst=inst_geom_dst, tib_const=config.tib_dsback_const, dataset_type="dsbackground", bkg_som=bkg_som) # Note: time_zero_slope MUST be a tuple if config.time_zero_slope is not None: ds_som1.attr_list["Time_zero_slope"] = \ config.time_zero_slope.toValErrTuple() # Note: time_zero_offset MUST be a tuple if config.time_zero_offset is not None: ds_som1.attr_list["Time_zero_offset"] = \ config.time_zero_offset.toValErrTuple() # Step 16: Linearly interpolate TOF elastic range in direct scattering # background data # First convert TOF elastic range to appropriate pixel initial # wavelengths if config.verbose: print "Determining initial wavelength range for elastic line" if tim is not None: tim.getTime(False) if config.tof_elastic is None: # Units are in microseconds tof_elastic_range = (140300, 141300) else: tof_elastic_range = config.tof_elastic ctof_elastic_low = dr_lib.convert_single_to_list(\ "tof_to_initial_wavelength_igs_lin_time_zero", (tof_elastic_range[0], 0.0), ds_som1) ctof_elastic_high = dr_lib.convert_single_to_list(\ "tof_to_initial_wavelength_igs_lin_time_zero", (tof_elastic_range[1], 0.0), ds_som1) ctof_elastic_range = [(ctof_elastic_low[i][0], ctof_elastic_high[i][0]) for i in xrange(len(ctof_elastic_low))] if tim is not None: tim.getTime(msg="After calculating initial wavelength range for "\ +"elastic line ") del ctof_elastic_low, ctof_elastic_high # Now interpolate spectra between TOF elastic range (converted to # initial wavelength) if config.verbose: print "Linearly interpolating direct scattering spectra" if tim is not None: tim.getTime(False) ds_som2 = dr_lib.lin_interpolate_spectra(ds_som1, ctof_elastic_range) if tim is not None: tim.getTime(msg="After linearly interpolating direct scattering "\ +"spectra ") if config.dump_dslin: ds_som2_1 = dr_lib.sum_all_spectra(ds_som2,\ rebin_axis=config.lambda_bins.toNessiList()) hlr_utils.write_file(config.output, "text/Spec", ds_som2_1, output_ext="lin", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="dsbackground linear interpolation") del ds_som2_1 del ds_som1 else: ds_som2 = None if inst_geom_dst is not None: inst_geom_dst.release_resource() # Steps 17-18: Subtract background spectrum from sample spectrum if config.dsback is None: back_som = b_som1 bkg_type = "background" else: back_som = ds_som2 bkg_type = "dsbackground" d_som2 = dr_lib.subtract_bkg_from_data(d_som1, back_som, verbose=config.verbose, timer=tim, dataset1="data", dataset2=bkg_type, scale=config.scale_bs) if config.dsback is not None: del ds_som2 # Step 19: Zero region outside TOF elastic for background for empty can if config.dsback is None: bcs_som = b_som1 cs_som = e_som1 else: if config.verbose and b_som1 is not None: print "Zeroing background spectra" if tim is not None and b_som1 is not None: tim.getTime(False) bcs_som = dr_lib.zero_spectra(b_som1, ctof_elastic_range) if tim is not None and b_som1 is not None: tim.getTime(msg="After zeroing background spectra") if config.verbose and e_som1 is not None: print "Zeroing empty can spectra" if tim is not None and e_som1 is not None: tim.getTime(False) cs_som = dr_lib.zero_spectra(e_som1, ctof_elastic_range) if tim is not None and e_som1 is not None: tim.getTime(msg="After zeroing empty can spectra") del ctof_elastic_range # Steps 20-21: Subtract background spectrum from empty can spectrum e_som2 = dr_lib.subtract_bkg_from_data(cs_som, bcs_som, verbose=config.verbose, timer=tim, dataset1="empty_can", dataset2="background", scale=config.scale_bcs) # Steps 22-23: Subtract background spectrum from empty can spectrum for # normalization e_som3 = dr_lib.subtract_bkg_from_data(e_som1, b_som1, verbose=config.verbose, timer=tim, dataset1="empty_can", dataset2="background", scale=config.scale_bcn) # Steps 24-25: Subtract background spectrum from normalization spectrum n_som2 = dr_lib.subtract_bkg_from_data(n_som1, b_som1, verbose=config.verbose, timer=tim, dataset1="normalization", dataset2="background", scale=config.scale_bn) del b_som1, e_som1, bcs_som, cs_som # Steps 26-27: Subtract empty can spectrum from sample spectrum d_som3 = dr_lib.subtract_bkg_from_data(d_som2, e_som2, verbose=config.verbose, timer=tim, dataset1="data", dataset2="empty_can", scale=config.scale_cs) del d_som2, e_som2 # Steps 28-29: Subtract empty can spectrum from normalization spectrum n_som3 = dr_lib.subtract_bkg_from_data(n_som2, e_som3, verbose=config.verbose, timer=tim, dataset1="normalization", dataset2="empty_can", scale=config.scale_cn) del n_som2, e_som3 # Step 30-32: Integrate normalization spectra if config.verbose and n_som3 is not None: print "Integrating normalization spectra" norm_int = dr_lib.integrate_spectra(n_som3, start=config.norm_start, end=config.norm_end, norm=True) del n_som3 # Step 33: Normalize data by integrated values if config.verbose and norm_int is not None: print "Normalizing data by normalization data" if norm_int is not None: d_som4 = common_lib.div_ncerr(d_som3, norm_int) else: d_som4 = d_som3 if norm_int is not None: if tim is not None: tim.getTime(msg="After normalizing data ") del d_som3, norm_int # Step 35: Convert initial wavelength to E_initial if config.verbose: print "Converting initial wavelength to E_initial" if tim is not None: tim.getTime(False) d_som6 = common_lib.wavelength_to_energy(d_som4) if tim is not None: tim.getTime(msg="After converting initial wavelength to E_initial ") if config.dump_initial_energy: hlr_utils.write_file(config.output, "text/Spec", d_som6, output_ext="ixl", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="pixel initial energy information") del d_som4 # Steps 36-37: Calculate energy transfer if config.verbose: print "Calculating energy transfer" if tim is not None: tim.getTime(False) d_som7 = dr_lib.igs_energy_transfer(d_som6) if tim is not None: tim.getTime(msg="After calculating energy transfer ") if config.dump_energy: hlr_utils.write_file(config.output, "text/Spec", d_som7, output_ext="exl", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="pixel energy transfer information") # Write 3-column ASCII file for E_t d_som7_1 = dr_lib.sum_all_spectra(d_som7, rebin_axis=config.E_bins.toNessiList()) hlr_utils.write_file(config.output, "text/Spec", d_som7_1, output_ext="etr", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="combined energy transfer information") del d_som7_1 # Steps 34,36-37: Calculate scaled energy transfer if config.verbose: print "Calculating scaled energy transfer" d_som9 = dr_lib.igs_energy_transfer(d_som6, scale=True) if tim is not None: tim.getTime(msg="After calculating scaled energy transfer ") if config.dump_energy: hlr_utils.write_file(config.output, "text/Spec", d_som9, output_ext="sexl", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="pixel scaled energy transfer "\ +"information") # Write 3-column ASCII file for scaled E_t d_som9_1 = dr_lib.sum_all_spectra(d_som9, rebin_axis=config.E_bins.toNessiList()) hlr_utils.write_file(config.output, "text/Spec", d_som9_1, output_ext="setr", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="combined scaled energy transfer "\ +"information") del d_som9_1 del d_som6, d_som7 d_som9.attr_list["config"] = config hlr_utils.write_file(config.output, "text/rmd", d_som9, output_ext="rmd", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="metadata") if tim is not None: tim.setOldTime(old_time) tim.getTime(msg="Total Running Time")
def run(config): """ 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} """ import sys import dr_lib import DST try: data_dst = DST.getInstance("application/x-NeXus", config.data[0]) except SystemError: print "ERROR: Failed to data read file %s" % config.data[0] sys.exit(-1) so_axis = "time_of_flight" if config.verbose: print "Reading data file" if config.roi_file is None: d_som0 = data_dst.getSOM(config.data_paths.toPath(), so_axis, start_id=config.starting_ids, end_id=config.ending_ids) else: d_som0 = data_dst.getSOM(config.data_paths.toPath(), so_axis, roi_file=config.roi_file) if config.width: d_som1 = dr_lib.fix_bin_contents(d_som0) else: d_som1 = d_som0 del d_som0 if config.dump_pxl: hlr_utils.write_file(config.data[0], "text/Spec", d_som1, output_ext="tfp", verbose=config.verbose, path_replacement=config.path_replacement, message="pixel TOF information") else: pass if config.tib_const is not None: import common_lib d_som2 = common_lib.sub_ncerr(d_som1, config.tib_const.toValErrTuple()) if config.dump_sxl: hlr_utils.write_file(config.data[0], "text/Spec", d_som2, output_ext="tsp", verbose=config.verbose, path_replacement=config.path_replacement, message="TIB const sub pixel TOF information") else: d_som2 = d_som1 del d_som1 if len(d_som2) == 1: if config.verbose: print "Summing 1 spectrum." d_som3 = d_som2 else: if config.verbose: print "Summing %d spectra." % len(d_som2) d_som3 = dr_lib.sum_all_spectra(d_som2) d_som3[0].id = d_som2[0].id del d_som2 hlr_utils.write_file(config.output, "text/Spec", d_som3, replace_ext=False, verbose=config.verbose, path_replacement=config.path_replacement, message="combined TOF information")
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