Пример #1
0
def det_shift_before_2016(ws_to_correct):
    """ Final detectors' alignement has been done using laser tracker in January, 2016.
     To correct data collected before that, some extra shift hardcoded here, shall be applied """

    shift_curtainl = 0.74 / 1000
    shift_curtainr = 6.92 / 1000
    shift_curtainu = -7.50 / 1000
    shift_curtaind = -1.59 / 1000

    MoveInstrumentComponent(ws_to_correct,
                            'CurtainLeft',
                            X=shift_curtainl,
                            Y=0,
                            Z=0)
    MoveInstrumentComponent(ws_to_correct,
                            'CurtainRight',
                            X=shift_curtainr,
                            Y=0,
                            Z=0)
    MoveInstrumentComponent(ws_to_correct,
                            'CurtainTop',
                            X=0,
                            Y=shift_curtainu,
                            Z=0)
    MoveInstrumentComponent(ws_to_correct,
                            'CurtainBottom',
                            X=0,
                            Y=shift_curtaind,
                            Z=0)

    correction_based_on_experiment(ws_to_correct)
def det_shift_before_2016(ws_to_correct):
    shift_curtainl = 0.74 / 1000
    shift_curtainr = 6.92 / 1000
    shift_curtainu = -7.50 / 1000
    shift_curtaind = -1.59 / 1000

    MoveInstrumentComponent(ws_to_correct,
                            'CurtainLeft',
                            X=shift_curtainl,
                            Y=0,
                            Z=0)
    MoveInstrumentComponent(ws_to_correct,
                            'CurtainRight',
                            X=shift_curtainr,
                            Y=0,
                            Z=0)
    MoveInstrumentComponent(ws_to_correct,
                            'CurtainTop',
                            X=0,
                            Y=shift_curtainu,
                            Z=0)
    MoveInstrumentComponent(ws_to_correct,
                            'CurtainBottom',
                            X=0,
                            Y=shift_curtaind,
                            Z=0)

    correction_based_on_experiment(ws_to_correct)
    return ws_to_correct
Пример #3
0
 def test_fix_y(self) -> None:
     CloneWorkspace(InputWorkspace='test_workspace_TOF',
                    OutputWorkspace='perturbed')
     y = -0.0042  # desired fixed position
     MoveInstrumentComponent(Workspace='perturbed',
                             ComponentName='bank1',
                             X=0,
                             y=y,
                             z=0,
                             RelativePosition=False)
     r"""Pass option FixY=True"""
     CorelliPowderCalibrationCreate(InputWorkspace='perturbed',
                                    OutputWorkspacesPrefix='cal_',
                                    TofBinning=[300, 1.0, 16666.7],
                                    PeakPositions=self.spacings_reference,
                                    SourceToSampleDistance=10.0,
                                    ComponentList='bank1',
                                    FixY=True,
                                    ComponentMaxTranslation=0.2,
                                    ComponentMaxRotation=10,
                                    Minimizer='L-BFGS-B')
     # Check Y-position of first bank hasn't changed
     row = mtd['cal_adjustments'].row(1)
     self.assertAlmostEquals(row['Yposition'], y, places=5)
     DeleteWorkspaces(['perturbed'])
