bilayer-containers / bilayers

https://bilayers.org
3 stars 1 forks source link

IndexError when processing single-page TIFF file in cellpose CLI due to multi-page assumption #69

Closed rajavishah closed 4 weeks ago

rajavishah commented 4 weeks ago

Please take a screenshot of this error and raise an issue at the Bilayers repository on GitHub.Command failed with error: Traceback (most recent call last):\n File "/opt/conda/lib/python3.9/runpy.py", line 197, in _run_module_as_main\n return _run_code(code, main_globals, None,\n File "/opt/conda/lib/python3.9/runpy.py", line 87, in _run_code\n exec(code, run_globals)\n File "/opt/conda/lib/python3.9/site-packages/cellpose/main.py", line 368, in \n main()\n File "/opt/conda/lib/python3.9/site-packages/cellpose/main.py", line 250, in main\n image = io.imread(image_name)\n File "/opt/conda/lib/python3.9/site-packages/cellpose/io.py", line 87, in imread\n img = tif.asarray()\n File "/opt/conda/lib/python3.9/site-packages/tifffile/tifffile.py", line 4267, in asarray\n result = stack_pages(pages, out=out, maxworkers=maxworkers)\n File "/opt/conda/lib/python3.9/site-packages/tifffile/tifffile.py", line 22179, in stack_pages\n for index, page in enumerate(pages):\n File "/opt/conda/lib/python3.9/site-packages/tifffile/tifffile.py", line 11990, in iter\n yield pages[index + i]\n File "/opt/conda/lib/python3.9/site-packages/tifffile/tifffile.py", line 7540, in getitem\n return getitem(key)\n File "/opt/conda/lib/python3.9/site-packages/tifffile/tifffile.py", line 7491, in _getitem\n raise IndexError(f\'index {key} out of range({len(pages)})\')\nIndexError: index 1 out of range(1)\n\n\n

What I understood from the error is - Cellpose tried to access a second page (index 1) in a TIFF file that has only one page (index 0). This indicates that cellpose was expecting either a multi-page TIFF file or it mistakenly attempted to handle the single-page TIFF as a multi-page one.

How to confirm if it's single page? So, to confirm whether its single page -

import tifffile

with tifffile.TiffFile('/path/to/file') as tif:
    num_pages = len(tif.pages)
    print(f"The image has {num_pages} page(s).”) 

Cellpose code Traced the error to the imread function in cellpose, which uses tifffile.TiffFile. Here, the code calls tif.asarray() without a clear distinction between single-page and multi-page TIFFs. The pre-condition if ltif < 10: suggests that it shouldn't be a problem even that's a single page tiff. Hence, it should work fine in either case.

tif.asarray() attempts to stack pages, even when only one page exists, resulting in IndexError: index 1 out of range(1).

But when we run the whole function independently

import tifffile
import numpy as np
from tqdm import tqdm

def read_tiff_image():
    with tifffile.TiffFile("/path/to/file.tif") as tif:
        ltif = len(tif.pages)
        print(ltif)
        try:
            full_shape = tif.shaped_metadata[0]["shape"]
        except:
            try:
                page = tif.series[0][0]
                print("Is it failing in try?")
                full_shape = tif.series[0].shape
                print("At the end of try?")
            except:
                ltif = 0
        if ltif < 10:
            print("Is it coming before asarray?")
            img = tif.asarray()
            print("Is it coming after asarray?")
        else:
            print("Is it coming in the starting of else?")
            page = tif.series[0][0]
            shape, dtype = page.shape, page.dtype
            ltif = int(np.prod(full_shape) / np.prod(shape))
            print(f"reading tiff with {ltif} planes")
            img = np.zeros((ltif, *shape), dtype=dtype)
            for i, page in enumerate(tqdm(tif.series[0])):
                img[i] = page.asarray()
            img = img.reshape(full_shape)
            print("End of else")
    return img

image_data = read_tiff_image()

# Check the result
print("Image data shape:", image_data.shape)

It works perfectly fine.

So, I am not sure why the discrepancy - and when Shata tried running the image to Cellpose GUI or try running with runcellpose module it worked fine.

Maybe a way around? Since png are naturally single page - we tried converting tif to png with the below code

from PIL import Image

# Open the TIFF image
img = Image.open('/path/to/file.tif')

# Save it as a PNG
img.save('/path/where/to/save.png', format='PNG')

And passing the png image to bilayersXcellpose docker image doesn't give the error


Solution --

But, ultimately @bethac07 checked it's the tiffile's version problem not bilayers. So, hopefully bumping the cellpose's docker version to 2.3.2 works fine! tiffile in cellprofiler/runcellpose_no_pretrained:0.1 is 2023.4.12 tiffile in cellprofiler/runcellpose_no_pretrained:2.3.2 is 2024.8.24