nibabel icon indicating copy to clipboard operation
nibabel copied to clipboard

Reader for Freesurfer Morphometry stats

Open raamana opened this issue 7 years ago • 13 comments

Hi Everyone,

I need to read various volumetric (subcortical) and morphometry stats from Freesurfer output (e.g. SUB/stats/aseg.stats) https://surfer.nmr.mgh.harvard.edu/fswiki/MorphometryStats

Apologies if I haven't looked hard enough, but it seems nibabel doesn't support it. This reader is rather simple to write, and I am wondering if this would be relevant and worthy of inclusion into nibabel? If so, I would be happy make a PR with it. Let me know what needs to be kept in mind other than dev guidelines noted on nibabel website http://nipy.org/nibabel/devel/devguide.html#chap-devguide

If you know of any other python-based tool that can reliably read aseg.stats, let me know, that would be great also.

Thanks, Pradeep

raamana avatar Mar 06 '17 03:03 raamana

Sorry. Ignore the previous message; I didn't read carefully.

I was able to parse an aseg.stats file with:

np.loadtxt(fname, dtype="i1,i1,i4,f4,S32,f4,f4,f4,f4,f4")

It doesn't label the columns nicely, but that can be fixed up. See the genfromtxt examples.

effigies avatar Mar 06 '17 20:03 effigies

Thanks @effigies for the reply. I was able to write a reader, which is not a problem for people who can code (like you and me). My question was more about how relevant/worthy it is to be included in the nibabel API? I know it is really very simple, but it is to be remembered there are novice neuroimaging coders (and others like me) who would rather prefer nib.freesurfer.io.read_aseg_stats(subjectid) as opposed to hacking one of their own.

Also, there are a few variations of aseg stats (whole brain and subcortical), and some specific statistics (such as estimatedTotalIntraCranialVolume) that are studied on their own that the following readers would be helpful:

nib.freesurfer.io.read_aseg_stats(subjectid, set = ['subcortical_only'])
nib.freesurfer.io.read_eTIV(subjectid)
nib.freesurfer.io.read_aseg_stats(subjectid, set = ['wholebrain'])

This is just my personal opinion, and I would like to learn from the regular developers if there are better solutions.

raamana avatar Mar 06 '17 20:03 raamana

Gotcha. Well, I'd say go ahead and develop your API. You can submit a PR and see if it people think it fits here (I do agree that nib.freesurfer.io` would be the right place to start) or in PySurfer. Even if they don't end up here, if you think something's useful, you can make a little package others can use.

Another thing you can do is email the nipy list and check whether something like this doesn't exist in another project, or if there's an existing project that would like to include it.

effigies avatar Mar 06 '17 21:03 effigies

@raamana - I think it would be a great idea to put this into nibabel - that way we can make sure that the reading is correct, and properly tested - I completely agree. Would you consider making a pull request? I'd be very happy to see that.

matthew-brett avatar Mar 06 '17 23:03 matthew-brett

Thanks @matthew-brett, glad to hear that. I will make a PR rather soon.

raamana avatar Mar 07 '17 13:03 raamana

what constitutes a test for such a thing in your opinion? Just reading the names and floating points right in the correct order? In my tests so far on 100s of Freesurfer outputs, I haven't encountered a problem. But I am trying to imagine cases it may fail e.g. varying precision for floats, missing values or names etc.

Also, any idea if this format will be stable for years to come? :)

raamana avatar Mar 08 '17 04:03 raamana

Also, I personally would ignore some segmentations/statistics, as some of them are redundant and some are almost always zero/missing. Although we could note this in the help text (in terms of what is being returned), I am not so sure if this would fit with the nibabel conventions! Any thoughts?

raamana avatar Mar 08 '17 05:03 raamana

Sorry - I don't use Freesurfer myself, so I can't give much guidance on the format.

@agramfort - so you have any thoughts on the format?

In general we have the approach of loading everything, so the user can get whatever they want, but sometimes we put an API on top of that to get the common stuff. For example, the NIfTI format header has some more obscure stuff in there, which you can get with header['whatever_field_you_want'], but there are access methods to get common information like dtypes - header.get_data_dtype()`.

Because you're using the format and writing the code - you get to decide !

matthew-brett avatar Mar 09 '17 18:03 matthew-brett

Pinging @agramfort .

raamana avatar Jun 30 '17 16:06 raamana

@raamana open a PR and make a proposal for the API. As this is a new type of data it should not be too painful to agree on API. I would try to return info as complete as the equivalent matlab code certainly shipped by freesurfer.

agramfort avatar Jun 30 '17 18:06 agramfort

hey guys, did this ever go anywhere?

nblauch avatar Apr 23 '20 17:04 nblauch

Hi @nblauch, I did hack something, but haven't gone through the full dev / PR yet. If you would like to take over, i am happy to share what I wrote.

raamana avatar Apr 23 '20 17:04 raamana

thanks, i ended up just running asegstats2table to get all my subjects in a .tsv and then reading that with pd.read_csv , columns nicely formatted. easy enough.

nblauch avatar Apr 23 '20 22:04 nblauch