Skip to content

ENH: Add write_morph_data to freesurfer.io #414

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

Merged
merged 8 commits into from
Mar 2, 2016

Conversation

effigies
Copy link
Member

@effigies effigies commented Mar 1, 2016

The first commit was in the midst of #249 and causing PEP8 warnings. Not otherwise relevant to Cifti, so I'm submitting as its own PR. Fixed the style and brought a little more in line with freesurfer.io functions.

STY: Conform to conventions of other freesurfer.io functions
@agramfort
Copy link
Contributor

LGTM

@@ -160,6 +160,29 @@ def read_morph_data(filepath):
return curv


def write_morph_data(filepath, values):
"""Write out a Freesurfer morphometry data file.
Copy link
Member

Choose a reason for hiding this comment

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

Mention parameters in first line? Something like

Write freesurfer morphometry data `values` to file `filepath`

@effigies
Copy link
Member Author

effigies commented Mar 1, 2016

Looking at write_curv.m, the MATLAB convention is to pass an fnum (number of faces) to write as the second of that triplet. Should that be an optional argument, to make converting MATLAB scripts as straightforward as possible?

@effigies
Copy link
Member Author

effigies commented Mar 1, 2016

Added fnum. I can drop that if it seems like a bad idea. Other comments addressed.

effigies added 2 commits March 1, 2016 14:53
Check bounds on values to be written
Add fnum parameter to match write_curv.m
Squeeze array to simplify dimension test
@effigies
Copy link
Member Author

effigies commented Mar 1, 2016

New tests added. Subtle bug for vectors of shape (1, n) fixed.

"""
magic_bytes = np.array([255, 255, 255], dtype=np.uint8)

array = np.asarray(values).astype('>f4').squeeze()
Copy link
Member

Choose a reason for hiding this comment

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

Just checking, but you want to allow arrays shape (1, 1, 20, 1, 1)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Is there a good reason not to?

Copy link
Member

Choose a reason for hiding this comment

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

You could imagine that user was making a mistake, passing in a multidimensional array, that just happened to have only one dimension not length 1. I mean, maybe you actually want to accept any of shape (N,), (1, N), (N, 1), but not other shapes. As in if array.ndim > 2 or (array.ndim == 2 and not 1 in array.shape):

Actually maybe array is a bit confusing as name (looks like np.array) ...

Copy link
Member Author

Choose a reason for hiding this comment

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

I suppose. Maybe it makes more sense to let people do their own squeezing, if that's what they want.

I would say allow (N, 1, 1) as well, though, since that's the default shape coming in from MGH or surface Nifti files.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds reasonable.

Coercing vector to float before checking size could cause memory blow-up

vector = np.asarray(values)
vnum = np.prod(vector.shape)
if vector.shape not in ((vnum,), (vnum, 1), (1, vnum), (vnum, 1, 1)):
Copy link
Member

Choose a reason for hiding this comment

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

Nice.

@matthew-brett
Copy link
Member

Great - thanks for your patience.

@matthew-brett
Copy link
Member

Oops - Appveyor failure ...

@effigies
Copy link
Member Author

effigies commented Mar 2, 2016

32bit Windows issue: https://ci.appveyor.com/project/Eric89GXL/nibabel/build/1.0.587/job/xrwxr6jdbj3s4vj9#L876

np.lib.stride_tricks.as_strided(np.array(0), (np.iinfo('i4').max + 1,), [0]) results in OverflowError: Python int too large to convert to C long.

Not sure where to start with that one.

np.zeros(shape), big_num)
if ctypes.c_long is not ctypes.c_int32:
assert_raises(ValueError, write_morph_data, 'test.curv',
strided_scalar((big_num,)))
Copy link
Member Author

Choose a reason for hiding this comment

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

Alternatives, if this is ugly:

  1. Check np.iinfo(ctypes.c_long)
  2. try: strided_scalar((big_num,))

Copy link
Member

Choose a reason for hiding this comment

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

How about:

if np.dtype(np.long) != np.dtype(np.int32):  # Windows 32-bit overflows Python int

Copy link
Member Author

Choose a reason for hiding this comment

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

Doesn't seem to capture the case for PYTHON_VERSION=2.7, PYTHON_ARCH=32.

assert_raises(ValueError, write_morph_data, 'test.curv',
np.zeros(shape), big_num)
# Windows 32-bit overflows Python int
if np.dtype(np.long) != np.dtype(np.int32):
Copy link
Member

Choose a reason for hiding this comment

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

Whoops. How about np.dtype(int) != np.dtype(np.int32) ?

@matthew-brett
Copy link
Member

Looks good on the tests - will merge unless I hear otherwise tomorrow.

@effigies
Copy link
Member Author

effigies commented Mar 2, 2016

Just squashed the final two commits. Should be good to go. Thanks for the review.

@matthew-brett
Copy link
Member

Great - thanks a lot.

matthew-brett added a commit that referenced this pull request Mar 2, 2016
ENH: Add write_morph_data to freesurfer.io

The first commit was in the midst of #249 and causing PEP8 warnings. Not otherwise relevant to Cifti, so I'm submitting as its own PR. Fixed the style and brought a little more in line with freesurfer.io functions.
@matthew-brett matthew-brett merged commit a7c6523 into nipy:master Mar 2, 2016
@nibotmi nibotmi mentioned this pull request Mar 2, 2016
4 tasks
grlee77 pushed a commit to grlee77/nibabel that referenced this pull request Mar 15, 2016
ENH: Add write_morph_data to freesurfer.io

The first commit was in the midst of nipy#249 and causing PEP8 warnings. Not otherwise relevant to Cifti, so I'm submitting as its own PR. Fixed the style and brought a little more in line with freesurfer.io functions.
@effigies effigies deleted the write_morph branch March 29, 2016 15:01
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.

3 participants