def test_temperature_log_is_time_series(self): outputWorkspaceName = "output_ws" EditInstrumentGeometry(self._input_ws, L2="4,8", Polar="0,15", Azimuthal="0,0", DetectorIDs="1,2") AddTimeSeriesLog(self._input_ws, 'temperature', '2010-09-14T04:20:12', Value='0.0') AddTimeSeriesLog(self._input_ws, 'temperature', '2010-09-14T04:20:13', Value='0.0') AddTimeSeriesLog(self._input_ws, 'temperature', '2010-09-14T04:20:14', Value='0.0') alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws, EPPTable=self._table, OutputWorkspace=outputWorkspaceName) self.assertTrue(alg_test.isExecuted()) wsoutput = AnalysisDataService.retrieve(outputWorkspaceName) self._checkDWF(wsoutput, 0.0)
def __loadCacheFile(self, filename, wkspname): '''@returns True if a file was loaded''' if os.path.exists(filename): self.log().notice('Loading cache from {}'.format(filename)) else: return False LoadNexusProcessed(Filename=filename, OutputWorkspace=wkspname) # TODO LoadNexusProcessed has a bug. When it finds the # instrument name without xml it reads in from an IDF # in the instrument directory. editinstrargs = {} for name in PROPS_FOR_INSTR: prop = self.getProperty(name) if not prop.isDefault: editinstrargs[name] = prop.value if editinstrargs: try: EditInstrumentGeometry(Workspace=wkspname, **editinstrargs) except RuntimeError as e: # treat this as a non-fatal error self.log().warning( 'Failed to update instrument geometry in cache file: {}'. format(e)) return True
def test_dwf(self): outputWorkspaceName = "output_ws" # change theta to make dwf != 1 EditInstrumentGeometry(self._input_ws, L2="4,8", Polar="0,15", Azimuthal="0,0", DetectorIDs="1,2") alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws, EPPTable=self._table, OutputWorkspace=outputWorkspaceName) self.assertTrue(alg_test.isExecuted()) wsoutput = AnalysisDataService.retrieve(outputWorkspaceName) # check dwf calculation y_sum = sum(self._input_ws.readY(1)[27:75]) mvan = 0.001 * 50.942 / N_A Bcoef = 4.736767162094296 * 1e+20 * hbar * hbar / (2.0 * mvan * k * 389.0) dwf = np.exp(-1.0 * Bcoef * (4.0 * np.pi * np.sin(0.5 * np.radians(15.0)) / 4.0)**2) self.assertAlmostEqual(y_sum * dwf, wsoutput.readY(1)[0]) DeleteWorkspace(wsoutput)
def test_temperature_from_sample_log(self): self._input_ws.mutableRun().addProperty('temperature', 0.0, True) outputWorkspaceName = "output_ws" EditInstrumentGeometry(self._input_ws, L2="4,8", Polar="0,15", Azimuthal="0,0", DetectorIDs="1,2") alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws, EPPTable=self._table, OutputWorkspace=outputWorkspaceName) self.assertTrue(alg_test.isExecuted()) wsoutput = AnalysisDataService.retrieve(outputWorkspaceName) self._checkDWF(wsoutput, 0.0) DeleteWorkspace(wsoutput)
def test_dwf_using_default_temperature(self): outputWorkspaceName = "output_ws" # change theta to make dwf != 1 EditInstrumentGeometry(self._input_ws, L2="4,8", Polar="0,15", Azimuthal="0,0", DetectorIDs="1,2") alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws, EPPTable=self._table, OutputWorkspace=outputWorkspaceName) self.assertTrue(alg_test.isExecuted()) wsoutput = AnalysisDataService.retrieve(outputWorkspaceName) self._checkDWF(wsoutput, 293.0) DeleteWorkspace(wsoutput)
def focus_workspace_list(self, ws_name_list, gsas_ws_name_list, group_ws_name): """ Do diffraction focus on a list workspaces and also convert them to IDL GSAS This is the main execution body to be executed in multi-threading environment :param ws_name_list: :param gsas_ws_name_list: name for GSAS :param group_ws_name: name for grouping workspace :return: """ datatypeutility.check_list('Workspace names', ws_name_list) datatypeutility.check_list('(Output) GSAS workspace name list', gsas_ws_name_list) if len(ws_name_list) != len(gsas_ws_name_list): raise RuntimeError('Input workspace names {} have different number than output GSAS workspace names {}' ''.format(ws_name_list, gsas_ws_name_list)) for index in range(len(ws_name_list)): # set GSAS workspace name same as input workspace name ws_name = ws_name_list[index] gsas_ws_name_list[index] = ws_name gsas_ws_name = ws_name datatypeutility.check_string_variable('Workspace name', ws_name) datatypeutility.check_string_variable('Output GSAS workspace name', gsas_ws_name) # skip empty workspace name that might be returned from FilterEvents if len(ws_name) == 0: continue # focus (simple) it is the same but simplied version in diffraction_focus() ConvertUnits(InputWorkspace=ws_name, OutputWorkspace=ws_name, Target='dSpacing') # diffraction focus DiffractionFocussing(InputWorkspace=ws_name, OutputWorkspace=ws_name, GroupingWorkspace=group_ws_name) # convert unit to TOF ConvertUnits(InputWorkspace=ws_name, OutputWorkspace=ws_name, Target='TOF', ConvertFromPointData=False) # edit instrument try: EditInstrumentGeometry(Workspace=ws_name, PrimaryFlightPath=self._focus_instrument_dict['L1'], SpectrumIDs=self._focus_instrument_dict['SpectrumIDs'], L2=self._focus_instrument_dict['L2'], Polar=self._focus_instrument_dict['Polar'], Azimuthal=self._focus_instrument_dict['Azimuthal']) except RuntimeError as run_err: print('[WARNING] Non-critical error from EditInstrumentGeometry for {}: {}' ''.format(ws_name, run_err)) # END-FOR return
def test_MARI_axis_cylinder(self): """ Test that default axis for MARI is different""" ash = Cylinder('Fe', [10, 2]) res = ash.shape self.assertEqual(res['Height'], 10) self.assertEqual(res['Radius'], 2) self.assertTrue(ash._axis_is_default) test_ws = CreateSampleWorkspace(NumBanks=1, BankPixelWidth=1) test_ws = ConvertUnits(test_ws, 'DeltaE', Emode='Direct', EFixed=2000) cor_ws, corrections = ash.correct_absorption(test_ws, is_fast=True) res = ash.shape self.assertEqual(res['Axis'], [0., 1., 0]) EditInstrumentGeometry(test_ws, [1], [0], InstrumentName='MARI') cor_ws, corrections = ash.correct_absorption(test_ws, is_fast=True) res = ash.shape self.assertEqual(res['Axis'], [1., 0., 0])
def test_disabled_debye_waller_correction(self): outputWorkspaceName = "output_ws" # change theta to make dwf != 1 EditInstrumentGeometry(self._input_ws, L2="4,8", Polar="0,15", Azimuthal="0,0", DetectorIDs="1,2") alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws, EPPTable=self._table, OutputWorkspace=outputWorkspaceName, EnableDWF=False) self.assertTrue(alg_test.isExecuted()) wsoutput = AnalysisDataService.retrieve(outputWorkspaceName) for i in range(wsoutput.getNumberHistograms()): self.assertEqual(100., wsoutput.readY(i)[0]) self.assertEqual(10., wsoutput.readE(i)[0]) DeleteWorkspace(wsoutput)
def test_temperature_log_name_from_IPF(self): self._input_ws.mutableRun().addProperty('sample.temperature', 0.0, True) EditInstrumentGeometry(self._input_ws, L2="4,8", Polar="0,15", Azimuthal="0,0", DetectorIDs="1,2") SetInstrumentParameter( Workspace=self._input_ws, ParameterName="temperature_log_entry", ParameterType="String", Value="sample.temperature") outputWorkspaceName = "output_ws" alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws, EPPTable=self._table, OutputWorkspace=outputWorkspaceName) self.assertTrue(alg_test.isExecuted()) wsoutput = AnalysisDataService.retrieve(outputWorkspaceName) self._checkDWF(wsoutput, 0.)
def create_test_ws(): """ This creates a workspace with 19 detectors with 2theta from every 5 degress from 0 to 90 """ wavelength = 1.7982 nspec = 19 ws = CreateWorkspace(DataX=[wavelength - 0.0001, wavelength + 0.0001], DataY=[0.0] * nspec, NSpec=nspec, UnitX="Wavelength", YUnitLabel="Counts") EditInstrumentGeometry(ws, PrimaryFlightPath=5.0, SpectrumIDs=list(range(1, nspec+1)), L2=[2.0]*nspec, Polar=list(range(0, 181, 10)), Azimuthal=[0.0]*nspec, DetectorIDs=list(range(1, nspec+1)), InstrumentName="Instrument") return ws
def live_reduce(self, input_ws, output_ws): ws = input_ws counter_ws = mtd['counter'] index = int(counter_ws.readX(0)[0]) print('index = ', index) counter_ws.dataX(0)[0] += 1 print('Iteration {0}: Number of events = {1}'.format(index, ws.getNumberEvents())) curr_ws_name = 'output_{0}'.format(index) CloneWorkspace(InputWorkspace=input_ws, OutputWorkspace=curr_ws_name) Rebin(InputWorkspace=input_ws, OutputWorkspace=output_ws, Params='5000., -0.001, 50000.') AlignAndFocusPowder(InputWorkspace=mtd[curr_ws_name], OutputWorkspace=curr_ws_name, CalFileName='/SNS/VULCAN/shared/CALIBRATION/2017_8_11_CAL/VULCAN_calibrate_2017_08_17.h5', Params='-0.001', DMin='0.5', DMax='3.5', PreserveEvents=False) # PrimaryFlightPath=43, SpectrumIDs='0-2', L2='2,2,2', Polar='90,270,145', Azimuthal='0, 0, 0') print('[SpecialDebug] Interface... EditInstrument on {0}'.format(curr_ws_name)) EditInstrumentGeometry(Workspace=curr_ws_name, PrimaryFlightPath=43.753999999999998, SpectrumIDs='1,2,3', L2='2.00944,2.00944,2.00944', Polar='90,270,150')
def PyExec(self): # Retrieve all relevant notice in_Runs = self.getProperty("RunNumbers").value maskWSname = self._getMaskWSname() # either type of file-based calibration is stored in the same variable calib = self.getProperty("Calibration").value if calib == "Calibration File": cal_File = self.getProperty("CalibrationFilename").value elif calib == 'DetCal File': cal_File = self.getProperty('DetCalFilename').value cal_File = ','.join(cal_File) else: cal_File = None params = self.getProperty("Binning").value norm = self.getProperty("Normalization").value if norm == "From Processed Nexus": norm_File = self.getProperty("NormalizationFilename").value LoadNexusProcessed(Filename=norm_File, OutputWorkspace='normWS') normWS = 'normWS' elif norm == "From Workspace": normWS = str(self.getProperty("NormalizationWorkspace").value) else: normWS = None group_to_real = { 'Banks': 'Group', 'Modules': 'bank', '2_4 Grouping': '2_4Grouping' } group = self.getProperty('GroupDetectorsBy').value real_name = group_to_real.get(group, group) if not mtd.doesExist(group): if group == '2_4 Grouping': group = '2_4_Grouping' CreateGroupingWorkspace(InstrumentName='SNAP', GroupDetectorsBy=real_name, OutputWorkspace=group) Process_Mode = self.getProperty("ProcessingMode").value prefix = self.getProperty("OptionalPrefix").value # --------------------------- REDUCE DATA ----------------------------- Tag = 'SNAP' for r in in_Runs: self.log().notice("processing run %s" % r) self.log().information(str(self.get_IPTS_Local(r))) if self.getProperty("LiveData").value: Tag = 'Live' LoadPreNexusLive(Instrument='SNAP', OutputWorkspace='WS') else: Load(Filename='SNAP' + str(r), OutputWorkspace='WS') NormaliseByCurrent(InputWorkspace='WS', OutputWorkspace='WS') CompressEvents(InputWorkspace='WS', OutputWorkspace='WS') CropWorkspace(InputWorkspace='WS', OutputWorkspace='WS', XMax=50000) RemovePromptPulse(InputWorkspace='WS', OutputWorkspace='WS', Width='1600', Frequency='60.4') if maskWSname is not None: MaskDetectors(Workspace='WS', MaskedWorkspace=maskWSname) self._alignAndFocus(params, calib, cal_File, group) normWS = self._generateNormalization('WS_red', norm, normWS) WS_nor = None if normWS is not None: WS_nor = 'WS_nor' Divide(LHSWorkspace='WS_red', RHSWorkspace=normWS, OutputWorkspace='WS_nor') ReplaceSpecialValues(Inputworkspace='WS_nor', OutputWorkspace='WS_nor', NaNValue='0', NaNError='0', InfinityValue='0', InfinityError='0') new_Tag = Tag if len(prefix) > 0: new_Tag += '_' + prefix # Edit instrument geomety to make final workspace smaller on disk det_table = PreprocessDetectorsToMD( Inputworkspace='WS_red', OutputWorkspace='__SNAP_det_table') polar = np.degrees(det_table.column('TwoTheta')) azi = np.degrees(det_table.column('Azimuthal')) EditInstrumentGeometry(Workspace='WS_red', L2=det_table.column('L2'), Polar=polar, Azimuthal=azi) if WS_nor is not None: EditInstrumentGeometry(Workspace='WS_nor', L2=det_table.column('L2'), Polar=polar, Azimuthal=azi) mtd.remove('__SNAP_det_table') # Save requested formats basename = '%s_%s_%s' % (new_Tag, r, group) self._save(r, basename, norm) # temporary workspace no longer needed DeleteWorkspace(Workspace='WS') # rename everything as appropriate and determine output workspace name RenameWorkspace(Inputworkspace='WS_d', OutputWorkspace='%s_%s_d' % (new_Tag, r)) RenameWorkspace(Inputworkspace='WS_red', OutputWorkspace=basename + '_red') if norm == 'None': outputWksp = basename + '_red' else: outputWksp = basename + '_nor' RenameWorkspace(Inputworkspace='WS_nor', OutputWorkspace=basename + '_nor') if norm == "Extracted from Data": RenameWorkspace(Inputworkspace='peak_clip_WS', OutputWorkspace='%s_%s_normalizer' % (new_Tag, r)) # delte some things in production if Process_Mode == "Production": DeleteWorkspace(Workspace='%s_%s_d' % (new_Tag, r)) # was 'WS_d' if norm != "None": DeleteWorkspace(Workspace=basename + '_red') # was 'WS_red' if norm == "Extracted from Data": DeleteWorkspace(Workspace='%s_%s_normalizer' % (new_Tag, r)) # was 'peak_clip_WS' propertyName = 'OutputWorkspace_' + str(outputWksp) self.declareProperty( WorkspaceProperty(propertyName, outputWksp, Direction.Output)) self.setProperty(propertyName, outputWksp)
def PyExec(self): filenames = self._getLinearizedFilenames('Filename') self.filterBadPulses = self.getProperty('FilterBadPulses').value self.chunkSize = self.getProperty('MaxChunkSize').value self.absorption = self.getProperty('AbsorptionWorkspace').value self.charac = self.getProperty('Characterizations').value finalname = self.getProperty('OutputWorkspace').valueAsStr self.prog_per_file = 1. / float( len(filenames)) # for better progress reporting # these are also passed into the child-algorithms self.kwargs = self.__getAlignAndFocusArgs() # outer loop creates chunks to load for (i, filename) in enumerate(filenames): # default name is based off of filename wkspname = os.path.split(filename)[-1].split('.')[0] self.__determineCharacterizations( filename, wkspname) # updates instance variable cachefile = self.__getCacheName(wkspname) wkspname += '_f%d' % i # add file number to be unique if cachefile is not None and os.path.exists(cachefile): LoadNexusProcessed(Filename=cachefile, OutputWorkspace=wkspname) # TODO LoadNexusProcessed has a bug. When it finds the # instrument name without xml it reads in from an IDF # in the instrument directory. editinstrargs = {} for name in PROPS_FOR_INSTR: prop = self.getProperty(name) if not prop.isDefault: editinstrargs[name] = prop.value if editinstrargs: EditInstrumentGeometry(Workspace=wkspname, **editinstrargs) else: self.__processFile(filename, wkspname, self.prog_per_file * float(i)) if cachefile is not None: SaveNexusProcessed(InputWorkspace=wkspname, Filename=cachefile) # accumulate runs if i == 0: if wkspname != finalname: RenameWorkspace(InputWorkspace=wkspname, OutputWorkspace=finalname) else: Plus(LHSWorkspace=finalname, RHSWorkspace=wkspname, OutputWorkspace=finalname, ClearRHSWorkspace=self.kwargs['PreserveEvents']) DeleteWorkspace(Workspace=wkspname) if self.kwargs['PreserveEvents']: CompressEvents(InputWorkspace=finalname, OutputWorkspace=finalname) # with more than one chunk or file the integrated proton charge is # generically wrong mtd[finalname].run().integrateProtonCharge() # set the output workspace self.setProperty('OutputWorkspace', mtd[finalname])
def PyExec(self): in_Runs = self.getProperty("RunNumbers").value progress = Progress(self, 0., .25, 3) finalUnits = self.getPropertyValue("FinalUnits") self.chunkSize = self.getProperty('MaxChunkSize').value # default arguments for AlignAndFocusPowder self.alignAndFocusArgs = {'Tmin': 0, 'TMax': 50000, 'RemovePromptPulseWidth': 1600, 'PreserveEvents': False, 'Dspacing': True, # binning parameters in d-space 'Params': self.getProperty("Binning").value, } # workspace for loading metadata only to be used in LoadDiffCal and # CreateGroupingWorkspace metaWS = None # either type of file-based calibration is stored in the same variable calib = self.getProperty("Calibration").value detcalFile = None if calib == "Calibration File": metaWS = self._loadMetaWS(in_Runs[0]) LoadDiffCal(Filename=self.getPropertyValue("CalibrationFilename"), WorkspaceName='SNAP', InputWorkspace=metaWS, MakeGroupingWorkspace=False, MakeMaskWorkspace=False) self.alignAndFocusArgs['CalibrationWorkspace'] = 'SNAP_cal' elif calib == 'DetCal File': detcalFile = ','.join(self.getProperty('DetCalFilename').value) progress.report('loaded calibration') norm = self.getProperty("Normalization").value if norm == "From Processed Nexus": norm_File = self.getProperty("NormalizationFilename").value normalizationWS = 'normWS' LoadNexusProcessed(Filename=norm_File, OutputWorkspace=normalizationWS) progress.report('loaded normalization') elif norm == "From Workspace": normalizationWS = str(self.getProperty("NormalizationWorkspace").value) progress.report('') else: normalizationWS = None progress.report('') self.alignAndFocusArgs['GroupingWorkspace'] = self._generateGrouping(in_Runs[0], metaWS, progress) self.alignAndFocusArgs['MaskWorkspace'] = self._getMaskWSname(in_Runs[0], metaWS) # can be empty string if metaWS is not None: DeleteWorkspace(Workspace=metaWS) Process_Mode = self.getProperty("ProcessingMode").value prefix = self.getProperty("OptionalPrefix").value Tag = 'SNAP' progStart = .25 progDelta = (1.-progStart)/len(in_Runs) # --------------------------- PROCESS BACKGROUND ---------------------- if not self.getProperty('Background').isDefault: progDelta = (1. - progStart) / (len(in_Runs) + 1) # redefine to account for background background = 'SNAP_{}'.format(self.getProperty('Background').value) self.log().notice("processing run background {}".format(background)) background, unfocussedBkgd = self._alignAndFocus(background, background+'_bkgd_red', detCalFilename=detcalFile, withUnfocussed=(Process_Mode == 'Set-Up'), progStart=progStart, progDelta=progDelta) else: background = None unfocussedBkgd = '' # --------------------------- REDUCE DATA ----------------------------- for i, runnumber in enumerate(in_Runs): self.log().notice("processing run %s" % runnumber) # put together output names new_Tag = Tag if len(prefix) > 0: new_Tag = prefix + '_' + new_Tag basename = '%s_%s_%s' % (new_Tag, runnumber, self.alignAndFocusArgs['GroupingWorkspace']) self.log().warning('{}:{}:{}'.format(i, new_Tag, basename)) redWS, unfocussedWksp = self._alignAndFocus('SNAP_{}'.format(runnumber), basename + '_red', detCalFilename=detcalFile, withUnfocussed=(Process_Mode == 'Set-Up'), progStart=progStart, progDelta=progDelta*.5) progStart += .5 * progDelta # subtract the background if it was supplied if background: self.log().information('subtracting {} from {}'.format(background, redWS)) Minus(LHSWorkspace=redWS, RHSWorkspace=background, OutputWorkspace=redWS) # intentionally don't subtract the unfocussed workspace since it hasn't been normalized by counting time # the rest takes up .25 percent of the run processing progress = Progress(self, progStart, progStart+.25*progDelta, 2) # AlignAndFocusPowder leaves the data in time-of-flight ConvertUnits(InputWorkspace=redWS, OutputWorkspace=redWS, Target='dSpacing', EMode='Elastic') # Edit instrument geometry to make final workspace smaller on disk det_table = PreprocessDetectorsToMD(Inputworkspace=redWS, OutputWorkspace='__SNAP_det_table') polar = np.degrees(det_table.column('TwoTheta')) azi = np.degrees(det_table.column('Azimuthal')) EditInstrumentGeometry(Workspace=redWS, L2=det_table.column('L2'), Polar=polar, Azimuthal=azi) mtd.remove('__SNAP_det_table') progress.report('simplify geometry') # AlignAndFocus doesn't necessarily rebin the data correctly if Process_Mode == "Set-Up": Rebin(InputWorkspace=unfocussedWksp, Params=self.alignAndFocusArgs['Params'], Outputworkspace=unfocussedWksp) if background: Rebin(InputWorkspace=unfocussedBkgd, Params=self.alignAndFocusArgs['Params'], Outputworkspace=unfocussedBkgd) # normalize the data as requested normalizationWS = self._generateNormalization(redWS, norm, normalizationWS) normalizedWS = None if normalizationWS is not None: normalizedWS = basename + '_nor' Divide(LHSWorkspace=redWS, RHSWorkspace=normalizationWS, OutputWorkspace=normalizedWS) ReplaceSpecialValues(Inputworkspace=normalizedWS, OutputWorkspace=normalizedWS, NaNValue='0', NaNError='0', InfinityValue='0', InfinityError='0') progress.report('normalized') else: progress.report() # rename everything as appropriate and determine output workspace name if normalizedWS is None: outputWksp = redWS else: outputWksp = normalizedWS if norm == "Extracted from Data" and Process_Mode == "Production": DeleteWorkspace(Workspace=redWS) DeleteWorkspace(Workspace=normalizationWS) # Save requested formats - function checks that saving is requested self._save(runnumber, basename, outputWksp) # set workspace as an output so it gets history ConvertUnits(InputWorkspace=str(outputWksp), OutputWorkspace=str(outputWksp), Target=finalUnits, EMode='Elastic') self._exportWorkspace('OutputWorkspace_' + str(outputWksp), outputWksp) # declare some things as extra outputs in set-up if Process_Mode != "Production": propprefix = 'OutputWorkspace_{:d}_'.format(i) propNames = [propprefix + it for it in ['d', 'norm', 'normalizer']] wkspNames = ['%s_%s_d' % (new_Tag, runnumber), basename + '_red', '%s_%s_normalizer' % (new_Tag, runnumber)] for (propName, wkspName) in zip(propNames, wkspNames): self._exportWorkspace(propName, wkspName) if background: ConvertUnits(InputWorkspace=str(background), OutputWorkspace=str(background), Target=finalUnits, EMode='Elastic') prefix = 'OutputWorkspace_{}'.format(len(in_Runs)) propNames = [prefix + it for it in ['', '_d']] wkspNames = [background, unfocussedBkgd] for (propName, wkspName) in zip(propNames, wkspNames): self._exportWorkspace(propName, wkspName)
def PyExec(self): in_Runs = self.getProperty("RunNumbers").value maskWSname = self._getMaskWSname() progress = Progress(self, 0., .25, 3) # default arguments for AlignAndFocusPowder alignAndFocusArgs = { 'TMax': 50000, 'RemovePromptPulseWidth': 1600, 'PreserveEvents': False, 'Dspacing': True, # binning parameters in d-space 'Params': self.getProperty("Binning").value } # workspace for loading metadata only to be used in LoadDiffCal and # CreateGroupingWorkspace metaWS = None # either type of file-based calibration is stored in the same variable calib = self.getProperty("Calibration").value detcalFile = None if calib == "Calibration File": metaWS = self._loadMetaWS(in_Runs[0]) LoadDiffCal(Filename=self.getPropertyValue("CalibrationFilename"), WorkspaceName='SNAP', InputWorkspace=metaWS, MakeGroupingWorkspace=False, MakeMaskWorkspace=False) alignAndFocusArgs['CalibrationWorkspace'] = 'SNAP_cal' elif calib == 'DetCal File': detcalFile = ','.join(self.getProperty('DetCalFilename').value) progress.report('loaded calibration') norm = self.getProperty("Normalization").value if norm == "From Processed Nexus": norm_File = self.getProperty("NormalizationFilename").value normalizationWS = 'normWS' LoadNexusProcessed(Filename=norm_File, OutputWorkspace=normalizationWS) progress.report('loaded normalization') elif norm == "From Workspace": normalizationWS = str( self.getProperty("NormalizationWorkspace").value) progress.report('') else: normalizationWS = None progress.report('') group = self._generateGrouping(in_Runs[0], metaWS, progress) if metaWS is not None: DeleteWorkspace(Workspace=metaWS) Process_Mode = self.getProperty("ProcessingMode").value prefix = self.getProperty("OptionalPrefix").value # --------------------------- REDUCE DATA ----------------------------- Tag = 'SNAP' if self.getProperty("LiveData").value: Tag = 'Live' progStart = .25 progDelta = (1. - progStart) / len(in_Runs) for i, runnumber in enumerate(in_Runs): self.log().notice("processing run %s" % runnumber) self.log().information(str(self.get_IPTS_Local(runnumber))) # put together output names new_Tag = Tag if len(prefix) > 0: new_Tag += '_' + prefix basename = '%s_%s_%s' % (new_Tag, runnumber, group) if self.getProperty("LiveData").value: raise RuntimeError('Live data is not currently supported') else: Load(Filename='SNAP' + str(runnumber), OutputWorkspace=basename + '_red', startProgress=progStart, endProgress=progStart + .25 * progDelta) progStart += .25 * progDelta redWS = basename + '_red' # overwrite geometry with detcal files if calib == 'DetCal File': LoadIsawDetCal(InputWorkspace=redWS, Filename=detcalFile) # create unfocussed data if in set-up mode if Process_Mode == "Set-Up": unfocussedWksp = '{}_{}_d'.format(new_Tag, runnumber) else: unfocussedWksp = '' AlignAndFocusPowder( InputWorkspace=redWS, OutputWorkspace=redWS, MaskWorkspace=maskWSname, # can be empty string GroupingWorkspace=group, UnfocussedWorkspace=unfocussedWksp, # can be empty string startProgress=progStart, endProgress=progStart + .5 * progDelta, **alignAndFocusArgs) progStart += .5 * progDelta # the rest takes up .25 percent of the run processing progress = Progress(self, progStart, progStart + .25 * progDelta, 2) # AlignAndFocusPowder leaves the data in time-of-flight ConvertUnits(InputWorkspace=redWS, OutputWorkspace=redWS, Target='dSpacing', EMode='Elastic') # Edit instrument geometry to make final workspace smaller on disk det_table = PreprocessDetectorsToMD( Inputworkspace=redWS, OutputWorkspace='__SNAP_det_table') polar = np.degrees(det_table.column('TwoTheta')) azi = np.degrees(det_table.column('Azimuthal')) EditInstrumentGeometry(Workspace=redWS, L2=det_table.column('L2'), Polar=polar, Azimuthal=azi) mtd.remove('__SNAP_det_table') progress.report('simplify geometry') # AlignAndFocus doesn't necessarily rebin the data correctly if Process_Mode == "Set-Up": Rebin(InputWorkspace=unfocussedWksp, Params=alignAndFocusArgs['Params'], Outputworkspace=unfocussedWksp) NormaliseByCurrent(InputWorkspace=redWS, OutputWorkspace=redWS) # normalize the data as requested normalizationWS = self._generateNormalization( redWS, norm, normalizationWS) normalizedWS = None if normalizationWS is not None: normalizedWS = basename + '_nor' Divide(LHSWorkspace=redWS, RHSWorkspace=normalizationWS, OutputWorkspace=normalizedWS) ReplaceSpecialValues(Inputworkspace=normalizedWS, OutputWorkspace=normalizedWS, NaNValue='0', NaNError='0', InfinityValue='0', InfinityError='0') progress.report('normalized') else: progress.report() # rename everything as appropriate and determine output workspace name if normalizedWS is None: outputWksp = redWS else: outputWksp = normalizedWS if norm == "Extracted from Data" and Process_Mode == "Production": DeleteWorkspace(Workspace=redWS) DeleteWorkspace(Workspace=normalizationWS) # Save requested formats saveDir = self.getPropertyValue("OutputDirectory").strip() if len(saveDir) <= 0: self.log().notice('Using default save location') saveDir = os.path.join(self.get_IPTS_Local(runnumber), 'shared', 'data') self._save(saveDir, basename, outputWksp) # set workspace as an output so it gets history propertyName = 'OutputWorkspace_' + str(outputWksp) self.declareProperty( WorkspaceProperty(propertyName, outputWksp, Direction.Output)) self.setProperty(propertyName, outputWksp) # declare some things as extra outputs in set-up if Process_Mode != "Production": prefix = 'OuputWorkspace_{:d}_'.format(i) propNames = [prefix + it for it in ['d', 'norm', 'normalizer']] wkspNames = [ '%s_%s_d' % (new_Tag, runnumber), basename + '_red', '%s_%s_normalizer' % (new_Tag, runnumber) ] for (propName, wkspName) in zip(propNames, wkspNames): if mtd.doesExist(wkspName): self.declareProperty( WorkspaceProperty(propName, wkspName, Direction.Output)) self.setProperty(propName, wkspName)
def PyExec(self): filenames = self._getLinearizedFilenames('Filename') self.filterBadPulses = self.getProperty('FilterBadPulses').value self.chunkSize = self.getProperty('MaxChunkSize').value self.absorption = self.getProperty('AbsorptionWorkspace').value self.charac = self.getProperty('Characterizations').value finalname = self.getPropertyValue('OutputWorkspace') useCaching = len(self.getProperty('CacheDir').value) > 0 # accumulate the unfocused workspace if it was requested # empty string means it is not used unfocusname = self.getPropertyValue('UnfocussedWorkspace') unfocusname_file = '' if len(unfocusname) > 0: unfocusname_file = '__{}_partial'.format(unfocusname) if useCaching: # unfocus check only matters if caching is requested if unfocusname != '': self.log().warning( 'CacheDir is specified with "UnfocussedWorkspace" - reading cache files disabled' ) else: self.log().warning( 'CacheDir is not specified - functionality disabled') self.prog_per_file = 1. / float( len(filenames)) # for better progress reporting # these are also passed into the child-algorithms self.kwargs = self.__getAlignAndFocusArgs() # outer loop creates chunks to load for (i, filename) in enumerate(filenames): # default name is based off of filename wkspname = os.path.split(filename)[-1].split('.')[0] if useCaching: self.__determineCharacterizations( filename, wkspname, True) # updates instance variable cachefile = self.__getCacheName(wkspname) else: cachefile = None wkspname += '_f%d' % i # add file number to be unique # if the unfocussed data is requested, don't read it from disk # because of the extra complication of the unfocussed workspace if useCaching and os.path.exists(cachefile) and unfocusname == '': LoadNexusProcessed(Filename=cachefile, OutputWorkspace=wkspname) # TODO LoadNexusProcessed has a bug. When it finds the # instrument name without xml it reads in from an IDF # in the instrument directory. editinstrargs = {} for name in PROPS_FOR_INSTR: prop = self.getProperty(name) if not prop.isDefault: editinstrargs[name] = prop.value if editinstrargs: EditInstrumentGeometry(Workspace=wkspname, **editinstrargs) else: self.__processFile(filename, wkspname, unfocusname_file, self.prog_per_file * float(i), not useCaching) # write out the cachefile for the main reduced data independent of whether # the unfocussed workspace was requested if useCaching: SaveNexusProcessed(InputWorkspace=wkspname, Filename=cachefile) # accumulate runs if i == 0: if wkspname != finalname: RenameWorkspace(InputWorkspace=wkspname, OutputWorkspace=finalname) if unfocusname != '': RenameWorkspace(InputWorkspace=unfocusname_file, OutputWorkspace=unfocusname) else: Plus(LHSWorkspace=finalname, RHSWorkspace=wkspname, OutputWorkspace=finalname, ClearRHSWorkspace=self.kwargs['PreserveEvents']) DeleteWorkspace(Workspace=wkspname) if unfocusname != '': Plus(LHSWorkspace=unfocusname, RHSWorkspace=unfocusname_file, OutputWorkspace=unfocusname, ClearRHSWorkspace=self.kwargs['PreserveEvents']) DeleteWorkspace(Workspace=unfocusname_file) if self.kwargs['PreserveEvents']: CompressEvents(InputWorkspace=finalname, OutputWorkspace=finalname) # not compressing unfocussed workspace because it is in d-spacing # and is likely to be from a different part of the instrument # with more than one chunk or file the integrated proton charge is # generically wrong mtd[finalname].run().integrateProtonCharge() # set the output workspace self.setProperty('OutputWorkspace', mtd[finalname]) if unfocusname != '': self.setProperty('UnfocussedWorkspace', mtd[unfocusname])