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

Writer functions #6

Open
Chris-N-K opened this issue Apr 16, 2021 · 9 comments
Open

Writer functions #6

Chris-N-K opened this issue Apr 16, 2021 · 9 comments
Labels
enhancement New feature or request

Comments

@Chris-N-K
Copy link

I would like to create a branch with the _writer.py script. At the moment my solution only supports the nifti format.

The functions works by creating a nibabel.Nifti1Image from the selected layer (image or labels) data and metadata. Do have an idea for a more elegant way to support the different formats in nibabel other than writing a specific writer for each?

@Chris-N-K Chris-N-K added the enhancement New feature or request label Apr 16, 2021
@effigies
Copy link
Member

nibabel.save() will do its best to convert to a format based on the extension. The affine will be converted, but most other header data will be lost, if the output format doesn't match the input format. When there are good mappings for specific fields between two formats, then we can improve the conversion.

@Chris-N-K
Copy link
Author

To use nibabel.save() wouldn't we need to store the SpatialImage in the napari.viewer.layer.metadata? At the moment only the header and affine matrix are stored in the metadata and the image is represented in the layer as array. I think we could do this as the header and affine matrix could still be accessed from the SpatialImage in the metadata.

@effigies
Copy link
Member

I assume header isn't a napari notion... why not store the image object itself as the header?

@Chris-N-K
Copy link
Author

Yes your right. We should switch from storing the affine matrix and the image header in naparis metadata to storing the image object. With the image object we can then use nibabel.save(). I will update my writer function and add it as a branch.

@Chris-N-K
Copy link
Author

I uploaded a basic writer implementation for the image layers to the writer_implementation branch.
Is there a way to select the image classes from a given extension.

@effigies
Copy link
Member

The logic is basically all in nibabel.save(), which uses a priority list of image classes in imageclasses. Each image type describes valid extensions.

@Chris-N-K
Copy link
Author

But nibabel.save() requires a image object. If the user wants to save a layer that was not loaded from a file format that nibabel supports the napari load functions will be used and no image object will be in the layer metadata. Thus, I would like to create a bare bone image object from the given save extension to feed it into nibabel.save().

@effigies
Copy link
Member

effigies commented Apr 29, 2021

I meant you could adapt the logic to something you need, such as:

valid_klasses = [klass for klass in all_image_classes
                 if ext in klass.valid_exts]
img = valid_klasses[0](data, affine)
img.to_filename(...)

But you can even just save time by creating a SpatialImage object:

In [1]: import nibabel as nb

In [2]: import numpy as np

In [3]: img = nb.spatialimages.SpatialImage(np.zeros((5,5,5)), np.eye(4))

In [4]: nb.save(img, "test.nii")

In [5]: nb.load("test.nii")
Out[5]: <nibabel.nifti1.Nifti1Image at 0x7fcd1cd74c10>

Though if you need to set additional header information, you will probably want to do something like the first option and modify img.header before writing it out.

@Chris-N-K
Copy link
Author

Thanks for the input.

I will use the second approach for the case of saving a layer with no additional information in its metadata.
To give the user the ability to modify the header a separate widget might be a better solution. I would like to add a widget to display the header information anyway.
This widget could have a button and file format selection to add an image object to the layer.

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

No branches or pull requests

2 participants