def _divideByCurves(self, ws, curves): """ Expects a workspace in ToF units. All operations are done in-place (the workspace is input/output). For every bank-curve pair, divides the corresponding spectra in the workspace by the (simulated) fitted curve. The division is done in d-spacing (the input workspace is converted to d-spacing inside this method, but results are converted back to ToF before returning from this method). The curves workspace is expected in d-spacing units (since it comes from fitting a sum of spectra for a bank or group of detectors). This method is capable of dealing with workspaces with range and bin size different from the range and bin size of the curves. It will rebin the curves workspace to match the input 'ws' workspace (using the algorithm RebinToWorkspace). @param ws :: workspace with (sample) spectra to divide by curves fitted to Vanadium spectra @param curves :: dictionary of fitting workspaces (in d-spacing), one per bank. The keys are the bank identifier and the values are their fitting workspaces. The fitting workspaces are expected as returned by the algorithm 'Fit': 3 spectra: original data, simulated data with fit, difference between original and simulated data. """ # Note that this division could use the algorithm 'Divide' # This is simple and more efficient than using divide workspace, which requires # cropping separate workspaces, dividing them separately, then appending them # with AppendSpectra, etc. ws = EnggUtils.convertToDSpacing(self, ws) for b in curves: # process all the spectra (indices) in one bank fittedCurve = curves[b] idxs = EnggUtils.getWsIndicesForBank(ws, b) if not idxs: pass # This RebinToWorkspace is required here: normal runs will have narrower range of X values, # and possibly different bin size, as compared to (long) Vanadium runs. Same applies to short # Ceria runs (for Calibrate -non-full) and even long Ceria runs (for Calibrate-Full). rebinnedFitCurve = self._rebinToMatchWS(fittedCurve, ws) for i in idxs: # take values of the second spectrum of the workspace (fit simulation - fitted curve) ws.setY(i, np.divide(ws.dataY(i), rebinnedFitCurve.readY(1))) # finally, convert back to ToF EnggUtils.convertToToF(self, ws)
def PyExec(self): # Get the run workspace wks = self.getProperty('InputWorkspace').value # Get spectra indices either from bank or direct list of indices, checking for errors bank = self.getProperty('Bank').value spectra = self.getProperty(self.INDICES_PROP_NAME).value indices = EnggUtils.getWsIndicesFromInProperties(wks, bank, spectra) detPos = self.getProperty("DetectorPositions").value nreports = 5 if detPos: nreports += 1 prog = Progress(self, start=0, end=1, nreports=nreports) # Leave only the data for the bank/spectra list requested prog.report('Selecting spectra from input workspace') wks = EnggUtils.cropData(self, wks, indices) prog.report('Masking some bins if requested') self._mask_bins(wks, self.getProperty('MaskBinsXMins').value, self.getProperty('MaskBinsXMaxs').value) prog.report('Preparing input workspace with vanadium corrections') # Leave data for the same bank in the vanadium workspace too vanWS = self.getProperty('VanadiumWorkspace').value vanIntegWS = self.getProperty('VanIntegrationWorkspace').value vanCurvesWS = self.getProperty('VanCurvesWorkspace').value EnggUtils.applyVanadiumCorrections(self, wks, indices, vanWS, vanIntegWS, vanCurvesWS) # Apply calibration if detPos: self._applyCalibration(wks, detPos) # Convert to dSpacing wks = EnggUtils.convertToDSpacing(self, wks) prog.report('Summing spectra') # Sum the values across spectra wks = EnggUtils.sumSpectra(self, wks) prog.report('Preparing output workspace') # Convert back to time of flight wks = EnggUtils.convertToToF(self, wks) prog.report('Normalizing input workspace if needed') if self.getProperty('NormaliseByCurrent').value: self._normalize_by_current(wks) # OpenGenie displays distributions instead of pure counts (this is done implicitly when # converting units), so I guess that's what users will expect self._convertToDistr(wks) self.setProperty("OutputWorkspace", wks)
def PyExec(self): import EnggUtils # Get the run workspace ws = self.getProperty('InputWorkspace').value # Get spectra indices either from bank or direct list of indices, checking for errors bank = self.getProperty('Bank').value spectra = self.getProperty(self.INDICES_PROP_NAME).value indices = EnggUtils.getWsIndicesFromInProperties(ws, bank, spectra) # Leave the data for the bank we are interested in only ws = EnggUtils.cropData(self, ws, indices) # Apply calibration detPos = self.getProperty("DetectorPositions").value if detPos: self._applyCalibration(ws, detPos) # Leave data for the same bank in the vanadium workspace too vanWS = self.getProperty("VanadiumWorkspace").value # if it is raw data (not precalculated curve), needs to be cropped if EnggUtils.vanadiumWorkspaceIsPrecalculated(ws): vanWS = EnggUtils.cropData(self, vanWS, indices) # These corrections rely on ToF<->Dspacing conversions, so they're done after the calibration step vanFittingWS = EnggUtils.applyVanadiumCorrection(self, ws, vanWS, self.getProperty('VanadiumIntegWorkspace').value) # Convert to dSpacing ws = EnggUtils.convertToDSpacing(self, ws) # Sum the values ws = EnggUtils.sumSpectra(self, ws) # Convert back to time of flight ws = EnggUtils.convertToToF(self, ws) # OpenGenie displays distributions instead of pure counts (this is done implicitly when # converting units), so I guess that's what users will expect self._convertToDistr(ws) self.setProperty("OutputWorkspace", ws) # optinally, generate the workspace with per-bank vanadium fitting curves outVanWSName = self.getPropertyValue('OutVanadiumCurveFits') if outVanWSName: mtd[outVanWSName] = vanFittingWS
def PyExec(self): # Get the run workspace wks = self.getProperty('InputWorkspace').value # Get spectra indices either from bank or direct list of indices, checking for errors bank = self.getProperty('Bank').value spectra = self.getProperty(self.INDICES_PROP_NAME).value indices = EnggUtils.getWsIndicesFromInProperties(wks, bank, spectra) # Leave the data for the bank we are interested in only wks = EnggUtils.cropData(self, wks, indices) prog = Progress(self, start=0, end=1, nreports=3) prog.report('Preparing input workspace') # Leave data for the same bank in the vanadium workspace too vanWS = self.getProperty('VanadiumWorkspace').value vanIntegWS = self.getProperty('VanIntegrationWorkspace').value vanCurvesWS = self.getProperty('VanCurvesWorkspace').value EnggUtils.applyVanadiumCorrections(self, wks, indices, vanWS, vanIntegWS, vanCurvesWS) # Apply calibration detPos = self.getProperty("DetectorPositions").value if detPos: self._applyCalibration(wks, detPos) # Convert to dSpacing wks = EnggUtils.convertToDSpacing(self, wks) prog.report('Summing spectra') # Sum the values wks = EnggUtils.sumSpectra(self, wks) prog.report('Preparing output workspace') # Convert back to time of flight wks = EnggUtils.convertToToF(self, wks) # OpenGenie displays distributions instead of pure counts (this is done implicitly when # converting units), so I guess that's what users will expect self._convertToDistr(wks) self.setProperty("OutputWorkspace", wks)