示例#1
0
 def twotheta_and_L2(self):
     wks_name = self.wks_name
     pp = msa.PreprocessDetectorsToMD(InputWorkspace=wks_name, OutputWorkspace='pp')
     pp = msa.SortTableWorkspace(pp, Columns='DetectorID')
     tt, L2 = np.array( pp.column('TwoTheta') ), np.array(pp.column('L2'))
     # pp may contain monitors
     nmon = (np.array(pp.column('DetectorID'))<=0).sum()
     assert nmon + self.detID.size == tt.size
     return tt[nmon:], L2[nmon:]
示例#2
0
def load_L2_from_nxs(path):
    "load L2 computed using mantid and saved as nxs"
    from mantid import simpleapi as msa
    L2_calib = msa.Load(path)
    L2_calib = msa.SortTableWorkspace(L2_calib, Columns='detid')
    L2 = np.array(L2_calib.column('L2'))
    L2_detID = np.array(L2_calib.column('detid'))
    nodata = np.array(L2_calib.column('nodata'), dtype=bool)
    return L2
示例#3
0
 def load_L2_from_nxs(self, path):
     "load L2 computed using mantid and saved as nxs"
     L2_calib = msa.Load(path)
     L2_calib = msa.SortTableWorkspace(L2_calib, Columns='detid')
     L2 = np.array(L2_calib.column('L2'))
     L2_detID = np.array(L2_calib.column('detid'))
     assert np.all(self.detIDs == L2_detID)
     nodata = np.array(L2_calib.column('nodata'), dtype=bool)
     self.L2 = L2
     self.L2_mask = nodata
     return L2, nodata
示例#4
0
 def L2(self):
     wks_name = self.wks_name
     pp = msa.PreprocessDetectorsToMD(InputWorkspace=wks_name, OutputWorkspace='pp')
     pp = msa.SortTableWorkspace(pp, Columns='DetectorID')
     L2 = np.array(pp.column('L2'))
     # pp may contain monitors
     nmon = (np.array(pp.column('DetectorID'))<0).sum()
     if nmon + self.detID.size != L2.size:
         import warnings
         warnings.warn( "%s + %s != %s" % (nmon, self.detID.size, L2.size) )
     return L2[-self.detID.size:]
示例#5
0
reload(align)

# ## Load difc
detID = np.load('./difc-2-detID.npy')

# use Silicon data
# difc = np.load("./difc-2-difc.npy")
# mask = np.load("./difc-2-mask.npy")

# special for short packs: use C60 data for just C25T
difc = np.load("./C60-difc-2-C25T.npy")
mask = np.load("./C60-difc-2-C25T-mask.npy")

# ## Load L2
L2_calib = msa.Load('L2table.nxs')
L2_calib = msa.SortTableWorkspace(L2_calib, Columns='detid')
L2 = np.array(L2_calib.column('L2'))
L2_detID = np.array(L2_calib.column('detid'))
assert np.all(detID == L2_detID)
nodata = np.array(L2_calib.column('nodata'), dtype=bool)
mask = np.logical_or(mask, nodata)

# ## Apply mask
difc = np.ma.masked_array(difc, mask)
L2 = np.ma.masked_array(L2, mask)

# ## Fit source, sample
import logging

