def process_sas_data(datalist, conf, **kwargs): """ This function combines Steps 1 through 9 of the data reduction process for Small-Angle Scattering section 2.5.1 as specified by the documents at U{http://neutrons.ornl.gov/asg/projects/SCL/reqspec/DR_Lib_RS.doc}. The function takes a list of file names, a L{hlr_utils.Configure} object and processes the data accordingly. This function should really only be used in the context of I{sas_reduction}. @param datalist: A list containing the filenames of the data to be processed. @type datalist: C{list} of C{string}s @param conf: Object that contains the current setup of the driver. @type conf: L{hlr_utils.Configure} @param kwargs: A list of keyword arguments that the function accepts: @keyword inst_geom_dst: File object that contains instrument geometry information. @type inst_geom_dst: C{DST.GeomDST} @keyword dataset_type: The practical name of the dataset being processed. The default value is I{data}. @type dataset_type: C{string} @keyword trans_data: Alternate data for the transmission spectrum. This is used in the absence of transmission monitors. @type trans_data: C{string} @keyword transmission: A flag that signals the function to stop after doing the conversion from TOF to wavelength. The default is I{False}. @type transmission: C{boolean} @keyword bkg_subtract: A list of coefficients that help determine the wavelength dependent background subtraction. @type bkg_subtract: C{list} @keyword get_background: A flag that signals the function to convert the main data to wavelength and exit before normalizing to the beam monitor. @type get_background: C{boolean} @keyword acc_down_time: The information for the accelerator downtime. @type acc_down_time: C{tuple} @keyword bkg_scale: The scaling used for the axis dependent background parameters. @type bkg_scale: C{float} @keyword timer: Timing object so the function can perform timing estimates. @type timer: C{sns_timer.DiffTime} @return: Object that has undergone all requested processing steps @rtype: C{SOM.SOM} """ import common_lib import dr_lib import hlr_utils # Check keywords try: dataset_type = kwargs["dataset_type"] except KeyError: dataset_type = "data" try: i_geom_dst = kwargs["inst_geom_dst"] except KeyError: i_geom_dst = None try: t = kwargs["timer"] except KeyError: t = None try: transmission = kwargs["transmission"] except KeyError: transmission = False try: bkg_subtract = kwargs["bkg_subtract"] except KeyError: bkg_subtract = None try: trans_data = kwargs["trans_data"] except KeyError: trans_data = None try: get_background = kwargs["get_background"] except KeyError: get_background = False acc_down_time = kwargs.get("acc_down_time") bkg_scale = kwargs.get("bkg_scale") # Add so_axis to Configure object conf.so_axis = "time_of_flight" # Step 0: Open appropriate data files # Data if conf.verbose: print "Reading %s file" % dataset_type # The [0] is to get the data SOM and ignore the None background SOM dp_som = dr_lib.add_files(datalist, Data_Paths=conf.data_paths.toPath(), SO_Axis=conf.so_axis, Signal_ROI=conf.roi_file, dataset_type=dataset_type, Verbose=conf.verbose, Timer=t) if t is not None: t.getTime(msg="After reading %s " % dataset_type) dp_som1 = dr_lib.fix_bin_contents(dp_som) del dp_som if conf.inst_geom is not None: i_geom_dst.setGeometry(conf.data_paths.toPath(), dp_som1) if conf.dump_tof_r: dp_som1_1 = dr_lib.create_param_vs_Y(dp_som1, "radius", "param_array", conf.r_bins.toNessiList(), y_label="counts", y_units="counts / (usec * m)", x_labels=["Radius", "TOF"], x_units=["m", "usec"]) hlr_utils.write_file(conf.output, "text/Dave2d", dp_som1_1, output_ext="tvr", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message="TOF vs radius information") del dp_som1_1 if conf.dump_tof_theta: dp_som1_1 = dr_lib.create_param_vs_Y(dp_som1, "polar", "param_array", conf.theta_bins.toNessiList(), y_label="counts", y_units="counts / (usec * rads)", x_labels=["Polar Angle", "TOF"], x_units=["rads", "usec"]) hlr_utils.write_file(conf.output, "text/Dave2d", dp_som1_1, output_ext="tvt", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message="TOF vs polar angle information") del dp_som1_1 # Beam monitor if not get_background: if conf.beammon_over is None: if conf.verbose: print "Reading in beam monitor data from %s file" \ % dataset_type # The [0] is to get the data SOM and ignore the None # background SOM dbm_som0 = dr_lib.add_files(datalist, Data_Paths=conf.bmon_path.toPath(), SO_Axis=conf.so_axis, dataset_type=dataset_type, Verbose=conf.verbose, Timer=t) if t is not None: t.getTime(msg="After reading beam monitor data ") if conf.inst_geom is not None: i_geom_dst.setGeometry(conf.bmon_path.toPath(), dbm_som0) else: if conf.verbose: print "Reading in vanadium data" dbm_som0 = dr_lib.add_files(datalist, Data_Paths=conf.data_paths.toPath(), Signal_ROI=conf.roi_file, SO_Axis=conf.so_axis, dataset_type=dataset_type, Verbose=conf.verbose, Timer=t) if t is not None: t.getTime(msg="After reading vanadium data ") if conf.inst_geom is not None: i_geom_dst.setGeometry(conf.data_paths.toPath(), dbm_som0) dbm_som1 = dr_lib.fix_bin_contents(dbm_som0) del dbm_som0 else: dbm_som1 = None # Transmission monitor if trans_data is None: if conf.verbose: print "Reading in transmission monitor data from %s file" \ % dataset_type try: dtm_som0 = dr_lib.add_files(datalist, Data_Paths=conf.tmon_path.toPath(), SO_Axis=conf.so_axis, dataset_type=dataset_type, Verbose=conf.verbose, Timer=t) if t is not None: t.getTime(msg="After reading transmission monitor data ") if conf.inst_geom is not None: i_geom_dst.setGeometry(conf.tmon_path.toPath(), dtm_som0) dtm_som1 = dr_lib.fix_bin_contents(dtm_som0) del dtm_som0 # Transmission monitor cannot be found except KeyError: if conf.verbose: print "Transmission monitor not found" dtm_som1 = None else: dtm_som1 = None # Note: time_zero_offset_det MUST be a tuple if conf.time_zero_offset_det is not None: dp_som1.attr_list["Time_zero_offset_det"] = \ conf.time_zero_offset_det.toValErrTuple() # Note: time_zero_offset_mon MUST be a tuple if conf.time_zero_offset_mon is not None and not get_background and \ conf.beammon_over is None: dbm_som1.attr_list["Time_zero_offset_mon"] = \ conf.time_zero_offset_mon.toValErrTuple() if conf.beammon_over is not None: dbm_som1.attr_list["Time_zero_offset_det"] = \ conf.time_zero_offset_det.toValErrTuple() if trans_data is None and dtm_som1 is not None: dtm_som1.attr_list["Time_zero_offset_mon"] = \ conf.time_zero_offset_mon.toValErrTuple() # Step 1: Convert TOF to wavelength for data and monitor if conf.verbose: print "Converting TOF to wavelength" if t is not None: t.getTime(False) if not get_background: # Convert beam monitor if conf.beammon_over is None: dbm_som2 = common_lib.tof_to_wavelength_lin_time_zero( dbm_som1, units="microsecond", time_zero_offset=conf.time_zero_offset_mon.toValErrTuple()) else: dbm_som2 = common_lib.tof_to_wavelength_lin_time_zero( dbm_som1, units="microsecond", time_zero_offset=conf.time_zero_offset_det.toValErrTuple(), inst_param="total") else: dbm_som2 = None # Convert detector pixels dp_som2 = common_lib.tof_to_wavelength_lin_time_zero( dp_som1, units="microsecond", time_zero_offset=conf.time_zero_offset_det.toValErrTuple(), inst_param="total") if get_background: return dp_som2 if dtm_som1 is not None: # Convert transmission monitor dtm_som2 = common_lib.tof_to_wavelength_lin_time_zero( dtm_som1, units="microsecond", time_zero_offset=conf.time_zero_offset_mon.toValErrTuple()) else: dtm_som2 = dtm_som1 if t is not None: t.getTime(msg="After converting TOF to wavelength ") del dp_som1, dbm_som1, dtm_som1 if conf.verbose and (conf.lambda_low_cut is not None or \ conf.lambda_high_cut is not None): print "Cutting data spectra" if t is not None: t.getTime(False) dp_som3 = dr_lib.cut_spectra(dp_som2, conf.lambda_low_cut, conf.lambda_high_cut) if t is not None: t.getTime(msg="After cutting data spectra ") del dp_som2 if conf.beammon_over is not None: dbm_som2 = dr_lib.cut_spectra(dbm_som2, conf.lambda_low_cut, conf.lambda_high_cut) if conf.dump_wave: hlr_utils.write_file(conf.output, "text/Spec", dp_som3, output_ext="pxl", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message="pixel wavelength information") if conf.dump_bmon_wave: if conf.beammon_over is None: hlr_utils.write_file(conf.output, "text/Spec", dbm_som2, output_ext="bmxl", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message="beam monitor wavelength information") else: dbm_som2_1 = dr_lib.sum_by_rebin_frac(dbm_som2, conf.lambda_bins.toNessiList()) hlr_utils.write_file(conf.output, "text/Spec", dbm_som2_1, output_ext="bmxl", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message="beam monitor override wavelength "\ +"information") del dbm_som2_1 # Step 2: Subtract wavelength dependent background if necessary if conf.verbose and bkg_subtract is not None: print "Subtracting wavelength dependent background" if bkg_subtract is not None: if t is not None: t.getTime(False) duration = dp_som3.attr_list["%s-duration" % dataset_type] scale = duration.getValue() - acc_down_time[0] dp_som4 = dr_lib.subtract_axis_dep_bkg(dp_som3, bkg_subtract, old_scale=bkg_scale, new_scale=scale) if t is not None: t.getTime(msg="After subtracting wavelength dependent background ") else: dp_som4 = dp_som3 del dp_som3 # Step 3: Efficiency correct beam monitor if conf.verbose and conf.mon_effc: print "Efficiency correct beam monitor data" if t is not None: t.getTime(False) if conf.mon_effc: dbm_som3 = dr_lib.feff_correct_mon(dbm_som2, inst_name=conf.inst, eff_const=conf.mon_eff_const) else: dbm_som3 = dbm_som2 if t is not None and conf.mon_effc: t.getTime(msg="After efficiency correcting beam monitor ") if conf.dump_bmon_effc and conf.mon_effc: hlr_utils.write_file(conf.output, "text/Spec", dbm_som3, output_ext="bmel", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message="beam monitor wavelength information "\ +"(efficiency)") del dbm_som2 # Step 4: Efficiency correct transmission monitor if dtm_som2 is not None: if conf.verbose and conf.mon_effc: print "Efficiency correct transmission monitor data" if t is not None: t.getTime(False) if conf.mon_effc: dtm_som3 = dr_lib.feff_correct_mon(dtm_som2) else: dtm_som3 = dtm_som2 else: dtm_som3 = dtm_som2 if t is not None and conf.mon_effc and dtm_som2 is not None: t.getTime(msg="After efficiency correcting beam monitor ") # Step 5: Efficiency correct detector pixels if conf.det_effc: if conf.verbose: print "Calculating detector efficiency" if t is not None: t.getTime(False) det_eff = dr_lib.create_det_eff(dp_som4, inst_name=conf.inst, eff_scale_const=conf.det_eff_scale_const, eff_atten_const=conf.det_eff_atten_const) if t is not None: t.getTime(msg="After calculating detector efficiency") if conf.verbose: print "Applying detector efficiency" if t is not None: t.getTime(False) dp_som5 = common_lib.div_ncerr(dp_som4, det_eff) if t is not None: t.getTime(msg="After spplying detector efficiency") else: dp_som5 = dp_som4 del dp_som4 # Step 6: Rebin beam monitor axis onto detector pixel axis if conf.beammon_over is None: if not conf.no_bmon_norm: if conf.verbose: print "Rebin beam monitor axis to detector pixel axis" if t is not None: t.getTime(False) dbm_som4 = dr_lib.rebin_monitor(dbm_som3, dp_som5, rtype="frac") if t is not None: t.getTime(msg="After rebinning beam monitor ") else: dbm_som4 = dbm_som3 else: dbm_som4 = dbm_som3 del dbm_som3 if conf.dump_bmon_rebin: hlr_utils.write_file(conf.output, "text/Spec", dbm_som4, output_ext="bmrl", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message="beam monitor wavelength information "\ +"(rebinned)") # Step 7: Normalize data by beam monitor if not conf.no_bmon_norm: if conf.verbose: print "Normalizing data by beam monitor" if t is not None: t.getTime(False) dp_som6 = common_lib.div_ncerr(dp_som5, dbm_som4) if t is not None: t.getTime(msg="After normalizing data by beam monitor ") else: dp_som6 = dp_som5 del dp_som5 if transmission: return dp_som6 if conf.dump_wave_bmnorm: dp_som6_1 = dr_lib.sum_by_rebin_frac(dp_som6, conf.lambda_bins.toNessiList()) write_message = "combined pixel wavelength information" write_message += " (beam monitor normalized)" hlr_utils.write_file(conf.output, "text/Spec", dp_som6_1, output_ext="pbml", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message=write_message) del dp_som6_1 if conf.dump_wave_r: dp_som6_1 = dr_lib.create_param_vs_Y(dp_som6, "radius", "param_array", conf.r_bins.toNessiList(), rebin_axis=conf.lambda_bins.toNessiList(), y_label="counts", y_units="counts / (Angstrom * m)", x_labels=["Radius", "Wavelength"], x_units=["m", "Angstrom"]) hlr_utils.write_file(conf.output, "text/Dave2d", dp_som6_1, output_ext="lvr", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message="wavelength vs radius information") del dp_som6_1 if conf.dump_wave_theta: dp_som6_1 = dr_lib.create_param_vs_Y(dp_som6, "polar", "param_array", conf.theta_bins.toNessiList(), rebin_axis=conf.lambda_bins.toNessiList(), y_label="counts", y_units="counts / (Angstrom * rads)", x_labels=["Polar Angle", "Wavelength"], x_units=["rads", "Angstrom"]) hlr_utils.write_file(conf.output, "text/Dave2d", dp_som6_1, output_ext="lvt", extra_tag=dataset_type, verbose=conf.verbose, data_ext=conf.ext_replacement, path_replacement=conf.path_replacement, message="wavelength vs polar angle information") del dp_som6_1 # Step 8: Rebin transmission monitor axis onto detector pixel axis if trans_data is not None: print "Reading in transmission monitor data from file" dtm_som3 = dr_lib.add_files([trans_data], dataset_type=dataset_type, dst_type="text/Spec", Verbose=conf.verbose, Timer=t) if conf.verbose and dtm_som3 is not None: print "Rebin transmission monitor axis to detector pixel axis" if t is not None: t.getTime(False) dtm_som4 = dr_lib.rebin_monitor(dtm_som3, dp_som6, rtype="frac") if t is not None and dtm_som3 is not None: t.getTime(msg="After rebinning transmission monitor ") del dtm_som3 # Step 9: Normalize data by transmission monitor if conf.verbose and dtm_som4 is not None: print "Normalizing data by transmission monitor" if t is not None: t.getTime(False) if dtm_som4 is not None: # The transmission spectra derived from sas_tranmission does not have # the same y information by convention as sample data or a # tranmission monitor. Therefore, we'll fake it by setting the # y information from the sample data into the transmission if trans_data is not None: dtm_som4.setYLabel(dp_som6.getYLabel()) dtm_som4.setYUnits(dp_som6.getYUnits()) dp_som7 = common_lib.div_ncerr(dp_som6, dtm_som4) else: dp_som7 = dp_som6 if t is not None and dtm_som4 is not None: t.getTime(msg="After normalizing data by transmission monitor ") del dp_som6 # Step 10: Convert wavelength to Q for data if conf.verbose: print "Converting data from wavelength to scalar Q" if t is not None: t.getTime(False) dp_som8 = common_lib.wavelength_to_scalar_Q(dp_som7) if t is not None: t.getTime(msg="After converting wavelength to scalar Q ") del dp_som7 if conf.facility == "LENS": # Step 11: Apply SAS correction factor to data if conf.verbose: print "Applying geometrical correction" if t is not None: t.getTime(False) dp_som9 = dr_lib.apply_sas_correct(dp_som8) if t is not None: t.getTime(msg="After applying geometrical correction ") return dp_som9 else: return dp_som8
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 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 Steps 1-11 on sample data d_som1 = dr_lib.process_sas_data(config.data, config, timer=tim, inst_geom_dst=inst_geom_dst, bkg_subtract=config.bkg_coeff, acc_down_time=config.data_acc_down_time.toValErrTuple(), bkg_scale=config.bkg_scale, trans_data=config.data_trans) # Perform Steps 1-11 on buffer/solvent only data if config.solv is not None: s_som1 = dr_lib.process_sas_data(config.solv, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="solvent", bkg_subtract=config.bkg_coeff, acc_down_time=config.solv_acc_down_time.toValErrTuple(), bkg_scale=config.bkg_scale, trans_data=config.solv_trans) else: s_som1 = None # Step 12: Subtract buffer/solvent only spectrum from sample spectrum d_som2 = dr_lib.subtract_bkg_from_data(d_som1, s_som1, verbose=config.verbose, timer=tim, dataset1="data", dataset2="solvent") del s_som1, d_som1 # Perform Steps 1-11 on empty-can data if config.ecan is not None: e_som1 = dr_lib.process_sas_data(config.ecan, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="empty_can", bkg_subtract=config.bkg_coeff, acc_down_time=config.ecan_acc_down_time.toValErrTuple(), bkg_scale=config.bkg_scale, trans_data=config.ecan_trans) else: e_som1 = None # Step 13: Subtract empty-can spectrum from sample spectrum d_som3 = dr_lib.subtract_bkg_from_data(d_som2, e_som1, verbose=config.verbose, timer=tim, dataset1="data", dataset2="empty_can") del e_som1, d_som2 # Perform Steps 1-11 on open beam data if config.open is not None: o_som1 = dr_lib.process_sas_data(config.open, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="open_beam", bkg_subtract=config.bkg_coeff, acc_down_time=config.open_acc_down_time.toValErrTuple(), bkg_scale=config.bkg_scale) else: o_som1 = None # Step 14: Subtract open beam spectrum from sample spectrum d_som4 = dr_lib.subtract_bkg_from_data(d_som3, o_som1, verbose=config.verbose, timer=tim, dataset1="data", dataset2="open_beam") del o_som1, d_som3 # Perform Steps 1-11 on dark current data if config.dkcur is not None: dc_som1 = dr_lib.process_sas_data(config.open, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="dark_current", bkg_subtract=config.bkg_coeff) else: dc_som1 = None # Step 15: Subtract dark current spectrum from sample spectrum d_som5 = dr_lib.subtract_bkg_from_data(d_som4, dc_som1, verbose=config.verbose, timer=tim, dataset1="data", dataset2="dark_current") del dc_som1, d_som4 # Create 2D distributions is necessary if config.dump_Q_r: d_som5_1 = dr_lib.create_param_vs_Y(d_som5, "radius", "param_array", config.r_bins.toNessiList(), rebin_axis=config.Q_bins.toNessiList(), binnorm=True, y_label="S", y_units="Counts / A^-1 m", x_labels=["Radius", "Q"], x_units=["m", "1/Angstroms"]) hlr_utils.write_file(config.output, "text/Dave2d", d_som5_1, output_ext="qvr", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="S(r, Q) information") del d_som5_1 if config.dump_Q_theta: d_som5_1 = dr_lib.create_param_vs_Y(d_som5, "polar", "param_array", config.theta_bins.toNessiList(), rebin_axis=config.Q_bins.toNessiList(), binnorm=True, y_label="S", y_units="Counts / A^-1 rads", x_labels=["Polar Angle", "Q"], x_units=["rads", "1/Angstroms"]) hlr_utils.write_file(config.output, "text/Dave2d", d_som5_1, output_ext="qvt", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="S(theta, Q) information") del d_som5_1 # Steps 16 and 17: Rebin and sum all spectra if config.verbose: print "Rebinning and summing for final spectrum" if tim is not None: tim.getTime(False) if config.dump_frac_rebin: set_conf = config else: set_conf = None d_som6 = dr_lib.sum_by_rebin_frac(d_som5, config.Q_bins.toNessiList(), configure=set_conf) if tim is not None: tim.getTime(msg="After rebinning and summing for spectrum") del d_som5 if config.facility == "LENS": # Step 18: Scale final spectrum by Q bin centers if config.verbose: print "Scaling final spectrum by Q centers" if tim is not None: tim.getTime(False) d_som7 = dr_lib.fix_bin_contents(d_som6, scale=True, width=True, units="1/Angstroms") if tim is not None: tim.getTime(msg="After scaling final spectrum") else: d_som7 = d_som6 del d_som6 # If rescaling factor present, rescale the data if config.rescale_final is not None: import common_lib d_som8 = common_lib.mult_ncerr(d_som7, (config.rescale_final, 0.0)) else: d_som8 = d_som7 del d_som7 hlr_utils.write_file(config.output, "text/Spec", d_som8, verbose=config.verbose, replace_path=False, replace_ext=False, message="combined S(Q) information") # Create 1D canSAS file hlr_utils.write_file(config.output, "text/canSAS", d_som8, verbose=config.verbose, output_ext="xml", data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="combined S(Q) information") d_som8.attr_list["config"] = config hlr_utils.write_file(config.output, "text/rmd", d_som8, output_ext="rmd", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="metadata") if tim is not None: tim.setOldTime(old_time) tim.getTime(msg="Total Running Time")
def run(config, tim=None): """ This method is where the data reduction process gets done. @param config: Object containing the data reduction configuration information. @type config: L{hlr_utils.Configure} @param tim: (OPTIONAL) Object that will allow the method to perform timing evaluations. @type tim: C{sns_time.DiffTime} """ import common_lib import dr_lib import DST if tim is not None: tim.getTime(False) old_time = tim.getOldTime() if config.data is None: raise RuntimeError("Need to pass a data filename to the driver "\ +"script.") # Read in geometry if one is provided if config.inst_geom is not None: if config.verbose: print "Reading in instrument geometry file" inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.inst_geom) else: inst_geom_dst = None # Perform early background subtraction if the hwfix flag is used if config.hwfix: if not config.mc: so_axis = "time_of_flight" else: so_axis = "Time_of_Flight" bkg_som0 = dr_lib.add_files(config.back, Data_Paths=config.data_paths.toPath(), SO_Axis=so_axis, Signal_ROI=config.roi_file, dataset_type="background", Verbose=config.verbose, Timer=tim) bkg_som = dr_lib.fix_bin_contents(bkg_som0) del bkg_som0 else: bkg_som = None # Perform Steps 1-15 on sample data d_som1 = dr_lib.process_igs_data(config.data, config, timer=tim, inst_geom_dst=inst_geom_dst, tib_const=config.tib_data_const, bkg_som=bkg_som) # Perform Steps 1-15 on empty can data if config.ecan is not None: e_som1 = dr_lib.process_igs_data(config.ecan, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="empty_can", tib_const=config.tib_ecan_const, bkg_som=bkg_som) else: e_som1 = None # Perform Steps 1-15 on normalization data if config.norm is not None: n_som1 = dr_lib.process_igs_data(config.norm, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="normalization", tib_const=config.tib_norm_const, bkg_som=bkg_som) else: n_som1 = None # Perform Steps 1-15 on background data if config.back is not None: b_som1 = dr_lib.process_igs_data(config.back, config, timer=tim, inst_geom_dst=inst_geom_dst, dataset_type="background", tib_const=config.tib_back_const, bkg_som=bkg_som) else: b_som1 = None # Perform Step 1-15 on direct scattering background data if config.dsback is not None: ds_som1 = dr_lib.process_igs_data(config.dsback, config, timer=tim, inst_geom_dst=inst_geom_dst, tib_const=config.tib_dsback_const, dataset_type="dsbackground", bkg_som=bkg_som) # Note: time_zero_slope MUST be a tuple if config.time_zero_slope is not None: ds_som1.attr_list["Time_zero_slope"] = \ config.time_zero_slope.toValErrTuple() # Note: time_zero_offset MUST be a tuple if config.time_zero_offset is not None: ds_som1.attr_list["Time_zero_offset"] = \ config.time_zero_offset.toValErrTuple() # Step 16: Linearly interpolate TOF elastic range in direct scattering # background data # First convert TOF elastic range to appropriate pixel initial # wavelengths if config.verbose: print "Determining initial wavelength range for elastic line" if tim is not None: tim.getTime(False) if config.tof_elastic is None: # Units are in microseconds tof_elastic_range = (140300, 141300) else: tof_elastic_range = config.tof_elastic ctof_elastic_low = dr_lib.convert_single_to_list(\ "tof_to_initial_wavelength_igs_lin_time_zero", (tof_elastic_range[0], 0.0), ds_som1) ctof_elastic_high = dr_lib.convert_single_to_list(\ "tof_to_initial_wavelength_igs_lin_time_zero", (tof_elastic_range[1], 0.0), ds_som1) ctof_elastic_range = [(ctof_elastic_low[i][0], ctof_elastic_high[i][0]) for i in xrange(len(ctof_elastic_low))] if tim is not None: tim.getTime(msg="After calculating initial wavelength range for "\ +"elastic line ") del ctof_elastic_low, ctof_elastic_high if config.split: lambda_filter = [(d_som1[i].axis[0].val[0], d_som1[i].axis[0].val[-1]) for i in xrange(len(d_som1))] else: lambda_filter = None # Now interpolate spectra between TOF elastic range (converted to # initial wavelength) if config.verbose: print "Linearly interpolating direct scattering spectra" if tim is not None: tim.getTime(False) ds_som2 = dr_lib.lin_interpolate_spectra(ds_som1, ctof_elastic_range, filter_axis=lambda_filter) if tim is not None: tim.getTime(msg="After linearly interpolating direct scattering "\ +"spectra ") if config.dump_dslin: ds_som2_1 = dr_lib.sum_all_spectra(ds_som2,\ rebin_axis=config.lambda_bins.toNessiList()) hlr_utils.write_file(config.output, "text/Spec", ds_som2_1, output_ext="lin", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="dsbackground linear interpolation") del ds_som2_1 del ds_som1 else: ds_som2 = None if inst_geom_dst is not None: inst_geom_dst.release_resource() # Steps 17-18: Subtract background spectrum from sample spectrum if config.dsback is None: back_som = b_som1 bkg_type = "background" else: back_som = ds_som2 bkg_type = "dsbackground" d_som2 = dr_lib.subtract_bkg_from_data(d_som1, back_som, verbose=config.verbose, timer=tim, dataset1="data", dataset2=bkg_type, scale=config.scale_bs) if config.dsback is not None: del ds_som2 # Step 19: Zero region outside TOF elastic for background for empty can if config.dsback is None: bcs_som = b_som1 cs_som = e_som1 else: if config.verbose and b_som1 is not None: print "Zeroing background spectra" if tim is not None and b_som1 is not None: tim.getTime(False) bcs_som = dr_lib.zero_spectra(b_som1, ctof_elastic_range) if tim is not None and b_som1 is not None: tim.getTime(msg="After zeroing background spectra") if config.verbose and e_som1 is not None: print "Zeroing empty can spectra" if tim is not None and e_som1 is not None: tim.getTime(False) cs_som = dr_lib.zero_spectra(e_som1, ctof_elastic_range) if tim is not None and e_som1 is not None: tim.getTime(msg="After zeroing empty can spectra") del ctof_elastic_range # Steps 20-21: Subtract background spectrum from empty can spectrum e_som2 = dr_lib.subtract_bkg_from_data(cs_som, bcs_som, verbose=config.verbose, timer=tim, dataset1="data-empty_can", dataset2="background", scale=config.scale_bcs) # Steps 22-23: Subtract background spectrum from empty can spectrum for # normalization try: config.pre_norm except AttributeError: config.pre_norm = False if not config.pre_norm: e_som3 = dr_lib.subtract_bkg_from_data(e_som1, b_som1, verbose=config.verbose, timer=tim, dataset1="norm-empty_can", dataset2="background", scale=config.scale_bcn) else: e_som3 = None # Steps 24-25: Subtract background spectrum from normalization spectrum if not config.pre_norm: n_som2 = dr_lib.subtract_bkg_from_data(n_som1, b_som1, verbose=config.verbose, timer=tim, dataset1="normalization", dataset2="background", scale=config.scale_bn) else: n_som2 = n_som1 del b_som1, e_som1, bcs_som, cs_som # Steps 26-27: Subtract empty can spectrum from sample spectrum d_som3 = dr_lib.subtract_bkg_from_data(d_som2, e_som2, verbose=config.verbose, timer=tim, dataset1="data", dataset2="empty_can", scale=config.scale_cs) del d_som2, e_som2 # Steps 28-29: Subtract empty can spectrum from normalization spectrum if not config.pre_norm: n_som3 = dr_lib.subtract_bkg_from_data(n_som2, e_som3, verbose=config.verbose, timer=tim, dataset1="normalization", dataset2="empty_can", scale=config.scale_cn) else: n_som3 = n_som2 del n_som2, e_som3 # Step 30-31: Integrate normalization spectra if config.verbose and n_som3 is not None and not config.pre_norm: print "Integrating normalization spectra" if not config.pre_norm: norm_int = dr_lib.integrate_spectra(n_som3, start=config.norm_start, end=config.norm_end, norm=True) else: norm_int = n_som3 del n_som3 # Step 32: Normalize data by integrated values if config.verbose and norm_int is not None: print "Normalizing data by normalization data" if norm_int is not None: d_som4 = common_lib.div_ncerr(d_som3, norm_int) else: d_som4 = d_som3 if norm_int is not None: if tim is not None: tim.getTime(msg="After normalizing data ") del d_som3, norm_int if config.dump_norm: if tim is not None: tim.getTime(False) hlr_utils.write_file(config.output, "text/Spec", d_som4, output_ext="wvn", data_ext=config.ext_replacement, path_replacement=config.path_replacement, verbose=config.verbose, message="wavelength (vanadium norm) information") if tim is not None: tim.getTime(msg="After writing wavelength (vanadium norm) info ") # Steps 33 to end: Creating S(Q,E) if config.Q_bins is not None: if config.verbose: print "Creating 2D spectrum" if tim is not None: tim.getTime(False) d_som5 = dr_lib.create_E_vs_Q_igs(d_som4, config.E_bins.toNessiList(), config.Q_bins.toNessiList(), so_id="Full Detector", y_label="counts", y_units="counts / (ueV * A^-1)", x_labels=["Q transfer", "energy transfer"], x_units=["1/Angstroms","ueV"], split=config.split, Q_filter=False, configure=config) if tim is not None: tim.getTime(msg="After creation of final spectrum ") del d_som4 # Steps 33 to 36: Create S(-cos(polar), E) elif config.ncospol_bins is not None: if config.verbose: print "Convert wavelength to energy transfer" if tim is not None: tim.getTime(False) d_som4a = dr_lib.energy_transfer(d_som4, "IGS", "Wavelength_final", sa_norm=True, scale=True, change_units=True) if tim is not None: tim.getTime(msg="After wavelength to energy transfer conversion ") del d_som4 if config.verbose: print "Creating 2D spectrum" if tim is not None: tim.getTime(False) d_som5 = dr_lib.create_param_vs_Y(d_som4a, "polar", "negcos_param_array", config.ncospol_bins.toNessiList(), rebin_axis=config.E_bins.toNessiList(), y_label="counts", y_units="counts / ueV", x_labels=["-cos(polar)", "Energy Transfer"], x_units=["", "ueV"]) if tim is not None: tim.getTime(msg="After creation of final spectrum ") # If rescaling factor present, rescale the data if config.rescale_final is not None and not config.split: d_som6 = common_lib.mult_ncerr(d_som5, (config.rescale_final, 0.0)) else: d_som6 = d_som5 if tim is None: old_time = None if not __name__ == "amorphous_reduction_sqe": del d_som5 __write_output(d_som6, config, tim, old_time) else: if config.create_output: del d_som5 __write_output(d_som6, config, tim, old_time) else: return d_som6
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