aicspylibczi icon indicating copy to clipboard operation
aicspylibczi copied to clipboard

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

Open markemus opened this issue 4 years ago • 22 comments

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?

markemus avatar Jan 15 '21 20:01 markemus

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

heeler avatar Jan 15 '21 21:01 heeler

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)

heeler avatar Jan 15 '21 23:01 heeler

@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?

markemus avatar Jan 19 '21 17:01 markemus

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 avatar Jan 19 '21 20:01 heeler

@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.

heeler avatar Jan 29 '21 15:01 heeler

@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.

markemus avatar Jan 29 '21 18:01 markemus

@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

heeler avatar Jan 29 '21 19:01 heeler

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

rg314 avatar Mar 02 '22 15:03 rg314

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 avatar Mar 02 '22 16:03 evamaxfield

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?

evamaxfield avatar Mar 02 '22 16:03 evamaxfield

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 https://github.com/AllenCellModeling/aicspylibczi/blob/96110fd2c22b7aecc61c1dc72b3f5933ddcfa0fa/_aicspylibczi/Reader.cpp#L438

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.

rg314 avatar Mar 02 '22 16:03 rg314

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?

evamaxfield avatar Mar 02 '22 17:03 evamaxfield

Cheers @JacksonMaxfield that was also my guess ;)

rg314 avatar Mar 02 '22 17:03 rg314

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.

heeler avatar Mar 02 '22 17:03 heeler

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.

toloudis avatar Mar 02 '22 18:03 toloudis

@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.

heeler avatar Mar 02 '22 19:03 heeler

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

rg314 avatar Mar 02 '22 21:03 rg314

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

r03ert0 avatar Jun 12 '22 15:06 r03ert0

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.

markemus avatar Jun 13 '22 07:06 markemus

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

rg314 avatar Jun 13 '22 10:06 rg314

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.

heeler avatar Jun 13 '22 11:06 heeler

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!

r03ert0 avatar Jun 13 '22 11:06 r03ert0