From angles to UB-Matrix / adding a peak via angles

Hallo everybody,

I’m new to Mantid, and I want to do the following:
I have neutron single crystal data with possibly wrong UB-Matrix. I want to use the function FindUBUsingFFT in order to determine the UB-Matrix from the angular positions of the peaks.
So far I can create a Workspace and add peaks like this:

from mantid.simpleapi import *
from mantid.kernel import *

sampleWs = CreateSampleWorkspace()
ws = CreatePeaksWorkspace(InstrumentWorkspace = sampleWs, NumberOfPeaks = 0)
qlab = V3D(1.23, 3.45, 2.22)
p = ws.createPeak(qlab)
ws.addPeak(p)

What I still need to do is converting the angles (four circle Eulerian cradle) to the reciprocal lab system. However, in the Mantid documentation I don’t find the exact definition of qlab.
Is there even a handy function that converts the angles to the reciprocal vector?

Best
Tobias

Hi Tobias,
a detailed description of the Q in the lab frame is given in documents/UBMatriximplementationnotes.pdf at master · mantidproject/documents · GitHub, in the conventions section (page 2). The Q in the lab frame depends only on the position of the detector, not the goniometer. The link between Qlab and (hkl) is given by equation 5, Qlab=2 Pi R UB (hkl), where R is the goniometer rotation matrix. Please consult the documentation of SetGoniometer algorithm in order to construct your rotation matrix.
For example, if we rotate 30 degrees around the vertical axis (y) we can get R like:
sampleWs = CreateSampleWorkspace() SetGoniometer(sampleWs,Axis0="30,0,1,0,1") print sampleWs.run().getGoniometer().getR()
which yields:

[[ 0.8660254 0. 0.5 ] [ 0. 1. 0. ] [-0.5 0. 0.8660254]]

You then get Qsample=Qlab*R^(-1)

Andrei

Hi Andrei,

thanks a lot, I think now I got it.
However, I’m still confused with the rotation direction.
I thought, viewing against the z-axis gives the rotation-direction in the xy-plane, like it is in 2 dimensions (I hope, you can perceive the diagonal rotation-arrow):

y     _ 
^    |  
|       \   (counter-clockwise rotation)
|        \
|
|_________> x

(z-axis pointing out of the plane, against you)

But it seems that you have to look in the direction of the z-axis in order to determine the direction of a rotation in the xy-plane. Thus opposite to the obove drawing. Is that correct?

Best
Tobias

Hi again,

as far as I understand, I have to drive the (virtual) goniometer to the position and then add the reflection with respect to the laboratory frame. However, the following code does not do the correct thing:

import mantid
from mantid.simpleapi import *
from mantid.kernel import *

sampleWs = CreateSampleWorkspace()  
ws = CreatePeaksWorkspace(InstrumentWorkspace=sampleWs, NumberOfPeaks=0)

SetGoniometer(sampleWs, Axis0="45,0,1,0,1")
qlab = V3D(1, 0, -1)
p = ws.createPeak(qlab)
ws.addPeak(p)

What am I doing wrong?

Best
Tobias

Hi Tobias,
The rotation seems fine in your picture. I don’t seem to understand where you have problem with the rotation. Could you explain how you arrived to that conclusion?
As for what is wrong with your script, here is what you need to change:
if you are using the default convention for momentum transfer (the inelastic one), Qz=2Pi/lambda*(1-cos(tt)), so Qz>0. Then, in order to get some results that make sense, make sure that you create a peak that you can see on the detector.
For example:

   from mantid.simpleapi import *
   from mantid.kernel import *

   sampleWs = CreateSampleWorkspace()
   SetGoniometer(sampleWs, Axis0="45,0,1,0,1")
    
   ws = CreatePeaksWorkspace(InstrumentWorkspace=sampleWs, NumberOfPeaks=0)
   
   det=ws.getInstrument().getDetector(297)
   tt=det.getTwoTheta(V3D(0,0,0),V3D(0,0,1))
   phi=det.getPhi()

   import numpy as np
   qLab=V3D(-np.sin(tt)*np.cos(phi),-np.sin(tt)*np.sin(phi),1.-np.cos(tt))*10.
   p = ws.createPeak(qLab)
   ws.addPeak(p)

Hi Tobias,
I have been discussing this with Andrei today and we have found two things that need to be fixed in Mantid. First setQSampleFrame for a peak only changes the Q in python when an additional distance argument is added to the function call. This second argument should be optional. Second setGoniometer needs to be available via python so the QSample and QLab are not identical. I will make a ticket and we will fix.

Vickie

Dear Vickie, dear Andrei,

thank you so much for your effort!
I have already found out, that this part works, when I set the detector-distance to 1 for example.
However, setGoniometer is still a problem.

Pease let me know, if I can help you in any way!

Best
Tobias

Hi Tobias,

The setGoniometer problem was fixed. You can use it in the nightly version of mantid.

Andrei