Skip to content
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

"free(): invalid size" crash trying to call CziFile.read_mosaic() #70

Open
markemus opened this issue Jan 15, 2021 · 22 comments
Open

"free(): invalid size" crash trying to call CziFile.read_mosaic() #70

markemus opened this issue Jan 15, 2021 · 22 comments

Comments

@markemus
Copy link

I'm trying to read a mosaic czi file but it crashes consistently when I call img.read_mosaic(). img.read_image() works, but returns a stack of (overlapping?) mosaic tiles so I would prefer to get read_mosaic working.

import aicspylibczi as acz
  ...: 
  ...: import numpy as np
  ...: import matplotlib.pyplot as plt
  ...: 
  ...: 
  ...: path = "/home/markemus/data/dev/Zeiss/2020_11_22__17_01__0165.czi"
  ...: img = acz.CziFile(path)
  ...: print(img.dims)
  ...: print(img.dims_shape())
  ...: y = img.read_mosaic(C=0)
  ...: 

results:

SCMYX
[{'X': (0, 1600), 'Y': (0, 1200), 'C': (0, 1), 'M': (0, 2203), 'S': (0, 1)}]
free(): invalid size

I tried specifying S=0, but the program told me that S is not used for mosaic images.
I tried again reading only a subregion:

y = img.read_mosaic(region=(100,100,100,100), C=0)
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/IPython/core/interactiveshell.py", line 2882, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-6-ef2c2c78f23d>", line 1, in <module>
    y = img.read_mosaic(region=(100,100,100,100), C=0)
  File "/home/markemus/.local/lib/python3.6/site-packages/aicspylibczi/CziFile.py", line 458, in read_mosaic
    img = self.reader.read_mosaic(plane_constraints, scale_factor, region)
_aicspylibczi.PylibCZI_RegionSelectionException: Requirement violated requested region is not a subset of the defined image! 
	 (100,100,100,100) ⊄ (-162802,9720,93906,55354)
	Requested region not in image!

This looks like an integer overflow problem? I searched previous issues but couldn't find anyone who had this before. Is there a bug or am I doing something incorrect?

@heeler
Copy link
Member

heeler commented Jan 15, 2021

Is there any chance you can share the file you are trying to read solely for the purpose of debugging?
[email protected]

@heeler
Copy link
Member

heeler commented Jan 15, 2021

So I just did a few local sanity checks with a mosaic file I have.

The output

SCMYX
[{'X': (0, 1600), 'Y': (0, 1200), 'C': (0, 1), 'M': (0, 2203), 'S': (0, 1)}]

suggests that dims and dims_shape() are working correctly.

The free(): invalid size I have not seen before but it could be you're exhausting the local memory available.

If that's the case then you are on the right track:
y = img.read_mosaic(region=(100,100,100,100), C=0)
the output line (100,100,100,100) ⊄ (-162802,9720,93906,55354) is trying to tell you what's wrong.
The coordinate system is from the file itself and the region box is defined by (x0, y0, width, height)
The origin for the image is (-162802, 9720) with width=93906, h=55354.

If you would try:
y = img.read_mosaic(region=(-162800,9800,100,100), C=0)

The other thing to try would be
y = img.read_mosaic(C=0, scale_factor=0.05)

@markemus
Copy link
Author

@heeler Thanks, that got me further. I believe you're correct about it running out of memory. However I ran into another issue.

I changed it to:

bbox = img.scene_bounding_box()
y = img.read_mosaic(region=(bbox[0],bbox[1],30000,30000), C=0, scale_factor=.1)
plt.imshow(y[0], cmap="gray")
plt.show()

The resulting image looks like a bunch of tiles overlaid on each other.

https://imgur.com/f4jqwxs

I exported to tiff using bioformat's bfconvert and I can confirm that in the exported tiff it doesn't look like that. Any advice?

@heeler
Copy link
Member

heeler commented Jan 19, 2021

