nipy / nibabel

Python package to access a cacophony of neuro-imaging file formats
http://nipy.org/nibabel/
Other
636 stars 258 forks source link

Data types in PAR / REC files #275

Closed matthew-brett closed 9 years ago

matthew-brett commented 9 years ago

PAR files have a field in the image information definition called "image pixel size (in bits)".

We currently assume that this value refers to the number of bits of a signed integer (int16, int32).

Bennett Landman has a PAR / REC toolbox at http://iacl.ece.jhu.edu/~bennett/research.shtml that includes the following code (in loadREC.m):

switch(par.scn.pix_bits)
    case 32
        type = 'float32';
    case 16
        type = 'uint16'; % fixed?
    case 8
        type='uint8';
    otherwise
        error('Unsupported data type');
end

So, he thinks the ints are unsigned and that '32' means float not (u)int32.

We have test images at:

All of the images are '16' bit width, so we can't check what '8' or '32' mean from these images.

These sets of PAR / REC data files have matching NIfTI files written by the Philips software. These all have NIfTI image data type <i2 (signed little-endian int16). The unscaled data array is identical between our PAR / REC conversion and the Philips conversion to NIfTI. Here's loading in the nitest-balls1 directory:

In [24]: import numpy as np
In [25]: import nibabel as nib
In [27]: n_img = nib.load('NIFTI/T1.nii.gz')
In [28]: p_img = nib.load('PARREC/T1.PAR')
In [29]: np.all(n_img.dataobj.get_unscaled() == p_img.dataobj.get_unscaled())
Out[29]: memmap(True, dtype=bool)

Only one of all the sample images has a negative minimum both on Philips conversion and our conversion - nitest-balls1/PARREC/fieldmap.PAR / nitest-balls1/NIFTI1/fieldmap.nii.gz:

In [30]: p_img = nib.load('PARREC/fieldmap.PAR')
In [31]: n_img = nib.load('NIFTI/fieldmap.nii.gz')
In [32]: np.all(n_img.dataobj.get_unscaled() == p_img.dataobj.get_unscaled())
Out[32]: False
In [33]: n_img.get_data().min()
Out[33]: -500.0
In [34]: p_img.get_data().min()
Out[34]: memmap(-500.0)

EDIT - these negative values in fact came from the data scaling and not the raw data.

In this case, the written NIfTI image is 3D shape (80, 80, 10), and our image is 4D with two volumes, shape (80, 80, 10, 2).

Loading the equivalent data in DICOM:

In [50]: import nibabel.nicom.dicomreaders as dcr
In [51]: img = dcr.wrapper_from_file('DICOM/fieldmap.dcm')
In [52]: res = img.get_pixel_array()
In [53]: res.shape
Out[53]: (20, 80, 80)
In [54]: res.dtype
Out[54]: dtype('uint16')

Investigating further, the T1 image also has 'uint16' DICOM data:

In [63]: t1_img = dcr.wrapper_from_file('DICOM/T1.dcm')
In [64]: t1_res = t1_img.get_pixel_array()
In [65]: t1_res.shape
Out[65]: (10, 80, 80)
In [66]: t1_res.dtype
Out[66]: dtype('uint16')
In [67]: t1_p_img = nib.load('PARREC/T1.PAR')
In [68]: np.all(t1_res.T == t1_p_img.dataobj.get_unscaled())
Out[68]: memmap(True, dtype=bool)

So far, it is possible that we and the Philips NIfTI conversions are wrong in interpreting the datatype as 'int16' instead of 'uint16'.

matthew-brett commented 9 years ago

r2agui also assumes little-endian REC data, and that N in the pixel width field corresponds to intN REC data. Older comments in our parrec.py file mentioned r2agui, so that may not be independent evidence.

matthew-brett commented 9 years ago

As far as I can see 3dPAR2AFNI.pl assumes 16 bit signed data of same endianness as the platform on which the code is running.

matthew-brett commented 9 years ago

See also #274

larsoner commented 9 years ago