Пример #4
0
    def _create_workspaces(self):
        cal=CreateSampleWorkspace(NumBanks=1,BinWidth=20000,PixelSpacing=0.1,BankPixelWidth=100)
        RotateInstrumentComponent(cal, ComponentName='bank1', X=1, Y=0.5, Z=2, Angle=35)
        MoveInstrumentComponent(cal, ComponentName='bank1', X=1, Y=1, Z=5)
        bkg=CloneWorkspace(cal)
        data=CloneWorkspace(cal)
        AddSampleLog(cal, LogName="gd_prtn_chrg", LogType='Number', NumberType='Double', LogText='200')
        AddSampleLog(bkg, LogName="gd_prtn_chrg", LogType='Number', NumberType='Double', LogText='50')
        AddSampleLog(data, LogName="gd_prtn_chrg", LogType='Number', NumberType='Double', LogText='100')
        AddSampleLog(cal, LogName="duration", LogType='Number', NumberType='Double', LogText='20')
        AddSampleLog(bkg, LogName="duration", LogType='Number', NumberType='Double', LogText='5')
        AddSampleLog(data, LogName="duration", LogType='Number', NumberType='Double', LogText='10')

        def get_cal_counts(n):
            if n < 5000:
                return 0.9
            else:
                return 1.0

        def get_bkg_counts(n):
            return 1.5*get_cal_counts(n)

        def get_data_counts(n,twoTheta):
            tt1=30
            tt2=45
            return get_bkg_counts(n)+10*np.exp(-(twoTheta-tt1)**2/1)+20*np.exp(-(twoTheta-tt2)**2/0.2)

        for i in range(cal.getNumberHistograms()):
            cal.setY(i, [get_cal_counts(i)*2.0])
            bkg.setY(i, [get_bkg_counts(i)/2.0])
            twoTheta=data.getInstrument().getDetector(i+10000).getTwoTheta(V3D(0,0,0),V3D(0,0,1))*180/np.pi
            data.setY(i, [get_data_counts(i,twoTheta)])

        return data, cal, bkg
 def _correctForFractionalForegroundCentre(self, ws, summedForeground):
     """
     This needs to be called after having summed the foreground but before transfering to momentum transfer.
     This needs to be called in both coherent and incoherent cases, regardless the angle calibration option.
     The reason for this is that up to this point is the fractional workspace index that correponds to the calibrated 2theta.
     However the momentum transfer calculation, which normally comes after summing the foreground,
     takes the 2theta from the spectrumInfo of the summed foreground workspace.
     Hence this code below translated the detector by the difference of the
     fractional and integer foreground centre along the detector plane.
     It also applies local rotation so that the detector continues to face the sample.
     Note that this translation has nothing to do with the difference of foreground centres in direct and reflected beams,
     which is handled already in pre-process algorithm.
     Here it's only about the difference of the fractional and integer foreground centre of the reflected beam
     with already calibrated angle no matter the option.
     Note also, that this could probably be avoided, if the loader placed
     the integer foreground at the given angle and not the fractional one.
     Fractional foreground centre only matter when calculating the difference between direct and reflected beams.
     But for the final Q (and sigma) calculation, it takes the position/angle from spectrumInfo()...(0),
     which corresponds to the centre of the pixel."""
     foreground = self._foregroundIndices(ws)
     # integer foreground centre
     beamPosIndex = foreground[1]
     # fractional foreground centre
     linePosition = ws.run().getProperty(
         common.SampleLogs.LINE_POSITION).value
     l2 = ws.run().getProperty('L2').value
     instr = common.instrumentName(ws)
     pixelSize = common.pixelSize(instr)
     # the distance between the fractional and integer foreground centres along the detector plane
     dist = pixelSize * (linePosition - beamPosIndex)
     if dist != 0.:
         detPoint1 = ws.spectrumInfo().position(0)
         detPoint2 = ws.spectrumInfo().position(20)
         beta = numpy.math.atan2((detPoint2[0] - detPoint1[0]),
                                 (detPoint2[2] - detPoint1[2]))
         xvsy = numpy.math.sin(beta) * dist
         mz = numpy.math.cos(beta) * dist
         if instr == 'D17':
             mx = xvsy
             my = 0.0
             rotationAxis = [0, 1, 0]
         else:
             mx = 0.0
             my = xvsy
             rotationAxis = [-1, 0, 0]
         MoveInstrumentComponent(Workspace=summedForeground,
                                 ComponentName='detector',
                                 X=mx,
                                 Y=my,
                                 Z=mz,
                                 RelativePosition=True)
         angle_corr = numpy.arctan2(dist, l2) * 180 / numpy.pi
         RotateInstrumentComponent(Workspace=summedForeground,
                                   ComponentName='detector',
                                   X=rotationAxis[0],
                                   Y=rotationAxis[1],
                                   Z=rotationAxis[2],
                                   Angle=angle_corr,
                                   RelativeRotation=True)
     return summedForeground
Пример #6
0
 def test_plotDOS_PlotMultiple(self):
     ws = CreateSampleWorkspace(NumBanks=1,
                                XUnit='DeltaE',
                                XMin=-12.,
                                XMax=12.,
                                BinWidth=0.2,
                                StoreInADS=False)
     MoveInstrumentComponent(ws, 'bank1', X=-0.5, StoreInADS=False)
     ws = ConvertSpectrumAxis(ws, 'Theta', 'Direct', 14., StoreInADS=False)
     SetInstrumentParameter(ws,
                            ParameterName='deltaE-mode',
                            Value='direct',
                            StoreInADS=False)
     AddSampleLog(ws,
                  LogName='Ei',
                  LogText=str(14.),
                  LogType='Number',
                  LogUnit='meV',
                  StoreInADS=False)
     stw = ComputeIncoherentDOS(ws)
     kwargs = {'workspaces': [stw, 'stw']}
     figure, axes = testhelpers.assertRaisesNothing(self,
                                                    directtools.plotDOS,
                                                    **kwargs)
     self.assertEqual(axes.get_xlabel(), 'Energy transfer ($meV$)')
     self.assertEqual(axes.get_ylabel(), '$g(E)$')
Пример #7
0
 def serve_instrument(output_workspace):
     scattering_angle = 20  # in degrees
     # Instrument with four spectra. Each spectrum has one single Gaussian peak in TOF, centered at 10000
     CreateSampleWorkspace(OutputWorkspace=output_workspace, BinWidth=0.1, NumBanks=1, BankPixelWidth=2,
                           Function='User Defined',
                           UserDefinedFunction='name=Gaussian, PeakCentre=10000, Height=100, Sigma=2',
                           Xmin=9900, Xmax=10100, BankDistanceFromSample=2, SourceDistanceFromSample=20)
     MoveInstrumentComponent(Workspace=output_workspace, ComponentName='bank1', RelativePosition=False,
                             X=0, Y=0.0, Z=0)  # move to the origin
     RotateInstrumentComponent(Workspace=output_workspace, ComponentName='bank1', X=0, Y=1, Z=0,
                               Angle=scattering_angle, RelativeRotation=False)
     sin, cos = np.sin(np.radians(scattering_angle)), np.cos(np.radians(scattering_angle))
     # detector pixel width is 0.008m, perpendicular to the scattered beam. Detector is 2m away from the sample
     z, x = 2 * cos + 0.004 * sin, 2 * sin - 0.004 * cos
     MoveInstrumentComponent(Workspace=output_workspace, ComponentName='bank1', RelativePosition=False,
                             X=x, Y=0, Z=z)  # translate 2 meters away and center the detector
     return mtd['original']
