예제 #1
0
    def _fitCurvesPerBank(self, vanWS, banks, spline_breaks):
        """
        Fits one curve to every bank (where for every bank the data fitted is the result of
        summing up all the spectra of the bank). The fitting is done in d-spacing.

        @param vanWS :: Vanadium run workspace to fit, expected in TOF units as they are archived
        @param banks :: list of banks to consider which is normally all the banks of the instrument
        @param spline_breaks :: number of break points when fitting spline functions

        @returns a workspace with fitting results for all banks (3 spectra per bank). The spectra
        are in dSpacing units.
        """
        curves = {}
        for b in banks:
            indices = EnggUtils.getWsIndicesForBank(vanWS, b)
            if not indices:
                # no indices at all for this bank, not interested in it, don't add it to the dictionary
                # (as when doing Calibrate (not-full)) which does CropData() the original workspace
                continue

            wsToFit = EnggUtils.cropData(self, vanWS, indices)
            wsToFit = EnggUtils.convertToDSpacing(self, wsToFit)
            wsToFit = EnggUtils.sumSpectra(self, wsToFit)

            fitWS = self._fitBankCurve(wsToFit, b, spline_breaks)
            curves.update({b: fitWS})

        curvesWS = self._prepareCurvesWS(curves)

        return curvesWS
예제 #2
0
    def _fitCurvesPerBank(self, vanWS, banks, spline_breaks):
        """
        Fits one curve to every bank (where for every bank the data fitted is the result of
        summing up all the spectra of the bank). The fitting is done in d-spacing.

        @param vanWS :: Vanadium run workspace to fit, expected in TOF units as they are archived
        @param banks :: list of banks to consider which is normally all the banks of the instrument
        @param spline_breaks :: number of break points when fitting spline functions

        @returns a workspace with fitting results for all banks (3 spectra per bank). The spectra
        are in dSpacing units.
        """
        curves = {}
        for b in banks:
            indices = EnggUtils.getWsIndicesForBank(vanWS, b)
            if not indices:
                # no indices at all for this bank, not interested in it, don't add it to the dictionary
                # (as when doing Calibrate (not-full)) which does CropData() the original workspace
                continue

            wsToFit = EnggUtils.cropData(self, vanWS, indices)
            wsToFit = EnggUtils.convertToDSpacing(self, wsToFit)
            wsToFit = EnggUtils.sumSpectra(self, wsToFit)

            fitWS = self._fitBankCurve(wsToFit, b, spline_breaks)
            curves.update({b: fitWS})

        curvesWS = self._prepareCurvesWS(curves)

        return curvesWS
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
    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
예제 #6
0
    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)
예제 #7
0
    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)
예제 #8
0
    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)
예제 #9
0
    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)