ZEISS / pylibczirw

A simple and easy-to-use Python wrapper for libCZI - a cross-platform C++ library intended for providing read and write access to CZI documents.
https://zeiss.github.io/pylibczirw/
GNU Lesser General Public License v3.0
13 stars 5 forks source link

Access CZI "attachments" (i.e. slide label image, slide / tissue preview, etc.) #38

Open alexbaras opened 3 months ago

alexbaras commented 3 months ago

From my perspective the pylibczirw module is one of the only modules that allows for writing czi files. As such, I think it would be important to enable both reading and writing of czi files to include various associated images like slide label and slide / tissue preview.

For now I use czifile for access to the "attachments". I've posted that code example below. I suspect this example and the czifile module code base could be put together to achieve the desired effect.

-Alex

get czi attachments

with czifile.CziFile(czi_files[i_file]) as czi:

get attachment objects

attachments = {a.attachment_entry.name: {'obj': a} for a in czi.attachments()}

# get label img
attachments['Label']['obj']._fh.seek(attachments['Label']['obj'].data_offset)
with BytesIO(attachments['Label']['obj']._fh.read(attachments['Label']['obj'].data_size)) as fh:
    attachments['Label']['img'] = czifile.CziFile(fh).asarray()
    attachments['Label']['img'] = 255. * attachments['Label']['img'][0].astype(np.float32) / 4096.
    attachments['Label']['img'] = np.clip(np.round(attachments['Label']['img'], 0), a_min=0, a_max=255).astype(np.uint8)

# get label img
attachments['SlidePreview']['obj']._fh.seek(attachments['SlidePreview']['obj'].data_offset)
with BytesIO(attachments['SlidePreview']['obj']._fh.read(attachments['SlidePreview']['obj'].data_size)) as fh:
    attachments['SlidePreview']['img'] = czifile.CziFile(fh).asarray()
    attachments['SlidePreview']['img'] = 255. * attachments['SlidePreview']['img'][0].astype(np.float32) / 4096.
    attachments['SlidePreview']['img'] = np.clip(np.round(attachments['SlidePreview']['img'], 0), a_min=0, a_max=255).astype(np.uint8)
horsto commented 2 months ago

Hi Alex, I followed your example above to get timestamp information from my czi file. At least I think this might be the only way to retrieve that data for every frame.

from io import BytesIO
import czifile

with czifile.CziFile(czi_file.as_posix()) as f:

    # get attachment objects
    attachments = {a.attachment_entry.name: {'obj': a} for a in f.attachments()}
    attachments['TimeStamps']['obj']._fh.seek(attachments['TimeStamps']['obj'].data_offset)
    with BytesIO(attachments['TimeStamps']['obj']._fh.read(attachments['TimeStamps']['obj'].data_size)) as fh:
        attachments['TimeStamps']['img'] = czifile.CziFile(fh).asarray()
Screenshot 2024-09-08 at 10 40 46

However I am running into this error

ValueError                                Traceback (most recent call last)
Cell In[1422], line 8
      5 attachments['TimeStamps']['obj']._fh.seek(attachments['TimeStamps']['obj'].data_offset)
      6 with BytesIO(attachments['TimeStamps']['obj']._fh.read(attachments['TimeStamps']['obj'].data_size)) as fh:
----> 8     attachments['TimeStamps']['img'] = czifile.CziFile(fh).asarray()

File [~/miniconda3/envs/suite2p/lib/python3.9/site-packages/czifile/czifile.py:266](http://localhost:8888/lab/tree/octo_code/calcium_imaging_slices/~/miniconda3/envs/suite2p/lib/python3.9/site-packages/czifile/czifile.py#line=265), in CziFile.__init__(self, arg, multifile, filesize, detectmosaic)
    264 try:
    265     if self._fh.read(10) != b'ZISRAWFILE':
--> 266         raise ValueError('not a CZI file')
    267     self.header = Segment(self._fh, 0).data()
    268 except Exception:

ValueError: not a CZI file

Do you have any ideas on how to solve that?

sebi06 commented 1 month ago

Hi all,

currently the functionality of redaing attachments & timestamps is not supported from pylibCZIrw. The typical workaround is to use other existing libraries like czifile or aicspylibczito read the attachments.

Example (use at your own risk) can be found here:

https://github.com/sebi06/czitools/blob/main/demo/scripts/read_attachment_images.py

(very similar appaoch to what @alexbaras posted above)

https://github.com/sebi06/czitools/blob/main/demo/notebooks/read_czi_metadata.ipynb

But I will add you feature request to our backlog.

horsto commented 1 month ago

Thank you @sebi06 . I found the solution for my problem here: https://github.com/cgohlke/czifile/issues/11 - this worked perfectly for me. Just posting it here in case others stumble over the same problem.