-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathFormatCBFMiniEigerQuadro.py
128 lines (102 loc) · 4.26 KB
/
FormatCBFMiniEigerQuadro.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""Experimental format class for miniCBF files from an ELDICO diffractometer,
which uses a DECTRIS QUADRO detector (EIGER technology)"""
from __future__ import annotations
from dxtbx.format.FormatCBFMiniEiger import FormatCBFMiniEiger
from dxtbx.model import SimplePxMmStrategy
from dxtbx.model.beam import Probe
class FormatCBFMiniEigerQuadro(FormatCBFMiniEiger):
"""We have to inherit from FormatCBFMiniEiger, as this class understands
these files. This is not ideal, as that class is geared towards EIGER
X-ray detectors"""
@staticmethod
def understand(image_file):
header = FormatCBFMiniEiger.get_cbf_header(image_file)
# This is not very specific for the QUADRO and would probably also match
# CBFs from e.g. the SINGLA.
for record in header.split("\n"):
if "# wavelength" in record.lower():
try:
wl = float(record.split()[-2])
except ValueError:
return False
if wl > 0.05:
return False
return True
def _goniometer(self):
"""Axis as determined by a single run of dials.find_rotation_axis, so
probably not exact"""
return self._goniometer_factory.known_axis((-0.0540788, 0.998537, 0))
def _beam(self):
"""Ensure an unpolarised beam"""
wavelength = float(self._cif_header_dictionary["Wavelength"].split()[0])
return self._beam_factory.make_polarized_beam(
sample_to_source=(0.0, 0.0, 1.0),
wavelength=wavelength,
polarization=(0, 1, 0),
polarization_fraction=0.5,
probe=Probe.electron,
)
def _detector(self):
distance = float(self._cif_header_dictionary["Detector_distance"].split()[0])
beam_xy = (
self._cif_header_dictionary["Beam_xy"]
.replace("(", "")
.replace(")", "")
.replace(",", "")
.split()[:2]
)
beam_x, beam_y = map(float, beam_xy)
pixel_xy = (
self._cif_header_dictionary["Pixel_size"]
.replace("m", "")
.replace("x", "")
.split()
)
pixel_x, pixel_y = map(float, pixel_xy)
if "Silicon" in self._cif_header_dictionary:
thickness = (
float(self._cif_header_dictionary["Silicon"].split()[2]) * 1000.0
)
material = "Si"
elif "CdTe" in self._cif_header_dictionary:
thickness = float(self._cif_header_dictionary["CdTe"].split()[2]) * 1000.0
material = "CdTe"
else:
thickness = 0.450
material = "Si"
nx = int(self._cif_header_dictionary["X-Binary-Size-Fastest-Dimension"])
ny = int(self._cif_header_dictionary["X-Binary-Size-Second-Dimension"])
if "Count_cutoff" in self._cif_header_dictionary:
overload = int(self._cif_header_dictionary["Count_cutoff"].split()[0])
else:
# missing from data transformed with GPhL converter - dials#376
overload = 1048576
if overload == 0:
overload = 1048576
minimum_trusted_value = 0
try:
identifier = self._cif_header_dictionary["Detector"].encode()
except KeyError:
identifier = "Unknown Eiger"
detector = self._detector_factory.simple(
sensor="PAD",
distance=distance * 1000.0,
beam_centre=(beam_x * pixel_x * 1000.0, beam_y * pixel_y * 1000.0),
fast_direction="+x",
slow_direction="-y",
pixel_size=(1000 * pixel_x, 1000 * pixel_y),
image_size=(nx, ny),
trusted_range=(minimum_trusted_value, overload),
mask=[],
)
# Here we set specifics, notably gain=3 and parallax correction and
# QE correction are effectively disabled by setting the simple
# pixel-to-millimetre strategy and a very high mu value.
for panel in detector:
panel.set_gain(3)
panel.set_thickness(thickness)
panel.set_material(material)
panel.set_identifier(identifier)
panel.set_px_mm_strategy(SimplePxMmStrategy())
panel.set_mu(1e10)
return detector