Skip to content

Commit faa7b2f

Browse files
committed
CalibMovieDelaysMapping: improve readability, docstrings as requested
1 parent b4e933e commit faa7b2f

File tree

1 file changed

+43
-26
lines changed

1 file changed

+43
-26
lines changed

src/instamatic/calibrate/calibrate_movie_delays.py

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -106,29 +106,37 @@ def to_file(
106106
calib_map.to_file(path)
107107

108108

109+
CalibConditions_T = Tuple[float, Tuple[str, ...], Tuple[str, ...]]
110+
111+
109112
class CalibMovieDelaysMapping(MutableMapping):
110-
"""Calibrated delays depend on the exposure time as well as information
111-
requested in movie header: requesting a lot of common information might
112-
elongate the initialization, large per-image headers may take too long to
113-
collect during `exposure`, artificially inflating yield times.
114-
This class loads, stores, and saves instances of `CalibMovieDelays`
115-
calibrated for each combination of exposure and common/variable header.
116-
117-
Instances of `CalibMovieDelays` are indexed using a composite string key,
118-
which takes form "exposure;common,header,elements;variable,header,elements".
119-
However, this class also allows accessing instances using the tuple-form.
113+
"""Calibrated delays depend on the exposure time as well information
114+
requested for movie header. This information can be split into two kinds:
115+
common information is collected once at the beginning of the movie,
116+
potentially leading to long initialization times. Variable information is
117+
collect for each image individually while it is gathered, potentially
118+
artificially inflating the "dead" time. This class manages instances of
119+
`CalibMovieDelays` calibrated for each combination of exposure and headers.
120+
121+
From the code perspective, the easiest way to express `CalibConditions_T`,
122+
i.e. exposure, common headers, and variable headers, is via a tuple.
123+
Unfortunately, tuples can not be used as a key for serialization purposes.
124+
Therefore, this class also allows converting the conditions to a string
125+
representation: "exposure;common,header,elements;variable,header,elements".
126+
127+
Instances of `CalibMovieDelays` are indexed using this composite header key;
128+
However, for convenience, this class allows accessing stored instances of
129+
`CalibMovieDelays` using either the composite string or tuple-style key.
120130
"""
121131

122-
ExposureHeadersHeaders_T = Tuple[float, Tuple[str, ...], Tuple[str, ...]]
123-
124132
def __init__(self, dict_: Dict[str, CalibMovieDelays] = None) -> None:
125133
self.dict = dict_ if dict_ else {}
126134

127-
def __delitem__(self, k: Union[str, ExposureHeadersHeaders_T]) -> None:
128-
del self.dict[k if isinstance(k, str) else self.ehh_to_str(*k)]
135+
def __delitem__(self, k: Union[str, CalibConditions_T]) -> None:
136+
del self.dict[k if isinstance(k, str) else self.calib_conditions2str(k)]
129137

130-
def __getitem__(self, k: Union[str, ExposureHeadersHeaders_T]) -> CalibMovieDelays:
131-
return self.dict[k if isinstance(k, str) else self.ehh_to_str(*k)]
138+
def __getitem__(self, k: Union[str, CalibConditions_T]) -> CalibMovieDelays:
139+
return self.dict[k if isinstance(k, str) else self.calib_conditions2str(k)]
132140

133141
def __len__(self) -> int:
134142
return len(self.dict)
@@ -137,20 +145,29 @@ def __iter__(self) -> Iterator:
137145
return self.dict.__iter__()
138146

139147
def __setitem__(self, k, v) -> None:
140-
self.dict[k if isinstance(k, str) else self.ehh_to_str(*k)] = v
148+
self.dict[k if isinstance(k, str) else self.calib_conditions2str(k)] = v
149+
150+
def str2tuple(self, str_: str, delimiter: str = ',') -> Tuple[str, ...]:
151+
"""Convert a `delimiter`-delimited string into a tuple of strings."""
152+
return tuple(sorted(str_.split(delimiter)))
153+
154+
def tuple2str(self, tuple_: Tuple[str, ...], delimiter: str = ',') -> str:
155+
"""Convert a tuple of strings into a `delimiter`-delimited string."""
156+
return delimiter.join([str(t) for t in sorted(tuple_)])
141157

142-
@staticmethod
143-
def str_to_ehh(key: str) -> ExposureHeadersHeaders_T:
144-
"""Convert a "1.0;t11,t12;t21"-form str to float & tuples t1 & t2."""
158+
def str2calib_conditions(self, key: str) -> CalibConditions_T:
159+
"""Convert calibration conditions from ,/;-delimited str to tuple."""
145160
exposure, header_keys_common, header_keys_variable = key.split(';', 3)
146-
header_keys_common = tuple(sorted(header_keys_common.split(',')))
147-
header_keys_variable = tuple(sorted(header_keys_variable.split(',')))
161+
header_keys_common = self.str2tuple(header_keys_common, ',')
162+
header_keys_variable = self.str2tuple(header_keys_variable, ',')
148163
return float(exposure), header_keys_common, header_keys_variable
149164

150-
@staticmethod
151-
def ehh_to_str(e: float, t1: Sequence[str, ...], t2: Sequence[str, ...]) -> str:
152-
"""Convert float & tuples t1 & t2 to "e;t11,t12;t21,t22"-form str."""
153-
return f'{round(e, 3):.3f};' + ','.join(sorted(t1)) + ';' + ','.join(sorted(t2))
165+
def calib_conditions2str(self, c: CalibConditions_T) -> str:
166+
"""Convert calibration conditions from tuple to ,/;-delimited str."""
167+
exposure, header_keys_common, header_keys_variable = c
168+
hkc = self.tuple2str(header_keys_common, ',')
169+
hkv = self.tuple2str(header_keys_variable, ',')
170+
return f'{round(exposure, 3):.3f};{hkc};{hkv}'
154171

155172
@classmethod
156173
def from_dict(cls, dict_: Dict[str, Dict[str, float]]) -> Self:

0 commit comments

Comments
 (0)