I looked into ITK's code, and this is what is in InsightToolkit-4.6.1\Modules\IO\PhilipsREC\src\itkPhilipsRECImageIO.cxx:

  // As far as I know, Philips REC files are only
  // 8-bit or 16-bit signed integers.
  switch ( par.bit )
    {
    case 8:
      m_ComponentType = CHAR;
      m_PixelType = SCALAR;
      break;
    case 16:
      m_ComponentType = SHORT;
      m_PixelType = SCALAR;
      break;
    default:
      std::ostringstream message;
      message << "Unknown data type. par.bit must be 8 or 16. "
              << "par.bit is "
              << par.bit;
      ExceptionObject exception(__FILE__, __LINE__,
                                message.str(),
                                ITK_LOCATION);
      throw exception;
    }
matthew-brett commented 9 years ago

@BennettLandman - if you follow your github email - we noticed that your old MATLAB code assumes that PAR REC files with bit widths 8, 16, and 32 are respectively uint8, uint16 and float32 - but it looks like it is more common to assume 8, 16 -> int8, int16. Did you find some data confirming int vs uint either way? How about 32 -> float32?

BennettLandman commented 9 years ago

It’s been a very long time since I looked a PAR/REC’s directly. I believe that there have been several major revisions to the PAR/REC format (since that code was written) and that we were getting unsigned data off the scanners.

We now use adapted r2aGUI code to interpret the PAR/REC file format into NIFTI volumes. We had to tinker with the orientations to get the images to consistently display across the various nifti viewers. Ben (cc’d) can help you get our code if you don’t have a working copy that you like.

We released a data resource with DICOM/++ transcoding data: https://www.nitrc.org/projects/rosetta/

-Bennett

