Skip to content
This repository was archived by the owner on May 7, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/diffcalc_API/controllers/Constraints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from pathlib import Path
from typing import Callable, Dict, Union

from diffcalc.hkl.calc import HklCalculation
from diffcalc.hkl.constraints import Constraints

from diffcalc_API.config import constraintsWithNoValue
from diffcalc_API.errors.Constraints import check_constraint_exists
from diffcalc_API.persistence import HklCalculationRepository


async def set_constraints(
name: str,
constraintDict: Dict[str, Union[float, bool]],
repo: HklCalculationRepository,
) -> None:
hkl_calc = await repo.load(name)

booleanConstraints = set(constraintDict.keys()).intersection(constraintsWithNoValue)
for constraint in booleanConstraints:
constraintDict[constraint] = bool(constraintDict[constraint])

hkl_calc.constraints = Constraints(constraintDict)
await repo.save(name, hkl_calc)


def remove_constraint(
name: str,
property: str,
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
check_constraint_exists(property)
setattr(hklCalc.constraints, property, None)
persist(hklCalc, name)
return


def set_constraint(
name: str,
property: str,
value: Union[float, bool],
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
check_constraint_exists(property)

if property in constraintsWithNoValue:
value = bool(value)

setattr(hklCalc.constraints, property, value)
persist(hklCalc, name)
return
106 changes: 106 additions & 0 deletions src/diffcalc_API/controllers/HklCalculation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from itertools import product
from typing import Dict, List, Tuple

import numpy as np
from diffcalc.hkl.calc import HklCalculation
from diffcalc.hkl.geometry import Position

from diffcalc_API.errors.HklCalculation import (
check_valid_miller_indices,
check_valid_scan_bounds,
)

positionType = Tuple[float, float, float]


def lab_position_from_miller_indices(
millerIndices: Tuple[float, float, float],
wavelength: float,
hklCalc: HklCalculation,
) -> List[Tuple[Position, Dict[str, float]]]:
check_valid_miller_indices(millerIndices)
allPositions = hklCalc.get_position(*millerIndices, wavelength)

return combine_lab_position_results(allPositions)


def miller_indices_from_lab_position(
pos: Tuple[float, float, float, float, float, float],
wavelength: float,
hklCalc: HklCalculation,
):
hklPosition = hklCalc.get_hkl(Position(*pos), wavelength)
return tuple(np.round(hklPosition, 16))


def scan_hkl(
start: positionType,
stop: positionType,
inc: positionType,
wavelength: float,
hklCalc: HklCalculation,
):
valueOfAxes = [
generate_axis(start[i], stop[i], inc[i]) if inc[i] != 0 else [0]
for i in range(3)
]

results = {}

for h, k, l in product(*valueOfAxes):
check_valid_miller_indices((h, k, l))
allPositions = hklCalc.get_position(h, k, l, wavelength)
results[f"({h}, {k}, {l})"] = combine_lab_position_results(allPositions)

return results


def scan_wavelength(
start: float,
stop: float,
inc: float,
hkl: positionType,
hklCalc: HklCalculation,
):
check_valid_scan_bounds(start, stop, inc)
wavelengths = np.arange(start, stop + inc, inc)
result = {}

for wavelength in wavelengths:
allPositions = hklCalc.get_position(*hkl, wavelength)
result[f"{wavelength}"] = combine_lab_position_results(allPositions)

return result


def scan_constraint(
constraint: str,
start: float,
stop: float,
inc: float,
hkl: positionType,
wavelength: float,
hklCalc: HklCalculation,
):
check_valid_scan_bounds(start, stop, inc)
result = {}
for value in np.arange(start, stop + inc, inc):
setattr(hklCalc, constraint, value)
allPositions = hklCalc.get_position(*hkl, wavelength)
result[f"{value}"] = combine_lab_position_results(allPositions)

return result


def generate_axis(start: float, stop: float, inc: float):
check_valid_scan_bounds(start, stop, inc)
return np.arange(start, stop + inc, inc)


def combine_lab_position_results(positions: List[Tuple[Position, Dict[str, float]]]):
result = []

for position in positions:
result.append({**position[0].asdict, **position[1]})

return result
147 changes: 147 additions & 0 deletions src/diffcalc_API/controllers/UBCalculation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
from pathlib import Path
from typing import Callable, Optional, Tuple, Union

from diffcalc.hkl.calc import HklCalculation
from diffcalc.hkl.geometry import Position

from diffcalc_API.errors.UBCalculation import (
calculate_UB_matrix,
get_orientation,
get_reflection,
)
from diffcalc_API.models.UBCalculation import (
addOrientationParams,
addReflectionParams,
editOrientationParams,
editReflectionParams,
setLatticeParams,
)


def add_reflection(
name: str,
params: addReflectionParams,
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
hklCalc.ubcalc.add_reflection(
params.hkl,
Position(*params.position),
params.energy,
params.tag,
)

persist(hklCalc, name)
return


def edit_reflection(
name: str,
params: editReflectionParams,
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
reflection = get_reflection(hklCalc, params.tagOrIdx)

hklCalc.ubcalc.edit_reflection(
params.tagOrIdx,
params.hkl if params.hkl else (reflection.h, reflection.k, reflection.l),
Position(params.position) if params.position else reflection.pos,
params.energy if params.energy else reflection.energy,
params.tagOrIdx if isinstance(params.tagOrIdx, str) else None,
)
persist(hklCalc, name)
return


def delete_reflection(
name: str,
tagOrIdx: Union[str, int],
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
_ = get_reflection(hklCalc, tagOrIdx)
hklCalc.ubcalc.del_reflection(tagOrIdx)
persist(hklCalc, name)
return


def add_orientation(
name: str,
params: addOrientationParams,
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
position = Position(*params.position) if params.position else None

hklCalc.ubcalc.add_orientation(
params.hkl,
params.xyz,
position,
params.tag,
)

persist(hklCalc, name)
return


def edit_orientation(
name: str,
params: editOrientationParams,
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
orientation = get_orientation(hklCalc, params.tagOrIdx)

hklCalc.ubcalc.edit_orientation(
params.tagOrIdx,
params.hkl if params.hkl else (orientation.h, orientation.k, orientation.l),
params.xyz if params.xyz else (orientation.x, orientation.y, orientation.z),
Position(params.position) if params.position else orientation.pos,
params.tagOrIdx if isinstance(params.tagOrIdx, str) else None,
)
persist(hklCalc, name)
return


def delete_orientation(
name: str,
tagOrIdx: Union[str, int],
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
_ = get_orientation(hklCalc, tagOrIdx)
hklCalc.ubcalc.del_orientation(tagOrIdx)
persist(hklCalc, name)


def set_lattice(
name: str,
params: setLatticeParams,
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
hklCalc.ubcalc.set_lattice(name=name, **params.dict())
persist(hklCalc, name)


def modify_property(
name: str,
property: str,
targetValue: Tuple[float, float, float],
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
setattr(hklCalc.ubcalc, property, targetValue)
persist(hklCalc, name)


def calculate_UB(
name: str,
firstTag: Optional[Union[int, str]],
secondTag: Optional[Union[int, str]],
hklCalc: HklCalculation,
persist: Callable[[HklCalculation, str], Path],
):
calculate_UB_matrix(hklCalc, firstTag, secondTag)
persist(hklCalc, name)
3 changes: 3 additions & 0 deletions src/diffcalc_API/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from diffcalc_API.controllers import Constraints, HklCalculation, UBCalculation

__all__ = ["UBCalculation", "HklCalculation", "Constraints"]
37 changes: 37 additions & 0 deletions src/diffcalc_API/examples/UBCalculation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from diffcalc_API.models.UBCalculation import (
addOrientationParams,
addReflectionParams,
editOrientationParams,
editReflectionParams,
setLatticeParams,
)

addReflection: addReflectionParams = addReflectionParams(
**{
"hkl": [0, 0, 1],
"position": [7.31, 0.0, 10.62, 0, 0.0, 0],
"energy": 12.39842,
"tag": "refl1",
}
)

editReflection: editReflectionParams = editReflectionParams(
**{"energy": 12.45, "tagOrIdx": "refl1"}
)

addOrientation: addOrientationParams = addOrientationParams(
**{
"hkl": [0, 1, 0],
"xyz": [0, 1, 0],
"tag": "plane",
}
)

editOrientation: editOrientationParams = editOrientationParams(
**{
"hkl": (0, 1, 0),
"tagOrIdx": "plane",
}
)

setLattice: setLatticeParams = setLatticeParams(**{"a": 4.913, "c": 5.405})
3 changes: 3 additions & 0 deletions src/diffcalc_API/examples/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from diffcalc_API.examples import UBCalculation

__all__ = ["UBCalculation"]
Loading