From bfbd78bbe25e28b15621e6f67311de9c25f11afa Mon Sep 17 00:00:00 2001 From: Lorenzo ZOLFANELLI Date: Mon, 21 Mar 2022 14:52:34 +0100 Subject: [PATCH] added x coordiantes and rotation matrix readout --- nd2reader/parser.py | 1 - nd2reader/raw_metadata.py | 62 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/nd2reader/parser.py b/nd2reader/parser.py index 2f7b58d..bebbcaa 100644 --- a/nd2reader/parser.py +++ b/nd2reader/parser.py @@ -6,7 +6,6 @@ import six import warnings from pims.base_frames import Frame import numpy as np -from tqdm import tqdm from nd2reader.common import get_version, read_chunk from nd2reader.label_map import LabelMap diff --git a/nd2reader/raw_metadata.py b/nd2reader/raw_metadata.py index 1152219..3c25d57 100644 --- a/nd2reader/raw_metadata.py +++ b/nd2reader/raw_metadata.py @@ -45,9 +45,13 @@ class RawMetadata(object): "frames": self._parse_frames(), "z_levels": self._parse_z_levels(), "z_coordinates": parse_if_not_none(self.z_data, self._parse_z_coordinates), + "x_coordinates": parse_if_not_none(self.x_data, self._parse_x_coordinates), + "y_coordinates": parse_if_not_none(self.y_data, self._parse_y_coordinates), "total_images_per_channel": frames_per_channel, "channels": self._parse_channels(), - "pixel_microns": parse_if_not_none(self.image_calibration, self._parse_calibration) + "pixel_microns": parse_if_not_none(self.image_calibration, self._parse_calibration), + "camera_stage_angle": parse_if_not_none(self.image_metadata_sequence, self._parse_camera_angle), + "camera_stage_matrix": parse_if_not_none(self.image_metadata_sequence, self._parse_camera_matrix) } self._set_default_if_not_empty('fields_of_view') @@ -195,6 +199,62 @@ class RawMetadata(object): """ return self.z_data.tolist() + def _parse_x_coordinates(self): + """The coordinate in micron for all x frames. + + Returns: + list: the x coordinates in micron + """ + return self.x_data.tolist() + + def _parse_y_coordinates(self): + """The coordinate in micron for all y frames. + + Returns: + list: the y coordinates in micron + """ + return self.y_data.tolist() + + def _parse_camera_angle(self): + if self.image_metadata_sequence is None: + return [] + + try: + metadata = self.image_metadata_sequence[six.b('SLxPictureMetadata')] + except KeyError: + return [] + + try: + return metadata[b'dAngle'] + except KeyError: + return None + + def _parse_camera_matrix(self): + if self.image_metadata_sequence is None: + return [] + + try: + metadata = self.image_metadata_sequence[six.b('SLxPictureMetadata')][b'sPicturePlanes'] + except KeyError: + return [] + + validity = self._get_channel_validity_list(metadata) + + channels = [] + for valid, (label, chan) in zip(validity, sorted(metadata[b'sSampleSetting'].items())): + if not valid: + continue + if chan[b'matCameraToStage'] is not None: + mat_data = chan[b'matCameraToStage'][b'Data'] + mat_rows = chan[b'matCameraToStage'][b'Rows'] + mat_columns = chan[b'matCameraToStage'][b'Columns'] + mat = np.frombuffer(mat_data, dtype=np.float64).reshape([mat_rows, mat_columns]) + channels.append(mat) + else: + channels.append(None) + return channels + + def _parse_dimension_text(self): """While there are metadata values that represent a lot of what we want to capture, they seem to be unreliable. Sometimes certain elements don't exist, or change their data type randomly. However, the human-readable text