예제 #1
0
    def test_HFIRCalculateGoniometer_HB3A_phi(self):
        omega = np.deg2rad(42)
        chi = np.deg2rad(-3)
        phi = np.deg2rad(23)
        R1 = np.array([
            [np.cos(omega), 0, -np.sin(omega)],  # omega 0,1,0,-1
            [0, 1, 0],
            [np.sin(omega), 0, np.cos(omega)]
        ])
        R2 = np.array([
            [np.cos(chi), np.sin(chi), 0],  # chi 0,0,1,-1
            [-np.sin(chi), np.cos(chi), 0],
            [0, 0, 1]
        ])
        R3 = np.array([
            [np.cos(phi), 0, -np.sin(phi)],  # phi 0,1,0,-1
            [0, 1, 0],
            [np.sin(phi), 0, np.cos(phi)]
        ])
        R = np.dot(np.dot(R1, R2), R3)

        wl = 1.54
        k = 2 * np.pi / wl
        theta = np.deg2rad(47)
        phi = np.deg2rad(13)

        q_lab = np.array([
            -np.sin(theta) * np.cos(phi), -np.sin(theta) * np.sin(phi),
            1 - np.cos(theta)
        ]) * k

        q_sample = np.dot(np.linalg.inv(R), q_lab)

        peaks = CreatePeaksWorkspace(OutputType="LeanElasticPeak",
                                     NumberOfPeaks=0)
        AddSampleLog(peaks, "Wavelength", str(wl), "Number")
        SetGoniometer(peaks, Axis0='42,0,1,0,-1',
                      Axis1='-3,0,0,1,-1')  # don't set phi

        p = peaks.createPeakQSample(q_sample)
        peaks.addPeak(p)

        HFIRCalculateGoniometer(peaks,
                                OverrideProperty=True,
                                InnerGoniometer=True)

        g = Goniometer()
        g.setR(peaks.getPeak(0).getGoniometerMatrix())
        YZY = g.getEulerAngles('YZY')
        self.assertAlmostEqual(YZY[0], -42, delta=1e-10)  # omega
        self.assertAlmostEqual(YZY[1], 3, delta=1e-10)  # chi
        self.assertAlmostEqual(YZY[2], -23, delta=1e-1)  # phi

        self.assertAlmostEqual(peaks.getPeak(0).getWavelength(),
                               1.54,
                               delta=1e-10)
예제 #2
0
    def test_get_hkls(self):
        ws = CreateSimulationWorkspace("IRIS", BinParams="1,5,10")
        peaks = CreatePeaksWorkspace(ws, 2)
        reference = np.array([
            [1, 1, 2],
            [2, 1, 4],
        ])

        peak = peaks.getPeak(0)
        peak.setHKL(1, 1, 2)
        peak = peaks.getPeak(1)
        peak.setHKL(2, 1, 4)

        hkl = indexing.get_hkls(peaks)
        npt.assert_array_equal(hkl, reference)
    def test_get_hkls(self):
        ws = CreateSimulationWorkspace("IRIS", BinParams="1,5,10")
        peaks = CreatePeaksWorkspace(ws, 2)
        reference = np.array([
            [1, 1, 2],
            [2, 1, 4],
        ])

        peak = peaks.getPeak(0)
        peak.setHKL(1, 1, 2)
        peak = peaks.getPeak(1)
        peak.setHKL(2, 1, 4)

        hkl = indexing.get_hkls(peaks)
        npt.assert_array_equal(hkl, reference)
예제 #4
0
 def test_basic_access(self):
     sampleWs = CreateSampleWorkspace()
     ws = CreatePeaksWorkspace(InstrumentWorkspace=sampleWs,NumberOfPeaks=1)
     peak = ws.getPeak(0)
     peak_shape = peak.getPeakShape()
     self.assertTrue(isinstance(peak_shape, PeakShape))
     self.assertEquals(peak_shape.shapeName(), "none")
예제 #5
0
 def test_basic_access(self):
     sampleWs = CreateSampleWorkspace()
     ws = CreatePeaksWorkspace(InstrumentWorkspace=sampleWs,NumberOfPeaks=1)
     peak = ws.getPeak(0)
     peak_shape = peak.getPeakShape()
     self.assertTrue(isinstance(peak_shape, PeakShape))
     self.assertEqual(peak_shape.shapeName(), "none")
