Browse Source

solved missing fields of view issue

feature/load_slices
jim 10 years ago
parent
commit
bf35675022
3 changed files with 86 additions and 18 deletions
  1. +45
    -12
      nd2reader/__init__.py
  2. +24
    -0
      nd2reader/model/__init__.py
  3. +17
    -6
      run.py

+ 45
- 12
nd2reader/__init__.py View File

@ -3,16 +3,21 @@ import numpy as np
import struct
from collections import namedtuple
from StringIO import StringIO
from nd2reader.model import Channel
from pprint import pprint
chunk = namedtuple('Chunk', ['location', 'length'])
field_of_view = namedtuple('FOV', ['number', 'x', 'y', 'z', 'pfs_offset'])
channel = namedtuple('Channel', ['name', 'camera', 'exposure_time'])
class Nd2(object):
def __init__(self, filename):
self._parser = Nd2Parser(filename)
@property
def timepoint_count(self):
return len(self._parser.metadata['ImageEvents']['RLxExperimentRecord']['pEvents'][''])
@property
def height(self):
return self._parser.metadata['ImageAttributes']['SLxImageAttributes']['uiHeight']
@ -23,21 +28,50 @@ class Nd2(object):
@property
def fields_of_view(self):
for number, fov in enumerate(self.metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx']['']['uLoopPars']['Points']['']):
yield field_of_view(number=number + 1, x=fov['dPosX'], y=fov['dPosY'], z=fov['dPosZ'], pfs_offset=fov['dPFSOffset'])
fov_data = self.metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx']['']
valid_fields = list(fov_data['pItemValid'])
for number, (fov, valid) in enumerate(zip(fov_data['uLoopPars']['Points'][''], valid_fields)):
if valid:
yield field_of_view(number=number + 1,
x=fov['dPosX'],
y=fov['dPosY'],
z=fov['dPosZ'],
pfs_offset=fov['dPFSOffset'])
@property
def fov_count(self):
return len(list(self.fields_of_view))
"""
The metadata contains information about fields of view, but it contains it even if some fields
of view were cropped. We can't find anything that states which fields of view are actually
in the image data, so we have to calculate it. There probably is something somewhere, since
NIS Elements can figure it out, but we haven't found it yet.
"""
return sum(self.metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx']['']['pItemValid'])
@property
def channels(self):
metadata = self.metadata['ImageMetadataSeq']['SLxPictureMetadata']['sPicturePlanes']
for label, chan in metadata['sPlaneNew'].items():
# Channel information is contained in dictionaries with the keys a0, a1...an where the number
# indicates the order in which the channel is stored. So by sorting the dicts alphabetically
# we get the correct order.
for label, chan in sorted(metadata['sPlaneNew'].items()):
name = chan['sDescription']
exposure_time = metadata['sSampleSetting'][label]['dExposureTime']
camera = metadata['sSampleSetting'][label]['pCameraSetting']['CameraUserName']
yield channel(name=name, exposure_time=exposure_time, camera=camera)
yield Channel(name, camera, exposure_time)
@property
def channel_count(self):
return self.metadata['ImageAttributes']["SLxImageAttributes"]["uiComp"]
@property
def z_level_count(self):
"""
The number of different z-axis levels.
"""
return 1
@property
def metadata(self):
@ -48,13 +82,12 @@ class Nd2(object):
def get_image(self, nr):
d = self._parser._read_chunk(self._parser._label_map["ImageDataSeq|%d!" % nr].location)
acqtime = struct.unpack("d", d[:8])[0]
res = [acqtime]
for i in range(self.metadata['ImageAttributes']["SLxImageAttributes"]["uiComp"]):
timestamp = struct.unpack("d", d[:8])[0]
res = [timestamp]
# The images for the various channels are interleaved within each other.
for i in range(self.channel_count):
a = array.array("H", d)
res.append(a[4+i::self.metadata['ImageAttributes']["SLxImageAttributes"]["uiComp"]])
arr = np.reshape(res[1], (self.height, self.width))
res.append(a[4+i::self.channel_count])
# TODO: Are you missing a zoom level? Is there extra data here? Can you get timestamps now?
return res


+ 24
- 0
nd2reader/model/__init__.py View File

@ -0,0 +1,24 @@
class Channel(object):
def __init__(self, name, camera, exposure_time):
self._name = name
self._camera = camera
self._exposure_time = exposure_time
@property
def name(self):
if self._name is not None and self._name != "":
return self._name
return "UnnamedChannel"
@property
def camera(self):
return self._camera
@property
def exposure_time(self):
return self._exposure_time
class Image(object):
def __init__(self):
self.timestamp = None

+ 17
- 6
run.py View File

@ -1,16 +1,27 @@
from nd2reader import Nd2
from pprint import pprint
import numpy as np
from skimage import io
# n = Nd2("/home/jim/Desktop/nd2hacking/test-141111.nd2")
n = Nd2("/home/jim/Desktop/nd2hacking/YFP-dsRed-GFP-BF.nd2")
n = Nd2("/home/jim/Desktop/nd2hacking/BFonly.nd2")
# print("Height: ", n.height)
# print("Width: ", n.width)
# for fov in n.fields_of_view:
# print(fov.number, fov.x, fov.y, fov.z, fov.pfs_offset)
#
# for channel in n.channels:
# print(channel.name)
# print(channel.camera)
# print(channel.exposure_time)
print(n.timepoint_count)
print(n.fov_count)
print(n.channel_count)
for fov in n.fields_of_view:
print(fov.number, fov.x, fov.y, fov.z)
# pprint(len(n.metadata['ImageMetadata']['SLxExperiment']['uLoopPars']['pPeriod']['']))
n.get_image(3)
# res = n.get_image(6)
# print(res[0])
# arr = np.reshape(res[1], (n.height, n.width))
# io.imshow(arr)
# io.show()
# pprint(n.metadata)

Loading…
Cancel
Save