|
@ -25,6 +25,25 @@ class BaseNd2(object): |
|
|
def width(self): |
|
|
def width(self): |
|
|
return self._metadata['ImageAttributes']['SLxImageAttributes']['uiWidth'] |
|
|
return self._metadata['ImageAttributes']['SLxImageAttributes']['uiWidth'] |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def channels(self): |
|
|
|
|
|
metadata = self._metadata['ImageMetadataSeq']['SLxPictureMetadata']['sPicturePlanes'] |
|
|
|
|
|
try: |
|
|
|
|
|
validity = self._metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx']['']['ppNextLevelEx']['']['pItemValid'] |
|
|
|
|
|
except KeyError: |
|
|
|
|
|
# If none of the channels have been deleted, there is no validity list, so we just make one |
|
|
|
|
|
validity = [True for i in metadata] |
|
|
|
|
|
# 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), valid in zip(sorted(metadata['sPlaneNew'].items()), validity): |
|
|
|
|
|
if not valid: |
|
|
|
|
|
continue |
|
|
|
|
|
name = chan['sDescription'] |
|
|
|
|
|
exposure_time = metadata['sSampleSetting'][label]['dExposureTime'] |
|
|
|
|
|
camera = metadata['sSampleSetting'][label]['pCameraSetting']['CameraUserName'] |
|
|
|
|
|
yield Channel(name, camera, exposure_time) |
|
|
|
|
|
|
|
|
@property |
|
|
@property |
|
|
def _image_count(self): |
|
|
def _image_count(self): |
|
|
return self._metadata['ImageAttributes']['SLxImageAttributes']['uiSequenceCount'] |
|
|
return self._metadata['ImageAttributes']['SLxImageAttributes']['uiSequenceCount'] |
|
@ -37,28 +56,6 @@ class BaseNd2(object): |
|
|
def _timepoint_count(self): |
|
|
def _timepoint_count(self): |
|
|
return self._image_count / self._field_of_view_count / self._z_level_count |
|
|
return self._image_count / self._field_of_view_count / self._z_level_count |
|
|
|
|
|
|
|
|
# @property |
|
|
|
|
|
# def _fields_of_view(self): |
|
|
|
|
|
# """ |
|
|
|
|
|
# Fields of view are the various places in the xy-plane where images were taken. |
|
|
|
|
|
# |
|
|
|
|
|
# """ |
|
|
|
|
|
# # Grab all the metadata about fields of view |
|
|
|
|
|
# fov_metadata = self._metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx'][''] |
|
|
|
|
|
# # The attributes include x, y, and z coordinates, and perfect focus (PFS) offset |
|
|
|
|
|
# fov_attributes = fov_metadata['uLoopPars']['Points'][''] |
|
|
|
|
|
# # If you crop fields of view from your ND2 file, the metadata is retained and only this list is |
|
|
|
|
|
# # updated to indicate that the fields of view have been deleted. |
|
|
|
|
|
# fov_validity = fov_metadata['pItemValid'] |
|
|
|
|
|
# # We only yield valid (i.e. uncropped) fields of view |
|
|
|
|
|
# for number, (fov, valid) in enumerate(zip(fov_attributes, fov_validity)): |
|
|
|
|
|
# if valid: |
|
|
|
|
|
# yield field_of_view(number=number + 1, |
|
|
|
|
|
# x=fov['dPosX'], |
|
|
|
|
|
# y=fov['dPosY'], |
|
|
|
|
|
# z=fov['dPosZ'], |
|
|
|
|
|
# pfs_offset=fov['dPFSOffset']) |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
@property |
|
|
def _z_level_count(self): |
|
|
def _z_level_count(self): |
|
|
return self._image_count / self._sequence_count |
|
|
return self._image_count / self._sequence_count |
|
@ -74,25 +71,6 @@ class BaseNd2(object): |
|
|
""" |
|
|
""" |
|
|
return sum(self._metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx']['']['pItemValid']) |
|
|
return sum(self._metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx']['']['pItemValid']) |
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def channels(self): |
|
|
|
|
|
metadata = self._metadata['ImageMetadataSeq']['SLxPictureMetadata']['sPicturePlanes'] |
|
|
|
|
|
try: |
|
|
|
|
|
validity = self._metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx']['']['ppNextLevelEx']['']['pItemValid'] |
|
|
|
|
|
except KeyError: |
|
|
|
|
|
# If none of the channels have been deleted, there is no validity list, so we just make one |
|
|
|
|
|
validity = [True for i in metadata] |
|
|
|
|
|
# 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), valid in zip(sorted(metadata['sPlaneNew'].items()), validity): |
|
|
|
|
|
if not valid: |
|
|
|
|
|
continue |
|
|
|
|
|
name = chan['sDescription'] |
|
|
|
|
|
exposure_time = metadata['sSampleSetting'][label]['dExposureTime'] |
|
|
|
|
|
camera = metadata['sSampleSetting'][label]['pCameraSetting']['CameraUserName'] |
|
|
|
|
|
yield Channel(name, camera, exposure_time) |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
@property |
|
|
def channel_offset(self): |
|
|
def channel_offset(self): |
|
|
if self._channel_offset is None: |
|
|
if self._channel_offset is None: |
|
|