Skip to content

Commit 485d085

Browse files
authored
Merge pull request #150 from DeepMicroscopy/improvment_cellvizio.py
improvment of the cellvizio reader: reading meta informations from hexcode directly
2 parents 768a367 + abbe918 commit 485d085

File tree

1 file changed

+78
-17
lines changed

1 file changed

+78
-17
lines changed

exact/util/cellvizio.py

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,36 +52,33 @@ def __init__(self,filename):
5252
self.fi = fileinfo()
5353
self.fileHandle = open(filename, 'rb');
5454
self.fileHandle.seek(5) # we find the FPS at position 05
55-
fFPSByte = self.fileHandle.read(4)
56-
self.fps = struct.unpack('>f', fFPSByte)[0]
57-
58-
5955
self.fileHandle.seek(10) # we find the image size at position 10
6056
fSizeByte = self.fileHandle.read(4)
6157
self.fi.size = int.from_bytes(fSizeByte, byteorder='big', signed=True)
62-
self.fi.nImages=1000
63-
64-
self.fi.width = 576
65-
if ((self.fi.size/(2*self.fi.width))%2!=0):
66-
self.fi.width=512
67-
self.fi.height=int(self.fi.size/(2*self.fi.width))
68-
else:
69-
self.fi.height=int(self.fi.size/(2*self.fi.width))
70-
7158
self.filestats = stat(self.fileName)
59+
self.fi.nImages=1000
7260
self.fi.nImages = int((self.filestats.st_size-self.fi.offset) / (self.fi.size+self.fi.gapBetweenImages))
73-
7461
self.numberOfFrames = self.fi.nImages
75-
62+
63+
meta = self.getMostRelevantMetaInfo()
64+
self.fi.width = int(meta.get('width', 0))
65+
self.fi.height = int(meta.get('height', 0))
66+
self.fps = float(meta.get('framerate', 0))
67+
7668
self.geometry_imsize = [self.fi.height, self.fi.width]
7769
self.imsize = [self.fi.height, self.fi.width]
7870
self.geometry_tilesize = [(self.fi.height, self.fi.width)]
7971
self.geometry_rows = [1]
8072
self.geometry_columns = [1]
8173
self.levels = [1]
8274
self.channels = 1
83-
self.mpp_x = 250/576 # approximate number for gastroflex, 250 ym field of view, 576 px
84-
self.mpp_y = 250/576
75+
76+
self.fovx = float(meta.get('fovx', 250))
77+
self.fovy = float(meta.get('fovy', 250))
78+
print(f"fovx: {self.fovx}, fovy: {self.fovy}")
79+
self.mpp_x = self.fovx/self.fi.width # approximate number for gastroflex, 250 ym field of view, 576 px
80+
self.mpp_y = self.fovy/self.fi.height
81+
8582

8683
# generate circular mask for this file
8784
self.circMask = circularMask(self.fi.width,self.fi.height, self.fi.width-2).mask
@@ -91,6 +88,52 @@ def __init__(self,filename):
9188
openslide.PROPERTY_NAME_MPP_Y: self.mpp_y,
9289
openslide.PROPERTY_NAME_OBJECTIVE_POWER:20,
9390
openslide.PROPERTY_NAME_VENDOR: 'MKT'}
91+
92+
93+
def getMetaInfo(self):
94+
# the meta information at the MKT file always starts with "00616C6C 6F776564 5F656761 696E5F65 6F666673 65745F70 61697273 3D" or allowed_egain_eoffset_pairs= in the hex code
95+
# we need to read the whole file to find the meta information
96+
with open(self.fileName, 'rb') as f:
97+
fileContent = f.read()
98+
# find start position with fileContent.find(b'allowed_egain_eoffset_pairs=') that searches for the byte sequence
99+
metaStart = fileContent.rfind(b'allowed_egain_eoffset_pairs=')
100+
metaEnd = fileContent.find(b'<CEND', metaStart)
101+
metaInfo = fileContent[metaStart:metaEnd].decode('utf-8')
102+
return metaInfo
103+
104+
105+
def getMostRelevantMetaInfo(self):
106+
metaInfo = self.getMetaInfo()
107+
relevantInfo = {}
108+
109+
for line in metaInfo.split('\n'):
110+
if "=" not in line:
111+
continue
112+
key, value = line.split('=')
113+
if key == 'framerate':
114+
value_str = value.strip()
115+
try:
116+
framerate = float(value_str)
117+
except ValueError:
118+
print(f"Warning: invalid framerate value in metadata: {value_str!r}")
119+
continue
120+
if framerate <= 0:
121+
print(f"Warning: non-positive framerate value in metadata: {framerate}")
122+
continue
123+
relevantInfo['framerate'] = value_str
124+
relevantInfo['duration_seconds'] = self.fi.nImages / framerate
125+
elif key == 'width':
126+
relevantInfo['width'] = value
127+
elif key == 'height':
128+
relevantInfo['height'] = value
129+
elif key == 'fovx':
130+
relevantInfo['fovx'] = value
131+
elif key == 'fovy':
132+
relevantInfo['fovy'] = value
133+
elif key == 'patient_id':
134+
relevantInfo['patient_id'] = value
135+
136+
return relevantInfo
94137

95138
def _2_init__(self, filename):
96139

@@ -137,7 +180,25 @@ def _2_init__(self, filename):
137180

138181
self.circMask = circularMask(self.fi.width,self.fi.height, self.fi.width-2).mask
139182

183+
@property
184+
def meta_data(self) -> dict:
185+
# Cache metadata to avoid repeated file I/O and parsing.
186+
if not hasattr(self, "_meta_data_cache"):
187+
self._meta_data_cache = self.getMostRelevantMetaInfo()
188+
return self._meta_data_cache
140189

190+
@property
191+
def meta_data_dict(self) -> dict:
192+
meta_data_dict = {
193+
'width': 'Image width (pixels)',
194+
'height': 'Image height (pixels)',
195+
'framerate': 'Frame rate (fps)',
196+
'duration_seconds': 'Duration (seconds)',
197+
'patient_id': 'Patient ID',
198+
'fovx': 'Field of view x (micrometers)',
199+
'fovy': 'Field of view y (micrometers)'
200+
}
201+
return meta_data_dict
141202

142203
@property
143204
def seriesInstanceUID(self) -> str:

0 commit comments

Comments
 (0)