예제 #6
0
    def setUp(self):
        # IPeak cannot currently be instatiated so this is a quick way
        # getting a handle to a peak object
        ws = CreateSimulationWorkspace("SXD", BinParams="1,1,10")
        peaks = CreatePeaksWorkspace(ws, 1)
        self._peak = peaks.getPeak(0)

        # tolerance for differences in q vectors that a recomputed
        # on every call.
        self._tolerance = 1e-2
예제 #7
0
    def setUp(self):
        # IPeak cannot currently be instatiated so this is a quick way
        # getting a handle to a peak object
        ws = CreateSimulationWorkspace("SXD", BinParams="1,1,10")
        peaks = CreatePeaksWorkspace(ws, 1)
        self._peak = peaks.getPeak(0)

        # tolerance for differences in q vectors that a recomputed
        # on every call.
        self._tolerance = 1e-2
예제 #8
0
    def test_HFIRCalculateGoniometer_HB2C_omega(self):
        omega = np.deg2rad(42)

        R = np.array([[np.cos(omega), 0, np.sin(omega)], [0, 1, 0],
                      [-np.sin(omega), 0, np.cos(omega)]])

        wl = 1.54
        k = 2 * np.pi / wl
        theta = np.deg2rad(47)
        phi = np.deg2rad(13)

        q_lab = np.array([
            -np.sin(theta) * np.cos(phi), -np.sin(theta) * np.sin(phi),
            1 - np.cos(theta)
        ]) * k

        q_sample = np.dot(np.linalg.inv(R), q_lab)

        peaks = CreatePeaksWorkspace(OutputType="LeanElasticPeak",
                                     NumberOfPeaks=0)

        p = peaks.createPeakQSample(q_sample)
        peaks.addPeak(p)

        HFIRCalculateGoniometer(peaks, wl)

        g = Goniometer()
        g.setR(peaks.getPeak(0).getGoniometerMatrix())
        YZY = g.getEulerAngles('YZY')
        self.assertAlmostEqual(YZY[0], 42, delta=1e-10)  # omega
        self.assertAlmostEqual(YZY[1], 0, delta=1e-10)  # chi
        self.assertAlmostEqual(YZY[2], 0, delta=1e-10)  # phi

        self.assertAlmostEqual(peaks.getPeak(0).getWavelength(),
                               1.54,
                               delta=1e-10)
예제 #9
0
q_lab = np.array([
    -np.sin(theta) * np.cos(phi), -np.sin(theta) * np.sin(phi),
    1 - np.cos(theta)
]) * k

q_sample = np.dot(np.linalg.inv(R), q_lab)

peaks = CreatePeaksWorkspace(OutputType="LeanElasticPeak", NumberOfPeaks=0)

p = peaks.createPeakQSample(q_sample)
peaks.addPeak(p)

HFIRCalculateGoniometer(peaks, wl, OverrideProperty=True, InnerGoniometer=True)

g = Goniometer()
g.setR(peaks.getPeak(0).getGoniometerMatrix())
print(g.getEulerAngles('YZY'))
assert np.isclose(g.getEulerAngles('YZY')[0], 42)

chi = np.deg2rad(-3)
phi = np.deg2rad(23)

