From 4efd9a2ea4711688f1d5a7660719085f360584b9 Mon Sep 17 00:00:00 2001 From: Gregor Lichtner Date: Thu, 23 May 2019 11:39:55 +0200 Subject: [PATCH 1/3] added image events to parser --- nd2reader/label_map.py | 10 +++++++++ nd2reader/raw_metadata.py | 45 +++++++++++++++++++++++++++++++++++++++ nd2reader/reader.py | 12 +++++++++++ 3 files changed, 67 insertions(+) diff --git a/nd2reader/label_map.py b/nd2reader/label_map.py index c46f785..dcd2e9c 100644 --- a/nd2reader/label_map.py +++ b/nd2reader/label_map.py @@ -43,6 +43,16 @@ class LabelMap(object): """ return self._get_location(six.b("ImageMetadataLV!")) + @property + def image_events(self): + """Get the location of the image events + + Returns: + int: The location of the image events + + """ + return self._get_location(six.b("ImageEventsLV!")) + @property def image_metadata_sequence(self): """Get the location of the image metadata sequence. There is always only one of these, even though it has a pipe diff --git a/nd2reader/raw_metadata.py b/nd2reader/raw_metadata.py index 6d9918e..c95c566 100644 --- a/nd2reader/raw_metadata.py +++ b/nd2reader/raw_metadata.py @@ -54,6 +54,7 @@ class RawMetadata(object): self._parse_roi_metadata() self._parse_experiment_metadata() + self._parse_events() return self._metadata_parsed @@ -373,6 +374,38 @@ class RawMetadata(object): return duration + def _parse_events(self): + """Extract events + + """ + + event_names = { + 10: 'Experiment Resumed', + 14: 'Experiment Paused for Refocusing', + 44: 'No Acquisition Phase Start', + 45: 'No Acquisition Phase End' + } + + self._metadata_parsed['events'] = [] + + events = read_metadata(read_chunk(self._fh, self._label_map.image_events), 1) + + if events is None or six.b('RLxExperimentRecord') not in events: + return + + events = events[six.b('RLxExperimentRecord')][six.b('pEvents')][six.b('')] + + for event in events: + event_info = { + 'index': event[six.b('I')], + 'time': event[six.b('T')], + 'type': event[six.b('M')], + } + if event_info['type'] in event_names.keys(): + event_info['name'] = event_names[event_info['type']] + + self._metadata_parsed['events'].append(event_info) + @property def image_text_info(self): @@ -554,3 +587,15 @@ class RawMetadata(object): """ if self._label_map.image_metadata: return read_metadata(read_chunk(self._fh, self._label_map.image_metadata), 1) + + @property + def image_events(self): + """Image events + + Returns: + dict: Image events + """ + if self._label_map.image_metadata: + for event in self._metadata_parsed["events"]: + yield event + diff --git a/nd2reader/reader.py b/nd2reader/reader.py index bbb2353..52078d0 100644 --- a/nd2reader/reader.py +++ b/nd2reader/reader.py @@ -102,6 +102,16 @@ class ND2Reader(FramesSequenceND): return self.get_timesteps() return self._timesteps + @property + def events(self): + """Get the events of the experiment + + Returns: + iterator of events as dict + """ + + return self._get_metadata_property("events") + @property def frame_rate(self): """The (average) frame rate @@ -186,3 +196,5 @@ class ND2Reader(FramesSequenceND): self._timesteps = np.array(list(self._parser._raw_metadata.acquisition_times), dtype=np.float) * 1000.0 return self._timesteps + + From 26bdbf36f06425467e2fa9fe9d112452f27793e1 Mon Sep 17 00:00:00 2001 From: Gregor Lichtner Date: Thu, 23 May 2019 16:11:40 +0200 Subject: [PATCH 2/3] fixed behavior when no events are available --- nd2reader/raw_metadata.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nd2reader/raw_metadata.py b/nd2reader/raw_metadata.py index c95c566..4636928 100644 --- a/nd2reader/raw_metadata.py +++ b/nd2reader/raw_metadata.py @@ -393,9 +393,12 @@ class RawMetadata(object): if events is None or six.b('RLxExperimentRecord') not in events: return - events = events[six.b('RLxExperimentRecord')][six.b('pEvents')][six.b('')] + events = events[six.b('RLxExperimentRecord')][six.b('pEvents')] - for event in events: + if len(events) == 0: + return + + for event in events[six.b('')]: event_info = { 'index': event[six.b('I')], 'time': event[six.b('T')], @@ -406,7 +409,6 @@ class RawMetadata(object): self._metadata_parsed['events'].append(event_info) - @property def image_text_info(self): """Textual image information From 016239f1dd4f922b3f7f2467a0307cfe24df55a5 Mon Sep 17 00:00:00 2001 From: Gregor Lichtner Date: Fri, 24 May 2019 14:10:16 +0200 Subject: [PATCH 3/3] added event names --- nd2reader/raw_metadata.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/nd2reader/raw_metadata.py b/nd2reader/raw_metadata.py index 4636928..66f3fb3 100644 --- a/nd2reader/raw_metadata.py +++ b/nd2reader/raw_metadata.py @@ -379,11 +379,31 @@ class RawMetadata(object): """ + # list of event names manually extracted from an ND2 file that contains all manually + # insertable events from NIS-Elements software (4.60.00 (Build 1171) Patch 02) event_names = { + 1: 'Autofocus', + 7: 'Command Executed', + 9: 'Experiment Paused', 10: 'Experiment Resumed', + 11: 'Experiment Stopped by User', + 13: 'Next Phase Moved by User', 14: 'Experiment Paused for Refocusing', + 16: 'External Stimulation', + 33: 'User 1', + 34: 'User 2', + 35: 'User 3', + 36: 'User 4', + 37: 'User 5', + 38: 'User 6', + 39: 'User 7', + 40: 'User 8', 44: 'No Acquisition Phase Start', - 45: 'No Acquisition Phase End' + 45: 'No Acquisition Phase End', + 46: 'Hardware Error', + 47: 'N-STORM', + 48: 'Incubation Info', + 49: 'Incubation Error' } self._metadata_parsed['events'] = []