def do_white(self, white_run, spectra_masks, map_file): """ Normalise to a specified white-beam run """ whitews_name = common.create_resultname(white_run, suffix='-white') if mtd.workspaceExists(whitews_name): return mtd[whitews_name] # Load white_data = self.load_data(white_run) # Normalise white_ws = self.normalise(white_data, whitews_name, self.normalise_method) # Units conversion ConvertUnits(white_ws, white_ws, "Energy", AlignBins=0) # This both integrates the workspace into one bin spectra and sets up common bin boundaries for all spectra low = self.wb_integr_range[0] upp = self.wb_integr_range[1] if low > upp: raise ValueError("White beam integration range is inconsistent. low=%d, upp=%d" % (low,upp)) delta = 2.0*(upp - low) Rebin(white_ws, white_ws, [low, delta, upp]) # Why aren't we doing this... #Integration(white_ws, white_ws, RangeLower=low, RangeUpper=upp) # Masking and grouping white_ws = self.remap(white_ws, spectra_masks, map_file) # White beam scale factor white_ws *= self.wb_scale_factor return white_ws
def convert_to_energy(self, mono_run, ei, white_run=None, mono_van=None,\ abs_ei=None, abs_white_run=None, save_path=None, Tzero=None, \ motor=None, offset=None): """ One-shot function to convert the given runs to energy """ # Check if we need to perform the absolute normalisation first if not mono_van is None: if abs_ei is None: abs_ei = ei mapping_file = self.abs_map_file spectrum_masks = self.spectra_masks monovan_wkspace = self.mono_van(mono_van, abs_ei, abs_white_run, mapping_file, spectrum_masks) # TODO: Need a better check than this... if (abs_white_run is None): self.log("Performing Normalisation to Mono Vanadium.") norm_factor = self.calc_average(monovan_wkspace) else: self.log("Performing Absolute Units Normalisation.") # Perform Abs Units... norm_factor = self.monovan_abs(monovan_wkspace) mtd.deleteWorkspace(monovan_wkspace.getName()) else: norm_factor = None # Figure out what to call the workspace result_name = mono_run if not result_name is None: result_name = common.create_resultname(mono_run) # Main run file conversion sample_wkspace = self.mono_sample(mono_run, ei, white_run, self.map_file, self.spectra_masks, result_name, Tzero) if not norm_factor is None: sample_wkspace /= norm_factor #calculate psi from sample environment motor and offset if (offset is None): self.motor_offset = 0 else: self.motor_offset = float(offset) self.motor=0 if not (motor is None): # Check if motor name exists if sample_wkspace.getRun().hasProperty(motor): self.motor=sample_wkspace.getRun()[motor].value[0] self.log("Motor value is %s" % self.motor) else: self.log("Could not find such sample environment log. Will use psi=offset") self.psi = self.motor+self.motor_offset # Save then finish self.save_results(sample_wkspace, save_path) # Clear loaded raw data to free up memory common.clear_loaded_data() return sample_wkspace
def mono_sample(self, mono_run, ei_guess, white_run=None, map_file=None, spectra_masks=None, result_name=None, Tzero=None): """Convert a mono-chromatic sample run to DeltaE. If multiple run files are passed to this function, they are summed into a run and then processed """ # Load data sample_data = self.load_data(mono_run) # Create the result name if necessary if result_name is None: result_name = common.create_resultname(mono_run, prefix=self.instr_name) return self._do_mono(sample_data, sample_data, result_name, ei_guess, white_run, map_file, spectra_masks, Tzero)
def mono_van(self, mono_van, ei_guess, white_run=None, map_file=None, spectra_masks=None, result_name=None, Tzero=None): """Convert a mono vanadium run to DeltaE. If multiple run files are passed to this function, they are summed into a run and then processed """ # Load data sample_data = self.load_data(mono_van) # Create the result name if necessary if result_name is None: result_name = common.create_resultname(mono_van) monovan = self._do_mono(sample_data, sample_data, result_name, ei_guess, white_run, map_file, spectra_masks, Tzero) # Normalize by vanadium sample weight monovan /= float(self.van_mass)/float(self.van_rmm) return monovan
def apply_absolute_normalization(Reducer,deltaE_wkspace_sample,monovan_run,ei_guess,wb_mono): """ Function applies absolute normalization factor to the target workspace and calculates this factor if necessary Inputs: Reducer -- properly initialized class which performs reduction deltaE_wkspace_sample-- the workspace which should be modified monovan_run -- run number for monochromatic vanadium sample at current energy ei_guess -- estimated neutrons incident energy wb_mono -- white bean vanadium run number. """ if Reducer.mono_correction_factor != None : absnorm_factor=float(Reducer.mono_correction_factor) Reducer.log('##### Using supplied workspace correction factor ######') Reducer.log(' Value : '+str(absnorm_factor)) else: Reducer.log('##### Evaluate the integral from the monovan run and calculate the correction factor ######') Reducer.log(' Using absolute units vanadium integration range : '+str(Reducer.monovan_integr_range)) # result_ws_name = common.create_resultname(monovan_run) # check the case when the sample is monovan itself (for testing purposes) if result_ws_name == deltaE_wkspace_sample.name() : deltaE_wkspace_monovan = CloneWorkspace(InputWorkspace=deltaE_wkspace_sample,OutputWorkspace=result_ws_name+'-monovan'); deltaE_wkspace_monovan=Reducer.remap(deltaE_wkspace_monovan,None,Reducer.monovan_mapfile) else: # convert to monovan to energy map_file = Reducer.map_file; Reducer.map_file = Reducer.monovan_mapfile; deltaE_wkspace_monovan = Reducer.convert_to_energy(monovan_run, ei_guess, wb_mono) Reducer.map_file = map_file ei_monovan = deltaE_wkspace_monovan.getRun().getLogData("Ei").value Reducer.log(' Incident energy found for monovanadium run: '+str(ei_monovan)+' meV') (absnorm_factorL,absnorm_factorSS,absnorm_factorP,absnorm_factTGP) = get_abs_normalization_factor(Reducer,deltaE_wkspace_monovan.getName(),ei_monovan) Reducer.log('Absolute correction factor S^2: {0:10.4f} Libisis: {1:10.4f} Puasonian: {2:10.4f} TGP: {3:10.4f} '.format(absnorm_factorSS,absnorm_factorL,absnorm_factorP,absnorm_factTGP)) absnorm_factor = absnorm_factTGP; deltaE_wkspace_sample = deltaE_wkspace_sample/absnorm_factor; return deltaE_wkspace_sample
def arb_units(wb_run,sample_run,ei_guess,rebin,map_file='default',monovan_run=None,**kwargs): """ One step conversion of run into workspace containing information about energy transfer Usage: >>arb_units(wb_run,sample_run,ei_guess,rebin) >>arb_units(wb_run,sample_run,ei_guess,rebin,**arguments) >>arb_units(wb_run,sample_run,ei_guess,rebin,mapfile,**arguments) >>arb_units(wb_run Whitebeam run number or file name or workspace sample_run sample run number or file name or workspace ei_guess Ei guess rebin Rebin parameters mapfile Mapfile -- if absent/'default' the defaults from IDF are used monovan_run If present will do the absolute units normalization. Number of additional parameters specified in **kwargs is usually requested for this. If they are absent, program uses defaults, but the defaults (e.g. sample_mass or sample_rmm ) are usually incorrect for a particular run. arguments The dictionary containing additional keyword arguments. The list of allowed additional arguments is defined in InstrName_Parameters.xml file, located in MantidPlot->View->Preferences->Mantid->Directories->Parameter Definitions with run numbers as input: >>dgreduce.arb_units(1000,10001,80,[-10,.1,70]) # will run on default instrument >>dgreduce.arb_units(1000,10001,80,[-10,.1,70],'mari_res', additional keywords as required) >>dgreduce.arb_units(1000,10001,80,'-10,.1,70','mari_res',fixei=True) A detector calibration file must be specified if running the reduction with workspaces as input namely: >>w2=iliad("wb_wksp","run_wksp",ei,rebin_params,mapfile,det_cal_file=cal_file ,diag_remove_zero=False,norm_method='current') type help() for the list of all available keywords. All availible keywords are provided in InstName_Parameters.xml file Some samples are: norm_method =[monitor-1],[monitor-2][Current] background =False , True fixei =False , True save_format =['.spe'],['.nxspe'],'none' detector_van_range =[20,40] in mev bkgd_range =[15000,19000] :integration range for background tests second_white - If provided an additional set of tests is performed on this. (default = None) hardmaskPlus - A file specifying those spectra that should be masked without testing (default=None) tiny - Minimum threshold for acceptance (default = 1e-10) large - Maximum threshold for acceptance (default = 1e10) bkgd_range - A list of two numbers indicating the background range (default=instrument defaults) diag_van_median_rate_limit_lo - Lower bound defining outliers as fraction of median value (default = 0.01) diag_van_median_rate_limit_hi - Upper bound defining outliers as fraction of median value (default = 100.) diag_van_median_sigma_lo - Fraction of median to consider counting low for the white beam diag (default = 0.1) diag_van_median_sigma_hi - Fraction of median to consider counting high for the white beam diag (default = 1.5) diag_van_sig - Error criterion as a multiple of error bar i.e. to fail the test, the magnitude of the difference with respect to the median value must also exceed this number of error bars (default=0.0) diag_remove_zero - If true then zeroes in the vanadium data will count as failed (default = True) diag_samp_samp_median_sigma_lo - Fraction of median to consider counting low for the white beam diag (default = 0) diag_samp_samp_median_sigma_hi - Fraction of median to consider counting high for the white beam diag (default = 2.0) diag_samp_sig - Error criterion as a multiple of error bar i.e. to fail the test, the magnitude of the" difference with respect to the median value must also exceed this number of error bars (default=3.3) variation -The number of medians the ratio of the first/second white beam can deviate from the average by (default=1.1) bleed_test - If true then the CreatePSDBleedMask algorithm is run bleed_maxrate - If the bleed test is on then this is the maximum framerate allowed in a tube bleed_pixels - If the bleed test is on then this is the number of pixels ignored within the bleed test diagnostic print_results - If True then the results are printed to the screen diag_remove_zero =True, False (default):Diag zero counts in background range bleed=True , turn bleed correction on and off on by default for Merlin and LET sum =True,False(default) , sum multiple files det_cal_file= a valid detector block file and path or a raw file. Setting this will use the detector calibraion from the specified file NOT the input raw file mask_run = RunNumber to use for diag instead of the input run number one2one =True, False :Reduction will not use a mapping file hardmaskPlus=Filename :load a hardmarkfile and apply together with diag mask hardmaskOnly=Filename :load a hardmask and use as only mask """ global Reducer if Reducer is None or Reducer.instrument is None: raise ValueError("instrument has not been defined, call setup(instrument_name) first.") # -------------------------------------------------------------------------------------------------------- # Deal with mandatory parameters for this and may be some top level procedures # -------------------------------------------------------------------------------------------------------- Reducer.log("****************************************************************"); if isinstance(sample_run,api.Workspace) or (isinstance(sample_run,str) and sample_run in mtd): Reducer.log('*** DGreduce run for: {0:>20} : Workspace name: {1:<20} '.format(Reducer.instr_name,str(sample_run))) else: Reducer.log('*** DGreduce run for: {0:>20} : Run number/s : {1:<20} '.format(Reducer.instr_name,str(sample_run))) try: n,r=funcreturns.lhs_info('both') wksp_out=r[0] except: if sample_run == 0: #deal with the current run being parsed as 0 rather than 00000 sample_run='00000' wksp_out=Reducer.instr_name+str(sample_run)+'.spe' if kwargs.has_key('sum') and kwargs.get('sum')==True: wksp_out=inst_name+str(sample_run[0])+'sum'+'.spe' start_time=time.time() if sample_run=='00000' and mtd.doesExist(inst_name+'00000.raw')==True: Reducer.log('Deleting previous instance of temp data') DeleteWorkspace(Workspace=inst_name+'00000.raw') # we may want to run absolute units normalization and this function has been called with monovan run or helper procedure abs_units_defaults_check = False if monovan_run != None : # check if mono-vanadium is provided as multiple files list or just put in brackets occasionally Reducer.log("****************************************************************"); Reducer.log('*** Output will be in absolute units of mb/str/mev/fu') if isinstance(monovan_run,list): if len(monovan_run)>1: raise IOError(' Can currently work only with single monovan file but list supplied') else: monovan_run = monovan_run[0]; abs_units_defaults_check =True if '_defaults_have_changed' in kwargs: del kwargs['_defaults_have_changed'] abs_units_defaults_check =False if "wb_for_monovanadium" in kwargs : wb_for_monovanadium = kwargs['wb_for_monovanadium'] del kwargs['wb_for_monovanadium'] else: wb_for_monovanadium = wb_run; if isinstance(ei_guess,str): ei_guess = float(ei_guess) # set rebinning range Reducer.energy_bins = rebin Reducer.incident_energy = ei_guess; if Reducer.energy_bins[2] > ei_guess: Reducer.log('Error: rebin max rebin range {0:f} exceeds incident energy {1:f}'.format(Reducer.energy_bins[2],ei_guess),'Error') return # Process old legacy parameters which are easy to re-define in dgreduce rather then transfer through Mantid program_args = process_legacy_parameters(**kwargs) # set non-default reducers parameters and check if all optional keys provided as parameters are acceptable and have been defined in IDF changed_Keys=Reducer.set_input_parameters(**program_args); # inform user about changed parameters Reducer.log("*** Provisional Incident energy: {0:>12.3f} mEv".format(ei_guess)) Reducer.log("****************************************************************"); for key in changed_Keys: val = getattr(Reducer,key); Reducer.log(" Value of : {0:<25} is set to : {1:<20} ".format(key,val)) save_dir = config.getString('defaultsave.directory') Reducer.log("****************************************************************"); if monovan_run != None and not('van_mass' in changed_Keys or 'vanadium-mass' in changed_Keys) : Reducer.log("*** Monochromatic vanadium mass used : {0} ".format(Reducer.van_mass)) Reducer.log("*** By default results are saved into: {0}".format(save_dir)); Reducer.log("****************************************************************"); #do we run absolute units normalization and need to warn users if the parameters needed for that have not changed from defaults if abs_units_defaults_check : Reducer.check_abs_norm_defaults_changed(changed_Keys); #process complex parameters # map file given in parameters overrides default map file if map_file != 'default' : Reducer.map_file = map_file # defaults can be None too, but can be a file if Reducer.map_file == None: Reducer.log('one2one map selected') if Reducer.det_cal_file != None : if isinstance(Reducer.det_cal_file,str) and not Reducer.det_cal_file in mtd : # it is a file Reducer.log('Setting detector calibration file to '+Reducer.det_cal_file) else: Reducer.log('Setting detector calibration to {0}, which is probably a workspace '.format(str(Reducer.det_cal_file))) else: Reducer.log('Setting detector calibration to detector block info from '+str(sample_run)) # check if reducer can find all non-run files necessary for the reduction before starting long run. Reducer.check_necessary_files(monovan_run); print 'Output will be normalized to', Reducer.normalise_method if (numpy.size(sample_run)) > 1 and Reducer.sum_runs: #this sums the runs together before passing the summed file to the rest of the reduction #this circumvents the inbuilt method of summing which fails to sum the files for diag #the D.E.C. tries to be too clever so we have to fool it into thinking the raw file is already exists as a workpsace sumfilename=Reducer.instr_name+str(sample_run[0])+'.raw' sample_run =sum_files(Reducer.instr_name,sumfilename, sample_run) common.apply_calibration(Reducer.instr_name,sample_run,Reducer.det_cal_file) #sample_run = RenameWorkspace(InputWorkspace=accum,OutputWorkspace=inst_name+str(sample_run[0])+'.raw') if Reducer.mask_run == None : mask_run=sample_run masking = None; masks_done=False if not Reducer.run_diagnostics: header="Diagnostics including hard masking is skipped " masks_done = True; if Reducer.save_and_reuse_masks : raise NotImplementedError("Save and reuse masks option is not yet implemented") mask_file_name = common.create_resultname(str(mask_run),Reducer.instr_name,'_masks.xml') mask_full_file = FileFinder.getFullPath(mask_file_name) if len(mask_full_file) > 0 : masking = LoadMask(Instrument=Reducer.instr_name,InputFile=mask_full_file,OutputWorkspace=mask_file_name) #Reducer.hard_mask_file = mask_full_file; #Reducer.use_hard_mask_only = True masks_done=True header="Masking fully skipped and processed {0} spectra and {1} bad spectra " else: pass #------------------------------------------------------------------------------------------------------------------------------------------------------- # Here we give control to the Reducer # -------------------------------------------------------------------------------------------------------- # diag the sample and detector vanadium. It will deal with hard mask only if it is set that way if not masks_done: print '########### Run diagnose for sample run ##############################' masking = Reducer.diagnose(wb_run,sample = mask_run, second_white = None,print_results=True) header = "Diag Processed workspace with {0:d} spectra and masked {1:d} bad spectra" # Calculate absolute units: if monovan_run != None : if Reducer.mono_correction_factor == None : if Reducer.use_sam_msk_on_monovan == True: Reducer.log(' Applying sample run mask to mono van') else: if not Reducer.use_hard_mask_only : # in this case the masking2 is different but points to the same workspace Should be better soulution for that. print '########### Run diagnose for monochromatic vanadium run ##############' masking2 = Reducer.diagnose(wb_for_monovanadium,sample=monovan_run, second_white = None,rint_results=True) masking += masking2 DeleteWorkspace(masking2) else: # if Reducer.mono_correction_factor != None : pass # save mask if it does not exist and has been already loaded if Reducer.save_and_reuse_masks and not masks_done: SaveMask(InputWorkspace=masking,OutputFile = mask_file_name,GroupedDetectors=True) # Very important statement propagating masks for further usage in convert_to_energy Reducer.spectra_masks=masking # estimate and report the number of failing detectors failed_sp_list,nSpectra = get_failed_spectra_list_from_masks(masking) nMaskedSpectra = len(failed_sp_list) # this tells turkey in case of hard mask only but everything else semens work fine print header.format(nSpectra,nMaskedSpectra) #Run the conversion first on the sample deltaE_wkspace_sample = Reducer.convert_to_energy(sample_run, ei_guess, wb_run) # calculate absolute units integral and apply it to the workspace if monovan_run != None or Reducer.mono_correction_factor != None : deltaE_wkspace_sample = apply_absolute_normalization(Reducer,deltaE_wkspace_sample,monovan_run,ei_guess,wb_run) # Hack for multirep #if isinstance(monovan_run,int): # filename = common.find_file(monovan_run) # output_name = common.create_dataname(filename); # DeleteWorkspace(output_name); results_name = deltaE_wkspace_sample.name(); if results_name != wksp_out: RenameWorkspace(InputWorkspace=results_name,OutputWorkspace=wksp_out) ei= (deltaE_wkspace_sample.getRun().getLogData("Ei").value) print 'Incident energy found for sample run: ',ei,' meV' end_time=time.time() print 'Elapsed time =',end_time-start_time, 's' if mtd.doesExist('_wksp.spe-white')==True: DeleteWorkspace(Workspace='_wksp.spe-white') # Hack for multirep mode? if mtd.doesExist('hard_mask_ws') == True: DeleteWorkspace(Workspace='hard_mask_ws') return deltaE_wkspace_sample