R1 = np.array([
    [np.cos(omega), 0, -np.sin(omega)],  # omega 0,1,0,-1
    [0, 1, 0],
    [np.sin(omega), 0, np.cos(omega)]
])
R2 = np.array([
    [np.cos(chi), np.sin(chi), 0],  # chi 0,0,1,-1
    [-np.sin(chi), np.cos(chi), 0],
    [0, 0, 1]
예제 #10
0
    def PyExec(self):
        input_workspaces = self._expand_groups()
        outWS = self.getPropertyValue("OutputWorkspace")
        CreatePeaksWorkspace(OutputType='LeanElasticPeak',
                             InstrumentWorkspace=input_workspaces[0],
                             NumberOfPeaks=0,
                             OutputWorkspace=outWS,
                             EnableLogging=False)

        method = self.getProperty("Method").value
        n_bkgr_pts = self.getProperty("NumBackgroundPts").value
        n_fwhm = self.getProperty("WidthScale").value
        scale = self.getProperty("ScaleFactor").value
        chisqmax = self.getProperty("ChiSqMax").value
        signalNoiseMin = self.getProperty("SignalNoiseMin").value
        ll = self.getProperty("LowerLeft").value
        ur = self.getProperty("UpperRight").value
        startX = self.getProperty('StartX').value
        endX = self.getProperty('EndX').value
        use_lorentz = self.getProperty("ApplyLorentz").value
        optmize_q = self.getProperty("OptimizeQVector").value
        output_fit = self.getProperty("OutputFitResults").value

        if output_fit and method != "Counts":
            fit_results = WorkspaceGroup()
            AnalysisDataService.addOrReplace(outWS + "_fit_results",
                                             fit_results)

        for inWS in input_workspaces:
            tmp_inWS = '__tmp_' + inWS
            IntegrateMDHistoWorkspace(InputWorkspace=inWS,
                                      P1Bin=f'{ll[1]},{ur[1]}',
                                      P2Bin=f'{ll[0]},{ur[0]}',
                                      OutputWorkspace=tmp_inWS,
                                      EnableLogging=False)
            ConvertMDHistoToMatrixWorkspace(tmp_inWS,
                                            OutputWorkspace=tmp_inWS,
                                            EnableLogging=False)
            data = ConvertToPointData(tmp_inWS,
                                      OutputWorkspace=tmp_inWS,
                                      EnableLogging=False)

            run = mtd[inWS].getExperimentInfo(0).run()
            scan_log = 'omega' if np.isclose(run.getTimeAveragedStd('phi'),
                                             0.0) else 'phi'
            scan_axis = run[scan_log].value
            scan_step = (scan_axis[-1] - scan_axis[0]) / (scan_axis.size - 1)
            data.setX(0, scan_axis)

            y = data.extractY().flatten()
            x = data.extractX().flatten()

            __tmp_pw = CreatePeaksWorkspace(OutputType='LeanElasticPeak',
                                            InstrumentWorkspace=inWS,
                                            NumberOfPeaks=0,
                                            EnableLogging=False)

            if method != "Counts":
                # fit against gaussian with flat background for both the Fitted and CountsWithFitting methods
                fit_result = self._fit_gaussian(inWS, data, x, y, startX, endX,
                                                output_fit)

                if fit_result and fit_result.OutputStatus == 'success' and fit_result.OutputChi2overDoF < chisqmax:
                    B, A, peak_centre, sigma, _ = fit_result.OutputParameters.toDict(
                    )['Value']
                    _, errA, _, errs, _ = fit_result.OutputParameters.toDict(
                    )['Error']

                    if method == "Fitted":
                        integrated_intensity = A * sigma * np.sqrt(2 * np.pi)

                        # Convert correlation back into covariance
                        cor_As = (
                            fit_result.OutputNormalisedCovarianceMatrix.cell(
                                1, 4) / 100 *
                            fit_result.OutputParameters.cell(1, 2) *
                            fit_result.OutputParameters.cell(3, 2))
                        # σ^2 = 2π (A^2 σ_s^2 + σ_A^2 s^2 + 2 A s σ_As)
                        integrated_intensity_error = np.sqrt(
                            2 * np.pi * (A**2 * errs**2 + sigma**2 * errA**2 +
                                         2 * A * sigma * cor_As))

                    elif method == "CountsWithFitting":
                        y = y[slice(
                            np.searchsorted(
                                x, peak_centre - 2.3548 * sigma * n_fwhm / 2),
                            np.searchsorted(
                                x, peak_centre + 2.3548 * sigma * n_fwhm / 2))]
                        # subtract out the fitted flat background
                        integrated_intensity = (y.sum() -
                                                B * y.size) * scan_step
                        integrated_intensity_error = np.sum(
                            np.sqrt(y)) * scan_step

                    # update the goniometer position based on the fitted peak center
                    if scan_log == 'omega':
                        SetGoniometer(Workspace=__tmp_pw,
                                      Axis0=f'{peak_centre},0,1,0,-1',
                                      Axis1='chi,0,0,1,-1',
                                      Axis2='phi,0,1,0,-1',
                                      EnableLogging=False)
                    else:
                        SetGoniometer(Workspace=__tmp_pw,
                                      Axis0='omega,0,1,0,-1',
                                      Axis1='chi,0,0,1,-1',
                                      Axis2=f'{peak_centre},0,1,0,-1',
                                      EnableLogging=False)
                else:
                    self.log().warning(
                        "Failed to fit workspace {}: Output Status={}, ChiSq={}"
                        .format(inWS, fit_result.OutputStatus,
                                fit_result.OutputChi2overDoF))
                    self._delete_tmp_workspaces(str(__tmp_pw), tmp_inWS)
                    continue
            else:
                integrated_intensity, integrated_intensity_error = self._counts_integration(
                    data, n_bkgr_pts, scan_step)

                # set the goniometer position to use the average of the scan
                SetGoniometer(Workspace=__tmp_pw,
                              Axis0='omega,0,1,0,-1',
                              Axis1='chi,0,0,1,-1',
                              Axis2='phi,0,1,0,-1',
                              EnableLogging=False)

            integrated_intensity *= scale
            integrated_intensity_error *= scale

            peak = __tmp_pw.createPeakHKL([
                run['h'].getStatistics().median,
                run['k'].getStatistics().median,
                run['l'].getStatistics().median
            ])
            peak.setWavelength(float(run['wavelength'].value))
            peak.setIntensity(integrated_intensity)
            peak.setSigmaIntensity(integrated_intensity_error)

            if integrated_intensity / integrated_intensity_error > signalNoiseMin:
                __tmp_pw.addPeak(peak)

                # correct q-vector using CentroidPeaksMD
                if optmize_q:
                    __tmp_q_ws = HB3AAdjustSampleNorm(InputWorkspaces=inWS,
                                                      NormaliseBy='None',
                                                      EnableLogging=False)
                    __tmp_pw = CentroidPeaksMD(__tmp_q_ws,
                                               __tmp_pw,
                                               EnableLogging=False)
                    DeleteWorkspace(__tmp_q_ws, EnableLogging=False)

                if use_lorentz:
                    # ILL Neutron Data Booklet, Second Edition, Section 2.9, Part 4.1, Equation 7
                    peak = __tmp_pw.getPeak(0)
                    lorentz = abs(
                        np.sin(peak.getScattering() *
                               np.cos(peak.getAzimuthal())))
                    peak.setIntensity(peak.getIntensity() * lorentz)
                    peak.setSigmaIntensity(peak.getSigmaIntensity() * lorentz)

                CombinePeaksWorkspaces(outWS,
                                       __tmp_pw,
                                       OutputWorkspace=outWS,
                                       EnableLogging=False)

                if output_fit and method != "Counts":
                    fit_results.addWorkspace(
                        RenameWorkspace(tmp_inWS + '_Workspace',
                                        outWS + "_" + inWS + '_Workspace',
                                        EnableLogging=False))
                    fit_results.addWorkspace(
                        RenameWorkspace(tmp_inWS + '_Parameters',
                                        outWS + "_" + inWS + '_Parameters',
                                        EnableLogging=False))
                    fit_results.addWorkspace(
                        RenameWorkspace(
                            tmp_inWS + '_NormalisedCovarianceMatrix',
                            outWS + "_" + inWS + '_NormalisedCovarianceMatrix',
                            EnableLogging=False))
                    fit_results.addWorkspace(
                        IntegrateMDHistoWorkspace(
                            InputWorkspace=inWS,
                            P1Bin=f'{ll[1]},0,{ur[1]}',
                            P2Bin=f'{ll[0]},0,{ur[0]}',
                            P3Bin='0,{}'.format(
                                mtd[inWS].getDimension(2).getNBins()),
                            OutputWorkspace=outWS + "_" + inWS + "_ROI",
                            EnableLogging=False))
            else:
                self.log().warning(
                    "Skipping peak from {} because Signal/Noise={:.3f} which is less than {}"
                    .format(inWS,
                            integrated_intensity / integrated_intensity_error,
                            signalNoiseMin))

            self._delete_tmp_workspaces(str(__tmp_pw), tmp_inWS)

        self.setProperty("OutputWorkspace", mtd[outWS])
    def PyExec(self):
        input_workspaces = self._expand_groups()
        outWS = self.getPropertyValue("OutputWorkspace")
        CreatePeaksWorkspace(OutputType='LeanElasticPeak',
                             InstrumentWorkspace=input_workspaces[0],
                             NumberOfPeaks=0,
                             OutputWorkspace=outWS,
                             EnableLogging=False)

        scale = self.getProperty("ScaleFactor").value
        chisqmax = self.getProperty("ChiSqMax").value
        signalNoiseMin = self.getProperty("SignalNoiseMin").value
        ll = self.getProperty("LowerLeft").value
        ur = self.getProperty("UpperRight").value
        startX = self.getProperty('StartX').value
        endX = self.getProperty('EndX').value
        use_lorentz = self.getProperty("ApplyLorentz").value
        optmize_q = self.getProperty("OptimizeQVector").value
        output_fit = self.getProperty("OutputFitResults").value

        if output_fit:
            fit_results = WorkspaceGroup()
            AnalysisDataService.addOrReplace(outWS + "_fit_results",
                                             fit_results)

        for inWS in input_workspaces:
            tmp_inWS = '__tmp_' + inWS
            IntegrateMDHistoWorkspace(InputWorkspace=inWS,
                                      P1Bin=f'{ll[1]},{ur[1]}',
                                      P2Bin=f'{ll[0]},{ur[0]}',
                                      OutputWorkspace=tmp_inWS,
                                      EnableLogging=False)
            ConvertMDHistoToMatrixWorkspace(tmp_inWS,
                                            OutputWorkspace=tmp_inWS,
                                            EnableLogging=False)
            data = ConvertToPointData(tmp_inWS,
                                      OutputWorkspace=tmp_inWS,
                                      EnableLogging=False)

            run = mtd[inWS].getExperimentInfo(0).run()
            scan_log = 'omega' if np.isclose(run.getTimeAveragedStd('phi'),
                                             0.0) else 'phi'
            scan_axis = run[scan_log].value
            data.setX(0, scan_axis)

            y = data.extractY().flatten()
            x = data.extractX().flatten()
            function = f"name=FlatBackground, A0={np.nanmin(y)};" \
                f"name=Gaussian, PeakCentre={x[np.nanargmax(y)]}, Height={np.nanmax(y)-np.nanmin(y)}, Sigma=0.25"
            constraints = f"f0.A0 > 0, f1.Height > 0, {x.min()} < f1.PeakCentre < {x.max()}"
            try:
                fit_result = Fit(function,
                                 data,
                                 Output=str(data),
                                 IgnoreInvalidData=True,
                                 OutputParametersOnly=not output_fit,
                                 Constraints=constraints,
                                 StartX=startX,
                                 EndX=endX,
                                 EnableLogging=False)
            except RuntimeError as e:
                self.log().warning("Failed to fit workspace {}: {}".format(
                    inWS, e))
                continue

            if fit_result.OutputStatus == 'success' and fit_result.OutputChi2overDoF < chisqmax:
                __tmp_pw = CreatePeaksWorkspace(OutputType='LeanElasticPeak',
                                                InstrumentWorkspace=inWS,
                                                NumberOfPeaks=0,
                                                EnableLogging=False)

                _, A, x, s, _ = fit_result.OutputParameters.toDict()['Value']
                _, errA, _, errs, _ = fit_result.OutputParameters.toDict(
                )['Error']

                if scan_log == 'omega':
                    SetGoniometer(Workspace=__tmp_pw,
                                  Axis0=f'{x},0,1,0,-1',
                                  Axis1='chi,0,0,1,-1',
                                  Axis2='phi,0,1,0,-1',
                                  EnableLogging=False)
                else:
                    SetGoniometer(Workspace=__tmp_pw,
                                  Axis0='omega,0,1,0,-1',
                                  Axis1='chi,0,0,1,-1',
                                  Axis2=f'{x},0,1,0,-1',
                                  EnableLogging=False)

                peak = __tmp_pw.createPeakHKL([
                    run['h'].getStatistics().median,
                    run['k'].getStatistics().median,
                    run['l'].getStatistics().median
                ])
                peak.setWavelength(float(run['wavelength'].value))

                integrated_intensity = A * s * np.sqrt(2 * np.pi) * scale
                peak.setIntensity(integrated_intensity)

                # Convert correlation back into covariance
                cor_As = (
                    fit_result.OutputNormalisedCovarianceMatrix.cell(1, 4) /
                    100 * fit_result.OutputParameters.cell(1, 2) *
                    fit_result.OutputParameters.cell(3, 2))
                # σ^2 = 2π (A^2 σ_s^2 + σ_A^2 s^2 + 2 A s σ_As)
                integrated_intensity_error = np.sqrt(
                    2 * np.pi * (A**2 * errs**2 + s**2 * errA**2 +
                                 2 * A * s * cor_As)) * scale
                peak.setSigmaIntensity(integrated_intensity_error)

                if integrated_intensity / integrated_intensity_error > signalNoiseMin:
                    __tmp_pw.addPeak(peak)

                    # correct q-vector using CentroidPeaksMD
                    if optmize_q:
                        __tmp_q_ws = HB3AAdjustSampleNorm(InputWorkspaces=inWS,
                                                          NormaliseBy='None',
                                                          EnableLogging=False)
                        __tmp_pw = CentroidPeaksMD(__tmp_q_ws,
                                                   __tmp_pw,
                                                   EnableLogging=False)
                        DeleteWorkspace(__tmp_q_ws, EnableLogging=False)

                    if use_lorentz:
                        # ILL Neutron Data Booklet, Second Edition, Section 2.9, Part 4.1, Equation 7
                        peak = __tmp_pw.getPeak(0)
                        lorentz = abs(
                            np.sin(peak.getScattering() *
                                   np.cos(peak.getAzimuthal())))
                        peak.setIntensity(peak.getIntensity() * lorentz)
                        peak.setSigmaIntensity(peak.getSigmaIntensity() *
                                               lorentz)

                    CombinePeaksWorkspaces(outWS,
                                           __tmp_pw,
                                           OutputWorkspace=outWS,
                                           EnableLogging=False)
                    DeleteWorkspace(__tmp_pw, EnableLogging=False)

                    if output_fit:
                        fit_results.addWorkspace(
                            RenameWorkspace(tmp_inWS + '_Workspace',
                                            outWS + "_" + inWS + '_Workspace',
                                            EnableLogging=False))
                        fit_results.addWorkspace(
                            RenameWorkspace(tmp_inWS + '_Parameters',
                                            outWS + "_" + inWS + '_Parameters',
                                            EnableLogging=False))
                        fit_results.addWorkspace(
                            RenameWorkspace(tmp_inWS +
                                            '_NormalisedCovarianceMatrix',
                                            outWS + "_" + inWS +
                                            '_NormalisedCovarianceMatrix',
                                            EnableLogging=False))
                        fit_results.addWorkspace(
                            IntegrateMDHistoWorkspace(
                                InputWorkspace=inWS,
                                P1Bin=f'{ll[1]},0,{ur[1]}',
                                P2Bin=f'{ll[0]},0,{ur[0]}',
                                P3Bin='0,{}'.format(
                                    mtd[inWS].getDimension(2).getNBins()),
                                OutputWorkspace=outWS + "_" + inWS + "_ROI",
                                EnableLogging=False))
                else:
                    self.log().warning(
                        "Skipping peak from {} because Signal/Noise={:.3f} which is less than {}"
                        .format(
                            inWS,
                            integrated_intensity / integrated_intensity_error,
                            signalNoiseMin))
            else:
                self.log().warning(
                    "Failed to fit workspace {}: Output Status={}, ChiSq={}".
                    format(inWS, fit_result.OutputStatus,
                           fit_result.OutputChi2overDoF))

            for tmp_ws in (tmp_inWS, tmp_inWS + '_Workspace',
                           tmp_inWS + '_Parameters',
                           tmp_inWS + '_NormalisedCovarianceMatrix'):
                if mtd.doesExist(tmp_ws):
                    DeleteWorkspace(tmp_ws, EnableLogging=False)

        self.setProperty("OutputWorkspace", mtd[outWS])