generated from neutrons/python_project_template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
743 additions
and
1,357 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
from typing import Literal, Optional | ||
|
||
import numpy as np | ||
|
||
from tavi.instrument.tas_cmponents import TASComponent | ||
|
||
|
||
class Goniometer(TASComponent): | ||
"""Goniometer table, type = Y-ZX or YZ-X""" | ||
|
||
def __init__( | ||
self, | ||
param_dict: Optional[dict] = None, | ||
component_name: str = "goniometer", | ||
): | ||
self.type: str = "Y-ZX" # Y-mZ-X for Huber stage at HB1A and HB3 | ||
self.sense: Literal[-1, +1] = -1 | ||
|
||
super().__init__(param_dict) | ||
self.component_name = component_name | ||
|
||
@staticmethod | ||
def rot_x(nu): | ||
"""rotation matrix about y-axis by angle nu | ||
Args: | ||
nu (float): angle in degrees | ||
Note: | ||
Using Mantid convention, beam along z, y is up, x in plane | ||
""" | ||
|
||
angle = np.deg2rad(nu) | ||
c = np.cos(angle) | ||
s = np.sin(angle) | ||
mat = np.array( | ||
[ | ||
[1, 0, 0], | ||
[0, c, -s], | ||
[0, s, c], | ||
] | ||
) | ||
return mat | ||
|
||
@staticmethod | ||
def rot_y(omega): | ||
"""rotation matrix about y-axis by angle omega | ||
Args: | ||
omega (float): angle in degrees | ||
Note: | ||
Using Mantid convention, beam along z, y is up, x in plane | ||
""" | ||
|
||
angle = np.deg2rad(omega) | ||
c = np.cos(angle) | ||
s = np.sin(angle) | ||
mat = np.array( | ||
[ | ||
[c, 0, s], | ||
[0, 1, 0], | ||
[-s, 0, c], | ||
] | ||
) | ||
return mat | ||
|
||
@staticmethod | ||
def rot_z(mu): | ||
"""rotation matrix about z-axis by angle mu | ||
Args: | ||
mu (float): angle in degrees | ||
Note: | ||
Using Mantid convention, beam along z, y is up, x in plane | ||
""" | ||
|
||
angle = np.deg2rad(mu) | ||
c = np.cos(angle) | ||
s = np.sin(angle) | ||
mat = np.array( | ||
[ | ||
[c, -s, 0], | ||
[s, c, 0], | ||
[0, 0, 1], | ||
] | ||
) | ||
return mat | ||
|
||
def r_mat( | ||
self, | ||
angles_deg: tuple[float, float, float], | ||
): | ||
"Goniometer rotation matrix R" | ||
|
||
omega, sgl, sgu = angles_deg # s2, s1, sgl, sgu | ||
match self.type: | ||
case "Y-ZX": # HB3 | ||
r_mat = Goniometer.rot_y(omega) @ Goniometer.rot_z(-1 * sgl) @ Goniometer.rot_x(sgu) | ||
case "YZ-X": # CG4C ?? | ||
r_mat = Goniometer.rot_y(omega) @ Goniometer.rot_z(sgl) @ Goniometer.rot_x(-1 * sgu) | ||
case _: | ||
r_mat = None | ||
print("Unknow goniometer type. Curruntly support Y-ZX and YZ-X") | ||
|
||
return r_mat | ||
|
||
def r_mat_inv( | ||
self, | ||
angles: tuple[float, float, float], | ||
): | ||
"""inverse of rotation matrix""" | ||
# return np.linalg.inv(self.r_mat(angles)) | ||
return self.r_mat(angles).T | ||
|
||
def angles_from_r_mat(self, r_mat): | ||
"""Calculate goniometer angles from the R matrix | ||
Note: | ||
range of np.arcsin is -pi/2 to pi/2 | ||
range of np.atan2 is -pi to pi | ||
""" | ||
|
||
match self.type: | ||
case "Y-ZX" | "YZ-X": # Y-mZ-X (s1, sgl, sgu) for HB1A and HB3, Y-Z-mX (s1, sgl, sgu) for CG4C | ||
# sgl1 = np.arcsin(r_mat[1, 0]) * rad2deg | ||
# sgl2 = np.arccos(np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2)) * rad2deg | ||
sgl_rad = np.arctan2(r_mat[1, 0], np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2)) | ||
sgl = np.rad2deg(sgl_rad) | ||
|
||
# sgu1 = np.arcsin(-r_mat[1, 2] / np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2)) * rad2deg | ||
# sgu2 = np.arccos(r_mat[1, 1] / np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2)) * rad2deg | ||
sgu_rad = np.arctan2( | ||
-r_mat[1, 2] / np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2), | ||
r_mat[1, 1] / np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2), | ||
) | ||
sgu = np.rad2deg(sgu_rad) | ||
|
||
# omega1 = np.arcsin(-r_mat[2, 0] / np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2)) * rad2deg | ||
# omega2 = np.arccos(r_mat[0, 0] / np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2)) * rad2deg | ||
omega_rad = np.arctan2( | ||
-r_mat[2, 0] / np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2), | ||
r_mat[0, 0] / np.sqrt(r_mat[0, 0] ** 2 + r_mat[2, 0] ** 2), | ||
) | ||
omega = np.rad2deg(omega_rad) | ||
|
||
match self.type: | ||
case "Y-ZX": | ||
angles = (omega, -1 * sgl, sgu) | ||
case "YZ-X": | ||
angles = (omega, sgl, -1 * sgu) | ||
|
||
case _: | ||
angles = None | ||
print("Unknow goniometer type. Curruntly support Y-ZX and YZ-X.") | ||
|
||
return angles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
{ | ||
"source": { | ||
"shape": "rectangular", | ||
"width": 0.0, | ||
"height": 0.0 | ||
}, | ||
"guide": { | ||
"in_use": false, | ||
"div_h": 0.0, | ||
"div_v": 0.0 | ||
}, | ||
"monochromator": { | ||
"type": "PG002", | ||
"mosaic_h": 30, | ||
"mosaic_v": 30, | ||
"sense": 1, | ||
"shape": "rectangular", | ||
"width": 10.0, | ||
"height": 18.0, | ||
"depth": 0.0, | ||
"curved_h": false, | ||
"curvh": 0.0, | ||
"optimally_curved_h": false, | ||
"curved_v": true, | ||
"curvv": 0.0, | ||
"optimally_curved_v": false | ||
}, | ||
"monitor": {}, | ||
"goniometer": { | ||
"sense": -1, | ||
"type": "Y-ZX" | ||
}, | ||
"analyzer": { | ||
"type": "Pg002", | ||
"mosaic_h": 30, | ||
"mosaic_v": 30, | ||
"sense": 1, | ||
"shape": "rectangular", | ||
"width": 15.0, | ||
"height": 15.6, | ||
"depth": 0.0, | ||
"curved_h": false, | ||
"curvh": 0.0, | ||
"optimally_curved_h": false, | ||
"curved_v": true, | ||
"curvv": 0.0, | ||
"optimally_curved_v": false | ||
}, | ||
"detector": { | ||
"shape": "rectangular", | ||
"width": 5.08, | ||
"height": 5.08 | ||
}, | ||
"distances": { | ||
"src_mono1": 474.5, | ||
"mono1_mono2": 227.6, | ||
"src_mono": 474.5, | ||
"mono_sample": 143.13, | ||
"sample_ana": 74.0, | ||
"ana_det": 50.0 | ||
}, | ||
"collimators": { | ||
"h_pre_mono": 40, | ||
"h_pre_sample": 40, | ||
"h_post_sample": 40, | ||
"h_post_ana": 80, | ||
"v_pre_mono": 600, | ||
"v_pre_sample": 600, | ||
"v_post_sample": 600, | ||
"v_post_ana": 600 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.