Пример #8
0
def correct_element_one_stripe(
    panel, pixelsize, shift, ws
):  # sutable for one Cd stripe correction and for the stripes on BorAl mask on left curtain
    """ Technical for correction_tubes_shift """

    eightpack = [
        'eight_pack1', 'eight_pack2', 'eight_pack3', 'eight_pack4',
        'eight_pack5'
    ]
    tube = [
        'tube1', 'tube2', 'tube3', 'tube4', 'tube5', 'tube6', 'tube7', 'tube8'
    ]

    i = 0
    for ei_pack, t_tube in product(eightpack, tube):
        if (panel == "BackDetectorLeft" or panel == "CurtainLeft"):
            direction = 1.0
            MoveInstrumentComponent(ws,
                                    panel + '/' + ei_pack + '/' + t_tube,
                                    X=0,
                                    Y=-float(shift[i]) * pixelsize * direction,
                                    Z=0)
        if (panel == "BackDetectorRight" or panel == "CurtainRight"):
            direction = -1.0
            MoveInstrumentComponent(ws,
                                    panel + '/' + ei_pack + '/' + t_tube,
                                    X=0,
                                    Y=-float(shift[i]) * pixelsize * direction,
                                    Z=0)
        if (panel == "CurtainBottom"):
            direction = 1.0
            MoveInstrumentComponent(ws,
                                    panel + '/' + ei_pack + '/' + t_tube,
                                    X=-float(shift[i]) * pixelsize * direction,
                                    Y=0,
                                    Z=0)
        if (panel == "CurtainTop"):
            direction = -1.0
            MoveInstrumentComponent(ws,
                                    panel + '/' + ei_pack + '/' + t_tube,
                                    X=-float(shift[i]) * pixelsize * direction,
                                    Y=0,
                                    Z=0)
        i = i + 1
    return ws
Пример #9
0
 def setUp(self) -> None:
     r"""Fixture runs at the beginning of every test method"""
     spacings_reference = [
         0.9179, 0.9600, 1.0451, 1.2458, 1.3576, 1.5677, 1.6374, 3.1353
     ]  # silicon
     # add one Gaussian peak for every reference d-spacing
     peak_functions = list()
     for spacing in spacings_reference:
         peak_function = f'name=Gaussian, PeakCentre={spacing}, Height={10 * np.sqrt(spacing)}, Sigma={0.003 * spacing}'
         peak_functions.append(peak_function)
     function = ';'.join(peak_functions)
     begin, end, bin_width = spacings_reference[
         0] - 0.5, spacings_reference[-1] + 0.5, 0.0001
     # Single 10x10 rectangular detector, located 4m downstream the sample along the X-axis
     # Each detector has the same histogram of intensities, showing eight Gaussian peaks with centers at the
     # reference d-spacings
     CreateSampleWorkspace(WorkspaceType='Histogram',
                           Function='User Defined',
                           UserDefinedFunction=function,
                           XUnit='dSpacing',
                           XMin=begin,
                           XMax=end,
                           BinWidth=bin_width,
                           NumBanks=1,
                           PixelSpacing=0.02,
                           SourceDistanceFromSample=10.0,
                           BankDistanceFromSample=4.0,
                           OutputWorkspace='test_workspace_dSpacing')
     RotateInstrumentComponent(Workspace='test_workspace_dSpacing',
                               ComponentName='bank1',
                               X=0.,
                               Y=1.,
                               z=0.,
                               Angle=90,
                               RelativeRotation=True)
     MoveInstrumentComponent(Workspace='test_workspace_dSpacing',
                             ComponentName='bank1',
                             X=4.0,
                             y=0.0,
                             z=0.0,
                             RelativePosition=False)
     # Eight peaks now in TOF. Only when the instrument is located 4m downstream along the X-axis will we obtain
     # the correct d-Spacings if we convert back to dSpacings units. If we perturb the instrument and convert
     # back to dSpacing units, we'll obtain eight peaks centered at d-spacings sligthly different than the
     # reference values
     ConvertUnits(InputWorkspace='test_workspace_dSpacing',
                  Target='TOF',
                  EMode='Elastic',
                  OutputWorkspace='test_workspace_TOF')
     Rebin(InputWorkspace='test_workspace_TOF',
           Params=[300, 1.0, 16666.7],
           OutputWorkspace='test_workspace_TOF')
     ConvertUnits(InputWorkspace='test_workspace_TOF',
                  Target='dSpacing',
                  EMode='Elastic',
                  OutputWorkspace='test_workspace_dSpacing')
     self.spacings_reference = spacings_reference