From: Matthew Brett notifications@github.com<mailto:notifications@github.com> Reply-To: nipy/nibabel reply@reply.github.com<mailto:reply@reply.github.com> Date: Saturday, November 15, 2014 at 9:46 PM To: nipy/nibabel nibabel@noreply.github.com<mailto:nibabel@noreply.github.com> Cc: Bennett Landman bennett.landman@vanderbilt.edu<mailto:bennett.landman@vanderbilt.edu> Subject: Re: [nibabel] Data types in PAR / REC files (#275)

@BennettLandmanhttps://github.com/BennettLandman - if you follow your github email - we noticed that your old MATLAB code assumes that PAR REC files with bit widths 8, 16, and 32 are respectively uint8, uint16 and float32 - but it looks like it is more common to assume 8, 16 -> int8, int16. Did you find some data confirming int vs uint either way? How about 32 -> float32?

— Reply to this email directly or view it on GitHubhttps://github.com/nipy/nibabel/issues/275#issuecomment-63202989.

matthew-brett commented 9 years ago

Thanks a lot for the reply. Do you happen to remember why you thought the data was unsigned? Our data appears to be compatible with either, with one odd exception? Do you remember why you thought 32 == float32?

We are fairly confident of our orientations now; we have an example dataset with several orientations that we test against : http://psydata.ovgu.de/philips_achieva_testfiles/conversion2/

I am very glad to hear about the transcoding data, but I couldn't find the downloads, and the SVN repository appears to be private still - is the released data on another site?

BennettLandman commented 9 years ago

We has some data sets that needed unsigned coming off the scanner. Dti if I recall... When I wrote that code, no par files were 32 bit. So, to save floating point information (dti fa), I allowed that tag in my code. I guess I might be guilty of format drift. I found par too burdensome to write out new data, so I switched to nii.

Svn should be public... All nitrc members open. Please let me know if that isn't working.

Sent from my iPhone

On Nov 15, 2014, at 10:18 PM, "Matthew Brett" notifications@github.com<mailto:notifications@github.com> wrote:

Thanks a lot for the reply. Do you happen to remember why you thought the data was unsigned? Our data appears to be compatible with either, with one odd exception? Do you remember why you thought 32 == float32?

We are fairly confident of our orientations now; we have an example dataset with several orientations that we test against : http://psydata.ovgu.de/philips_achieva_testfiles/conversion2/

I am very glad to hear about the transcoding data, but I couldn't find the downloads, and the SVN repository appears to be private still - is the released data on another site?

— Reply to this email directly or view it on GitHubhttps://github.com/nipy/nibabel/issues/275#issuecomment-63203581.

matthew-brett commented 9 years ago

Thanks for the info.

I am a nitric member, I get:

$ svn --username matthewbrett checkout https://www.nitrc.org/svn/rosetta
Error validating server certificate for 'https://www.nitrc.org:443':
 - The certificate is not issued by a trusted authority. Use the
   fingerprint to validate the certificate manually!
Certificate information:
 - Hostname: www.nitrc.org
 - Valid: from Thu, 09 Oct 2014 00:00:00 GMT until Tue, 30 Aug 2016 23:59:59 GMT
 - Issuer: Domain Validated SSL, thawte, Inc., US
 - Fingerprint: 62:89:87:4f:b2:97:63:8c:cc:6b:a5:8e:48:a0:fa:08:62:9f:79:27
(R)eject, accept (t)emporarily or accept (p)ermanently? t
Authentication realm: <https://www.nitrc.org:443> Subversion User Authentication
Password for 'matthewbrett': 
svn: E175013: Access to '/svn/rosetta/!svn/bc/9' forbidden
BennettLandman commented 9 years ago

I think I fixed it… I can’t get public svn to be read-only right now...

So, I posted a public release with DICOM, PAR, and NII files:

Plausibility-Horizon:Desktop landmaba$ du -sh rosetta

3.2G rosetta:

Plausibility-Horizon:rosetta landmaba$ ls

General_electric Siemens philips

Plausibility-Horizon:rosetta landmaba$ find . -name '*.PAR'

./philips/philips_1_5T_intera/volume_2/PARREC/x_32_dir_7_1.PAR

./philips/philips_1_5T_intera/volume_3/PARREC/x_32_dir_8_1.PAR

./philips/philips_1_5T_intera/volume_4/PARREC/x_32_dir_9_1.PAR

./philips/philips_1_5T_intera/volume_5/PARREC/x_32_dir_10_1.PAR

./philips/philips_1_5T_intera/volume_6/PARREC/x_32_dir_11_1.PAR

./philips/philips_3T_achieva/b0map/PARREC/B0map.PAR

./philips/philips_3T_achieva/dti/PARREC/dti.PAR

./philips/philips_3T_achieva/fMRI/PARREC/fMRI.PAR

./philips/philips_3T_achieva/T1/PARREC/T1.PAR


Bennett Landman, Ph.D., bennett.landman@vanderbilt.edumailto:bennett.landman@vanderbilt.edu Assistant Professor Electrical Engineering (primary), Computer Science, Biomedical Engineering, Radiology and Radiological Sciences Vanderbilt University Director of the Center for Computational Imaging Vanderbilt University Institute of Image Science

From: Matthew Brett notifications@github.com<mailto:notifications@github.com> Reply-To: nipy/nibabel reply@reply.github.com<mailto:reply@reply.github.com> Date: Saturday, November 15, 2014 at 11:14 PM To: nipy/nibabel nibabel@noreply.github.com<mailto:nibabel@noreply.github.com> Cc: Bennett Landman bennett.landman@vanderbilt.edu<mailto:bennett.landman@vanderbilt.edu> Subject: Re: [nibabel] Data types in PAR / REC files (#275)

Thanks for the info.

I am a nitric member, I get:

$ svn --username matthewbrett checkout https://www.nitrc.org/svn/rosetta Error validating server certificate for 'https://www.nitrc.org:443':

— Reply to this email directly or view it on GitHubhttps://github.com/nipy/nibabel/issues/275#issuecomment-63204953.

cni-md commented 9 years ago

Hi, if the unofficial Philips documentation from Gyrotools (Research Tools and data handling) is correct PAR/REC is always uint (little endian), or 24 bit RGB for color overlayed data.

The MR signal will be scaled #1 in the receiver and gives us *.RAW (float) files.

After scale #2 and preprocessing we get *.DATA (float)

FFT gives us *.CPX (float)

Image processing and scale #3 gives us (8 or) 12 bit stored value -> export as DICOM, NIFTI or PAR/REC (8 bit can be choosen in the ControlReconstructionParameter)

scale #4 -> Display value

Windowing -> Display on the scanner console

The PAR/REC pixel size is by default "force 12bit". Possible is also 8 bit or 16 bit.

matthew-brett commented 9 years ago

Joerg - thanks for looking this up. Do you have a quote from the manual to say the data is uint rather than int?

I suppose the fact that the data is usually 12 bit explains why it looks like int16.

Can you give some reference we can write in the docs?

cni-md commented 9 years ago

If you look in the XML/REC file you see, that the key attribute "Pixel Size" Tag 0x00280100 is UInt16. This is also mentioned in the Gyrotools script of the Data handling course (http://www.gyrotools.com/courses/gt-research.html). In 2012 it was on page 44 ;)

The12 bit for image data should come from the dicom standard. 12 bit for the data and 4 bit for overlay.

matthew-brett commented 9 years ago

Thanks - that's very helpful.

I have had a look at the Rosetta images, and back at our own test images.

The image I listed above, fieldmap.PAR, has all positive values within int16 in the unscaled data, the negative values come from the scaling. All the Rosetta images we can read have positive values within int16 in the unscaled data. All the converted nifti images have int16 as the data type.

As you said, Joerg, all the XML / REC 'Pixel size' attributes for data in http://psydata.ovgu.de/philips_achieva_testfiles/conversion/ are all UInt16.

All of the DICOM files in the same directory have uint16 datatype, as do all of the Rosetta Philips DICOMs.

So, all the image data we have to hand could be read as int16 or uint16 to give the same image. Gyrotools training docs and DICOM reads and Philips XML think the data is uint. Philips NIfTI conversions and almost every other PAR reader thinks the data is int.

I think we should switch to uint in our code ; what do y'all think?

larsoner commented 9 years ago

Sounds like the most likely candidate is little endian, unsigned integers, so +1 for me

matthew-brett commented 9 years ago

Bennett - thanks for releasing the Rosetta data - it is very useful.

Is there a good place to ask licensing questions about the Rosetta data?

BennettLandman commented 9 years ago

You can ask on our NITRC forums. We used the BIRN Data License [as shown on the front page]. Please let us know if you see something that we screwed up.


Bennett Landman, Ph.D., bennett.landman@vanderbilt.edumailto:bennett.landman@vanderbilt.edu Assistant Professor Electrical Engineering (primary), Computer Science, Biomedical Engineering, Radiology and Radiological Sciences Vanderbilt University Director of the Center for Computational Imaging Vanderbilt University Institute of Image Science

From: Matthew Brett notifications@github.com<mailto:notifications@github.com> Reply-To: nipy/nibabel reply@reply.github.com<mailto:reply@reply.github.com> Date: Monday, November 17, 2014 at 2:23 PM To: nipy/nibabel nibabel@noreply.github.com<mailto:nibabel@noreply.github.com> Cc: Bennett Landman bennett.landman@vanderbilt.edu<mailto:bennett.landman@vanderbilt.edu> Subject: Re: [nibabel] Data types in PAR / REC files (#275)

Bennett - thanks for releasing the Rosetta data - it is very useful.

Is there a good place to ask licensing questions about the Rosetta data?

— Reply to this email directly or view it on GitHubhttps://github.com/nipy/nibabel/issues/275#issuecomment-63369326.

matthew-brett commented 9 years ago

Is it possible you have not enabled the forum or mailing list for the Rosetta site yet? I can't see the links I was expecting to the left of the home page.

BennettLandman commented 9 years ago

Fixed. (again)

Bennett Landman, Ph.D., bennett.landman@vanderbilt.edumailto:bennett.landman@vanderbilt.edu Assistant Professor Electrical Engineering (primary), Computer Science, Biomedical Engineering, Radiology and Radiological Sciences Vanderbilt University Director of the Center for Computational Imaging Vanderbilt University Institute of Image Science

From: Matthew Brett notifications@github.com<mailto:notifications@github.com> Reply-To: nipy/nibabel reply@reply.github.com<mailto:reply@reply.github.com> Date: Monday, November 17, 2014 at 2:52 PM To: nipy/nibabel nibabel@noreply.github.com<mailto:nibabel@noreply.github.com> Cc: Bennett Landman bennett.landman@vanderbilt.edu<mailto:bennett.landman@vanderbilt.edu> Subject: Re: [nibabel] Data types in PAR / REC files (#275)

Is it possible you have not enabled the forum or mailing list for the Rosetta site yet? I can't see the links I was expecting to the left of the home page.

— Reply to this email directly or view it on GitHubhttps://github.com/nipy/nibabel/issues/275#issuecomment-63373564.

matthew-brett commented 9 years ago

Commit to uints - https://github.com/nipy/nibabel/pull/279

larsoner commented 9 years ago

I think this can be closed because your PR is merged, right?

Also, I got some share-able Philips PAR/REC files! We can add them with a BSD license. I've uploaded them here:

https://www.dropbox.com/s/lgy4j4brvb12mfp/parrec_test_files.zip?dl=0

Let me know when you have them so I can save some Dropbox space.

Do you have time to check these out? In particular, our interpretations of the orientations seem to be incorrect because Philips assumes a negative Y direction (or so I'm told by @mrjeffs).

matthew-brett commented 9 years ago

Yes, this can be closed, will do that when current discussion done.

Any chance you would consent to PDDL? : http://opendatacommons.org/licenses/pddl/

larsoner commented 9 years ago

Yep, we consent to PDDL.

matthew-brett commented 9 years ago

Orientations look fine in SPM. Eric - would you mind checking with your viewer? @mrjeffs - can you say why you think the orientations look off?

Eric - do you have any other conversions (say from DICOM to nifti) that we can compare against?

matthew-brett commented 9 years ago

https://bitbucket.org/nipy/nitest-parrec

larsoner commented 9 years ago

Unfortunately I only have the PAR/REC versions. @mrjeffs can you comment on the orientations when you get a chance?

matthew-brett commented 9 years ago

@mrjeffs - you can use my integration branch that has Eric's viewer and my resampling code.

https://github.com/matthew-brett/nibabel/tree/integration

With that branch you can review what the image looks like when resampled into the output coordinate space.

It doesn't really matter what arrangement the input data block is in (flips transposes etc) - as long as the affine correctly orients the data to real space - as in the output in the viewer here.

""" Show images in reference space
"""
from __future__ import print_function, absolute_import

import sys

from nibabel import load as top_load, Nifti1Image
from nibabel.processing import resample_to_output

def to_real_3d(img):
    if len(img.shape) == 4:
        img = Nifti1Image(img.get_data()[..., 0], img.affine, img.header)
    return resample_to_output(img)

def show_real_3d(fname):
    img = top_load(fname)
    real_img = to_real_3d(img)
    viewer = real_img.plot()
    viewer.show()

def main():
    show_real_3d(sys.argv[1])

if __name__ == '__main__':
    main()
mrjeffs commented 9 years ago

great timing. will do. j

On Nov 20, 2014, at 2:00 PM, Matthew Brett notifications@github.com wrote:

@mrjeffs - you can use my integration branch that has Eric's viewer and my resampling code.

https://github.com/matthew-brett/nibabel/tree/integration

With that branch you can review what the image looks like when resampled into the output coordinate space.

It doesn't really matter what arrangement the input data block is in (flips transposes etc) - as long as the affine correctly orients the data to real space - as in the output in the viewer here.

""" Show images in reference space """ from future import print_function, absolute_import

import sys

from nibabel import load as top_load, Nifti1Image from nibabel.processing import resample_to_output

def to_real_3d(img): if len(img.shape) == 4: img = Nifti1Image(img.get_data()[..., 0], img.affine, img.header) return resample_to_output(img)

def show_real_3d(fname): img = top_load(fname) real_img = to_real_3d(img) viewer = real_img.plot() viewer.show()

def main(): show_real_3d(sys.argv[1])

if name == 'main': main() — Reply to this email directly or view it on GitHub.

mrjeffs commented 9 years ago

hi matthew, being slammed these past few days i have only had the chance to test on 1.4dev from 2 weeks ago and i see that fslview shows different orientation labels depending on nii selected so you can be looking at an image with orientation labels from a disabled nii. hence the confusion, so be careful. when i paid careful attention to each files' orientation, although it is upside down the “S” is on the bottom where it belongs and “L” is on the side with my vitamin E pill which left so the affine is good. as a convenience to the user it would be great if parrec2nii or all of nibabel have an argument for output orientation (RAS, LPS, etc).

with respect to the bvals they are all good.

HOWEVER: the bvecs have the Y gradient direction reversed because the philips scanner frame of reference is the oposite for Y. X and Z are the same for all 3 vendors. since we need to be in RAS for our pipelines the reorienting coincidentally fixes the Y direction but the Z gradient needed fixing. changing the sign of the Z gradient, leaving the Y gradient alone, and swapping z orientation gave us a true axial RAS image with correct vectors and labels.

summary: no reorienting and Y gradient is opposite sign from scanner reorient into RAS and Z gradient is upside-down and sign reversal is required.

great work all.

jeff

On Nov 20, 2014, at 2:00 PM, Matthew Brett notifications@github.com wrote:

@mrjeffs - you can use my integration branch that has Eric's viewer and my resampling code.

https://github.com/matthew-brett/nibabel/tree/integration

With that branch you can review what the image looks like when resampled into the output coordinate space.

It doesn't really matter what arrangement the input data block is in (flips transposes etc) - as long as the affine correctly orients the data to real space - as in the output in the viewer here.

""" Show images in reference space """ from future import print_function, absolute_import

import sys

from nibabel import load as top_load, Nifti1Image from nibabel.processing import resample_to_output

def to_real_3d(img): if len(img.shape) == 4: img = Nifti1Image(img.get_data()[..., 0], img.affine, img.header) return resample_to_output(img)

def show_real_3d(fname): img = top_load(fname) real_img = to_real_3d(img) viewer = real_img.plot() viewer.show()

def main(): show_real_3d(sys.argv[1])

if name == 'main': main() — Reply to this email directly or view it on GitHub.

larsoner commented 9 years ago

Awesome, thanks for double-checking. So it sounds like we should add some options to parrec2nii for resampling to RAS once the resampling routines are in place, taking care to also adjust the bvals/bvecs (as part of the 1.5 release, not the upcoming 1.4 one).

larsoner commented 9 years ago

Also, Jeff was able to get some matching DICOM files (plus MRIConvert'ed to nii versions) to go with the philips PAR/REC files. Hopefully I can get those added to the bitbucket repo tonight or tomorrow sometime.

matthew-brett commented 9 years ago

Jeff / Eric,

Sorry - I did not understand what you said.

I think you were suggesting that you would like to be able to change the orientation of the voxel block, and adjust the gradient directions accordingly. Is there some software that needs the voxel block in a particular orientation?

I think you are saying that the current bvectors are off by a flip in the second voxel axis - is that correct?

For example, the output b vectors from the DTI file in https://bitbucket.org/nipy/nitest-parrec have y b vector values with a sign flip?

mrjeffs commented 9 years ago

hi Matthew, even if we did nothing but apply the bvecs as they come out to the dti the Y direction sign is reversed due to philips using different scanner frame of reference. so that needs to be addressed first. then once the vectors and images are aligned as intended then if you are building a reorienting tool to call out desired output orientation such as RAS then the vectors would change sign according to which orientation is specified and which axes is swapped for which.

jeff

On Nov 22, 2014, at 3:29 PM, Matthew Brett notifications@github.com wrote:

Jeff / Eric,

Sorry - I did not understand what you said.

I think you were suggesting that you would like to be able to change the orientation of the voxel block, and adjust the gradient directions accordingly. Is there some software that needs the voxel block in a particular orientation?

I think you are saying that the current bvectors are off by a flip in the second voxel axis - is that correct?

For example, the output b vectors from the DTI file in https://bitbucket.org/nipy/nitest-parrec have y b vector values with a sign flip?

— Reply to this email directly or view it on GitHub.

matthew-brett commented 9 years ago

Just to check, here are the current output bvecs from running parrec2nii over DTI_15DIR_SENSE_4_1.PAR in https://bitbucket.org/nipy/nitest-parrec :

0.0 -1.0 0.0 0.0 0.179 0.064 -0.71 -0.619 -0.242 0.259 0.817 0.844 0.263 0.0 -0.745 -0.973 0.0 
0.0 0.0 -1.0 0.0 0.111 -0.377 -0.052 0.438 -0.784 0.618 -0.17 -0.526 -0.955 -0.969 -0.666 -0.232 0.0 
0.0 0.0 0.0 1.0 -0.978 -0.924 -0.701 -0.651 -0.571 -0.742 -0.551 -0.106 -0.139 0.248 0.024 0.021 0.0

You are saying that the second column (corresponding to the second voxel axis) should be sign-flipped?

matthew-brett commented 9 years ago

And - can you say more about what you mean by Philips using a different frame of reference for the bvecs? I see that the PAR file says the diffusion orientations are:

#  diffusion (ap, fh, rl)                   (3*float)

Is that right?

mrjeffs commented 9 years ago

hi matthew, yes, when i look at the eigenvectors produced by the bvec file below the AP or Y axis vectors do correspond to the biology, when the signs are flipped on row 2 or Y direction then they line up right. j

On Nov 23, 2014, at 1:45 AM, Matthew Brett notifications@github.com wrote:

Just to check, here are the current output bvecs from running parrec2nii over DTI_15DIR_SENSE_4_1.PAR in https://bitbucket.org/nipy/nitest-parrec :

0.0 -1.0 0.0 0.0 0.179 0.064 -0.71 -0.619 -0.242 0.259 0.817 0.844 0.263 0.0 -0.745 -0.973 0.0 0.0 0.0 -1.0 0.0 0.111 -0.377 -0.052 0.438 -0.784 0.618 -0.17 -0.526 -0.955 -0.969 -0.666 -0.232 0.0 0.0 0.0 0.0 1.0 -0.978 -0.924 -0.701 -0.651 -0.571 -0.742 -0.551 -0.106 -0.139 0.248 0.024 0.021 0.0 You are saying that the second column (corresponding to the second voxel axis) should be sign-flipped?

— Reply to this email directly or view it on GitHub.

mrjeffs commented 9 years ago

philips uses a different frame of reference for the whole scanner not just dti or vectors. so anytime you consider cross vendor software you must account for the fact every vendor is free to choose its own frame of reference. GE and Siemens chose +y=anterior (which seems intuitively logical to me) and philips chose +y=POSTERIOR or -y=anterior. that is probably why your parrec output appears upside-down, because it is according to GE and Siemens :-).

jeff

On Nov 23, 2014, at 1:57 AM, Matthew Brett notifications@github.com wrote:

And - can you say more about what you mean by Philips using a different frame of reference for the bvecs? I see that the PAR file says the diffusion orientations are:

diffusion (ap, fh, rl) (3*float)

Is that right?

— Reply to this email directly or view it on GitHub.

mrjeffs commented 9 years ago

sorry the section below should read "the AP or Y axis vectors do NOT correspond to the biology” my bad. j

On Nov 23, 2014, at 10:56 AM, Jeff Stevenson mrjeffs@uw.edu wrote:

hi matthew, yes, when i look at the eigenvectors produced by the bvec file below the AP or Y axis vectors do correspond to the biology, when the signs are flipped on row 2 or Y direction then they line up right. j

On Nov 23, 2014, at 1:45 AM, Matthew Brett notifications@github.com wrote:

Just to check, here are the current output bvecs from running parrec2nii over DTI_15DIR_SENSE_4_1.PAR in https://bitbucket.org/nipy/nitest-parrec :

0.0 -1.0 0.0 0.0 0.179 0.064 -0.71 -0.619 -0.242 0.259 0.817 0.844 0.263 0.0 -0.745 -0.973 0.0 0.0 0.0 -1.0 0.0 0.111 -0.377 -0.052 0.438 -0.784 0.618 -0.17 -0.526 -0.955 -0.969 -0.666 -0.232 0.0 0.0 0.0 0.0 1.0 -0.978 -0.924 -0.701 -0.651 -0.571 -0.742 -0.551 -0.106 -0.139 0.248 0.024 0.021 0.0 You are saying that the second column (corresponding to the second voxel axis) should be sign-flipped?

— Reply to this email directly or view it on GitHub.

matthew-brett commented 9 years ago

We do take account of the AP, FH, RL frame of reference though, in order to get the right affine.

For the bvecs, we assume they are oriented AP, FH, RL, and then rotate / flip them to match the voxel orientations, or at least, that's what I meant the code to do - see:

https://github.com/nipy/nibabel/blob/master/nibabel/parrec.py#L700

The bvecs do look wrong, but my problem is I don't know the correct general way to fix them.

larsoner commented 9 years ago

I pushed DICOMs along with a missing .PAR file to bitbucket.org/nipy/nitest-parrec. @matthew-brett would it be possible to look at the DICOMs with various tools / converters to get some insight on what the standard procedure is?

larsoner commented 9 years ago

Could be relevant:

http://www.nitrc.org/forum/forum.php?thread_id=2886&forum_id=2

matthew-brett commented 9 years ago

Closing this one in favor of #285