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

Write ndarray to nifti #21

Merged
merged 9 commits into from
Oct 23, 2018
Merged

Write ndarray to nifti #21

merged 9 commits into from
Oct 23, 2018

Conversation

nilgoyette
Copy link
Collaborator

As explained in #19, here's our code to write a ndarray to a nifti file. I kept it simple, it's all in the same file, you simply need to call write_nifti with an Array or an ArrayView, in c or f ordering. When you want to create a new image with the same header (same position, spacing, etc.), simply call the function with the optional NiftiHeader.

In a generic context, you will need to use the trait TypeTool. I'm not a fan of it, but I don't know how to avoid it, and it's not too bad, maybe it simply needs to be hidden :)

Some problems that I can see with my code:

  • The if slope != 1.0 || header.scl_inter != 0.0 { condition is not required. Maybe we shouldn't care about some substraction and divisions...
  • As I said, TypeTool. The name is bad, I know. But I do think it's a good trait usage.
  • The ndarray dim and datatype currently win over the same fields in the header. That may or may not be what the user wants. I know that nibabel prefers the header, so it casts the data. I personally don't like automatic hidden casts, I prefer converting my ndarray myself.
  • Afaik, NiBabel ignores scl_slope and scl_inter on writing. They are simply set to 1.0 or 0.0. I never ignore them. This is sadly as "automatic" as the casts...
  • The last 2 points are complex. Not complex to code but to decide what should be done.

By the way, do not hesitate to be critical! I won't cry over it. It's the best way to learn.

Copy link
Owner

@Enet4 Enet4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! We're going to need a few more iterations before merging. I also didn't make a full assessment of the ndarray writing routine yet.

Besides the suggestions inline, it might also be worth checking whether we can build a function for writing just an .img[.gz] file.

src/writer.rs Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated Show resolved Hide resolved
src/writer.rs Outdated
}
}

fn read_2d_image<P: AsRef<::std::path::Path>>(path: P) -> Array2<f32> {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My convention is to use where clauses for all traits (except ?Sized and lifetime constraints):

Suggested change
fn read_2d_image<P: AsRef<::std::path::Path>>(path: P) -> Array2<f32> {
fn read_2d_image<P>(path: P) -> Array2<f32>
where
P: AsRef<::std::path::Path>,
{

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I probably concluded that you put them 'in' when I checked extension.rs by "chance"

pub fn from_stream<S: Read>(mut source: S) -> Result<Self> {

There are some other examples in your code, but I won't touch them because they are not related at all to this PR. I'll change mine.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm yeah, that code was written before I left my wicked ways. 😊

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hahaha, sorry, I just need to add another example that I just found

fn from_file_2<P: AsRef<Path>, S>(path: P, mut stream: S) -> Result<InMemNiftiObject>
where
    S: Read,

Ok, I'll see myself out ^^

Copy link
Owner

@Enet4 Enet4 Oct 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah, I figured there'd be more. This one here is worse though, as it clearly shows how adding the type constraints at the beginning makes a long-cat long function prototype. If we ever consider a full restyle, this one ought to go first.

    pub fn from_stream<B: ByteOrder, S: Read>(
        extender: Extender,
        mut source: S,
        len: usize,
    ) -> Result<Self> {

src/writer.rs Outdated
@@ -230,7 +232,9 @@ pub mod tests {
}
}

fn read_2d_image<P: AsRef<::std::path::Path>>(path: P) -> Array2<f32> {
fn read_2d_image<P>(path: P) -> Array2<f32>
where P: AsRef<Path>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that how rustfmt put it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, sorry. I'm not used to run rustfmt! Will do.

Copy link
Owner

@Enet4 Enet4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good to go! 🎉 In the near future, we can make a public function for writing header files.

@Enet4 Enet4 merged commit c796543 into Enet4:master Oct 23, 2018
@nilgoyette nilgoyette deleted the ndarray_to_nifti branch June 4, 2020 13:26
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

Successfully merging this pull request may close these issues.

2 participants