Пример #10
0
def create_test_ws_and_group():
    myFunc = "name=Gaussian, PeakCentre=2, Height=100, Sigma=0.01;" + \
        "name=Gaussian, PeakCentre=1, Height=100, Sigma=0.01;" + \
        "name=Gaussian, PeakCentre=4, Height=100, Sigma=0.01"
    ws = CreateSampleWorkspace("Event",
                               "User Defined",
                               myFunc,
                               BankPixelWidth=1,
                               XUnit='dSpacing',
                               XMax=5,
                               BinWidth=0.001,
                               NumEvents=100000,
                               NumBanks=8)
    for n in range(1, 5):
        MoveInstrumentComponent(ws,
                                ComponentName=f'bank{n}',
                                X=1 + n / 10,
                                Y=0,
                                Z=1 + n / 10,
                                RelativePosition=False)
        MoveInstrumentComponent(ws,
                                ComponentName=f'bank{n+4}',
                                X=2 + n / 10,
                                Y=0,
                                Z=2 + n / 10,
                                RelativePosition=False)

    MaskDetectors(ws, WorkspaceIndexList=[3, 7])

    ws = ScaleX(ws, Factor=1.05, IndexMin=1, IndexMax=1)
    ws = ScaleX(ws, Factor=0.95, IndexMin=2, IndexMax=2)
    ws = ScaleX(ws, Factor=1.05, IndexMin=4, IndexMax=6)
    ws = ScaleX(ws, Factor=1.02, IndexMin=5, IndexMax=5)
    ws = ScaleX(ws, Factor=0.98, IndexMin=6, IndexMax=6)
    ws = Rebin(ws, '0,0.001,5')
    ws = ConvertUnits(ws, Target='TOF')

    groups, _, _ = CreateGroupingWorkspace(InputWorkspace=ws,
                                           ComponentName='basic_rect',
                                           CustomGroupingString='1-4,5-8')

    return ws, groups
def move_rear_panels(shift, pixelsize, ws):
    """ Technical for CorrectionTubesShift """

    panel = "BackDetectorLeft"
    direction = 1.0
    MoveInstrumentComponent(ws,
                            panel,
                            X=0,
                            Y=-float(shift) * pixelsize * direction,
                            Z=0)

    panel = "BackDetectorRight"
    direction = -1.0
    MoveInstrumentComponent(ws,
                            panel,
                            X=0,
                            Y=-float(shift) * pixelsize * direction,
                            Z=0)

    return ws
Пример #12
0
def move_rear_panels(
    shift, pixelsize, ws
):  # moves only rear left and rear right, each on shift; +1 to the right panel to make them symmetrical
    """ Technical for correction_tubes_shift """

    panel = "BackDetectorLeft"
    direction = 1.0
    MoveInstrumentComponent(ws,
                            panel,
                            X=0,
                            Y=-float(shift) * pixelsize * direction,
                            Z=0)

    panel = "BackDetectorRight"
    direction = -1.0
    MoveInstrumentComponent(ws,
                            panel,
                            X=0,
                            Y=-float(shift) * pixelsize * direction,
                            Z=0)

    return ws
Пример #13
0
 def test_translation(self):
     CloneWorkspace(InputWorkspace='test_workspace_TOF',
                    OutputWorkspace='perturbed')
     CloneWorkspace(InputWorkspace='test_workspace_TOF',
                    OutputWorkspace='perturbed')
     MoveInstrumentComponent(Workspace='perturbed',
                             ComponentName='bank1',
                             X=0.02,
                             y=0.005,
                             z=0.005,
                             RelativePosition=True)
     assert self.spacings_recovered('perturbed', calibrate=False) is False
     assert self.spacings_recovered('perturbed', calibrate=True)
     DeleteWorkspaces(['perturbed'])
    def _fixed_source_set_and_table(self, table_name):
        r"""Create a table with appropriate column names for saving the location of the source"""
        # collect info on the source
        input_workspace = self.getPropertyValue(
            'InputWorkspace')  # name of the input workspace
        source = mtd[self.getPropertyValue(
            'InputWorkspace')].getInstrument().getSource()
        source_name, source_full_name = source.getName(), source.getFullName()

        # Update the position of the source
        z_position = -abs(self.getProperty('SourceToSampleDistance').value)
        MoveInstrumentComponent(input_workspace,
                                source_full_name,
                                X=0.0,
                                Y=0.0,
                                Z=z_position,
                                RelativePosition=False)

        # Initialize the table of adjustments for the source
        table = CreateEmptyTableWorkspace(OutputWorkspace=table_name)
        item_types = [
            'str', 'double', 'double', 'double', 'double', 'double', 'double',
            'double'
        ]
        item_names = [
            'ComponentName', 'Xposition', 'Yposition', 'Zposition',
            'XdirectionCosine', 'YdirectionCosine', 'ZdirectionCosine',
            'RotationAngle'
        ]
        for column_name, column_type in zip(item_names, item_types):
            table.addColumn(name=column_name, type=column_type)

        # Add the appropriate row in the table for the source
        table.addRow([
            source_name,
            0.0,
            0.0,
            z_position,  # new position for the source
            0.0,
            0.0,
            0.0,  # no rotation axis
            0.0
        ])  # no rotation angle
        return table