logger = logging.getLogger("Align component")
logger.setLevel(logging.DEBUG)
示例#6
0
    def PyExec(self):
        self._eulerConvention = self.getProperty('EulerConvention').value
        calWS = self.getProperty('CalibrationTable').value
        calWS = api.SortTableWorkspace(calWS, Columns='detid')
        maskWS = self.getProperty("MaskWorkspace").value

        difc = calWS.column('difc')
        if maskWS is not None:
            self._masking = True
            mask = maskWS.extractY().flatten()
            difc = np.ma.masked_array(difc, mask)

        detID = calWS.column('detid')

        if self.getProperty("Workspace").value is not None:
            wks_name = self.getProperty("Workspace").value.name()
        else:
            wks_name = "alignedWorkspace"
            api.LoadEmptyInstrument(
                Filename=self.getProperty("InstrumentFilename").value,
                OutputWorkspace=wks_name)

        # Make a dictionary of what options are being refined for sample/source. No rotation.
        for opt in self._optionsList[:3]:
            self._optionsDict[opt] = self.getProperty(opt).value
        for opt in self._optionsList[3:]:
            self._optionsDict[opt] = False

        # First fit L1 if selected for Source and/or Sample
        for component in "Source", "Sample":
            if self.getProperty("Fit" + component + "Position").value:
                self._move = True
                if component == "Sample":
                    comp = api.mtd[wks_name].getInstrument().getSample()
                else:
                    comp = api.mtd[wks_name].getInstrument().getSource()
                componentName = comp.getFullName()
                logger.notice("Working on " + componentName +
                              " Starting position is " + str(comp.getPos()))
                firstIndex = 0
                lastIndex = len(difc)
                if self._masking:
                    mask_out = mask[firstIndex:lastIndex + 1]
                else:
                    mask_out = None

                self._initialPos = [
                    comp.getPos().getX(),
                    comp.getPos().getY(),
                    comp.getPos().getZ(), 0, 0, 0
                ]

                # Set up x0 and bounds lists
                x0List = []
                boundsList = []
                for iopt, opt in enumerate(self._optionsList[:3]):
                    if self._optionsDict[opt]:
                        x0List.append(self._initialPos[iopt])
                        boundsList.append(
                            (self._initialPos[iopt] +
                             self.getProperty("Min" + opt).value,
                             self._initialPos[iopt] +
                             self.getProperty("Max" + opt).value))

                results = minimize(self._minimisation_func,
                                   x0=x0List,
                                   method='L-BFGS-B',
                                   args=(wks_name, componentName, firstIndex,
                                         lastIndex, difc[firstIndex:lastIndex +
                                                         1], mask_out),
                                   bounds=boundsList)

                # Apply the results to the output workspace
                xmap = self._mapOptions(results.x)

                # Need to grab the component again, as things have changed
                api.MoveInstrumentComponent(wks_name,
                                            componentName,
                                            X=xmap[0],
                                            Y=xmap[1],
                                            Z=xmap[2],
                                            RelativePosition=False)
                comp = api.mtd[wks_name].getInstrument().getComponentByName(
                    componentName)
                logger.notice("Finished " + componentName +
                              " Final position is " + str(comp.getPos()))
                self._move = False

        # Now fit all the components if any
        components = self.getProperty("ComponentList").value

        # Make a dictionary of what options are being refined.
        for opt in self._optionsList:
            self._optionsDict[opt] = self.getProperty(opt).value

        self._move = (self._optionsDict["Xposition"]
                      or self._optionsDict["Yposition"]
                      or self._optionsDict["Zposition"])

        self._rotate = (self._optionsDict["AlphaRotation"]
                        or self._optionsDict["BetaRotation"]
                        or self._optionsDict["GammaRotation"])

        prog = Progress(self, start=0, end=1, nreports=len(components))
        for component in components:
            comp = api.mtd[wks_name].getInstrument().getComponentByName(
                component)
            firstDetID = self._getFirstDetID(comp)
            firstIndex = detID.index(firstDetID)
            lastDetID = self._getLastDetID(comp)
            lastIndex = detID.index(lastDetID)
            if lastDetID - firstDetID != lastIndex - firstIndex:
                raise RuntimeError(
                    "Calibration detid doesn't match instrument")

            eulerAngles = comp.getRotation().getEulerAngles(
                self._eulerConvention)

            logger.notice("Working on " + comp.getFullName() +
                          " Starting position is " + str(comp.getPos()) +
                          " Starting rotation is " + str(eulerAngles))

            x0List = []
            self._initialPos = [
                comp.getPos().getX(),
                comp.getPos().getY(),
                comp.getPos().getZ(), eulerAngles[0], eulerAngles[1],
                eulerAngles[2]
            ]

            boundsList = []

            if self._masking:
                mask_out = mask[firstIndex:lastIndex + 1]
                if mask_out.sum() == mask_out.size:
                    self.log().warning(
                        "All pixels in '%s' are masked. Skipping calibration."
                        % component)
                    continue
            else:
                mask_out = None

            for iopt, opt in enumerate(self._optionsList):
                if self._optionsDict[opt]:
                    x0List.append(self._initialPos[iopt])
                    boundsList.append((self._initialPos[iopt] +
                                       self.getProperty("Min" + opt).value,
                                       self._initialPos[iopt] +
                                       self.getProperty("Max" + opt).value))

            results = minimize(self._minimisation_func,
                               x0=x0List,
                               method='L-BFGS-B',
                               args=(wks_name, component, firstIndex,
                                     lastIndex, difc[firstIndex:lastIndex + 1],
                                     mask_out),
                               bounds=boundsList)

            # Apply the results to the output workspace
            xmap = self._mapOptions(results.x)

            if self._move:
                api.MoveInstrumentComponent(wks_name,
                                            component,
                                            X=xmap[0],
                                            Y=xmap[1],
                                            Z=xmap[2],
                                            RelativePosition=False)

            if self._rotate:
                (rotw, rotx, roty,
                 rotz) = self._eulerToAngleAxis(xmap[3], xmap[4], xmap[5],
                                                self._eulerConvention)
                api.RotateInstrumentComponent(wks_name,
                                              component,
                                              X=rotx,
                                              Y=roty,
                                              Z=rotz,
                                              Angle=rotw,
                                              RelativeRotation=False)

            # Need to grab the component again, as things have changed
            comp = api.mtd[wks_name].getInstrument().getComponentByName(
                component)
            logger.notice(
                "Finshed " + comp.getFullName() + " Final position is " +
                str(comp.getPos()) + " Final rotation is " +
                str(comp.getRotation().getEulerAngles(self._eulerConvention)))

            prog.report()
        logger.notice("Results applied to workspace " + wks_name)
