Skip to content

Commit b2640ae

Browse files
Updates to detector metadata handling
1 parent 42e103c commit b2640ae

File tree

1 file changed

+58
-14
lines changed

1 file changed

+58
-14
lines changed

src/ffs/service.py

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
import time
1212
from datetime import datetime
1313
from pathlib import Path
14-
from typing import Iterator, Optional
14+
from typing import Iterator, Optional, Union, Literal
1515
import pydantic
1616

1717
import gemmi
1818
import numpy as np
1919
import workflows.recipe
20-
from pydantic import BaseModel, ValidationError
20+
from pydantic import BaseModel, ValidationError, Field
2121
from rich.logging import RichHandler
2222
from workflows.services.common_service import CommonService
2323

@@ -45,13 +45,15 @@ class PiaRequest(BaseModel):
4545
d_min: float | None = None
4646
d_max: float | None = None
4747
unit_cell: tuple[float, float, float, float, float, float] | None = None
48+
detector: str = "Eiger16M"
4849

4950
@pydantic.validator("unit_cell", pre=True)
5051
def check_unit_cell(cls, v):
5152
if not v:
5253
return None
5354
orig_v = v
5455
if isinstance(v, str):
56+
5557
v = v.replace(",", " ").split()
5658
v = [float(v) for v in v]
5759
try:
@@ -61,19 +63,58 @@ def check_unit_cell(cls, v):
6163
return v
6264

6365

64-
class DetectorGeometry(BaseModel):
66+
class DetectorParameters(BaseModel):
67+
type: str
68+
thickness: float
69+
material: str
70+
pixel_size_x: float
71+
pixel_size_y: float
72+
image_size_x: int
73+
image_size_y: int
74+
_mu_cache: dict = {}
75+
76+
class Config:
77+
extra = "forbid" # Don't allow instantiation of this base class
78+
79+
def calculate_mu(self, wavelength: float) -> float:
80+
if wavelength not in self._mu_cache:
81+
self._mu_cache[wavelength] = calculate_mu_from_parameters(
82+
self.thickness, self.material, wavelength
83+
)
84+
return self._mu_cache[wavelength]
85+
86+
87+
class Eiger16M(DetectorParameters):
88+
type: Literal["Eiger16M"]
89+
thickness: float = 0.45
90+
material: str = "Si" # atomic no 14
6591
pixel_size_x: float = 0.075 # Default value for Eiger
6692
pixel_size_y: float = 0.075 # Default value for Eiger
6793
image_size_x: int = 2068 # Default value for Eiger
6894
image_size_y: int = 2162 # Default value for Eiger
95+
mu: float = 3.9220781 # Default value for Eiger (Silicon) #FIXME replace with mu calculation
96+
97+
98+
class Eiger9M(DetectorParameters):
99+
type: Literal["Eiger9M"]
100+
thickness: float = 0.45
101+
material: str = "Si"
102+
pixel_size_x: float = 0.075 # Default value for Eiger
103+
pixel_size_y: float = 0.075 # Default value for Eiger
104+
image_size_x: int = 1000 # Default value for Eiger9M #FIXME
105+
image_size_y: int = 1000 # Default value for Eiger9M #FIXME
106+
mu: float = 3.9220781 # Default value for Eiger (Silicon) #FIXME replace with mu calculation
107+
108+
class DetectorGeometry(BaseModel):
69109
distance: float
70110
beam_center_x: float
71111
beam_center_y: float
72-
thickness: float = 0.45 # Default value for Eiger (Silicon)
73-
mu: float = 3.9220781 # Default value for Eiger (Silicon)
112+
detector: Union[Eiger9M, Eiger16M] = Field(..., discriminator="type")
74113

75114
def to_json(self):
76-
return json.dumps(self.dict(), indent=4)
115+
d = self.dict()
116+
d.update(self.detector.dict())
117+
return json.dumps(d, indent=4)
77118

78119

79120
def _setup_rich_logging(level=logging.DEBUG):
@@ -231,6 +272,7 @@ def gpu_per_image_analysis(
231272
distance=parameters.detector_distance,
232273
beam_center_x=parameters.xBeam,
233274
beam_center_y=parameters.yBeam,
275+
detector={"type":parameters.detector},
234276
)
235277
self.log.debug("{detector_geometry.to_json()=}")
236278
except ValidationError as e:
@@ -245,16 +287,18 @@ def gpu_per_image_analysis(
245287
np.array(cell.orth.mat, dtype="float32"), (3, 3)
246288
) ## Cell as an orthogonalisation matrix
247289
## convert beam centre to correct units (given in mm, want in px).
290+
px_size_x = detector_geometry.detector.pixel_size_x
291+
px_size_y = detector_geometry.detector.pixel_size_y
248292
self.indexer.panel = ffs.index.make_panel(
249293
detector_geometry.distance,
250-
detector_geometry.beam_center_x / detector_geometry.pixel_size_x,
251-
detector_geometry.beam_center_y / detector_geometry.pixel_size_y,
252-
detector_geometry.pixel_size_x,
253-
detector_geometry.pixel_size_y,
254-
detector_geometry.image_size_x,
255-
detector_geometry.image_size_y,
256-
detector_geometry.thickness,
257-
detector_geometry.mu,
294+
detector_geometry.beam_center_x / px_size_x,
295+
detector_geometry.beam_center_y / px_size_y,
296+
px_size_x,
297+
px_size_y,
298+
detector_geometry.detector.image_size_x,
299+
detector_geometry.detector.image_size_y,
300+
detector_geometry.detector.thickness,
301+
detector_geometry.detector.mu,
258302
)
259303
self.indexer.wavelength = parameters.wavelength
260304
self.output_for_index = (

0 commit comments

Comments
 (0)