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 run(config, tim): """ This method is where the data reduction process gets done. @param config: Object containing the data reduction configuration information. @type config: L{hlr_utils.Configure} @param tim: Object that will allow the method to perform timing evaluations. @type tim: C{sns_time.DiffTime} """ import array_manip import common_lib import dr_lib import DST import SOM import math if tim is not None: tim.getTime(False) old_time = tim.getOldTime() if config.data is None: raise RuntimeError("Need to pass a data filename to the driver "\ +"script.") # Read in sample data geometry if one is provided if config.data_inst_geom is not None: if config.verbose: print "Reading in sample data instrument geometry file" data_inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.data_inst_geom) else: data_inst_geom_dst = None # Read in normalization data geometry if one is provided if config.norm_inst_geom is not None: if config.verbose: print "Reading in normalization instrument geometry file" norm_inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.norm_inst_geom) else: norm_inst_geom_dst = None # Perform Steps 1-2 on sample data d_som1 = dr_lib.process_reflp_data(config.data, config, None, config.dbkg_roi_file, config.no_bkg, inst_geom_dst=data_inst_geom_dst, timer=tim) # Get the detector angle if config.omega is None: # Make a fake SO so = SOM.SO() try: theta = hlr_utils.get_special(d_som1.attr_list["Theta"], so) except KeyError: theta = (float('nan'), float('nan')) else: theta = config.omega.toFullTuple() if theta[0] is not None: if theta[2] == "degrees" or theta[2] == "degree": theta_rads = (theta[0] * (math.pi / 180.0), 0.0) else: theta_rads = (theta[0], 0.0) else: theta_rads = (float('nan'), float('nan')) d_som1.attr_list["data-theta"] = (theta_rads[0], theta_rads[1], "radians") # Perform Steps 1-3 on normalization data if config.norm is not None: n_som1 = dr_lib.process_reflp_data(config.norm, config, config.norm_roi_file, config.nbkg_roi_file, config.no_norm_bkg, inst_geom_dst=norm_inst_geom_dst, timer=tim) else: n_som1 = None # Closing sample data instrument geometry file if data_inst_geom_dst is not None: data_inst_geom_dst.release_resource() # Closing normalization data instrument geometry file if norm_inst_geom_dst is not None: norm_inst_geom_dst.release_resource() # Step 4: Divide data by normalization if config.verbose and config.norm is not None: print "Scale data by normalization" if tim is not None: tim.getTime(False) if config.norm is not None: # Need to rebin the normalization spectra to the data pixel spectra n_som2 = dr_lib.rebin_monitor(n_som1, d_som1, rtype="frac") # Now divide the spectra d_som2 = common_lib.div_ncerr(d_som1, n_som2) del n_som2 else: d_som2 = d_som1 if tim is not None and config.norm is not None: tim.getTime(msg="After normalizing signal spectra") del d_som1, n_som1 sin_theta_rads = (math.sin(theta_rads[0]), math.sin(theta_rads[1])) if sin_theta_rads[0] < 0.0: sin_theta_rads = (math.fabs(sin_theta_rads[0]), math.fabs(sin_theta_rads[1])) # Step 6: Scale wavelength axis by sin(theta) to make lambda_T if config.verbose: print "Scaling wavelength axis by sin(theta)" if tim is not None: tim.getTime(False) d_som3 = common_lib.div_ncerr(d_som2, sin_theta_rads, axis="x") if tim is not None: tim.getTime(msg="After scaling wavelength axis ") del d_som2 d_som3.setAxisLabel(0, "lambda_T") # Step 7: Rebin to lambda_T axis if config.verbose: print "Rebinning spectra" if config.lambdap_bins is None: # Create a binning scheme pathlength = d_som3.attr_list.instrument.get_total_path( det_secondary=True) delta_lambda = common_lib.tof_to_wavelength((config.delta_TOF, 0.0), pathlength=pathlength) delta_lambdap = array_manip.div_ncerr(delta_lambda[0], delta_lambda[1], sin_theta_rads[0], 0.0) config.lambdap_bins = dr_lib.create_axis_from_data( d_som3, width=delta_lambdap[0]) else: # Do nothing, got the binning scheme pass if tim is not None: tim.getTime(False) d_som4 = common_lib.rebin_axis_1D_frac(d_som3, config.lambdap_bins.toNessiList()) if tim is not None: tim.getTime(msg="After rebinning spectra ") del d_som3 if config.inst == "REF_M": # Clean up spectrum if config.tof_cut_min is not None: tof_cut_min = float(config.tof_cut_min) else: tof_cut_min = config.TOF_min if config.tof_cut_max is not None: tof_cut_max = float(config.tof_cut_max) else: tof_cut_max = config.TOF_max pathlength = d_som4.attr_list.instrument.get_total_path( det_secondary=True) lambda_min = common_lib.tof_to_wavelength((tof_cut_min, 0.0), pathlength=pathlength) lambda_T_min = common_lib.div_ncerr(lambda_min, sin_theta_rads) lambda_max = common_lib.tof_to_wavelength((tof_cut_max, 0.0), pathlength=pathlength) lambda_T_max = common_lib.div_ncerr(lambda_max, sin_theta_rads) nz_list = [] for i in xrange(hlr_utils.get_length(d_som4)): nz_list.append((lambda_T_min[0], lambda_T_max[0])) d_som4A = dr_lib.zero_spectra(d_som4, nz_list) else: d_som4A = d_som4 del d_som4 # Step 8: Write out all spectra to a file hlr_utils.write_file(config.output, "text/Spec", d_som4A, replace_ext=False, replace_path=False, verbose=config.verbose, message="Reflectivity information") if config.dump_twod: d_som5 = dr_lib.create_X_vs_pixpos(d_som4A, config.lambdap_bins.toNessiList(), rebin=False, y_label="R", y_units="", x_label="$\lambda_T$", x_units="$\AA$") hlr_utils.write_file(config.output, "text/Dave2d", d_som5, output_ext="plp", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="2D Reflectivity information") d_som4A.attr_list["config"] = config hlr_utils.write_file(config.output, "text/rmd", d_som4A, output_ext="rmd", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="metadata") if tim is not None: tim.setOldTime(old_time) tim.getTime(msg="Total Running Time")
def add_files_dm(filelist, **kwargs): """ This function takes a list of U{NeXus<www.nexusformat.org>} files and various keyword arguments and returns a data C{SOM} and a monitor C{SOM} that is the sum of all the data from the specified files. B{It is assumed that the files contain similar data as only crude cross-checks will be made. You have been warned.} @param filelist: A list containing the names of the files to sum @type filelist: C{list} @param kwargs: A list of keyword arguments that the function accepts: @keyword SO_Axis: This is the name of the main axis to read from the NeXus file @type SO_Axis: C{string} @keyword Data_Paths: This contains the data paths and signals for the requested detector banks @type Data_Paths: C{tuple} of C{tuple}s @keyword Mon_Paths: This contains the data paths and signals for the requested monitor banks @type Mon_Paths: C{tuple} of C{tuple}s @keyword Signal_ROI: This is the name of a file that contains a list of pixel IDs that will be read from the data file and stored as a signal C{SOM} @type Signal_ROI: C{string} @keyword Signal_MASK: This is the name of a file that contains a list of pixel IDs that will be read from the data file and stored as a signal C{SOM} @type Signal_MASK: C{string} @keyword dataset_type: The practical name of the dataset being processed. The default value is I{data}. @type dataset_type: C{string} @keyword dataset_cwp: A set of chopper phase corrections for the dataset. This will instruct the function to shift the TOF axes of mulitple datasets and perform rebinning. The TOF axis for the first dataset is the one that all other datasets will be rebinned to. @type dataset_cwp: C{list} of C{float}s @keyword Verbose: This is a flag to turn on print statments. The default is I{False}. @type Verbose: C{boolean} @keyword Timer: This is an SNS Timer object used for showing the performance timing in the function. @type Timer: C{sns_timing.Timer} @return: Signal C{SOM.SOM} and monitor C{SOM.SOM} @rtype: C{tuple} @raise SystemExit: If any file cannot be read @raise RuntimeError: If both a ROI and MASK file are specified """ import sys import common_lib import DST # Parse keywords try: so_axis = kwargs["SO_Axis"] except KeyError: so_axis = "time_of_flight" try: data_paths = kwargs["Data_Paths"] except KeyError: data_paths = None try: mon_paths = kwargs["Mon_Paths"] except KeyError: mon_paths = None try: signal_roi = kwargs["Signal_ROI"] except KeyError: signal_roi = None try: signal_mask = kwargs["Signal_MASK"] except KeyError: signal_mask = None try: dataset_type = kwargs["dataset_type"] except KeyError: dataset_type = "data" try: verbose = kwargs["Verbose"] except KeyError: verbose = False try: timer = kwargs["Timer"] except KeyError: timer = None dataset_cwp = kwargs.get("dataset_cwp") if signal_roi is not None and signal_mask is not None: raise RuntimeError("Cannot specify both ROI and MASK file! Please "\ +"choose!") dst_type = "application/x-NeXus" counter = 0 for filename in filelist: if verbose: print "File:", filename if dataset_cwp is not None: print "TOF Offset:", dataset_cwp[counter] if dataset_cwp is not None: cwp = dataset_cwp[counter] else: cwp = None try: data_dst = DST.getInstance(dst_type, filename) except SystemError: print "ERROR: Failed to data read file %s" % filename sys.exit(-1) if timer is not None: timer.getTime(msg="After parsing file") if verbose: print "Reading data file %d" % counter if counter == 0: d_som1 = data_dst.getSOM(data_paths, so_axis, roi_file=signal_roi, mask_file=signal_mask, tof_offset=cwp) d_som1.rekeyNxPars(dataset_type) if verbose: print "# Signal SO:", len(d_som1) try: print "# TOF:", len(d_som1[0]) print "# TOF Axis:", len(d_som1[0].axis[0].val) except IndexError: # No data is present so say so again print "information is unavailable since no data "\ +"present. Exiting." sys.exit(0) if timer is not None: timer.getTime(msg="After reading data") if mon_paths is not None: if verbose: print "Reading monitor %d" % counter if counter == 0: m_som1 = data_dst.getSOM(mon_paths, so_axis, tof_offset=cwp) m_som1.rekeyNxPars(dataset_type) if verbose: print "# Monitor SO:", len(m_som1) print "# TOF:", len(m_som1[0]) print "# TOF Axis:", len(m_som1[0].axis[0].val) if timer is not None: timer.getTime(msg="After reading monitor data") else: m_som1 = None else: d_som_t0 = data_dst.getSOM(data_paths, so_axis, roi_file=signal_roi, mask_file=signal_mask, tof_offset=cwp) d_som_t0.rekeyNxPars(dataset_type) if timer is not None: timer.getTime(msg="After reading data") if dataset_cwp is not None: d_som_t = common_lib.rebin_axis_1D_frac( d_som_t0, d_som1[0].axis[0].val) del d_som_t0 else: d_som_t = d_som_t0 d_som1 = common_lib.add_ncerr(d_som_t, d_som1, add_nxpars=True) if timer is not None: timer.getTime(msg="After adding data spectra") del d_som_t if timer is not None: timer.getTime(msg="After data SOM deletion") if mon_paths is not None: m_som_t0 = data_dst.getSOM(mon_paths, so_axis, tof_offset=cwp) m_som_t0.rekeyNxPars(dataset_type) if timer is not None: timer.getTime(msg="After reading monitor data") if dataset_cwp is not None: m_som_t = common_lib.rebin_axis_1D_frac( m_som_t0, m_som1[0].axis[0].val) del m_som_t0 else: m_som_t = m_som_t0 m_som1 = common_lib.add_ncerr(m_som_t, m_som1, add_nxpars=True) if timer is not None: timer.getTime(msg="After adding monitor spectra") del m_som_t if timer is not None: timer.getTime(msg="After monitor SOM deletion") data_dst.release_resource() del data_dst counter += 1 if timer is not None: timer.getTime(msg="After resource release and DST deletion") som_key_parts = [dataset_type, "filename"] som_key = "-".join(som_key_parts) d_som1.attr_list[som_key] = filelist if m_som1 is not None: m_som1.attr_list[som_key] = filelist return (d_som1, m_som1)
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 run(config, tim): """ This method is where the data reduction process gets done. @param config: Object containing the data reduction configuration information. @type config: L{hlr_utils.Configure} @param tim: Object that will allow the method to perform timing evaluations. @type tim: C{sns_time.DiffTime} """ import array_manip import common_lib import dr_lib import DST import SOM import math if tim is not None: tim.getTime(False) old_time = tim.getOldTime() if config.data is None: raise RuntimeError("Need to pass a data filename to the driver "\ +"script.") # Read in sample data geometry if one is provided if config.data_inst_geom is not None: if config.verbose: print "Reading in sample data instrument geometry file" data_inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.data_inst_geom) else: data_inst_geom_dst = None # Read in normalization data geometry if one is provided if config.norm_inst_geom is not None: if config.verbose: print "Reading in normalization instrument geometry file" norm_inst_geom_dst = DST.getInstance("application/x-NxsGeom", config.norm_inst_geom) else: norm_inst_geom_dst = None # Perform Steps 1-2 on sample data d_som1 = dr_lib.process_reflp_data(config.data, config, None, config.dbkg_roi_file, config.no_bkg, inst_geom_dst=data_inst_geom_dst, timer=tim) # Get the detector angle if config.omega is None: # Make a fake SO so = SOM.SO() try: theta = hlr_utils.get_special(d_som1.attr_list["Theta"], so) except KeyError: theta = (float('nan'), float('nan')) else: theta = config.omega.toFullTuple() if theta[0] is not None: if theta[2] == "degrees" or theta[2] == "degree": theta_rads = (theta[0] * (math.pi / 180.0), 0.0) else: theta_rads = (theta[0], 0.0) else: theta_rads = (float('nan'), float('nan')) d_som1.attr_list["data-theta"] = (theta_rads[0], theta_rads[1], "radians") # Perform Steps 1-3 on normalization data if config.norm is not None: n_som1 = dr_lib.process_reflp_data(config.norm, config, config.norm_roi_file, config.nbkg_roi_file, config.no_norm_bkg, inst_geom_dst=norm_inst_geom_dst, timer=tim) else: n_som1 = None # Closing sample data instrument geometry file if data_inst_geom_dst is not None: data_inst_geom_dst.release_resource() # Closing normalization data instrument geometry file if norm_inst_geom_dst is not None: norm_inst_geom_dst.release_resource() # Step 4: Divide data by normalization if config.verbose and config.norm is not None: print "Scale data by normalization" if tim is not None: tim.getTime(False) if config.norm is not None: # Need to rebin the normalization spectra to the data pixel spectra n_som2 = dr_lib.rebin_monitor(n_som1, d_som1, rtype="frac") # Now divide the spectra d_som2 = common_lib.div_ncerr(d_som1, n_som2) del n_som2 else: d_som2 = d_som1 if tim is not None and config.norm is not None: tim.getTime(msg="After normalizing signal spectra") del d_som1, n_som1 sin_theta_rads = (math.sin(theta_rads[0]), math.sin(theta_rads[1])) if sin_theta_rads[0] < 0.0: sin_theta_rads = (math.fabs(sin_theta_rads[0]), math.fabs(sin_theta_rads[1])) # Step 6: Scale wavelength axis by sin(theta) to make lambda_T if config.verbose: print "Scaling wavelength axis by sin(theta)" if tim is not None: tim.getTime(False) d_som3 = common_lib.div_ncerr(d_som2, sin_theta_rads, axis="x") if tim is not None: tim.getTime(msg="After scaling wavelength axis ") del d_som2 d_som3.setAxisLabel(0, "lambda_T") # Step 7: Rebin to lambda_T axis if config.verbose: print "Rebinning spectra" if config.lambdap_bins is None: # Create a binning scheme pathlength = d_som3.attr_list.instrument.get_total_path( det_secondary=True) delta_lambda = common_lib.tof_to_wavelength((config.delta_TOF, 0.0), pathlength=pathlength) delta_lambdap = array_manip.div_ncerr(delta_lambda[0], delta_lambda[1], sin_theta_rads[0], 0.0) config.lambdap_bins = dr_lib.create_axis_from_data(d_som3, width=delta_lambdap[0]) else: # Do nothing, got the binning scheme pass if tim is not None: tim.getTime(False) d_som4 = common_lib.rebin_axis_1D_frac(d_som3, config.lambdap_bins.toNessiList()) if tim is not None: tim.getTime(msg="After rebinning spectra ") del d_som3 if config.inst == "REF_M": # Clean up spectrum if config.tof_cut_min is not None: tof_cut_min = float(config.tof_cut_min) else: tof_cut_min = config.TOF_min if config.tof_cut_max is not None: tof_cut_max = float(config.tof_cut_max) else: tof_cut_max = config.TOF_max pathlength = d_som4.attr_list.instrument.get_total_path( det_secondary=True) lambda_min = common_lib.tof_to_wavelength((tof_cut_min, 0.0), pathlength=pathlength) lambda_T_min = common_lib.div_ncerr(lambda_min, sin_theta_rads) lambda_max = common_lib.tof_to_wavelength((tof_cut_max, 0.0), pathlength=pathlength) lambda_T_max = common_lib.div_ncerr(lambda_max, sin_theta_rads) nz_list = [] for i in xrange(hlr_utils.get_length(d_som4)): nz_list.append((lambda_T_min[0], lambda_T_max[0])) d_som4A = dr_lib.zero_spectra(d_som4, nz_list) else: d_som4A = d_som4 del d_som4 # Step 8: Write out all spectra to a file hlr_utils.write_file(config.output, "text/Spec", d_som4A, replace_ext=False, replace_path=False, verbose=config.verbose, message="Reflectivity information") if config.dump_twod: d_som5 = dr_lib.create_X_vs_pixpos(d_som4A, config.lambdap_bins.toNessiList(), rebin=False, y_label="R", y_units="", x_label="$\lambda_T$", x_units="$\AA$") hlr_utils.write_file(config.output, "text/Dave2d", d_som5, output_ext="plp", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="2D Reflectivity information") d_som4A.attr_list["config"] = config hlr_utils.write_file(config.output, "text/rmd", d_som4A, output_ext="rmd", verbose=config.verbose, data_ext=config.ext_replacement, path_replacement=config.path_replacement, message="metadata") if tim is not None: tim.setOldTime(old_time) tim.getTime(msg="Total Running Time")
def process_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 add_files_dm(filelist, **kwargs): """ This function takes a list of U{NeXus<www.nexusformat.org>} files and various keyword arguments and returns a data C{SOM} and a monitor C{SOM} that is the sum of all the data from the specified files. B{It is assumed that the files contain similar data as only crude cross-checks will be made. You have been warned.} @param filelist: A list containing the names of the files to sum @type filelist: C{list} @param kwargs: A list of keyword arguments that the function accepts: @keyword SO_Axis: This is the name of the main axis to read from the NeXus file @type SO_Axis: C{string} @keyword Data_Paths: This contains the data paths and signals for the requested detector banks @type Data_Paths: C{tuple} of C{tuple}s @keyword Mon_Paths: This contains the data paths and signals for the requested monitor banks @type Mon_Paths: C{tuple} of C{tuple}s @keyword Signal_ROI: This is the name of a file that contains a list of pixel IDs that will be read from the data file and stored as a signal C{SOM} @type Signal_ROI: C{string} @keyword Signal_MASK: This is the name of a file that contains a list of pixel IDs that will be read from the data file and stored as a signal C{SOM} @type Signal_MASK: C{string} @keyword dataset_type: The practical name of the dataset being processed. The default value is I{data}. @type dataset_type: C{string} @keyword dataset_cwp: A set of chopper phase corrections for the dataset. This will instruct the function to shift the TOF axes of mulitple datasets and perform rebinning. The TOF axis for the first dataset is the one that all other datasets will be rebinned to. @type dataset_cwp: C{list} of C{float}s @keyword Verbose: This is a flag to turn on print statments. The default is I{False}. @type Verbose: C{boolean} @keyword Timer: This is an SNS Timer object used for showing the performance timing in the function. @type Timer: C{sns_timing.Timer} @return: Signal C{SOM.SOM} and monitor C{SOM.SOM} @rtype: C{tuple} @raise SystemExit: If any file cannot be read @raise RuntimeError: If both a ROI and MASK file are specified """ import sys import common_lib import DST # Parse keywords try: so_axis = kwargs["SO_Axis"] except KeyError: so_axis = "time_of_flight" try: data_paths = kwargs["Data_Paths"] except KeyError: data_paths = None try: mon_paths = kwargs["Mon_Paths"] except KeyError: mon_paths = None try: signal_roi = kwargs["Signal_ROI"] except KeyError: signal_roi = None try: signal_mask = kwargs["Signal_MASK"] except KeyError: signal_mask = None try: dataset_type = kwargs["dataset_type"] except KeyError: dataset_type = "data" try: verbose = kwargs["Verbose"] except KeyError: verbose = False try: timer = kwargs["Timer"] except KeyError: timer = None dataset_cwp = kwargs.get("dataset_cwp") if signal_roi is not None and signal_mask is not None: raise RuntimeError("Cannot specify both ROI and MASK file! Please "\ +"choose!") dst_type = "application/x-NeXus" counter = 0 for filename in filelist: if verbose: print "File:", filename if dataset_cwp is not None: print "TOF Offset:", dataset_cwp[counter] if dataset_cwp is not None: cwp = dataset_cwp[counter] else: cwp = None try: data_dst = DST.getInstance(dst_type, filename) except SystemError: print "ERROR: Failed to data read file %s" % filename sys.exit(-1) if timer is not None: timer.getTime(msg="After parsing file") if verbose: print "Reading data file %d" % counter if counter == 0: d_som1 = data_dst.getSOM(data_paths, so_axis, roi_file=signal_roi, mask_file=signal_mask, tof_offset=cwp) d_som1.rekeyNxPars(dataset_type) if verbose: print "# Signal SO:", len(d_som1) try: print "# TOF:", len(d_som1[0]) print "# TOF Axis:", len(d_som1[0].axis[0].val) except IndexError: # No data is present so say so again print "information is unavailable since no data "\ +"present. Exiting." sys.exit(0) if timer is not None: timer.getTime(msg="After reading data") if mon_paths is not None: if verbose: print "Reading monitor %d" % counter if counter == 0: m_som1 = data_dst.getSOM(mon_paths, so_axis, tof_offset=cwp) m_som1.rekeyNxPars(dataset_type) if verbose: print "# Monitor SO:", len(m_som1) print "# TOF:", len(m_som1[0]) print "# TOF Axis:", len(m_som1[0].axis[0].val) if timer is not None: timer.getTime(msg="After reading monitor data") else: m_som1 = None else: d_som_t0 = data_dst.getSOM(data_paths, so_axis, roi_file=signal_roi, mask_file=signal_mask, tof_offset=cwp) d_som_t0.rekeyNxPars(dataset_type) if timer is not None: timer.getTime(msg="After reading data") if dataset_cwp is not None: d_som_t = common_lib.rebin_axis_1D_frac(d_som_t0, d_som1[0].axis[0].val) del d_som_t0 else: d_som_t = d_som_t0 d_som1 = common_lib.add_ncerr(d_som_t, d_som1, add_nxpars=True) if timer is not None: timer.getTime(msg="After adding data spectra") del d_som_t if timer is not None: timer.getTime(msg="After data SOM deletion") if mon_paths is not None: m_som_t0 = data_dst.getSOM(mon_paths, so_axis, tof_offset=cwp) m_som_t0.rekeyNxPars(dataset_type) if timer is not None: timer.getTime(msg="After reading monitor data") if dataset_cwp is not None: m_som_t = common_lib.rebin_axis_1D_frac(m_som_t0, m_som1[0].axis[0].val) del m_som_t0 else: m_som_t = m_som_t0 m_som1 = common_lib.add_ncerr(m_som_t, m_som1, add_nxpars=True) if timer is not None: timer.getTime(msg="After adding monitor spectra") del m_som_t if timer is not None: timer.getTime(msg="After monitor SOM deletion") data_dst.release_resource() del data_dst counter += 1 if timer is not None: timer.getTime(msg="After resource release and DST deletion") som_key_parts = [dataset_type, "filename"] som_key = "-".join(som_key_parts) d_som1.attr_list[som_key] = filelist if m_som1 is not None: m_som1.attr_list[som_key] = filelist return (d_som1, m_som1)