Пример #15
0
def correction_based_on_experiment(ws_to_correct):
    """ The function to move curtains, based on fits/analysis of a massive set of AgBeh and liquid crystals data.
          Laser tracker has not picked up these imperfections.
         Added on October, 6th, 2016 """

    MoveInstrumentComponent(ws_to_correct,
                            'CurtainLeft',
                            X=-5.3 / 1000,
                            Y=0,
                            Z=13.0 / 1000)
    MoveInstrumentComponent(ws_to_correct,
                            'CurtainRight',
                            X=5.5 / 1000,
                            Y=0,
                            Z=17.0 / 1000)
    MoveInstrumentComponent(ws_to_correct,
                            'CurtainTop',
                            X=0,
                            Y=-4.0 / 1000,
                            Z=0)
    MoveInstrumentComponent(ws_to_correct,
                            'CurtainBottom',
                            X=0,
                            Y=6.0 / 1000,
                            Z=0)
    MoveInstrumentComponent(ws_to_correct,
                            'BackDetectorRight',
                            X=0,
                            Y=-2.0 / 1000,
                            Z=0)
    MoveInstrumentComponent(ws_to_correct,
                            'BackDetectorLeft',
                            X=0,
                            Y=-2.0 / 1000,
                            Z=0)

    return
Пример #16
0
    def testAlignComponentsPosition(self):
        r"""

        CreateSampleWorkspace here generates one bank of 2x2 pixels. All pixels have a single peak at
        TOF=10000 micro-seconds. The bank is facing the sample, centered along the vertical axis (Y),
        and at a scattering angle from the beam axis (Z).
        Because the pixels are at different locations, converting units to d-spacing results in peaks at different
        values of d-spacing. For the bank in this test we have:

            workspace index       | 0      | 1      | 2      | 3      |
            ----------------------|--------|--------|--------|--------|
            detector ID           | 4      | 5      | 6      | 6      |
            ----------------------|--------|--------|--------|--------|
            peack-center TOF      |10000   | 10000  | 10000  | 10000  |
            ----------------------|--------|--------|--------|--------|
            peak-center d-spacing | 5.2070 | 5.2070 | 5.1483 | 5.1483 |

        The first workspace index corresponds to a pixel centered on the beam axis, hence the scattering angle is zero
        and the corresponding d-spacing is infinite.

        Correspondence betwee
        """

        def serve_instrument(output_workspace):
            scattering_angle = 20  # in degrees
            # Instrument with four spectra. Each spectrum has one single Gaussian peak in TOF, centered at 10000
            CreateSampleWorkspace(OutputWorkspace=output_workspace, BinWidth=0.1, NumBanks=1, BankPixelWidth=2,
                                  Function='User Defined',
                                  UserDefinedFunction='name=Gaussian, PeakCentre=10000, Height=100, Sigma=2',
                                  Xmin=9900, Xmax=10100, BankDistanceFromSample=2, SourceDistanceFromSample=20)
            MoveInstrumentComponent(Workspace=output_workspace, ComponentName='bank1', RelativePosition=False,
                                    X=0, Y=0.0, Z=0)  # move to the origin
            RotateInstrumentComponent(Workspace=output_workspace, ComponentName='bank1', X=0, Y=1, Z=0,
                                      Angle=scattering_angle, RelativeRotation=False)
            sin, cos = np.sin(np.radians(scattering_angle)), np.cos(np.radians(scattering_angle))
            # detector pixel width is 0.008m, perpendicular to the scattered beam. Detector is 2m away from the sample
            z, x = 2 * cos + 0.004 * sin, 2 * sin - 0.004 * cos
            MoveInstrumentComponent(Workspace=output_workspace, ComponentName='bank1', RelativePosition=False,
                                    X=x, Y=0, Z=z)  # translate 2 meters away and center the detector
            return mtd['original']

        serve_instrument('original')
        # Convert to d-spacing
        ConvertUnits(InputWorkspace='original', Target='dSpacing', EMode='Elastic', OutputWorkspace='original_dspacing')
        # Find the bin boundaries limiting the peak maximum
        Max(InputWorkspace='original_dspacing', OutputWorkspace='original_d_at_max')
        # Average the two bin boundaries to find the bin center, taken to be the location of the peak center
        original_d = np.average(mtd['original_d_at_max'].extractX(), axis=1)

        peak_positions = [5.1483, 5.2070]  # reference peak positions in d-spacing (Angstroms)

        # Generate a table of peak centers in TOF units
        table_tofs = CreateEmptyTableWorkspace(OutputWorkspace='table_tofs')
        column_info = [('int', 'detid'), ('double', '@5.1483'), ('double', '@5.2070')]
        [table_tofs.addColumn(c_type, c_name) for c_type, c_name in column_info]
        table_tofs.addRow([4, float('nan'), 10000.0])
        table_tofs.addRow([5, float('nan'), 10000.0])  # a peak in TOF correspoding to a peak of 306.5928 Angstroms
        table_tofs.addRow([6, 10000.0, float('nan')])  # a peak in TOF correspoding to a peak of 306.5928 Angstroms
        table_tofs.addRow([7, 10000.0, float('nan')])  # a peak in TOF correspoding to a peak of 216.7940 Angstroms

        # perturb the position of the bank with a translation or the order of a few milimeters
        component = 'bank1'
        xyz_shift = V3D(0.005, 0.010, 0.007)
        CloneWorkspace(InputWorkspace='original', OutputWorkspace='perturbed')
        MoveInstrumentComponent(Workspace='perturbed', ComponentName='bank1', RelativePosition=True,
                                X=xyz_shift.X(), Y=xyz_shift.Y(), Z=xyz_shift.Z())

        # calibrate the perturbed bank
        AlignComponents(PeakCentersTofTable='table_tofs', PeakPositions=peak_positions, OutputWorkspace='calibrated',
                        InputWorkspace='perturbed', ComponentList=component, AdjustmentsTable='adjustments',
                        Xposition=True, Yposition=True, Zposition=True)

        # compare the peak-centers (in d-spacing units) between the original and calibrated
        # spectra, up to 0.001 Angstroms
        ConvertUnits(InputWorkspace='calibrated', Target='dSpacing', EMode='Elastic',
                     OutputWorkspace='calibrated_dspacing')
        Max(InputWorkspace='calibrated_dspacing', OutputWorkspace='calibrated_d_at_max')
        calibrated_d = np.average(mtd['calibrated_d_at_max'].extractX(), axis=1)
        assert np.allclose(original_d, calibrated_d, atol=0.001)

        # perturb the orientation of the bank with a rotation of a small angle around an axis almost parallel
        # to the vertical
        axis_shift, angle_shift = V3D(0.2, 0.8, np.sqrt(1 - 0.2 ** 2 - 0.8 ** 2)), 9.0  # angle shift in degrees
        CloneWorkspace(InputWorkspace='original', OutputWorkspace='perturbed')
        RotateInstrumentComponent(Workspace='perturbed', ComponentName='bank1', RelativeRotation=True,
                                  X=axis_shift.X(), Y=axis_shift.Y(), Z=axis_shift.Z(), Angle=angle_shift)
        ConvertUnits(InputWorkspace='perturbed', OutputWorkspace='perturbed_dspacing', Target='dSpacing', Emode='Elastic')

        # calibrate the perturbed bank
        AlignComponents(PeakCentersTofTable='table_tofs', PeakPositions=peak_positions, OutputWorkspace='calibrated',
                        InputWorkspace='perturbed', ComponentList=component, AdjustmentsTable='adjustments',
                        AlphaRotation=True, BetaRotation=True, GammaRotation=True)
        ConvertUnits(InputWorkspace='calibrated', OutputWorkspace='calibrated_dspacing', Target='dSpacing', Emode='Elastic')

        # compare the peak-centers (in d-spacing units) between the original and calibrated
        # spectra, up to 0.001 Angstroms
        Max(InputWorkspace='calibrated_dspacing', OutputWorkspace='calibrated_d_at_max')
        calibrated_d = np.average(mtd['calibrated_d_at_max'].extractX(), axis=1)
        assert np.allclose(original_d, calibrated_d, atol=0.001)
