60 lines
2.5 KiB
Python
60 lines
2.5 KiB
Python
from abc import ABC
|
|
from itertools import product
|
|
from pathlib import Path
|
|
from struct import unpack
|
|
from warnings import warn
|
|
|
|
import numpy as np
|
|
from ome_types import model
|
|
from tifffile import TiffFile
|
|
|
|
from .. import AbstractReader
|
|
|
|
|
|
class Reader(AbstractReader, ABC):
|
|
""" Can read some tif files written with Fiji which are broken because Fiji didn't finish writing. """
|
|
priority = 90
|
|
do_not_pickle = 'reader'
|
|
|
|
@staticmethod
|
|
def _can_open(path):
|
|
if isinstance(path, Path) and path.suffix in ('.tif', '.tiff'):
|
|
with TiffFile(path) as tif:
|
|
return tif.is_imagej and not tif.is_bigtiff
|
|
else:
|
|
return False
|
|
|
|
def __frame__(self, c, z, t): # Override this, return the frame at c, z, t
|
|
self.reader.filehandle.seek(self.offset + t * self.count)
|
|
return np.reshape(unpack(self.fmt, self.reader.filehandle.read(self.count)), self.base_shape['yx'])
|
|
|
|
def open(self):
|
|
warn(f'File {self.path.name} is probably damaged, opening with fijiread.')
|
|
self.reader = TiffFile(self.path)
|
|
assert self.reader.pages[0].compression == 1, 'Can only read uncompressed tiff files.'
|
|
assert self.reader.pages[0].samplesperpixel == 1, 'Can only read 1 sample per pixel.'
|
|
self.offset = self.reader.pages[0].dataoffsets[0] # noqa
|
|
self.count = self.reader.pages[0].databytecounts[0] # noqa
|
|
self.bytes_per_sample = self.reader.pages[0].bitspersample // 8 # noqa
|
|
self.fmt = self.reader.byteorder + self.count // self.bytes_per_sample * 'BHILQ'[self.bytes_per_sample - 1] # noqa
|
|
|
|
def close(self):
|
|
self.reader.close()
|
|
|
|
def get_ome(self):
|
|
size_y, size_x = self.reader.pages[0].shape
|
|
size_c, size_z = 1, 1
|
|
size_t = int(np.floor((self.reader.filehandle.size - self.reader.pages[0].dataoffsets[0]) / self.count))
|
|
pixel_type = model.PixelType(self.reader.pages[0].dtype.name)
|
|
ome = model.OME()
|
|
ome.instruments.append(model.Instrument())
|
|
ome.images.append(
|
|
model.Image(
|
|
pixels=model.Pixels(
|
|
size_c=size_c, size_z=size_z, size_t=size_t, size_x=size_x, size_y=size_y,
|
|
dimension_order='XYCZT', type=pixel_type),
|
|
objective_settings=model.ObjectiveSettings(id='Objective:0')))
|
|
for c, z, t in product(range(size_c), range(size_z), range(size_t)):
|
|
ome.images[0].pixels.planes.append(model.Plane(the_c=c, the_z=z, the_t=t, delta_t=0))
|
|
return ome
|