Skip to content

Commit b79ac3f

Browse files
committed
Read navigation shape of .mib files from .hdr
Added a function to read the navigation shape of a .mib dataset from the corresponding .hdr file. In case the data contains more frames than expected from the .hdr scan shape, the scan shape is compared to the number of frames to see if an integer number of frames are skipped per line (i.e. a lineskip>0 was used when acquiring the data). If a mismatch is detected, the function does returns None rather than doing a best guess (the data is most likely incomplete, but it is not certain whether frames are missing inside the scan or if the scan was stopped before it was finished. Also fixed some typos in various docstrings. Create 270.enhancements.rst
1 parent bcb2057 commit b79ac3f

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

rsciio/quantumdetector/_api.py

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ def load_mib_data(
281281
# to load is too small, we can't reshape and we fall back to stack of images
282282
_logger.warning(
283283
"The `navigation_shape` doesn't match the number of frames to load. "
284-
"The `navigation_shape` is set to the number of read to read: "
284+
"The `navigation_shape` is set to the number of frames to read: "
285285
f"({number_of_frames_to_load},)."
286286
)
287287
navigation_shape = (number_of_frames_to_load,)
@@ -349,6 +349,10 @@ def load_mib_data(
349349

350350
# remove navigation_dimension with value 1 before reshaping
351351
navigation_shape = tuple(i for i in navigation_shape if i > 1)
352+
if np.prod(navigation_shape) != np.prod(data.shape[:-2]):
353+
raise ValueError(
354+
f"Cannot load MIB file. Navigation shape {navigation_shape} does not match data size {data.shape}"
355+
)
352356
data = data.reshape(navigation_shape + mib_prop.merlin_size)
353357
if lazy and isinstance(chunks, tuple) and len(chunks) > 2:
354358
# rechunk navigation space when chunking is specified as a tuple
@@ -357,7 +361,7 @@ def load_mib_data(
357361
if return_headers:
358362
if distributed:
359363
raise ValueError(
360-
"Retuning headers is not supported with `distributed=True`."
364+
"Returning headers is not supported with `distributed=True`."
361365
)
362366
return data, headers
363367
else:
@@ -389,6 +393,51 @@ def parse_hdr_file(path):
389393
return result
390394

391395

396+
def _get_navigation_shape_from_hdr(_hdr):
397+
"""
398+
Find the navigation shape from the .hdr file.
399+
400+
The resulting navigation shape also takes into account integer line-skips if present.
401+
402+
Returns
403+
-------
404+
tuple
405+
The navigation shape as a tuple.
406+
"""
407+
navigation_shape = None
408+
if "ScanX" in _hdr and "ScanY" in _hdr:
409+
# Use the scan parameters in the hdr file to find the scan shape
410+
frames_number = int(_hdr["Frames in Acquisition (Number)"])
411+
navigation_shape = (
412+
int(_hdr["ScanX"]),
413+
int(_hdr["ScanY"]),
414+
) # Get navigation shape from the header file
415+
if frames_number != np.prod(navigation_shape):
416+
extra_frames = frames_number - np.prod(navigation_shape)
417+
if extra_frames < 0:
418+
_logger.warning(
419+
f"Total frames ({frames_number} in .mib file is less than expected from scan shape in hdr file "
420+
f"({np.prod(navigation_shape)}). The data looks to be incomplete."
421+
)
422+
navigation_shape = None
423+
else:
424+
425+
if extra_frames % navigation_shape[0] == 0:
426+
lineskip = extra_frames // navigation_shape[0]
427+
navigation_shape = (
428+
navigation_shape[0] + lineskip,
429+
navigation_shape[1],
430+
)
431+
else:
432+
_logger.warning(
433+
f"Total frames in .mib file is larger than expected from scan shape in hdr file "
434+
f"({extra_frames} frames in excess), but does not match an integer lineskip "
435+
f"({extra_frames / navigation_shape[0]}). The data may be incomplete."
436+
)
437+
navigation_shape = None
438+
return navigation_shape
439+
440+
392441
def _parse_exposure_to_ms(str_):
393442
# exposure is in "ns", remove unit, convert to float and to ms
394443
return float(str_[:-2]) / 1e6
@@ -533,13 +582,13 @@ def file_reader(
533582
In case of interrupted acquisition, only the completed lines are read and
534583
the incomplete line are discarded.
535584
536-
When the scanning shape (i. e. navigation shape) is not available from the
585+
When the scanning shape (i.e. navigation shape) is not available from the
537586
metadata (for example with acquisition using pixel trigger), the timestamps
538587
will be used to guess the navigation shape.
539588
540589
Examples
541590
--------
542-
In case, the navigation shape can't read from the data itself (for example,
591+
In case the navigation shape can't read from the data itself (for example,
543592
type of acquisition unsupported), the ``navigation_shape`` can be specified:
544593
545594
.. code-block:: python
@@ -563,6 +612,10 @@ def file_reader(
563612

564613
frame_per_trigger = 1
565614
headers = None
615+
616+
if hdr is not None:
617+
navigation_shape = _get_navigation_shape_from_hdr(hdr)
618+
566619
if navigation_shape is None:
567620
if hdr is not None:
568621
# Use the hdr file to find the number of frames
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:ref:`quantumdetector-format`: Add support for reading MIB files acquired with lineskips when acquired in "Scan Mode" and with a corresponding HDR file present.

0 commit comments

Comments
 (0)