Browse Source

Improve documentation

feature/load_slices
Ruben Verweij 7 years ago
parent
commit
f3d5c62042
5 changed files with 113 additions and 38 deletions
  1. +78
    -15
      nd2reader/common.py
  2. +1
    -1
      nd2reader/label_map.py
  3. +14
    -11
      nd2reader/parser.py
  4. +18
    -10
      nd2reader/raw_metadata.py
  5. +2
    -1
      nd2reader/reader.py

+ 78
- 15
nd2reader/common.py View File

@ -72,11 +72,12 @@ def read_array(fh, kind, chunk_location):
""" """
Args: Args:
fh:
kind:
chunk_location:
fh: File handle of the nd2 file
kind: data type, can be one of 'double', 'int' or 'float'
chunk_location: the location of the array chunk in the binary nd2 file
Returns: Returns:
array.array: an array of the data
""" """
kinds = {'double': 'd', kinds = {'double': 'd',
@ -91,22 +92,67 @@ def read_array(fh, kind, chunk_location):
def _parse_unsigned_char(data): def _parse_unsigned_char(data):
"""
Args:
data: binary data
Returns:
char: the data converted to unsigned char
"""
return struct.unpack("B", data.read(1))[0] return struct.unpack("B", data.read(1))[0]
def _parse_unsigned_int(data): def _parse_unsigned_int(data):
"""
Args:
data: binary data
Returns:
int: the data converted to unsigned int
"""
return struct.unpack("I", data.read(4))[0] return struct.unpack("I", data.read(4))[0]
def _parse_unsigned_long(data): def _parse_unsigned_long(data):
"""
Args:
data: binary data
Returns:
long: the data converted to unsigned long
"""
return struct.unpack("Q", data.read(8))[0] return struct.unpack("Q", data.read(8))[0]
def _parse_double(data): def _parse_double(data):
"""
Args:
data: binary data
Returns:
double: the data converted to double
"""
return struct.unpack("d", data.read(8))[0] return struct.unpack("d", data.read(8))[0]
def _parse_string(data): def _parse_string(data):
"""
Args:
data: binary data
Returns:
string: the data converted to string
"""
value = data.read(2) value = data.read(2)
while not value.endswith(six.b("\x00\x00")): while not value.endswith(six.b("\x00\x00")):
# the string ends at the first instance of \x00\x00 # the string ends at the first instance of \x00\x00
@ -115,6 +161,15 @@ def _parse_string(data):
def _parse_char_array(data): def _parse_char_array(data):
"""
Args:
data: binary data
Returns:
array.array: the data converted to an array
"""
array_length = struct.unpack("Q", data.read(8))[0] array_length = struct.unpack("Q", data.read(8))[0]
return array.array("B", data.read(array_length)) return array.array("B", data.read(array_length))
@ -124,9 +179,10 @@ def parse_date(text_info):
The date and time when acquisition began. The date and time when acquisition began.
Args: Args:
text_info:
text_info: the text that contains the date and time information
Returns: Returns:
datetime: the date and time of the acquisition
""" """
for line in text_info.values(): for line in text_info.values():
@ -147,18 +203,21 @@ def _parse_metadata_item(data, cursor_position):
"""Reads hierarchical data, analogous to a Python dict. """Reads hierarchical data, analogous to a Python dict.
Args: Args:
data:
cursor_position:
data: the binary data that needs to be parsed
cursor_position: the position in the binary nd2 file
Returns: Returns:
dict: a dictionary containing the metadata item
""" """
new_count, length = struct.unpack("<IQ", data.read(12)) new_count, length = struct.unpack("<IQ", data.read(12))
length -= data.tell() - cursor_position length -= data.tell() - cursor_position
next_data_length = data.read(length) next_data_length = data.read(length)
value = read_metadata(next_data_length, new_count) value = read_metadata(next_data_length, new_count)
# Skip some offsets # Skip some offsets
data.read(new_count * 8) data.read(new_count * 8)
return value return value
@ -166,11 +225,13 @@ def _get_value(data, data_type, cursor_position):
"""ND2s use various codes to indicate different data types, which we translate here. """ND2s use various codes to indicate different data types, which we translate here.
Args: Args:
data:
data_type:
cursor_position:
data: the binary data
data_type: the data type (unsigned char = 1, unsigned int = 2 or 3, unsigned long = 5, double = 6, string = 8,
char array = 9, metadata item = 11)
cursor_position: the cursor position in the binary nd2 file
Returns: Returns:
mixed: the parsed value
""" """
parser = {1: _parse_unsigned_char, parser = {1: _parse_unsigned_char,
@ -186,13 +247,14 @@ def _get_value(data, data_type, cursor_position):
def read_metadata(data, count): def read_metadata(data, count):
""" """
Iterates over each element some section of the metadata and parses it.
Iterates over each element of some section of the metadata and parses it.
Args: Args:
data:
count:
data: the metadata in binary form
count: the number of metadata elements
Returns: Returns:
dict: a dictionary containing the parsed metadata
""" """
if data is None: if data is None:
@ -226,11 +288,12 @@ def _add_to_metadata(metadata, name, value):
Add the name value pair to the metadata dict Add the name value pair to the metadata dict
Args: Args:
metadata:
name:
value:
metadata (dict): a dictionary containing the metadata
name (string): the dictionary key
value: the value to add
Returns: Returns:
dict: the new metadata dictionary
""" """
if name not in metadata.keys(): if name not in metadata.keys():


+ 1
- 1
nd2reader/label_map.py View File

@ -123,7 +123,7 @@ class LabelMap(object):
@property @property
def roi_metadata(self): def roi_metadata(self):
""" """
Information about any regions of interest (ROIs) defined in the nd2 file
Returns: Returns:
""" """


+ 14
- 11
nd2reader/parser.py View File

@ -200,9 +200,9 @@ class Parser(object):
Images are grouped together if they share the same time index, field of view, and z-level. Images are grouped together if they share the same time index, field of view, and z-level.
Args: Args:
frame_number:
fov:
z_level:
frame_number: the time index
fov: the field of view number
z_level: the z level number
Returns: Returns:
int: the image group number int: the image group number
@ -216,9 +216,9 @@ class Parser(object):
Images are in the same frame if they share the same group number and field of view and are taken sequentially. Images are in the same frame if they share the same group number and field of view and are taken sequentially.
Args: Args:
image_group_number:
field_of_view:
z_level:
image_group_number: the image group number (see _calculate_image_group_number)
field_of_view: the field of view number
z_level: the z level number
Returns: Returns:
@ -242,17 +242,17 @@ class Parser(object):
"""Reads the raw bytes and the timestamp of an image. """Reads the raw bytes and the timestamp of an image.
Args: Args:
image_group_number:
channel_offset:
height:
width:
image_group_number: the image group number (see _calculate_image_group_number)
channel_offset: the number of the color channel
height: the height of the image
width: the width of the image
Returns: Returns:
""" """
chunk = self._label_map.get_image_data_location(image_group_number) chunk = self._label_map.get_image_data_location(image_group_number)
data = read_chunk(self._fh, chunk) data = read_chunk(self._fh, chunk)
# print("data", data, "that was data")
# All images in the same image group share the same timestamp! So if you have complicated image data, # All images in the same image group share the same timestamp! So if you have complicated image data,
# your timestamps may not be entirely accurate. Practically speaking though, they'll only be off by a few # your timestamps may not be entirely accurate. Practically speaking though, they'll only be off by a few
# seconds unless you're doing something super weird. # seconds unless you're doing something super weird.
@ -278,5 +278,8 @@ class Parser(object):
def _get_frame_metadata(self): def _get_frame_metadata(self):
"""Get the metadata for one frame """Get the metadata for one frame
Returns:
dict: a dictionary containing the parsed metadata
""" """
return self.metadata return self.metadata

+ 18
- 10
nd2reader/raw_metadata.py View File

@ -8,17 +8,18 @@ import numpy as np
def ignore_missing(func): def ignore_missing(func):
""" """
Ignore missing properties
Args: Args:
func:
func: function to decorate
Returns: Returns:
function: a wrapper function
""" """
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
""" """
Wrapper function to ignore missing class properties
Args: Args:
*args: *args:
**kwargs: **kwargs:
@ -48,12 +49,16 @@ class RawMetadata(object):
def __dict__(self): def __dict__(self):
"""Returns the parsed metadata in dictionary form """Returns the parsed metadata in dictionary form
Returns:
dict: the parsed metadata
""" """
return self.get_parsed_metadata() return self.get_parsed_metadata()
def get_parsed_metadata(self): def get_parsed_metadata(self):
""" Returns the parsed metadata in dictionary form """ Returns the parsed metadata in dictionary form
Returns:
dict: the parsed metadata
""" """
if self._metadata_parsed is not None: if self._metadata_parsed is not None:
@ -82,7 +87,8 @@ class RawMetadata(object):
""" """
These are labels created by the NIS Elements user. Typically they may a short description of the filter cube These are labels created by the NIS Elements user. Typically they may a short description of the filter cube
used (e.g. "bright field", "GFP", etc.) used (e.g. "bright field", "GFP", etc.)
Returns:
list: the color channels
""" """
channels = [] channels = []
metadata = self.image_metadata_sequence[six.b('SLxPictureMetadata')][six.b('sPicturePlanes')] metadata = self.image_metadata_sequence[six.b('SLxPictureMetadata')][six.b('sPicturePlanes')]
@ -114,14 +120,16 @@ class RawMetadata(object):
def _parse_frames(self): def _parse_frames(self):
"""The number of cycles. """The number of cycles.
Returns:
list: list of all the frame numbers
""" """
return self._parse_dimension(r""".*?T'?\((\d+)\).*?""") return self._parse_dimension(r""".*?T'?\((\d+)\).*?""")
def _parse_z_levels(self): def _parse_z_levels(self):
"""The different levels in the Z-plane. """The different levels in the Z-plane.
Just a sequence from 0 to n.
Returns:
list: the z levels, just a sequence from 0 to n.
""" """
return self._parse_dimension(r""".*?Z\((\d+)\).*?""") return self._parse_dimension(r""".*?Z\((\d+)\).*?""")
@ -357,9 +365,9 @@ class RawMetadata(object):
@ignore_missing @ignore_missing
def image_calibration(self): def image_calibration(self):
""" """
The amount of pixels per micron.
Returns: Returns:
float: pixels per micron
""" """
return read_metadata(read_chunk(self._fh, self._label_map.image_calibration), 1) return read_metadata(read_chunk(self._fh, self._label_map.image_calibration), 1)
@ -407,9 +415,9 @@ class RawMetadata(object):
@ignore_missing @ignore_missing
def roi_metadata(self): def roi_metadata(self):
""" """
Contains information about the defined ROIs: shape, position and type (reference/background/stimulation).
Returns: Returns:
dict: ROI metadata dictionary
""" """
return read_metadata(read_chunk(self._fh, self._label_map.roi_metadata), 1) return read_metadata(read_chunk(self._fh, self._label_map.roi_metadata), 1)


+ 2
- 1
nd2reader/reader.py View File

@ -93,7 +93,8 @@ class ND2Reader(FramesSequenceND):
def pixel_type(self): def pixel_type(self):
"""Return the pixel data type """Return the pixel data type
Returns: the pixel data type
Returns:
dtype: the pixel data type
""" """
return self._dtype return self._dtype


Loading…
Cancel
Save