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:
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:
array.array: an array of the data
"""
kinds = {'double': 'd',
@ -91,22 +92,67 @@ def read_array(fh, kind, chunk_location):
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]
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]
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]
def _parse_double(data):
"""
Args:
data: binary data
Returns:
double: the data converted to double
"""
return struct.unpack("d", data.read(8))[0]
def _parse_string(data):
"""
Args:
data: binary data
Returns:
string: the data converted to string
"""
value = data.read(2)
while not value.endswith(six.b("\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):
"""
Args:
data: binary data
Returns:
array.array: the data converted to an array
"""
array_length = struct.unpack("Q", data.read(8))[0]
return array.array("B", data.read(array_length))
@ -124,9 +179,10 @@ def parse_date(text_info):
The date and time when acquisition began.
Args:
text_info:
text_info: the text that contains the date and time information
Returns:
datetime: the date and time of the acquisition
"""
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.
Args:
data:
cursor_position:
data: the binary data that needs to be parsed
cursor_position: the position in the binary nd2 file
Returns:
dict: a dictionary containing the metadata item
"""
new_count, length = struct.unpack("<IQ", data.read(12))
length -= data.tell() - cursor_position
next_data_length = data.read(length)
value = read_metadata(next_data_length, new_count)
# Skip some offsets
data.read(new_count * 8)
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.
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:
mixed: the parsed value
"""
parser = {1: _parse_unsigned_char,
@ -186,13 +247,14 @@ def _get_value(data, data_type, cursor_position):
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:
data:
count:
data: the metadata in binary form
count: the number of metadata elements
Returns:
dict: a dictionary containing the parsed metadata
"""
if data is None:
@ -226,11 +288,12 @@ def _add_to_metadata(metadata, name, value):
Add the name value pair to the metadata dict
Args:
metadata:
name:
value:
metadata (dict): a dictionary containing the metadata
name (string): the dictionary key
value: the value to add
Returns:
dict: the new metadata dictionary
"""
if name not in metadata.keys():


+ 1
- 1
nd2reader/label_map.py View File

@ -123,7 +123,7 @@ class LabelMap(object):
@property
def roi_metadata(self):
"""
Information about any regions of interest (ROIs) defined in the nd2 file
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.
Args:
frame_number:
fov:
z_level:
frame_number: the time index
fov: the field of view number
z_level: the z level number
Returns:
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.
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:
@ -242,17 +242,17 @@ class Parser(object):
"""Reads the raw bytes and the timestamp of an image.
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:
"""
chunk = self._label_map.get_image_data_location(image_group_number)
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,
# 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.
@ -278,5 +278,8 @@ class Parser(object):
def _get_frame_metadata(self):
"""Get the metadata for one frame
Returns:
dict: a dictionary containing the parsed metadata
"""
return self.metadata

+ 18
- 10
nd2reader/raw_metadata.py View File

@ -8,17 +8,18 @@ import numpy as np
def ignore_missing(func):
"""
Ignore missing properties
Args:
func:
func: function to decorate
Returns:
function: a wrapper function
"""
def wrapper(*args, **kwargs):
"""
Wrapper function to ignore missing class properties
Args:
*args:
**kwargs:
@ -48,12 +49,16 @@ class RawMetadata(object):
def __dict__(self):
"""Returns the parsed metadata in dictionary form
Returns:
dict: the parsed metadata
"""
return self.get_parsed_metadata()
def get_parsed_metadata(self):
""" Returns the parsed metadata in dictionary form
Returns:
dict: the parsed metadata
"""
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
used (e.g. "bright field", "GFP", etc.)
Returns:
list: the color channels
"""
channels = []
metadata = self.image_metadata_sequence[six.b('SLxPictureMetadata')][six.b('sPicturePlanes')]
@ -114,14 +120,16 @@ class RawMetadata(object):
def _parse_frames(self):
"""The number of cycles.
Returns:
list: list of all the frame numbers
"""
return self._parse_dimension(r""".*?T'?\((\d+)\).*?""")
def _parse_z_levels(self):
"""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+)\).*?""")
@ -357,9 +365,9 @@ class RawMetadata(object):
@ignore_missing
def image_calibration(self):
"""
The amount of pixels per micron.
Returns:
float: pixels per micron
"""
return read_metadata(read_chunk(self._fh, self._label_map.image_calibration), 1)
@ -407,9 +415,9 @@ class RawMetadata(object):
@ignore_missing
def roi_metadata(self):
"""
Contains information about the defined ROIs: shape, position and type (reference/background/stimulation).
Returns:
dict: ROI metadata dictionary
"""
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):
"""Return the pixel data type
Returns: the pixel data type
Returns:
dtype: the pixel data type
"""
return self._dtype


Loading…
Cancel
Save