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
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'])
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
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)$')
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']
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
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
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
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
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
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
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)
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, )
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])
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])
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