TimVanMourik / Armadillo

Augmented Reality brains
https://armadillo-brain.herokuapp.com
GNU General Public License v3.0
5 stars 4 forks source link

[BUG] Remove hard-coded GifTI format 'GZipBase64Binary' parsing #11

Closed TimVanMourik closed 6 years ago

TimVanMourik commented 6 years ago

Currently, the parsed encoding format of the GifTI files is 'GZipBase64Binary', which is a hard-coded default: https://github.com/TimVanMourik/Armadillo/blob/95d947dda272b1d1acb4163824f1648da4687fb8/app/api/views.py#L40

In this PR to Neurovault, @chrisfilo points out that the file format of new files will be 'ASCII' instead. That puts some urgency on doing it more dynamically. We tried this earlier but didn't get it to work, and thus resorted to hard-coding.

TimVanMourik commented 6 years ago

I had a shot at fixing this and I think I'm pretty far, but I'm stuck nonetheless: I put some first idea to fix this in the branch gifti-test.

UPDATE: code rephrased with import statements to minimal working example with link from Chris below

from nibabel.gifti.parse_gifti_fast import GiftiImageParser
from urllib.request import urlopen

surface_file='https://neurovault.org/media/images/3954/65068.L.func.gii'
giftiParser = GiftiImageParser(buffer_size=35000000)

giftiObject = giftiParser.parse(string=urlopen(surface_file).read())

But it doesn't work and I don't know why. Any ideas, @dokato?

@chrisfilo, do you happen to have an example imageid that has a gifti in 'ASCII' format for testing?

chrisgorgo commented 6 years ago

Try this one: https://neurovault.org/media/images/3954/65068.L.func.gii

Best, Chris

On Fri, Jul 27, 2018 at 5:58 AM Tim van Mourik notifications@github.com wrote:

I had a shot at fixing this and I think I'm pretty far, but I'm stuck nonetheless: I put some first idea to fix this in the branch gifti-test.

giftiParser = GiftiImageParser(buffer_size=35000000) giftiObject = giftiParser.parse(string=urllib.request.urlopen(surface).read())

But it doesn't work and I don't know why. Any ideas, @dokato https://github.com/dokato?

@chrisfilo https://github.com/chrisfilo, do you happen to have an example imageid that has a gifti in 'ASCII' format for testing?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/TimVanMourik/Armadillo/issues/11#issuecomment-408410915, or mute the thread https://github.com/notifications/unsubscribe-auth/AAOkp1ZbrqxwMIxSD-xCV9swA3Oq_Gk3ks5uKw5dgaJpZM4U_BUr .

TimVanMourik commented 6 years ago

Thanks @chrisfilo!

On further inspection, in the nibabel code, this reaches the xmlutils.py line 79 parse function and creates a fptr = BytesIO(string) normally, but after the parsing returns a NoneType.

Is this something I'd better make an issue of in nibabel or don't I use the functions right? @nibabel guys, @effigies, @matthew-brett

TLDR: the minimal working example above is minimally failing when reading in a Gifti file from a remote source.

Work-arounds without GiftiImageParser are welcome too

effigies commented 6 years ago

Following the example of GiftiImage.from_file_map():

    @classmethod
    def from_file_map(klass, file_map, buffer_size=35000000):
        """ Load a Gifti image from a file_map

        Parameters
        ----------
        file_map : dict
            Dictionary with single key ``image`` with associated value which is
            a :class:`FileHolder` instance pointing to the image file.

        Returns
        -------
        img : GiftiImage
        """
        parser = klass.parser(buffer_size=buffer_size)
        parser.parse(fptr=file_map['image'].get_prepare_fileobj('rb'))
        return parser.img

Looks like what you want is:

from nibabel.gifti.parse_gifti_fast import GiftiImageParser
from urllib.request import urlopen

surface_file='https://neurovault.org/media/images/3954/65068.L.func.gii'
giftiParser = GiftiImageParser(buffer_size=35000000)

giftiParser.parse(string=urlopen(surface_file).read())
giftiObject = giftiParser.img
effigies commented 6 years ago

I do think this argues for an FileBasedImage.deserialize() method (related: nipy/nibabel#644), as it should be this simple:

import nibabel as nb
from urllib.request import urlopen

surface_file='https://neurovault.org/media/images/3954/65068.L.func.gii'
with urlopen(surface_file) as stream:
    img = nb.GiftiImage.deserialize(stream.read())

(I'm assuming a urlopen() can be used as a context manager.)

TimVanMourik commented 6 years ago

Ahhhh, got it, I was just being an idiot and misunderstood how the parse command worked. I'm too indoctrinated by MATLAB, I suppose, and expected the image as a returned object. But it's good ol' object orientation and it creates a .img onto itself.

Works like a charm now, i.e. Armadillo can now deal with any proper gitfti image!

Yes, your second solution sounds even more elegant, as it removes the need for going into the weeds of the gifti functionality. Looking forward to the release!

Thanks @effigies and @chrisfilo!