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

Tifimage: problem to use getframe function for stacks of single image files #501

Open
osholm opened this issue Nov 19, 2022 · 11 comments
Open
Assignees
Labels

Comments

@osholm
Copy link
Contributor

osholm commented Nov 19, 2022

Apparently, there is a problem in tif image when using getframe to jump to another image. It seems related to tifimage expecting a multi-image file and not a series of images (possibly therefore it doesn't inherit the fabioutils version of getframe).

Example:

imtif = tifimage.tifimage()
imtif.read('Rasterscan-ACT_Raster10deg-2000mu_Export_0010.tiff')
imtif.getframe(30)
Leads to this:
File ~/opt/miniconda3/envs/MyPySide-conda/lib/python3.10/site-packages/fabio/tifimage.py:231, in TifImage.getframe(self, num)
229 tiff_header = self._tiffio.getInfo(num)
230 return self._create_frame(image_data, tiff_header)
--> 231 raise Exception("getframe out of range")

Exception: getframe out of range

it ends up here in tifimage.py:

   if 0 <= num < self.nframes:
        image_data = self._tiffio.getData(num)
        tiff_header = self._tiffio.getInfo(num)
        return self._create_frame(image_data, tiff_header)
    raise Exception("getframe out of range")

where nframes is 1 because of only having one image in the file.

The code has changed quite a bit since I last looked at it, so I am unsure if I am expected to use another function for jumping to another file in the stack of tiffs but generally it should capture that it is a series (actually .next() and .previous() does work) and therefore try to goto to another file if there is no stack of images in the file itself, or?

@kif
Copy link
Member

kif commented Dec 1, 2022

The module was re-written by @vallsv some time ago ... he is the one knowing best the changes he made (4 years back ...)

@kif kif added the bug label Dec 1, 2022
@kif
Copy link
Member

kif commented Dec 1, 2022

Indeed this is a bug since the fabio is expected to search in fileseries... but I think I remember that there is now a file-series class to handle explicitly the case.

@kif
Copy link
Member

kif commented Dec 7, 2022

I had a chat with @vallsv : the behaviour has changed on purpose and to play within file-series, there is a specific class which makes things cleaner. It is documented here:
http://www.silx.org/doc/fabio/latest/getting_started.html?highlight=file%20series#fabio-file-series

@kif kif closed this as completed Dec 7, 2022
@osholm
Copy link
Contributor Author

osholm commented Dec 7, 2022

Hi Jerome,

Thanks for the update and it might be me, but currently I find it a bit complex for the average Joe to use the get_frame/getframe to jump forth and back in file series. It might be that is just an update of the documentation (the page you linked to in your last comment) that is needed. In the section under "FabIO old-fashion file series" there is this example:

import fabio
im100 = fabio.open('Quartz_0100.tif') # Open image file
print(im0.data[1024,1024])            # Check a pixel value
im101 = im100.next()                  # Open next image
im270 = im100.getframe(270)           # Jump to file number 270: Quartz_0270.tif

Is this purely a historic use of fabio? When I read the documentation it appears to me that it should still work, but there are better ways to handle this. If this example is not working anymore, I think we need to mark this more clearly.

Please, don't get me wrong, I think it is great that the code has developed and new and faster ways of dealing with reading large amount of data have been introduced. But our original vision was also to make it really easy to open a file a move around in a stack of images without knowing too many Python tricks.

Instead of the old way, I also tried the new "random" way.

import fabio
# The first filename of consecutive filenames while foobar_xxxx.edf exists
filename = "foobar_0000.edf"
with fabio.open_series(first_filename=filename) as series:
    frame1 = series.get_frame(1)
    frame100 = series.get_frame(100)
    frame19 = series.get_frame(19)

I can see that I can use this fairly similar to the old way:
series = fabio.open_series(first_filename='Raster10deg-2000mu_Export_0010.tiff')
and then do, e.g.:
image10 = series.get_frame(10)
but it appears that some functionality is broken, e.g.
image10.getmin()
gives this error:

File ~/opt/miniconda3/envs/MyPySide-conda/lib/python3.10/site-packages/fabio/fabioimage.py:160, in _FabioArray.getmin(self)
    158 def getmin(self):
    159     """ Find min value in self.data, caching for the future """
--> 160     if self.minval is None:
    161         if self.data is not None:
    162             self.minval = self.data.min()

apparently because TiffFrame is something different from Tiffimage. A similar situation is the same for all the "gets" .getstddev, .getmean etc

Sequential reading:
I managed to read the file series sequentially. Although the example merely "scrolls" through the data. I think it would be good to add an example, which shows how use the sequentially read data in straight forward way.

If I follow the example below:

# Sequencial access
import fabio
# The first filename of consecutive filenames while foobar_xxxx.edf exists
filename = "foobar_0000.edf"
with fabio.open_series(first_filename=filename) as series:
    for frame in series.frames():
        frame.data
        frame.header
        frame.index                    # frame index inside the file series
        frame.file_index               # frame index inside the edf file
        frame.file_container.filename  # name of the source file

I get Attribute errors for index, file_index, file_container, e.g.

AttributeError: 'TifImage' object has no attribute 'file_container'
So it seems there might be a some bugs for the new files series handling of tiff files.

Sorry, this got a bit long and possibly some this should have been move to a separate issue.

BR
Henning

@osholm
Copy link
Contributor Author

osholm commented Dec 7, 2022

A small update. I played a bit more with the sequential reading and I believe this example might help the user:

myframes = {}
i=0

with fabio.open_series(first_filename=filename) as series:
     for frame in series.frames():
          i += 1
          myframes[i] = frame

the objects in myframes seems to working in the usual way. E.g.

myframes[3].getmax()
provides the maximum value of the frame.

@kif
Copy link
Member

kif commented Dec 8, 2022

There are bugs in the documentation which deserve correction ...

Reopen this as iteration over fileseries.frames() sometimes gives FabioImage sometimes FabioFrame

@osholm
Copy link
Contributor Author

osholm commented Dec 8, 2022

Sounds good, Jerome. Thanks.

@kif kif reopened this Dec 8, 2022
@kif
Copy link
Member

kif commented Dec 8, 2022

Do you want to have a look at #516 ?
It should make the doc consistent with the code ... I tested locally with edf and tiff and in the doc with mar345

@osholm
Copy link
Contributor Author

osholm commented Dec 9, 2022

Of course. I will have a look.

@osholm
Copy link
Contributor Author

osholm commented Jan 23, 2023

As mentioned in my comment (to reviewing #516) the doc is now consistent with the code.

I have testet tiff files (both including single images and multiple images) and I find that the present function is a bit inconsistent. Wouldn't it make sense that all formats worked the same even if some has a possibility of being multiple image files. I believe that most data sets of tiff files (or edf files) or stored as single image files, despite the ability to store more images in one file. The example now given in the documentation with the mar2300 data can be used:

im1 = fabio.open("200mMmgso4_001.mar2300")

im4 = im1.getframe(4)
or
im2 = im1.next()

whereas
im1 = fabio.open("Export_0001.tiff")
im2 = im1.next()
but

im1.getframe(4)

results in the following error despite im1.nframes is 1:

Exception Traceback (most recent call last)
Cell In [93], line 1
----> 1 im2.getframe(4)

File ~/Documents/Github/fabio/build/lib.macosx-11.0-arm64-cpython-310/fabio/tifimage.py:231, in TifImage.getframe(self, num)
229 tiff_header = self._tiffio.getInfo(num)
230 return self._create_frame(image_data, tiff_header)
--> 231 raise Exception("getframe out of range")

Exception: getframe out of range

What do you think?

@vallsv
Copy link
Contributor

vallsv commented Jan 24, 2023

To me next and the transparent file switch are both part of the old API which should be removed and not used anymore.

That's unefficient and it mix concepts of frames and file series.

That's in the end, difficult to maintain, difficult to predict, and difficult to adapt.

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

No branches or pull requests

3 participants