Пример #17
0
 def test_should_not_accept_loaded_workspace_if_moved(self):
     my_workspace = Load(self.load_run)
     MoveInstrumentComponent(my_workspace, self.inst_comp, X=2, Y=1, Z=0)
     ## attempt to use a workspace that has been moved
     self.assertRaises(RuntimeError, AssignSample, my_workspace, False)
 def get_target_instrument(self):
     self.ws_target = "ws_target"
     LoadEmptyInstrument(Filename="CORELLI_Definition.xml",
                         OutputWorkspace=self.ws_target)
     ConvertToEventWorkspace(InputWorkspace=self.ws_target,
                             OutputWorkspace=self.ws_target)
     # explicitly translate component TO designated location
     MoveInstrumentComponent(
         Workspace=self.ws_target,
         ComponentName="moderator",
         X=0,
         Y=0,
         Z=-19.9997,
         RelativePosition=False,
     )
     MoveInstrumentComponent(
         Workspace=self.ws_target,
         ComponentName="sample-position",
         X=0,
         Y=0,
         Z=0,
         RelativePosition=False,
     )
     MoveInstrumentComponent(
         Workspace=self.ws_target,
         ComponentName="bank7/sixteenpack",
         X=2.25637,
         Y=-0.814864,
         Z=-0.883485,
         RelativePosition=False,
     )
     MoveInstrumentComponent(
         Workspace=self.ws_target,
         ComponentName="bank42/sixteenpack",
         X=2.58643,
         Y=0.0725628,
         Z=0.0868798,
         RelativePosition=False,
     )
     MoveInstrumentComponent(
         Workspace=self.ws_target,
         ComponentName="bank57/sixteenpack",
         X=0.4545,
         Y=0.0788326,
         Z=2.53234,
         RelativePosition=False,
     )
     # explicitly rotate component TO designated orientation
     RotateInstrumentComponent(
         Workspace=self.ws_target,
         ComponentName="bank7/sixteenpack",
         X=-0.0244456,
         Y=-0.99953,
         Z=-0.0184843,
         Angle=69.4926,
         RelativeRotation=False,
     )
     RotateInstrumentComponent(
         Workspace=self.ws_target,
         ComponentName="bank42/sixteenpack",
         X=-0.011362,
         Y=-0.999935,
         Z=-0.000173303,
         Angle=91.8796,
         RelativeRotation=False,
     )
     RotateInstrumentComponent(
         Workspace=self.ws_target,
         ComponentName="bank42/sixteenpack",
         X=-0.0158497,
         Y=-0.999694,
         Z=0.0189818,
         Angle=169.519,
         RelativeRotation=False,
     )