So the code for stitching together the mosaic files is from Zeiss, specifically libCZI. My understanding is that Mosaic files can be acquired in various ways with gaps between the image acquisitions and imaging settings can be changed across the image. That may be what you're seeing but it's hard for me to know. You can use read_image will give you the (img(np.ndarray), dict of dims). That will have an M dimension which is an index for the tiles in the plane (it's the m_index).

  1. how do you expect the image to appear? Can you share images of what you expect vs what you're getting? I'm not sure I can fix it but I'll have a look.

  2. what is the pixel_type of the image?

  3. when I open the test file in the repo aicspylibczi/tests/resources/mosaic_test.czi
    it seems to render correctly. Does that work in your environment? Snapshot below.

Screen Shot 2021-01-19 at 11 58 06 AM

@heeler
Copy link
Member

heeler commented Jan 29, 2021

@markemus Can you share the image file with me that is causing this or was this resolved?
Also, could you check the version you have installed? I reimplemented the core memory management somewhere after 2.6 and there were bugs that crept in. If you upgrade to 2.8 and it still has this problem it would be incredibly helpful to have this file to debug with. Thanks.

@markemus
Copy link
Author

@heeler Unfortunately I can't share the file- it's proprietary data and we don't currently have a way to anonymize czis. The version I was using was 2.7.7. I haven't had a chance to test another file, but I will try to do so and report back- feel free to remind me.

@heeler
Copy link
Member

heeler commented Jan 29, 2021

@markemus Thanks for letting me know. Details wise

  1. what's the pixel type?
  2. what does dims_shape() return?

I doubt upgrading to 2.8.0 will fix it but it might be worth trying.

If you are able to create a file that you can share I would really appreciate it. If you don't have time to create a file if you could explain acquisition settings I can ask our microscopy team to attempt to reproduce it for me.

Thanks

@rg314
Copy link

rg314 commented Mar 2, 2022

Any updates on this? I have the same issues as reported above.

@evamaxfield
Copy link
Collaborator

Hey @rg314 can you answer the above questions:

what's the pixel type?
what does dims_shape() return?

It may be that your machine simply doesn't have enough memory to fit the whole mosaic in memory.

@evamaxfield
Copy link
Collaborator

evamaxfield commented Mar 2, 2022

And re above, we dont have any test data ourselves to work on the issue. We cant debug something we cant reproduce. Can you share your file somehow?

@rg314
Copy link

rg314 commented Mar 2, 2022

Hey @JacksonMaxfield

Pixel type:

czi.pixel_type
'gray16'

Shape:

czi = CziFile(pth_fl)
czi.get_dims_shape()
[{'X': (...), 'Y': (...), 'C': (...), 'M': (...), 'S': (...)}, {'X': (...), 'Y': (...), 'C': (...), 'M': (...), 'S': (...)}]
special variables
function variables
0:{'X': (0, 1920), 'Y': (0, 2040), 'C': (0, 5), 'M': (0, 308), 'S': (0, 1)}
1:{'X': (0, 1920), 'Y': (0, 2040), 'C': (0, 5), 'M': (0, 324), 'S': (1, 2)}
len():2

The following code works

SCALE_FACTOR=0.1
czi.read_mosaic(C=0, scale_factor=SCALE_FACTOR)

In terms of memory I think things are fine as I can get the image into an np.array and manipulate given I use the scale_factor arg. But FYI

(base) ryan@ryan:~$ grep MemTotal /proc/meminfo
MemTotal:       65757720 kB

If I run:

czi.read_mosaic(C=0, scale_factor=0.1, region=(0,0,1000,1000))

Then I get the following error

_aicspylibczi.PylibCZI_RegionSelectionException: Requirement violated requested region is not a subset of the defined image! 
         (0,0,1000,1000) ⊄ (-138240,16503,79744,44309)
        Requested region not in image

Running the following code works fine.

czi.read_mosaic(C=0, scale_factor=0.1, region=(-138240,16503,79744,44309))

When I try czi.read_mosaic(C=0, scale_factor=0.1, region=(-138240-10000,16503,79744,44309)) I get the same error as before. However, ff I comment out the following exception and rebuild it works

throw RegionSelectionException(in_box_, czi_box_, "Requested region not in image!");

However, I have to calculate the pos from x0=-138240,y0=16503 which is strange. Not sure why the image is indexed in this way.

Let me know if this help. I will need to check with client if I can send over an example image.

@evamaxfield
Copy link
Collaborator

Thanks for all the info!

Hmmm. I think it may be indexed by the overall stage position? But that is a good question.

cc @toloudis any ideas?

@rg314
Copy link

rg314 commented Mar 2, 2022

Cheers @JacksonMaxfield that was also my guess ;)

