Skip to content

Commit 4a8edc2

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 4a8edc2

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

rsciio/quantumdetector/_api.py

Lines changed: 56 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,50 @@ 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+
if extra_frames % navigation_shape[0] == 0:
425+
lineskip = extra_frames // navigation_shape[0]
426+
navigation_shape = (
427+
navigation_shape[0] + lineskip,
428+
navigation_shape[1],
429+
)
430+
else:
431+
_logger.warning(
432+
f"Total frames in .mib file is larger than expected from scan shape in hdr file "
433+
f"({extra_frames} frames in excess), but does not match an integer lineskip "
434+
f"({extra_frames / navigation_shape[0]}). The data may be incomplete."
435+
)
436+
navigation_shape = None
437+
return navigation_shape
438+
439+
392440
def _parse_exposure_to_ms(str_):
393441
# exposure is in "ns", remove unit, convert to float and to ms
394442
return float(str_[:-2]) / 1e6
@@ -533,13 +581,13 @@ def file_reader(
533581
In case of interrupted acquisition, only the completed lines are read and
534582
the incomplete line are discarded.
535583
536-
When the scanning shape (i. e. navigation shape) is not available from the
584+
When the scanning shape (i.e. navigation shape) is not available from the
537585
metadata (for example with acquisition using pixel trigger), the timestamps
538586
will be used to guess the navigation shape.
539587
540588
Examples
541589
--------
542-
In case, the navigation shape can't read from the data itself (for example,
590+
In case the navigation shape can't read from the data itself (for example,
543591
type of acquisition unsupported), the ``navigation_shape`` can be specified:
544592
545593
.. code-block:: python
@@ -563,6 +611,10 @@ def file_reader(
563611

564612
frame_per_trigger = 1
565613
headers = None
614+
615+
if hdr is not None:
616+
navigation_shape = _get_navigation_shape_from_hdr(hdr)
617+
566618
if navigation_shape is None:
567619
if hdr is not None:
568620
# 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)