Пример #19
0
    def testAlignComponentsRotationY(self):
        CreateSampleWorkspace(OutputWorkspace='testWS',
                              NumBanks=1,
                              BankPixelWidth=4)
        component = 'bank1'
        MoveInstrumentComponent(Workspace='testWS',
                                ComponentName=component,
                                X=2.00,
                                Y=0,
                                Z=2.00,
                                RelativePosition=False)
        RotateInstrumentComponent(Workspace='testWS',
                                  ComponentName='bank1',
                                  X=0,
                                  Y=1,
                                  Z=0,
                                  Angle=50,
                                  RelativeRotation=False)

        ### Detector should rotate to +45deg around Y
        ### Calibration table generated with:
        # CreateSampleWorkspace(OutputWorkspace='sample2', NumBanks=1,BankPixelWidth=4)
        # MoveInstrumentComponent(Workspace='sample2',ComponentName='bank1',X=2.0,Y=0.0,Z=2.0,RelativePosition=False)
        # RotateInstrumentComponent(Workspace='sample2',ComponentName='bank1',X=0,Y=1,Z=0,Angle=45,RelativeRotation=False)
        # CalculateDIFC(InputWorkspace='sample2', OutputWorkspace='sample2')
        # d=mtd['sample2'].extractY()
        # for i in range(len(d)):
        #        print "calTable.addRow(["+str(i+16)+", "+str(d[i][0])+"])"

        calTable = CreateEmptyTableWorkspace()
        calTable.addColumn("int", "detid")
        calTable.addColumn("double", "difc")

        calTable.addRow([16, 2481.89300158])
        calTable.addRow([17, 2481.90717397])
        calTable.addRow([18, 2481.94969])
        calTable.addRow([19, 2482.02054626])
        calTable.addRow([20, 2490.36640334])
        calTable.addRow([21, 2490.38050851])
        calTable.addRow([22, 2490.42282292])
        calTable.addRow([23, 2490.49334316])
        calTable.addRow([24, 2498.83911141])
        calTable.addRow([25, 2498.85314962])
        calTable.addRow([26, 2498.89526313])
        calTable.addRow([27, 2498.96544859])
        calTable.addRow([28, 2507.31101837])
        calTable.addRow([29, 2507.32498986])
        calTable.addRow([30, 2507.36690322])
        calTable.addRow([31, 2507.43675513])

        ws = mtd["testWS"]
        startPos = ws.getInstrument().getComponentByName(component).getPos()
        startRot = ws.getInstrument().getComponentByName(
            component).getRotation().getEulerAngles("YZX")  #YZX
        AlignComponents(CalibrationTable="calTable",
                        Workspace="testWS",
                        ComponentList=component,
                        AlphaRotation=True)
        ws = mtd["testWS"]
        endPos = ws.getInstrument().getComponentByName(component).getPos()
        endRot = ws.getInstrument().getComponentByName(
            component).getRotation().getEulerAngles("YZX")  #YZX
        self.assertEqual(startPos, endPos)
        self.assertAlmostEqual(endRot[0], 45.0, places=0)
        self.assertEqual(startRot[1], endRot[1])
        self.assertEqual(startRot[2], endRot[2])