@heeler
Copy link
Member

heeler commented Mar 2, 2022

I'm rusty on this but if I remember correctly it's the format that Zeiss's libczi takes. It could possibly translate into a more sensible system but I was hesitant to depart from what Zeiss used and in their system (-138240,16503) is the origin of the image.

@toloudis
Copy link
Collaborator

toloudis commented Mar 2, 2022

Having any image to repro with would help. I'm not sure what's going on with these coordinates or how a user would know what coordinates to use. I'm prepared to do a deep dive when we can repro.

@heeler
Copy link
Member

heeler commented Mar 2, 2022

@toloudis, the documentation get_mosaic_bounding_box() should give you the origin and the size of the mosaic so you know where to start from. I can't comment on the logic behind Zeiss's origin. I do wonder what Zen does.

@rg314
Copy link

rg314 commented Mar 2, 2022

Okay, I'm going to get the client in on the thread. I’m sure we can get something sorted.

@r03ert0
Copy link

r03ert0 commented Jun 12, 2022

Hey! I have a czi mosaic that shows the error and that I'm happy to share :)
It's 2.77GB, though... If that's ok, I can put it on Zenodo for example.
Would that work?

print(dimensions)
print(czi.dims)
print(czi.is_mosaic())
print(czi.pixel_type)

[{'A': (0, 3), 'X': (0, 1600), 'Y': (0, 1200), 'C': (0, 1), 'M': (0, 27492), 'S': (0, 1), 'B': (0, 1)}]
BSCMYXA
True
bgr24

@markemus
Copy link
Author

Wow, I completely forgot about this issue, so sorry! As a backup for @r03ert0 I will try to find an image I can send you as well. Roberto, do not depend on me, clearly I am unreliable. Let's get these people some examples.

@rg314
Copy link

rg314 commented Jun 13, 2022

Excellent thanks @r03ert0. We weren't able to get shareable data from our client.

@heeler
Copy link
Member

heeler commented Jun 13, 2022

Hi @r03ert0 If you can share the file on Zenodo I'll have a look and see if I can figure out what's going wrong.
Thanks for this.

@r03ert0
Copy link

r03ert0 commented Jun 13, 2022

here's the link:
https://zenodo.org/record/6637864

loading the whole image doesn't work, but loading subregions does:

from matplotlib import pyplot as plt
from aicspylibczi import CziFile
from pathlib import Path
pth = Path("ferret-slices-mosaic-encoding.czi")
czi = CziFile(pth)
d = czi.get_dims_shape()
bbox = czi.get_mosaic_bounding_box()

plt.figure(figsize=(20,15))
for row in range(0, 5):
    for col in range(0, 5):
        x = bbox.x + int(col*bbox.w/5)
        y = bbox.y + int(row*bbox.h/5)
        w = int(bbox.w/5)-1000 # -1000 just to make sure the region is well inside...
        h = int(bbox.h/5)-1000 # ... it doesn't really work, because the last tile throws an error anyway
        img = czi.read_mosaic(
            C=0,
            scale_factor=1/8,
            region=(x, y, w, h)
        )
        plt.subplot(5, 5, row*5 + col + 1)
        plt.imshow(img[0,:,:,:])

The result is this (the last tile throws an error):

1d25d668-b669-49b4-8365-f65eba17f7a7

What I would like to do is to convert the image to bigtiff, or to deepzoom (dzi) format.

thank you for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants