Skip to content

Commit

Permalink
updated sample class
Browse files Browse the repository at this point in the history
  • Loading branch information
bingli621 committed Aug 19, 2024
1 parent d5cb0ec commit 201e31f
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 105 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
"python.testing.pytestEnabled": true,
}
2 changes: 1 addition & 1 deletion conda.recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{% set build_number = 0 %}

package:
name: mypackagename
name: tavi
version: {{ version_number }}

source:
Expand Down
14 changes: 7 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
dependencies = [
# list all runtime dependencies here
]
description = "Example Python repo for neutrons"
description = "Triple-Axis data Visualization"
dynamic = ["version"]
license = {text = "LGPL-3.0"}
name = "examplepyapp"
requires-python = ">=3.10"

[project.urls]
homepage = "https://github.com/neutrons/python_project_template/" # if no homepage, use repo url
homepage = "https://github.com/neutrons/TAVI"

[build-system]
build-backend = "setuptools.build_meta"
Expand All @@ -36,7 +36,7 @@ distance = "{next_version}.dev{distance}"
distance-dirty = "{next_version}.dev{distance}+d{build_date:%Y%m%d%H%M}"

[tool.versioningit.write]
file = "src/packagenamepy/_version.py"
file = "src/tavi/_version.py"

[tool.setuptools.packages.find]
exclude = ["tests*", "scripts*", "docs*", "notebooks*"]
Expand All @@ -45,11 +45,11 @@ where = ["src"]
[tool.setuptools.package-data]
"*" = ["*.yml", "*.yaml", "*.ini"]

[project.scripts]
packagename-cli = "packagenamepy.packagename:main"
# [project.scripts]
# packagename-cli = "packagenamepy.packagename:main"

[project.gui-scripts]
packagenamepy = "packagenamepy.packagename:gui"
# [project.gui-scripts]
# packagenamepy = "packagenamepy.packagename:gui"

[tool.pytest.ini_options]
markers = [
Expand Down
13 changes: 8 additions & 5 deletions src/tavi/instrument/tas.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json

import numpy as np

from tavi.instrument.tas_cmponents import *
from tavi.sample.powder import Powder
from tavi.sample.sample import Sample
Expand Down Expand Up @@ -74,11 +75,13 @@ def load_sample_from_json(self, path_to_json):
with open(path_to_json, "r", encoding="utf-8") as file:
sample_params = json.load(file)

if sample_params["type"] == "xtal":
sample = Xtal.from_json(sample_params)
elif sample_params["type"] == "powder":
sample = Powder.from_json(sample_params)
else:
try: # is type xtal ot powder?
sample_type = sample_params["type"]
if sample_type == "xtal":
sample = Xtal.from_json(sample_params)
elif sample_type == "powder":
sample = Powder.from_json(sample_params)
except KeyError: # sample type is not given
sample = Sample.from_json(sample_params)

self.load_sample(sample)
Expand Down
190 changes: 107 additions & 83 deletions src/tavi/sample/sample.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
import numpy as np

from tavi.utilities import *

np.set_printoptions(floatmode="fixed", precision=4)
# from tavi.utilities import *


class Sample(object):
Expand All @@ -19,7 +18,6 @@ class Sample(object):
a, b, c lattice constants in Angstrom
alpha, beta, gamma angles in degrees
a_vec, b_vec, c_vec real sapce lattice vector
_v_abg V_alpha_beta_gamma = unit_cell_volume/(abc)
a_star, b_star, c_star lattice constants in inverse Angstrom
alpha_star, beta_star, gamma_star reciprocal angles in degrees
a_star_vec, b_star_vec, c_star_vec reciprocal lattice vector
Expand All @@ -42,16 +40,20 @@ class Sample(object):
"""

def __init__(self, lattice_params=(1, 1, 1, 90, 90, 90)):
def __init__(
self,
lattice_params: tuple[float] = (1, 1, 1, 90, 90, 90),
) -> None:
assert len(lattice_params) == 6, "Incomplete lattice parameters."
for length in lattice_params[:3]:
assert length > 0, "Lattice parameters smaller than zero."
for angle in lattice_params[3:]:
assert 0.0 < angle < 180.0, "Lattice angles out of range."

self.update_lattice_parameters(lattice_params)
# parameters for resolution calculation
self.shape = "cuboid"
self.width = 1.0 # * cm2angstrom
self.height = 1.0 # * cm2angstrom
self.depth = 1.0 # * cm2angstrom
self.mosaic = 30 # * min2rad # horizontal mosaic
self.mosaic_v = 30 # * min2rad # vertical mosaic

self.update_lattice(lattice_params)
self.set_mosaic() # with defalt values
self.set_shape() # with defalt values

@classmethod
def from_json(cls, sample_params):
Expand All @@ -64,24 +66,34 @@ def from_json(cls, sample_params):
sample_params["beta"],
sample_params["gamma"],
)

sample = cls(lattice_params=lattice_params)

param_dict = ("shape", "width", "height", "depth", "mosaic", "mosaic_v")

for key, val in sample_params.items():
match key:
case "height" | "width" | "depth":
setattr(sample, key, val * cm2angstrom)
# case "mosaic" | "mosaic_v":
# setattr(sample, key, val * min2rad)
case _:
if key in param_dict:
setattr(sample, key, val)
sample.update_lattice(lattice_params)
return sample

def update_lattice(self, lattice_params=(1, 1, 1, 90, 90, 90)):
return cls(lattice_params=lattice_params)

def set_shape(
self,
shape: str = "cuboid",
width: float = 1.0, # in cm
height: float = 1.0, # in cm
depth: float = 1.0, # in cm
) -> None:
"""set sample shape"""
self.shape = shape
self.width = width
self.height = height
self.depth = depth

def set_mosaic(
self,
mosaic: float = 30, # horizontal mosaic
mosaic_v: float = 30, # vertical mosaic
) -> None:
"""Set horizontal and vertical mosaic in units of minitues of arc"""
self.mosaic_h = mosaic # * min2rad
self.mosaic_v = mosaic_v # * min2rad

def update_lattice_parameters(
self,
lattice_params: tuple[float] = (1, 1, 1, 90, 90, 90),
):
"""update real and reciprocal space lattice parameters and vectors"""

a, b, c, alpha, beta, gamma = lattice_params
Expand All @@ -92,8 +104,11 @@ def update_lattice(self, lattice_params=(1, 1, 1, 90, 90, 90)):
self.beta = beta
self.gamma = gamma

self._v_abg = Sample.v_alpha_beta_gamma_calc(alpha, beta, gamma)
self.a_vec, self.b_vec, self.c_vec = self.real_vec_cart()
(
self.a_vec,
self.b_vec,
self.c_vec,
) = self._real_space_vectors()
(
self.a_star,
self.b_star,
Expand All @@ -103,30 +118,34 @@ def update_lattice(self, lattice_params=(1, 1, 1, 90, 90, 90)):
self.gamma_star,
) = self.reciprocal_latt_params()

self.a_star_vec, self.b_star_vec, self.c_star_vec = self.reciprocal_vec_cart()
(
self.a_star_vec,
self.b_star_vec,
self.c_star_vec,
) = self._reciprocal_space_vectors()

@staticmethod
def v_alpha_beta_gamma_calc(alpha, beta, gamma):
def v_alpha_beta_gamma_calc(alpha, beta, gamma) -> float:
"""
Calculate V_alpha_bet_gamma = Volume/(abc)
Volume = a * (b x c)
"""
cos_alpha = np.cos(alpha / 180 * np.pi)
cos_beta = np.cos(beta / 180 * np.pi)
cos_gamma = np.cos(gamma / 180 * np.pi)
cos_alpha = np.cos(np.deg2rad(alpha))
cos_beta = np.cos(np.deg2rad(beta))
cos_gamma = np.cos(np.deg2rad(gamma))
v_alpha_beta_gamma = np.sqrt(
1 - cos_alpha**2 - cos_beta**2 - cos_gamma**2 + 2 * cos_alpha * cos_beta * cos_gamma
)
return v_alpha_beta_gamma

def real_vec_cart(self):
def _real_space_vectors(self) -> tuple[np.ndarray]:
"""
Calculate the real space lattice vectors in Cartesian coordiantes
"""
cos_alpha = np.cos(self.alpha / 180 * np.pi)
cos_beta = np.cos(self.beta / 180 * np.pi)
cos_gamma = np.cos(self.gamma / 180 * np.pi)
sin_gamma = np.sin(self.gamma / 180 * np.pi)
cos_alpha = np.cos(np.deg2rad(self.alpha))
cos_beta = np.cos(np.deg2rad(self.beta))
cos_gamma = np.cos(np.deg2rad(self.gamma))
sin_gamma = np.sin(np.deg2rad(self.gamma))

ac = np.array([self.a, 0, 0])
bc = np.array(
Expand All @@ -136,89 +155,94 @@ def real_vec_cart(self):
0,
]
)

v_abg = Sample.v_alpha_beta_gamma_calc(self.alpha, self.beta, self.gamma)
cc = np.array(
[
self.c * cos_beta,
self.c * (cos_alpha - cos_gamma * cos_beta) / sin_gamma,
self.c * self._v_abg / sin_gamma,
self.c * v_abg / sin_gamma,
]
)
# ac = np.round(ac, 8)
# bc = np.round(bc, 8)
# cc = np.round(cc, 8)
return (ac, bc, cc)

def reciprocal_latt_params(self):
"""Calculate the reciprocal lattice parameters and angles"""
sin_alpha = np.sin(self.alpha / 180 * np.pi)
cos_alpha = np.cos(self.alpha / 180 * np.pi)
sin_beta = np.sin(self.beta / 180 * np.pi)
cos_beta = np.cos(self.beta / 180 * np.pi)
cos_gamma = np.cos(self.gamma / 180 * np.pi)
sin_gamma = np.sin(self.gamma / 180 * np.pi)

a_star = sin_alpha / self.a / self._v_abg * np.pi * 2
b_star = sin_beta / self.b / self._v_abg * np.pi * 2
c_star = sin_gamma / self.c / self._v_abg * np.pi * 2
alpha_star = np.arccos((cos_beta * cos_gamma - cos_alpha) / sin_beta / sin_gamma) / np.pi * 180
beta_star = np.arccos((cos_gamma * cos_alpha - cos_beta) / sin_alpha / sin_gamma) / np.pi * 180
gamma_star = np.arccos((cos_alpha * cos_beta - cos_gamma) / sin_beta / sin_alpha) / np.pi * 180
# a_star = np.round(a_star, 8)
# b_star = np.round(b_star, 8)
# c_star = np.round(c_star, 8)
# alpha_star = np.round(alpha_star, 8)
# beta_star = np.round(beta_star, 8)
# gamma_star = np.round(gamma_star, 8)
"""Calculate the reciprocal lattice parameter lengths and angles"""
sin_alpha = np.sin(np.deg2rad(self.alpha))
cos_alpha = np.cos(np.deg2rad(self.alpha))
sin_beta = np.sin(np.deg2rad(self.beta))
cos_beta = np.cos(np.deg2rad(self.beta))
cos_gamma = np.cos(np.deg2rad(self.gamma))
sin_gamma = np.sin(np.deg2rad(self.gamma))

v_abg = Sample.v_alpha_beta_gamma_calc(self.alpha, self.beta, self.gamma)

a_star = sin_alpha / self.a / v_abg * np.pi * 2
b_star = sin_beta / self.b / v_abg * np.pi * 2
c_star = sin_gamma / self.c / v_abg * np.pi * 2
alpha_star = np.arccos((cos_beta * cos_gamma - cos_alpha) / sin_beta / sin_gamma)
beta_star = np.arccos((cos_gamma * cos_alpha - cos_beta) / sin_alpha / sin_gamma)
gamma_star = np.arccos((cos_alpha * cos_beta - cos_gamma) / sin_beta / sin_alpha)
alpha_star = np.rad2deg(alpha_star)
beta_star = np.rad2deg(beta_star)
gamma_star = np.rad2deg(gamma_star)

return (a_star, b_star, c_star, alpha_star, beta_star, gamma_star)

def reciprocal_vec_cart(self):
def _reciprocal_space_vectors(self) -> tuple[np.ndarray]:
"""
Calculate the reciprocal space lattice vectors in the Cartesian coordinates
"""
v = self._v_abg * self.a * self.b * self.c
v_abg = Sample.v_alpha_beta_gamma_calc(self.alpha, self.beta, self.gamma)
v = v_abg * self.a * self.b * self.c
prefactor = 2 * np.pi / v
a_star_vec = np.cross(self.b_vec, self.c_vec) * prefactor
b_star_vec = np.cross(self.c_vec, self.a_vec) * prefactor
c_star_vec = np.cross(self.a_vec, self.b_vec) * prefactor

return (a_star_vec, b_star_vec, c_star_vec)

def hkl2q(self, hkl):
def hkl2q(self, hkl: tuple[float]) -> float:
"""Convert (h,k,l) to q, in units of inverse Angstrom"""
(h, k, l) = hkl
q = np.linalg.norm(h * self.a_star_vec + k * self.b_star_vec + l * self.c_star_vec)
return q
assert len(hkl) == 3, "Length of (h,k,l) is not 3."
(qh, qk, ql) = hkl
q_vec = qh * self.a_star_vec + qk * self.b_star_vec + ql * self.c_star_vec
q_norm = np.linalg.norm(q_vec)
return q_norm

def b_mat(self):
def b_mat(self) -> np.ndarray:
"""
Calculate the B matrix
B * (h,k,l) gives Q in terms of i_star, j_star, k_star
"""
alpha_star_deg = np.deg2rad(self.alpha_star)
beta_star_deg = np.deg2rad(self.beta_star)
gamma_star_deg = np.deg2rad(self.gamma_star)
b_mat = np.array(
[
[
self.a_star,
self.b_star * np.cos(self.gamma_star / 180 * np.pi),
self.c_star * np.cos(self.beta_star / 180 * np.pi),
self.b_star * np.cos(gamma_star_deg),
self.c_star * np.cos(beta_star_deg),
],
[
0,
self.b_star * np.sin(self.gamma_star / 180 * np.pi),
-self.c_star * np.sin(self.beta_star / 180 * np.pi) * np.cos(self.alpha / 180 * np.pi),
self.b_star * np.sin(gamma_star_deg),
-self.c_star * np.sin(beta_star_deg) * np.cos(alpha_star_deg),
],
[0, 0, 2 * np.pi / self.c],
]
)
b_mat = b_mat / 2 / np.pi
b_mat = np.round(b_mat, 8)
b_mat = b_mat / (2 * np.pi)
# b_mat = np.round(b_mat, 8)
return b_mat

def reciprocal_basis(self):
def _reciprocal_basis(self) -> tuple[np.ndarray]:
"""Calculate the reciprocal basis vectors i_star, j_star, k_star"""
i_star = self.a_star_vec / np.linalg.norm(self.a_star_vec)
a_star_perp = np.cross(np.cross(self.a_star_vec, self.b_star_vec), self.a_star_vec)
a_star_perp = np.cross(
np.cross(self.a_star_vec, self.b_star_vec),
self.a_star_vec,
)
j_star = a_star_perp / np.linalg.norm(a_star_perp)
k_star = np.cross(i_star, j_star)
return (i_star, j_star, k_star)
4 changes: 2 additions & 2 deletions src/tavi/sample/xtal.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __init__(self, lattice_params=(1, 1, 1, 90, 90, 90)):
self.plane_normal = None
self.in_plane_ref = None

self.i_star, self.j_star, self.k_star = self.reciprocal_basis()
self.i_star, self.j_star, self.k_star = self._reciprocal_basis()

@classmethod
def from_json(cls, sample_params):
Expand Down Expand Up @@ -61,7 +61,7 @@ def from_json(cls, sample_params):
case _:
if key in param_dict:
setattr(sample, key, val)
sample.update_lattice(lattice_params)
sample.update_lattice_parameters(lattice_params)
return sample

@property
Expand Down
Loading

0 comments on commit 201e31f

Please sign in to comment.