Пример #20
0
    def testAlignComponentsPositionXY(self):
        CreateSampleWorkspace(OutputWorkspace='testWS',
                              NumBanks=1,
                              BankPixelWidth=4)
        component = 'bank1'
        MoveInstrumentComponent(Workspace='testWS',
                                ComponentName=component,
                                X=0.06,
                                Y=0.04,
                                Z=4.98,
                                RelativePosition=False)

        ### Detector should move to [0.05,0.03,4.98]
        ### Calibration table generated with:
        # CreateSampleWorkspace(OutputWorkspace='sample', NumBanks=1,BankPixelWidth=4)
        # MoveInstrumentComponent(Workspace='sample',ComponentName='bank1',X=0.05,Y=0.03,Z=4.98,RelativePosition=False)
        # CalculateDIFC(InputWorkspace='sample', OutputWorkspace='sample')
        # d=mtd['sample'].extractY()
        # for i in range(len(d)):
        #        print "calTable.addRow(["+str(i+16)+", "+str(d[i][0])+"])"

        calTable = CreateEmptyTableWorkspace()
        calTable.addColumn("int", "detid")
        calTable.addColumn("double", "difc")

        calTable.addRow([16, 44.3352831346])
        calTable.addRow([17, 47.7503426493])
        calTable.addRow([18, 51.6581064544])
        calTable.addRow([19, 55.9553976608])
        calTable.addRow([20, 49.6495672525])
        calTable.addRow([21, 52.7214213944])
        calTable.addRow([22, 56.285004349])
        calTable.addRow([23, 60.2530897937])
        calTable.addRow([24, 55.1227558338])
        calTable.addRow([25, 57.9048914599])
        calTable.addRow([26, 61.1671229038])
        calTable.addRow([27, 64.8369848035])
        calTable.addRow([28, 60.7118272387])
        calTable.addRow([29, 63.2484968666])
        calTable.addRow([30, 66.2480051141])
        calTable.addRow([31, 69.650545037])

        ws = mtd["testWS"]
        startPos = ws.getInstrument().getComponentByName(component).getPos()
        startRot = ws.getInstrument().getComponentByName(
            component).getRotation().getEulerAngles()
        AlignComponents(CalibrationTable="calTable",
                        Workspace="testWS",
                        ComponentList=component,
                        Xposition=True,
                        Yposition=True)
        ws = mtd["testWS"]
        endPos = ws.getInstrument().getComponentByName(component).getPos()
        endRot = ws.getInstrument().getComponentByName(
            component).getRotation().getEulerAngles()
        self.assertAlmostEqual(endPos.getX(), 0.05)
        self.assertAlmostEqual(endPos.getY(), 0.03)
        self.assertEqual(startPos.getZ(), endPos.getZ())
        self.assertEqual(startRot[0], endRot[0])
        self.assertEqual(startRot[1], endRot[1])
        self.assertEqual(startRot[2], endRot[2])
Пример #21
0
    def _sumForegroundInLambda(self, ws):
        """Sum the foreground region into a single histogram."""
        foreground = self._foregroundIndices(ws)
        sumIndices = [i for i in range(foreground[0], foreground[2] + 1)]
        beamPosIndex = foreground[1]
        foregroundWSName = self._names.withSuffix('grouped')
        foregroundWS = ExtractSingleSpectrum(InputWorkspace=ws,
                                             OutputWorkspace=foregroundWSName,
                                             WorkspaceIndex=beamPosIndex,
                                             EnableLogging=self._subalgLogging)
        maxIndex = ws.getNumberHistograms() - 1
        foregroundYs = foregroundWS.dataY(0)
        foregroundEs = foregroundWS.dataE(0)
        numpy.square(foregroundEs, out=foregroundEs)
        for i in sumIndices:
            if i == beamPosIndex:
                continue
            if i < 0 or i > maxIndex:
                self.log().warning(
                    'Foreground partially out of the workspace.')
            addeeWSName = self._names.withSuffix('addee')
            addeeWS = ExtractSingleSpectrum(InputWorkspace=ws,
                                            OutputWorkspace=addeeWSName,
                                            WorkspaceIndex=i,
                                            EnableLogging=self._subalgLogging)
            addeeWS = RebinToWorkspace(WorkspaceToRebin=addeeWS,
                                       WorkspaceToMatch=foregroundWS,
                                       OutputWorkspace=addeeWSName,
                                       EnableLogging=self._subalgLogging)
            ys = addeeWS.readY(0)
            foregroundYs += ys
            es = addeeWS.readE(0)
            foregroundEs += es**2
            self._cleanup.cleanup(addeeWS)
        self._cleanup.cleanup(ws)
        numpy.sqrt(foregroundEs, out=foregroundEs)
        # Move the detector to the fractional linePosition
        linePosition = ws.run().getProperty(
            common.SampleLogs.LINE_POSITION).value
        instr = common.instrumentName(ws)
        pixelSize = common.pixelSize(instr)
        dist = pixelSize * (linePosition - beamPosIndex)

        if dist != 0.:
            detPoint1 = ws.spectrumInfo().position(0)
            detPoint2 = ws.spectrumInfo().position(20)
            beta = numpy.math.atan2((detPoint2[0] - detPoint1[0]),
                                    (detPoint2[2] - detPoint1[2]))
            xvsy = numpy.math.sin(beta) * dist
            mz = numpy.math.cos(beta) * dist
            if instr == 'D17':
                mx = xvsy
                my = 0.0
                rotationAxis = [0, 1, 0]
            else:
                mx = 0.0
                my = xvsy
                rotationAxis = [-1, 0, 0]
            MoveInstrumentComponent(Workspace=foregroundWS,
                                    ComponentName='detector',
                                    X=mx,
                                    Y=my,
                                    Z=mz,
                                    RelativePosition=True)
            theta = foregroundWS.spectrumInfo().twoTheta(0) / 2.
            RotateInstrumentComponent(Workspace=foregroundWS,
                                      ComponentName='detector',
                                      X=rotationAxis[0],
                                      Y=rotationAxis[1],
                                      Z=rotationAxis[2],
                                      Angle=theta,
                                      RelativeRotation=True)
        return foregroundWS