示例#7
0
#!/usr/bin/env python
# coding: utf-8

from mantid import simpleapi as msa, mtd
import numpy as np, os, math, collections
import scipy.optimize as sopt

import align
reload(align)

# ## Load difc
difc_table = msa.Load('./difc_cal.nxs')
difc_table = msa.SortTableWorkspace(difc_table, Columns='detid')
detID = np.array(difc_table.column('detid'))
difc = np.array(difc_table.column('difc'))
mask = np.load('./mask_difc.npy')
# difc2 = np.load('./difc_cal2.npy') # this was computed using scipy optimize curvefit
difc2 = np.load("./difc-2-difc.npy")
mask2 = np.load("./difc-2-mask.npy")
mask = np.logical_or(mask, mask2)

# ## Load L2
L2_calib = msa.Load('L2table.nxs')
L2_calib = msa.SortTableWorkspace(L2_calib, Columns='detid')
L2 = np.array(L2_calib.column('L2'))
nodata = np.array(L2_calib.column('nodata'), dtype=bool)
mask = np.logical_or(mask, nodata)

# ## Apply mask
difc = np.ma.masked_array(difc, mask)
L2 = np.ma.masked_array(L2, mask)
示例#8
0
    def PyExec(self):
        table_tof = self.getProperty('PeakCentersTofTable').value
        self.peaks_tof = self._extract_tofs(table_tof)
        detector_count, peak_count = self.peaks_tof.shape
        table_tof = api.SortTableWorkspace(table_tof, Columns='detid')
        detID = table_tof.column('detid')
        peaks_ref = np.sort(self.getProperty(
            'PeakPositions').value)  # sort by increasing value
        self.peaks_ref = peaks_ref[np.newaxis, :]  # shape = (1, peak_count)

        # Process input mask
        maskWS = self.getProperty("MaskWorkspace").value
        if maskWS is not None:
            mask = maskWS.extractY().flatten()  # shape=(detector_count,)
            peaks_mask = np.tile(
                mask[:, np.newaxis],
                peak_count)  # shape=(detector_count, peak_count)
        else:
            peaks_mask = np.zeros(
                (detector_count, peak_count))  # no detectors are masked
        peaks_mask[np.isnan(self.peaks_tof)] = True
        # mask the defective detectors and missing peaks
        self.peaks_tof = np.ma.masked_array(self.peaks_tof, peaks_mask)

        input_workspace = self.getProperty('InputWorkspace').value

        # Table containing the optimized absolute locations and orientations for each component
        adjustments_table_name = self.getProperty('AdjustmentsTable').value
        if len(adjustments_table_name) > 0:
            adjustments_table = self._initialize_adjustments_table(
                adjustments_table_name)
            saving_adjustments = True
        else:
            saving_adjustments = False

        # Table containing the relative changes in position and euler angles for each bank component
        displacements_table_name = self.getProperty('DisplacementsTable').value
        if len(displacements_table_name) > 0:
            displacements_table = self._initialize_displacements_table(
                displacements_table_name)
            saving_displacements = True
        else:
            saving_displacements = False

        self._eulerConvention = self.getProperty('EulerConvention').value

        output_workspace = self.getPropertyValue("OutputWorkspace")
        wks_name = '__alignedworkspace'  # workspace whose counts will be DIFC values
        if bool(input_workspace) is True:
            api.CloneWorkspace(InputWorkspace=input_workspace,
                               OutputWorkspace=wks_name)
            if output_workspace != str(input_workspace):
                api.CloneWorkspace(InputWorkspace=input_workspace,
                                   OutputWorkspace=output_workspace)
        else:
            api.LoadEmptyInstrument(
                Filename=self.getProperty("InstrumentFilename").value,
                OutputWorkspace=wks_name)

        # Make a dictionary of what options are being refined for sample/source. No rotation.
        for translation_option in self._optionsList[:3]:
            self._optionsDict[translation_option] = self.getProperty(
                translation_option).value
        for rotation_option in self._optionsList[3:]:
            self._optionsDict[rotation_option] = False

        # First fit L1 if selected for Source and/or Sample
        sample_position_begin = api.mtd[wks_name].getInstrument().getSample(
        ).getPos()
        for component in "Source", "Sample":  # fit first the source position, then the sample position
            if self.getProperty("Fit" + component + "Position").value:
                self._move = True
                if component == "Sample":
                    comp = api.mtd[wks_name].getInstrument().getSample()
                else:
                    comp = api.mtd[wks_name].getInstrument().getSource()
                componentName = comp.getFullName()
                logger.notice("Working on " + componentName +
                              " Starting position is " + str(comp.getPos()))
                firstIndex = 0
                lastIndex = detector_count - 1

                self._initialPos = [
                    comp.getPos().getX(),
                    comp.getPos().getY(),
                    comp.getPos().getZ(), 0, 0, 0
                ]  # no rotation

                # Set up x0 and bounds lists
                x0List = []  # initial X, Y, Z coordinates
                boundsList = []  # [(minX, maxX), (minZ, maxZ), (minZ, maxZ)]
                for iopt, translation_option in enumerate(
                        self._optionsList[:3]):  # iterate over X, Y, and Z
                    if self._optionsDict[translation_option]:
                        x0List.append(self._initialPos[iopt])
                        # default range for X is (x0 - 0.1m, x0 + 0.1m), same for Y and Z
                        boundsList.append((
                            self._initialPos[iopt] +
                            self.getProperty("Min" + translation_option).value,
                            self._initialPos[iopt] +
                            self.getProperty("Max" +
                                             translation_option).value))

                # scipy.opimize.minimize with the L-BFGS-B algorithm
                results: OptimizeResult = minimize(
                    self._minimisation_func,
                    x0=x0List,
                    method='L-BFGS-B',
                    args=(wks_name, componentName, firstIndex, lastIndex),
                    bounds=boundsList)

                # Apply the results to the output workspace
                xmap = self._mapOptions(results.x)

                # Save translation and rotations, if requested
                if saving_adjustments:
                    instrument = api.mtd[wks_name].getInstrument()
                    name_finder = {
                        'Source': instrument.getSource().getName(),
                        'Sample': instrument.getSample().getName()
                    }
                    component_adjustments = [
                        name_finder[component]
                    ] + xmap[:3] + [0.0] * 4  # no rotations
                    adjustments_table.addRow(component_adjustments)

                # Need to grab the component again, as things have changed
                kwargs = dict(X=xmap[0],
                              Y=xmap[1],
                              Z=xmap[2],
                              RelativePosition=False,
                              EnableLogging=False)
                api.MoveInstrumentComponent(wks_name, componentName,
                                            **kwargs)  # adjust workspace
                api.MoveInstrumentComponent(output_workspace, componentName,
                                            **kwargs)  # adjust workspace
                comp = api.mtd[wks_name].getInstrument().getComponentByName(
                    componentName)
                logger.notice("Finished " + componentName +
                              " Final position is " + str(comp.getPos()))
                self._move = False
        sample_position_end = api.mtd[wks_name].getInstrument().getSample(
        ).getPos()

        # Now fit all the remaining components, if any
        components = self.getProperty("ComponentList").value

        # Make a dictionary of what translational and rotational options are being refined.
        for opt in self._optionsList:
            self._optionsDict[opt] = self.getProperty(opt).value

        self._move = any([
            self._optionsDict[t]
            for t in ('Xposition', 'Yposition', 'Zposition')
        ])
        self._rotate = any([
            self._optionsDict[r]
            for r in ('AlphaRotation', 'BetaRotation', 'GammaRotation')
        ])

        prog = Progress(self, start=0, end=1, nreports=len(components))
        for component in components:
            comp = api.mtd[wks_name].getInstrument().getComponentByName(
                component)
            firstDetID = self._getFirstDetID(comp)
            firstIndex = detID.index(
                firstDetID)  # a row index in the input TOFS table
            lastDetID = self._getLastDetID(comp)
            lastIndex = detID.index(
                lastDetID)  # a row index in the input TOFS table
            if lastDetID - firstDetID != lastIndex - firstIndex:
                raise RuntimeError("TOFS detid doesn't match instrument")

            eulerAngles: List[float] = comp.getRotation().getEulerAngles(
                self._eulerConvention)

            logger.notice("Working on " + comp.getFullName() +
                          " Starting position is " + str(comp.getPos()) +
                          " Starting rotation is " + str(eulerAngles))

            x0List = []
            self._initialPos = [
                comp.getPos().getX(),
                comp.getPos().getY(),
                comp.getPos().getZ(), eulerAngles[0], eulerAngles[1],
                eulerAngles[2]
            ]

            # Distance between the original position of the sample and the original position of the component
            comp_sample_distance_begin = (comp.getPos() -
                                          sample_position_begin).norm()

            boundsList = []

            if np.all(peaks_mask[firstIndex:lastIndex + 1].astype(bool)):
                self.log().warning(
                    "All pixels in '%s' are masked. Skipping calibration." %
                    component)
                continue

            for iopt, opt in enumerate(self._optionsList):
                if self._optionsDict[opt]:
                    x0List.append(self._initialPos[iopt])
                    boundsList.append((self._initialPos[iopt] +
                                       self.getProperty("Min" + opt).value,
                                       self._initialPos[iopt] +
                                       self.getProperty("Max" + opt).value))

            minimizer_selection = self.getProperty('Minimizer').value
            if minimizer_selection == 'L-BFGS-B':
                # scipy.opimize.minimize with the L-BFGS-B algorithm
                results: OptimizeResult = minimize(self._minimisation_func,
                                                   x0=x0List,
                                                   method='L-BFGS-B',
                                                   args=(wks_name, component,
                                                         firstIndex,
                                                         lastIndex),
                                                   bounds=boundsList)
            elif minimizer_selection == 'differential_evolution':
                results: OptimizeResult = differential_evolution(
                    self._minimisation_func,
                    bounds=boundsList,
                    args=(wks_name, component, firstIndex, lastIndex),
                    maxiter=self.getProperty('MaxIterations').value)
            # Apply the results to the output workspace
            xmap = self._mapOptions(results.x)

            comp = api.mtd[wks_name].getInstrument().getComponentByName(
                component)  # adjusted component
            # Distance between the adjusted position of the sample and the adjusted position of the component
            comp_sample_distance_end = (comp.getPos() -
                                        sample_position_end).norm()

            component_adjustments = [
                0.
            ] * 7  # 3 for translation, 3 for rotation axis, 1 for rotation angle
            component_displacements = [
                0.
            ] * 7  # 1 for distnace, 3 for translation, 3 for Euler angles
            component_displacements[0] = 1000 * (
                comp_sample_distance_end - comp_sample_distance_begin
            )  # in mili-meters

            if self._move:
                kwargs = dict(X=xmap[0],
                              Y=xmap[1],
                              Z=xmap[2],
                              RelativePosition=False,
                              EnableLogging=False)
                api.MoveInstrumentComponent(wks_name, component,
                                            **kwargs)  # adjust workspace
                api.MoveInstrumentComponent(output_workspace, component,
                                            **kwargs)  # adjust workspace
                component_adjustments[:3] = xmap[:3]
                for i in range(3):
                    component_displacements[i + 1] = 1000 * (
                        xmap[i] - self._initialPos[i])  # in mili-meters

            if self._rotate:
                (rotw, rotx, roty,
                 rotz) = self._eulerToAngleAxis(xmap[3], xmap[4], xmap[5],
                                                self._eulerConvention)
                kwargs = dict(X=rotx,
                              Y=roty,
                              Z=rotz,
                              Angle=rotw,
                              RelativeRotation=False,
                              EnableLogging=False)
                api.RotateInstrumentComponent(wks_name, component,
                                              **kwargs)  # adjust workspace
                api.RotateInstrumentComponent(output_workspace, component,
                                              **kwargs)  # adjust workspace
                component_adjustments[3:] = [rotx, roty, rotz, rotw]
                for i in range(3, 6):
                    component_displacements[
                        i + 1] = xmap[i] - self._initialPos[i]  # in degrees

            if saving_adjustments and (self._move or self._rotate):
                adjustments_table.addRow([component] + component_adjustments)

            if saving_displacements and (self._move or self._rotate):
                displacements_table.addRow([component] +
                                           component_displacements)

            # Need to grab the component object again, as things have changed
            logger.notice(
                "Finished " + comp.getFullName() + " Final position is " +
                str(comp.getPos()) + " Final rotation is " +
                str(comp.getRotation().getEulerAngles(self._eulerConvention)))

            prog.report()
        api.DeleteWorkspace(wks_name)
        self.setProperty("OutputWorkspace", output_workspace)
        logger.notice("Results applied to workspace " + wks_name)