-
Notifications
You must be signed in to change notification settings - Fork 19
improvment of the cellvizio reader: reading meta informations from hexcode directly #150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
f81612a
1098f94
bc332f7
c1be0f3
797b2e7
abbe918
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -52,36 +52,35 @@ def __init__(self,filename): | |||||||||||||||||||||||||||||||||||||||||||
| self.fi = fileinfo() | ||||||||||||||||||||||||||||||||||||||||||||
| self.fileHandle = open(filename, 'rb'); | ||||||||||||||||||||||||||||||||||||||||||||
| self.fileHandle.seek(5) # we find the FPS at position 05 | ||||||||||||||||||||||||||||||||||||||||||||
| fFPSByte = self.fileHandle.read(4) | ||||||||||||||||||||||||||||||||||||||||||||
| self.fps = struct.unpack('>f', fFPSByte)[0] | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # fFPSByte = self.fileHandle.read(4) | ||||||||||||||||||||||||||||||||||||||||||||
| # self.fps = struct.unpack('>f', fFPSByte)[0] | ||||||||||||||||||||||||||||||||||||||||||||
| self.fileHandle.seek(10) # we find the image size at position 10 | ||||||||||||||||||||||||||||||||||||||||||||
| fSizeByte = self.fileHandle.read(4) | ||||||||||||||||||||||||||||||||||||||||||||
| self.fi.size = int.from_bytes(fSizeByte, byteorder='big', signed=True) | ||||||||||||||||||||||||||||||||||||||||||||
| self.fi.nImages=1000 | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| self.fi.width = 576 | ||||||||||||||||||||||||||||||||||||||||||||
| if ((self.fi.size/(2*self.fi.width))%2!=0): | ||||||||||||||||||||||||||||||||||||||||||||
| self.fi.width=512 | ||||||||||||||||||||||||||||||||||||||||||||
| self.fi.height=int(self.fi.size/(2*self.fi.width)) | ||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||
| self.fi.height=int(self.fi.size/(2*self.fi.width)) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| self.filestats = stat(self.fileName) | ||||||||||||||||||||||||||||||||||||||||||||
| self.fi.nImages=1000 | ||||||||||||||||||||||||||||||||||||||||||||
| self.fi.nImages = int((self.filestats.st_size-self.fi.offset) / (self.fi.size+self.fi.gapBetweenImages)) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| self.numberOfFrames = self.fi.nImages | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| meta = self.getMostRelevantMetaInfo() | ||||||||||||||||||||||||||||||||||||||||||||
| self.fi.width = int(meta.get('width', 0)) | ||||||||||||||||||||||||||||||||||||||||||||
| self.fi.height = int(meta.get('height', 0)) | ||||||||||||||||||||||||||||||||||||||||||||
| self.fps = float(meta.get('framerate', 0)) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| self.geometry_imsize = [self.fi.height, self.fi.width] | ||||||||||||||||||||||||||||||||||||||||||||
| self.imsize = [self.fi.height, self.fi.width] | ||||||||||||||||||||||||||||||||||||||||||||
| self.geometry_tilesize = [(self.fi.height, self.fi.width)] | ||||||||||||||||||||||||||||||||||||||||||||
| self.geometry_rows = [1] | ||||||||||||||||||||||||||||||||||||||||||||
| self.geometry_columns = [1] | ||||||||||||||||||||||||||||||||||||||||||||
| self.levels = [1] | ||||||||||||||||||||||||||||||||||||||||||||
| self.channels = 1 | ||||||||||||||||||||||||||||||||||||||||||||
| self.mpp_x = 250/576 # approximate number for gastroflex, 250 ym field of view, 576 px | ||||||||||||||||||||||||||||||||||||||||||||
| self.mpp_y = 250/576 | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| self.fovx = float(meta.get('fovx', 250)) | ||||||||||||||||||||||||||||||||||||||||||||
| self.fovy = float(meta.get('fovy', 250)) | ||||||||||||||||||||||||||||||||||||||||||||
| print(f"fovx: {self.fovx}, fovy: {self.fovy}") | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| self.mpp_x = self.fovx/self.fi.width # approximate number for gastroflex, 250 ym field of view, 576 px | ||||||||||||||||||||||||||||||||||||||||||||
| self.mpp_y = self.fovy/self.fi.height | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+79
to
+80
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # generate circular mask for this file | ||||||||||||||||||||||||||||||||||||||||||||
| self.circMask = circularMask(self.fi.width,self.fi.height, self.fi.width-2).mask | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -91,6 +90,44 @@ def __init__(self,filename): | |||||||||||||||||||||||||||||||||||||||||||
| openslide.PROPERTY_NAME_MPP_Y: self.mpp_y, | ||||||||||||||||||||||||||||||||||||||||||||
| openslide.PROPERTY_NAME_OBJECTIVE_POWER:20, | ||||||||||||||||||||||||||||||||||||||||||||
| openslide.PROPERTY_NAME_VENDOR: 'MKT'} | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| def getMetaInfo(self): | ||||||||||||||||||||||||||||||||||||||||||||
| # 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 | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| # 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 | |
| # the meta information in the MKT file always starts with "allowed_egain_eoffset_pairs=" |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the '<CEND' marker is not found, find() will return -1, resulting in an incorrect slice that includes content from the start position to near the beginning of the file. Add validation to check if metaEnd is -1 and handle this case appropriately.
| metaStart = fileContent.rfind(b'allowed_egain_eoffset_pairs=') | |
| metaEnd = fileContent.find(b'<CEND', metaStart) | |
| metaInfo = fileContent[metaStart:metaEnd].decode('utf-8') | |
| metaStart = fileContent.rfind(b'allowed_egain_eoffset_pairs=') | |
| if metaStart == -1: | |
| # expected metadata start marker not found | |
| self.fileHandle.close() | |
| print("Meta information start marker 'allowed_egain_eoffset_pairs=' not found.") | |
| return "" | |
| metaEnd = fileContent.find(b'<CEND', metaStart) | |
| if metaEnd == -1: | |
| # expected metadata end marker not found | |
| self.fileHandle.close() | |
| print("Meta information end marker '<CEND' not found.") | |
| return "" | |
| metaInfo = fileContent[metaStart:metaEnd].decode('utf-8') | |
| self.fileHandle.close() |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The decode operation assumes UTF-8 encoding but provides no error handling if the metadata contains invalid UTF-8 sequences. Consider adding error handling with errors='ignore' or errors='replace' parameter, or catching UnicodeDecodeError to handle corrupted metadata gracefully.
| metaInfo = fileContent[metaStart:metaEnd].decode('utf-8') | |
| metaInfo = fileContent[metaStart:metaEnd].decode('utf-8', errors='replace') |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no error handling if the metadata marker is not found. If rfind() returns -1 (not found), the subsequent find() and slice operations will produce incorrect results. Add validation to check if metaStart is -1 and handle this case appropriately, potentially falling back to default values or raising a meaningful error.
| metaStart = fileContent.rfind(b'allowed_egain_eoffset_pairs=') | |
| metaEnd = fileContent.find(b'<CEND', metaStart) | |
| metaInfo = fileContent[metaStart:metaEnd].decode('utf-8') | |
| print(f"Meta information found: ") | |
| print(metaInfo) | |
| metaStart = fileContent.rfind(b'allowed_egain_eoffset_pairs=') | |
| if metaStart == -1: | |
| # metadata marker not found; return empty meta info to avoid invalid slicing | |
| print("Meta information marker 'allowed_egain_eoffset_pairs=' not found in file.") | |
| self.fileHandle.close() | |
| return "" | |
| metaEnd = fileContent.find(b'<CEND', metaStart) | |
| if metaEnd == -1 or metaEnd <= metaStart: | |
| # end marker not found or invalid; return empty meta info to avoid invalid slicing | |
| print("Meta information end marker '<CEND' not found or invalid in file.") | |
| self.fileHandle.close() | |
| return "" | |
| metaInfo = fileContent[metaStart:metaEnd].decode('utf-8') | |
| print(f"Meta information found: ") | |
| print(metaInfo) | |
| self.fileHandle.close() |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The split logic is fragile and will fail if a line contains multiple '=' characters. For example, a line like "key=value=something" would be incorrectly parsed. Consider using split('=', 1) to split only on the first occurrence of '=', or use a more robust parsing approach.
| key, value = line.split('=') | |
| key, value = line.split('=', 1) |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key from the split operation is not stripped of whitespace, which could cause comparison failures if there's any leading or trailing whitespace in the metadata. Consider using key.strip() when comparing against expected key names to make the parsing more robust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally not a problem in MKT File format.
Uh oh!
There was an error while loading. Please reload this page.