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

Suggestions for GE dicom header info to use in BIDS sidecar #163

Closed
mick-d opened this issue Feb 19, 2018 · 71 comments
Closed

Suggestions for GE dicom header info to use in BIDS sidecar #163

mick-d opened this issue Feb 19, 2018 · 71 comments

Comments

@mick-d
Copy link

mick-d commented Feb 19, 2018

Hi,

I needed to use the BIDS sidecar created by dcm2niix for one project, and unfortunately some information about DICOM data from a GE Signa (HDxt) scanner was missing. I am opening an issue here as recommended by Chris Gorgolewski on this NeuroStars post to provide information which might be useful for the missing information I could find and the missing information I could not solve. Please find the original post below for convenience.

I could not get any of the following fields (among others) with dcm2niix (including latest version I compiled myself at the time of writing):

  • BandwidthPerPixelPhaseEncode
  • EffectiveEchoSpacing
  • TotalReadoutTime
  • SliceTiming
  • PhaseEncodingDirection

I could manually get EffectiveEchoSpacing by looking at DICOM field 0043 102c (cf GE doc) and SliceTiming by looking at DICOM field “Trigger Time”.

I could compute TotalReadoutTime with (<DICOM field “IMG Columns”> - 1) * (1 / EffectiveEchoSpacing).

However I could not find a way to get BandwidthPerPixelPhaseEncode (the DICOM field “ACQ Pixel Bandwidth” seems to be something different) and could only get part of the PhaseEncodingDirection: the direction but not the sign (direction was “j” as DICOM field “ACQ Phase Encoding Direction” was ROW).

@neurolabusc
Copy link
Collaborator

I do not have access to a GE hardware. We would need a set of validation images (ideally ones we could share publicly, so it would help other conversion tools). As an example @mharms provided publicly available Siemens data with careful attention to deriving effective echo spacing. Note his sample images systematically vary PhaseResolution, PhaseOversampling, PercentPhaseFOV, EchoTrainLength, PhaseEncodingSteps, AcquisitionMatrixPE, ReconMatrixPE, and BandwidthPerPixelPhaseEncoding.

When I wrote the BIDS export for GE data, I tried to include all the values I could reliably determine. However, in my sample datasets I was not able to determine the BIDS tags you are requesting. At the time, Paul Morgan provided my with several GE datasets designed to elucidate these values, but I was unable to confidently work these out.

One other suggestion - you may want to try Xiangrui Li's dicm2nii. I think he devoted more time than me in attempting to decode GE datasets. You may find that it provides a richer set of BIDS data than dcm2niix. If this is the case, you may want to use dicm2nii instead of dcm2niix, or alternatively since dicm2nii and dcm2niix are both open source, you can decipher the method used by dicm2nii and provide a pull request for dcm2niix. This would help all GE users who rely on dcm2niix. You should find dicm2nii and dcm2niix have relatively similar functions, as we worked together to developer our tools.

@mick-d
Copy link
Author

mick-d commented Feb 19, 2018

Many thanks for the feedback @neurolabusc. I did not know about dicm2nii. I will look into it and get back to you.

@neurolabusc
Copy link
Collaborator

Please test the latest pre-release. The notes describe the features extracted from the GE protocol data block as well as the limitations. @mick-d please test with your data and report any issues.

@mick-d
Copy link
Author

mick-d commented Mar 26, 2018

@neurolabusc Will do and report here. Thank you!

@leej3
Copy link
Contributor

leej3 commented Mar 30, 2018

I did a little more testing with this. And sat down with one of our physicists to try figure out some of the inconsistencies I was observing. Here's a summary of what we figured out:

Many EPI sequences collected at out site use an interface at the scanner console that writes to the GE proprietary "Protocol Data Block". The code code works for these nicely. This includes a stock GE epi sequence. I've linked to scans collected on a phantom in both directions below.

It seems that the phase encoding polarity cannot be extracted for multiphase EPI sequence variant used for the ADNI protocol (http://adni.loni.usc.edu) though. The sequence does not use the same console interface to specify the image polarity and so VIEWORDER is not written to the data block. Currently the code seems to "find" a VIEWORDER. I'm not sure why. If the information is buried in there somewhere else that would be great.

It appears product DTI (including ADNI scans) leaves out SLICEORDER and incorrectly specifies VIEWORDER. Again dcm2niix specifies j- for these scans. Perhaps NA or something would be more appropriate? I've again linked to scans collected in both directions below.

@roopchansinghv can add some adni epis in both directions if that would help

Thanks

John

ADNI DTIs , both directions:
https://drive.google.com/file/d/1wLCgISdE4guL_ROb4U_Lb77vVvSo7GMb/view?usp=sharing

Stock GE EPI, both directions:
https://drive.google.com/file/d/1ULITxqJ5SPn3OMKO1oV0daHaY4DEah4r/view?usp=sharing

@neurolabusc
Copy link
Collaborator

I agree, the Protocol Data Block in the sample ADNI images reports VIEWORDER "1" regardless of phase encoding direction. Is your proposed solution that we ignore VIEWORDER (and leave phase encoding direction unknown in the BIDS header) if the PHASEACCEL tag is present and greater than 1? In the example ADNI dataset PHASEACCEL "2.00". Since I do not have GE hardware available, I appreciate any advice or examples that test the robustness of dcm2niix.

By the way, since the Protocol Data Block (0025,101B) is gzip compressed, you can not view it with most DICOM header viewing utilities (e.g. dcmdump, Horos, etc). If you run dcm2niix in extreme verbosity mode -v 2, it will display the text fields of the Protocol Data Block.

@leej3
Copy link
Contributor

leej3 commented Mar 31, 2018 via email

@neurolabusc
Copy link
Collaborator

Since I suspect this will take a few weeks to sort out, I think we should push ahead with a new release. I would suggest that for the imminent release for GE images we insert the BIDS tags "ProbableSliceTiming" and "ProbablePhaseEncodingDirection", since we can often determine these but in a few corner cases our current methods fail.

@chrisfilo - do you think this is a good solution for the next stable release, or is it best to omit these tags entirely if we are not yet able to predict these values with 100% accuracy? I will use whichever approach you use. The question is whether to include tags that are usually correct and useful, but where we know there are some instances where they fail (e.g. phase direction for ADNI sample) or suspect they will fail (slice timing for multi-band).

By the way, I know that dicm2nii uses the ProtocolDataBlock SLICEORDER only when the timing can not be determined using the RTIA_Timer (0021,105E). However, none of the sample I have seen provide information in 0021,105E, so I am vary to add support for a method where I have no sample datasets.

Finally, I am set the label for this as an enhancement. These are wish list features rather than known bugs. I am eager to have a new stable release as the handling of enhanced Philips DICOM has improved a lot since December.

@chrisgorgo
Copy link
Collaborator

Thanks for looking into this!

Ideally I would keep the real field names you are fairly confident values are correct and print a warning (on stderr) when a known edge case is discovered.

@neurolabusc
Copy link
Collaborator

@chrisfilo - thanks for your rapid comments. The issue is that I know we get the wrong answer with the ADNI example, and I do not know how to detect it (adjusting PHASEACCEL is a testable hypothesis). I also know that computing slicetiming based on SLICEORDER will give the wrong value if the acquisition is sparse or hyperband (e.g. SMS/multiband). We get SLICEORDER from decoding a proprietary DICOM element, and I have very few examples of GE datasets. Therefore, the issue is how we identify BIDS tags that we suspect might be unreliable, or if we only include tags that we are confident of.

@mharms
Copy link
Collaborator

mharms commented Apr 3, 2018 via email

@neurolabusc
Copy link
Collaborator

Thanks @mharms for your input. If @chrisfilo agrees the next major release will comment out the line #define myReadGeProtocolBlock, and therefore will not attempt to decode GE's proprietary Protocol Block. Advanced users and developers will still be able to compile their own version. From what I have seen, GE changes the included fields and usage between versions. Indeed, the ADNI sample provided by @leej3 suggests that for some variations of GE the phase direction is simply not recorded in the header. I spent a lot of time testing this out, so psychologically I am in an escalation of commitment spiral. However, my sense is we tell GE users there is currently no reliable way to extract slice timing and phase encoding and perhaps they can lobby the vendor for proper support.

@chrisgorgo
Copy link
Collaborator

chrisgorgo commented Apr 3, 2018 via email

@mick-d
Copy link
Author

mick-d commented Apr 10, 2018

@neurolabusc Apologies for the delay, the data was not mine and it took time to get it back for testing.

The results are that “EffectiveEchoSpacing”, “TotalReadoutTime”, “SliceTiming” and
“PhaseEncodingDirection” are now included, although "PhaseEncodingDirection" includes direction ("i") but no sign ("+/-"). There is not "BandwidthPerPixelPhaseEncode" but there is "PixelBandwidth". I can also confirm that the first 4 fields are the same as the Matlab tool dicm2nii, while neither "BandwidthPerPixelPhaseEncode" or "PixelBandwidth" is output by that tool.

Thanks a lot.

@neurolabusc
Copy link
Collaborator

Great. Note you can recompile with the compiler flag -DmyReadGeProtocolBlock and it will report PhaseEncodingDirection with the polarity (e.g. j+ or j-). Just be aware that we know of explicit cases where this value is wrong (the ADNI file linked above). @xiangruili (of dicm2nii fame), Paul Morgan and I have looked exhaustively at the GE headers and we have concluded there is no simple and reliable method to determine these features. In theory, a system that new the GE software version and a few other features might be able to report some of these elements some of the time. However, this would require some knowledge of when these features are used.

Therefore, I am closing this issue. It seems like the current release of dcm2niix reports everything we are able to reliably extract from GE data. I strongly encourage you to contact GE and ask them to explicitly export and document the parameters that are important to you in private fields of the DICOM image (rather than in their proprietary protocol block).

@mharms
Copy link
Collaborator

mharms commented Apr 10, 2018

If I'm reading this thread correctly, the current release (without any recompiling) will report a PhaseEncodingDirection for GE data, but the polarity will always be positive? If so, I think that is dangerous, because users will have no indication that polarity is NOT included. If "direction" is to be reported, but without polarity, I think that needs its own specific tag, so as to avoid any mixing up with the existing PhaseEncodingDirection.

@xiangruili
Copy link

xiangruili commented Apr 10, 2018 via email

@mharms
Copy link
Collaborator

mharms commented Apr 10, 2018

If we can't confidently know both the direction and polarity for GE data, then I don't think there should be a PhaseEncodingDirection tag. To have such a tag in that context is going to lead to all sorts of errors. There could be a differently named tag (e.g., PhaseEncodingAxis), but I think it is really problematic to have a PhaseEncodingDirection tag that doesn't convey polarity (because there is no indication from the name that polarity is NOT being conveyed).

@neurolabusc
Copy link
Collaborator

@mharms - I always appreciate your perspective. @chrisfilo would you be willing to make a decision on this. The background is that for Siemens scanners we can determine both phaseencoding dimension as well as phaseencoding polarity. Therefore, we can complete populate the JSON header, e.g. "PhaseEncodingDirection": "j-". In contrast, we are only reliably able to determine phase encoding dimension for GE systems, so for these systems we only specify "PhaseEncodingDirection": "j" or "PhaseEncodingDirection": "i". My previous thought was that we give the user all the information we feel confident about. However, @mharms would prefer that we use a separate tag if we are unable to determine both the dimension and the polarity. I can see logic in both approaches, so I am not lobbying for one approach. Can you provide any guidance on this.

@mick-d
Copy link
Author

mick-d commented Apr 11, 2018

Thanks for the feedback @neurolabusc. For the flag "-DmyReadGeProtocolBlock", I got a warning that flag was not used when running cmake -DmyReadGeProtocolBlock=ON .. :

(`CMake Warning:
  Manually-specified variables were not used by the project:

    myReadGeProtocolBlock
`)

How should one use this flag?

@neurolabusc
Copy link
Collaborator

To build from the command line (while in the console folder) you would run:

g++ -dead_strip -O3 -I. main_console.cpp nii_foreign.cpp nii_dicom.cpp jpg_0XC3.cpp ujpeg.cpp nifti1_io_core.cpp nii_ortho.cpp nii_dicom_batch.cpp  -o dcm2niix -DmyDisableOpenJPEG -DmyReadGeProtocolBlock

@mick-d
Copy link
Author

mick-d commented Apr 12, 2018

Thanks @neurolabusc. I got the same json file than before when using this custom built (i.e. still without polarity).

Also not sure if this is a problem, but it seems the build command misinterpreted the first option -dead-strip as a debug flag followed by specific flags:

cc1plus: warning: unrecognized gcc debugging option: e
cc1plus: warning: unrecognized gcc debugging option: d
cc1plus: warning: unrecognized gcc debugging option: _
cc1plus: warning: unrecognized gcc debugging option: s
cc1plus: warning: unrecognized gcc debugging option: t
cc1plus: warning: unrecognized gcc debugging option: r
cc1plus: warning: unrecognized gcc debugging option: i
cc1plus: warning: unrecognized gcc debugging option: e
cc1plus: warning: unrecognized gcc debugging option: d
cc1plus: warning: unrecognized gcc debugging option: _
cc1plus: warning: unrecognized gcc debugging option: s
cc1plus: warning: unrecognized gcc debugging option: t
cc1plus: warning: unrecognized gcc debugging option: r
cc1plus: warning: unrecognized gcc debugging option: i
cc1plus: warning: unrecognized gcc debugging option: e
cc1plus: warning: unrecognized gcc debugging option: d
cc1plus: warning: unrecognized gcc debugging option: _
cc1plus: warning: unrecognized gcc debugging option: s
cc1plus: warning: unrecognized gcc debugging option: t
cc1plus: warning: unrecognized gcc debugging option: r
cc1plus: warning: unrecognized gcc debugging option: i
cc1plus: warning: unrecognized gcc debugging option: e
cc1plus: warning: unrecognized gcc debugging option: d
cc1plus: warning: unrecognized gcc debugging option: _
cc1plus: warning: unrecognized gcc debugging option: s
cc1plus: warning: unrecognized gcc debugging option: t
cc1plus: warning: unrecognized gcc debugging option: r
cc1plus: warning: unrecognized gcc debugging option: i
cc1plus: warning: unrecognized gcc debugging option: e
cc1plus: warning: unrecognized gcc debugging option: d
cc1plus: warning: unrecognized gcc debugging option: _
cc1plus: warning: unrecognized gcc debugging option: s
cc1plus: warning: unrecognized gcc debugging option: t
cc1plus: warning: unrecognized gcc debugging option: r
cc1plus: warning: unrecognized gcc debugging option: i
cc1plus: warning: unrecognized gcc debugging option: e
cc1plus: warning: unrecognized gcc debugging option: d
cc1plus: warning: unrecognized gcc debugging option: _
cc1plus: warning: unrecognized gcc debugging option: s
cc1plus: warning: unrecognized gcc debugging option: t
cc1plus: warning: unrecognized gcc debugging option: r
cc1plus: warning: unrecognized gcc debugging option: i
cc1plus: warning: unrecognized gcc debugging option: e
cc1plus: warning: unrecognized gcc debugging option: d
cc1plus: warning: unrecognized gcc debugging option: _
cc1plus: warning: unrecognized gcc debugging option: s
cc1plus: warning: unrecognized gcc debugging option: t
cc1plus: warning: unrecognized gcc debugging option: r
cc1plus: warning: unrecognized gcc debugging option: i
cc1plus: warning: unrecognized gcc debugging option: e
cc1plus: warning: unrecognized gcc debugging option: d
cc1plus: warning: unrecognized gcc debugging option: _
cc1plus: warning: unrecognized gcc debugging option: s
cc1plus: warning: unrecognized gcc debugging option: t
cc1plus: warning: unrecognized gcc debugging option: r
cc1plus: warning: unrecognized gcc debugging option: i
nii_dicom_batch.cpp:635:0: warning: "myReadGeProtocolBlock" redefined
  #define myReadGeProtocolBlock
 ^
<command-line>:0:0: note: this is the location of the previous definition
nii_dicom_batch.cpp: In function ‘int geProtocolBlock(const char*, int, int, int, int*, int*)’:
nii_dicom_batch.cpp:701:121: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘size_t {aka long unsigned int}’ [-Wformat=]
   printMessage("GE Protocol Block %s bytes %d compressed, %d uncompressed @ %d\n", filename, geLength, unCmpSz, geOffset);
                                                                                                                         ^

@neurolabusc
Copy link
Collaborator

You can ignore the warnings about dead strip (or just remove -dead_strip), that is a compiler script that has a few specific calls for old versions of gcc and for clang/llvm. It sounds like you are attempting to compile an older version of dcm2niix, as #define myReadGeProtocolBlock is commented out in the latest code. You can either re-download the repository or if you cloned the repository you can run git pull from the command line while in your dcm2niix folder to update your source code.

The old code automatically parsed the GE Protocol Block by defining #define myReadGeProtocolBlock. However, since the ADNI dataset provided above shows that the Protocol Block is not a reliable way to infer Phase Encoding Polarity, the new code requires you to explicitly compile for this experimental feature.

@leej3
Copy link
Contributor

leej3 commented Apr 12, 2018

Thanks again for all the help with this. It is disappointing that so many sequences from GE have this issue.

I'm sharing a full session collected by @roopchansinghv with more informative series descriptions. Hopefully this helps in the future if any further testing is required, or perhaps other GE issues. It contains GE product DTI (forward and reverse blip), multiphase EPI (forward and reversed blip), and epiRT (forward and reversed blip). As determined above, phase encoding direction should only be inferred in the last case (with epiRT).

https://drive.google.com/file/d/12KRejaoQ1FyidUQAhPze9DGawJYZqFbs/view?usp=sharing

@mick-d
Copy link
Author

mick-d commented Apr 12, 2018

Thank you for the help @neurolabusc. However, even with the latest version I did not get the polarity. Below is an extract from the resulting json file (created by the latest dcm2niix code)

"PhaseEncodingDirection": "i",
"ProbablePhaseEncodingDirection": "i",
"ConversionSoftwareVersion": "v1.0.20180403 GCC5.4.0"

@xiangruili
Copy link

xiangruili commented Apr 12, 2018 via email

@neurolabusc
Copy link
Collaborator

@mick-d according to the BIDS spec the possiblevalues:“i”,“j”,“k”,“i-”,“j-”,“k-”.
http://bids.neuroimaging.io/bids_spec.pdf
so in your case i suggests positive blip direction. As @mharms pointed out, this can cause confusion for GE data where we are not able to determine phase encoding polarity. @chrisfilo may want to weight in here. Options would be to have the option to report i+ (known positive), i- (known negative) and i (known dimension but polarity unknown), or to simply exclude the phaseEncodingDirection tag when either dimension or direction are unknown.

@neurolabusc
Copy link
Collaborator

I plan to close this issue. Users have shared three GE datasets and the current version appears to accurately report phase encoding polarity, slice timing information and b-values. This is admittedly a limited sample (in particular, only using recent 3T Discovery MR750 data). I strongly urge any GE sites to test the current code base. Since I do not have GE hardware, GE users need to take responsibility to test this software.

@captainnova
Copy link
Collaborator

captainnova commented Sep 13, 2018 via email

@jdkent
Copy link

jdkent commented Sep 13, 2018

here is another dataset from the University of Iowa's 3T GE Discovery 750, I'm hoping to get some better optics after speaking with @brussj and @vmagnotta about the data since I think my confusion lays with the descriptions of the sequences and the actual data in the dicoms.

This dataset should include all possible permutations of acquisition assuming axial slices, some acquisitions with motion, and a couple multishell dwi collections.
Int = interleaved
Seq = sequential
S-I = Superior to Inferior
I-S = Inferior to Superior
TD = Top Down
BU = Bottom Up
Mo = Motion
PA = ??? (I'm not sure what this is referring to).

I will supplement the dataset with README and description once I understand the "ground truth" of how all the images were acquired.

with my confusion and ignorance in mind, I did find it strange that for Int_I-S_TD and Int_I-S_BU I got j- for the phase encoding direction/polarity. I thought that Top Down and Bottom Up would give opposite phase encoding polarities.

@neurolabusc
Copy link
Collaborator

@jdkent I believe only series 22 reverses the phase encoding polarity (PE=1). Nikadon's Github web page describes how to reverse phase encoding polarity. TD/BU refer to the slice order for EPI volumes (e.g. head -> foot vs foot -> head). Note that you need to know BOTH the slice order and the Slice num at head top to work out the correct slice order. This is also described here. I think this explains your confusion: the slice numbering can run S-I or I-S and the ordering can be TD/BU.

To really be confident that slice order is accurate, you should acquire S-I/I-S; BU/TD data where a couple volumes have the head aligned to the scanner bore and then the head pitches rapidly within one volume. This method is described here. Nikadon attempted to acquire such a dataset but the head movements were far too slow for me to ascertain that the slice order was correct. I do not have a GE scanner, but the website provides sample SIemens data that allows you to test this.

neurolabusc added a commit that referenced this issue Sep 17, 2018
@neurolabusc
Copy link
Collaborator

@jdkent - I stand corrected. It seems like both TopDown/BottomUp and PE refer to phase encoding polarity. I have uploaded a new version that resolves this and if you choose -v 2 it will explicitly report the slice timing for images. The data below is for your sessions 6,3,5,4 which correspond to Nikadon's 7.8.9,10. Note that dcm2niix flips axial slices so the foot direction is the first on disk (mimicking Siemens):

6 SeqS->ITD (head slice first)
	Time	X	Y	Z	Instance
	0	-105	-93.4252	81.09	38
	0.2702	-105	-93.4252	77.09	39
	0.5405	-105	-93.4252	73.09	40
	0.8108	-105	-93.4252	69.09	41
...
	9.7297	-105	-93.4252	-62.91	74
"SliceTiming": [
		9.7297,
		9.4594,
		9.1891,
...
		0	],

"PhaseEncodingDirection": "j-",
	
3 SeqS->IBU (head slice first)
	Time	X	Y	Z	Instance
	0	-105	-93.4252	81.09	38
	0.2702	-105	-93.4252	77.09	39
	0.5405	-105	-93.4252	73.09	40
	0.8108	-105	-93.4252	69.09	41
...
	9.7297	-105	-93.4252	-62.91	74
	"SliceTiming": [
		9.7297,
		9.4594,
		9.1891,
...
		0	],
	
	
	"PhaseEncodingDirection": "j",
	
5 SeqI->STD (foot slice first)
	Time	X	Y	Z	Instance
	0	-105	-93.4252	-62.91	38
	0.2702	-105	-93.4252	-58.91	39
	0.5405	-105	-93.4252	-54.91	40
	0.8108	-105	-93.4252	-50.91	41
...
	9.7297	-105	-93.4252	81.09	74
"SliceTiming": [
		0,
		0.2702,
		0.5405,
		0.8108,
...
		9.7297	],	
"PhaseEncodingDirection": "j-",
	
4 SeqI->SBU (foot slice first)
	Time	X	Y	Z	Instance
	0	-105	-93.4252	-62.91	38
	0.2702	-105	-93.4252	-58.91	39
	0.5405	-105	-93.4252	-54.91	40
	0.8108	-105	-93.4252	-50.91	41
...
	9.7297	-105	-93.4252	81.09	74
"SliceTiming": [
		0,
		0.2702,
		0.5405,
		0.8108,
...
		9.7297	],
"PhaseEncodingDirection": "j",

@leej3
Copy link
Contributor

leej3 commented Sep 17, 2018

Hi I wanted to update the phase-encoding polarity extraction from GE dicoms.

I have described what I mean by phase-encoding polarity here.

The rough summary as I understand it, is that on a GE scanner you can switch the polarity by two principle mechanisms in the scanner interface that are independently implemented in the GE software internals. One way, involves setting the pepolar flag in CVs. The other method, a part of the functional MRI GE interface, switches the scan between bottom-up and top-down. A reliable way of inferring both of these can be found in GEs reconstruction byte-stream.

I have submitted a pull-request ( #227) that modifies the code to take these two settings (and their combination) into account. This reliably predicts the phase-encoding polarity for a series of scans that we collected at our facility to demonstrate this (described here) and have uploaded here.

Regarding slice-timing correction does the trigger time tag,(0018, 1060), help?

@neurolabusc
Copy link
Collaborator

@leej3 I think our messages overlapped - can you test my latest code as I think it has similar features to your pull request.

@leej3
Copy link
Contributor

leej3 commented Sep 17, 2018

Correct. The output polarity matches between your commit and mine (e6bbc91). In addition, I made a subsequent commit that now flips the polarity. This makes the direction of distortion similar for our GE and Siemens scanners. We don't know how general this is though. There's a a couple of arbitrary decisions in mapping from k-space to brain space and it may not be as consistent as we hope.

@neurolabusc
Copy link
Collaborator

@leej3 - can you see my recent update. This now uses your clearer variable naming and should replicate your method for matching sign of PhaseEncodingDirection to match the distortion between GE and Siemens. Did you test this for both AP/PA and LR/RL phase encoding polarities? I would be grateful if you could test the latest code as it should include all your suggestions and get the same output.

@leej3
Copy link
Contributor

leej3 commented Sep 17, 2018

did you push it? i don't see it on the master branch. I only compared the polarity for AP/PA. I don't have any RL/LR convenient. I can try get my hands on such a set tomorrow.

neurolabusc added a commit that referenced this issue Sep 17, 2018
@leej3
Copy link
Contributor

leej3 commented Sep 18, 2018

The outputs of c32c5b4 and f487d61 match in everything but sign now. For the test dataset with c32c5b I get:

��$grep '"PhaseEncodingDirection":' dcm2niix_c32c5b4055fb70e/*json|sort -n
dcm2niix_c32c5b4055fb70e/0003_20180907-26974_Axial_4_directions_3_shells_20180907105726_3.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0004_20180907-26974_Axial_4_directions_3_shells_pepolar_1_20180907105726_4.json:	"PhaseEncodingDirection": "j-",
dcm2niix_c32c5b4055fb70e/0005_20180907-26974_Axial_EPI__slice_order_S_to_I__20180907105726_5.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0006_20180907-26974_Axial_EPI__slice_order_I_to_S__20180907105726_6.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0007_20180907-26974_Axial_EPI-FMRI__Interleaved_S_to_I__20180907105726_7.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0008_20180907-26974_Axial_EPI-FMRI__Interleaved_I_to_S__20180907105726_8.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0010_20180907-26974_Axial_EPI-FMRI__Sequential_S_to_I__20180907105726_10.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0011_20180907-26974_Axial_EPI-FMRI__Sequential_I_to_S__20180907105726_11.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0012_20180907-26974_Axial_EPI-FMRI__RL_and_Bottom-Up__20180907105726_12.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0013_20180907-26974_Axial_EPI-FMRI__RL_and_Top-Down__20180907105726_13.json:	"PhaseEncodingDirection": "j-",
dcm2niix_c32c5b4055fb70e/0014_20180907-26974_Axial_EPI-FMRI__AP_and_Bottom-Up__20180907105726_14.json:	"PhaseEncodingDirection": "i-",
dcm2niix_c32c5b4055fb70e/0015_20180907-26974_Axial_EPI-FMRI__AP_and_Top-Down__20180907105726_15.json:	"PhaseEncodingDirection": "i",
dcm2niix_c32c5b4055fb70e/0016_20180907-26974_Axial_EPI-FMRI__RL_and_Bottom-Up_pepolar_0__20180907105726_16.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0017_20180907-26974_Axial_EPI-FMRI__RL_and_Bottom-Up_pepolar_1__20180907105726_17.json:	"PhaseEncodingDirection": "j-",
dcm2niix_c32c5b4055fb70e/0018_20180907-26974_Axial_EPI-FMRI__AP_and_Bottom-Up_pepolar_0__20180907105726_18.json:	"PhaseEncodingDirection": "i-",
dcm2niix_c32c5b4055fb70e/0019_20180907-26974_Axial_EPI-FMRI__AP_and_Bottom-Up_pepolar_1__20180907105726_19.json:	"PhaseEncodingDirection": "i",
dcm2niix_c32c5b4055fb70e/0020_20180907-26974_Axial_EPI-FMRI__RL_and_Top-Down_pepolar_1__20180907105726_20.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0021_20180907-26974_Axial_EPI-FMRI__AP_and_Top-Down_pepolar_1__20180907105726_21.json:	"PhaseEncodingDirection": "i-",
dcm2niix_c32c5b4055fb70e/0025_20180907-26974_Axial_EPI-FMRI__Interleaved_S_to_I_nodding__20180907105726_25.json:	"PhaseEncodingDirection": "j",
dcm2niix_c32c5b4055fb70e/0026_20180907-26974_Axial_EPI-FMRI__Interleaved_S_to_I_in-plane_rot__20180907105726_26.json:	"PhaseEncodingDirection": "j",

@mharms
Copy link
Collaborator

mharms commented Sep 18, 2018

I'm following the progress of this effort only tangentially, but if the dcm2niix outputs are LAS/RAS oriented, shouldn't "AP/PA" phase encoding have a PhaseEncodingDirection value of either j or j-. And "RL/LR" should have a PhaseEncodingDirection value of either i or i-. Or are the AP/PA/RL/LR labels in the file names referring to the readout direction?

@neurolabusc
Copy link
Collaborator

@mharms

I believe the NIH are referring to the readout/frequency encoding direction, as this is the dimension you set on the console. You can see this clearly in Nikadon's GE dataset where he refers to series as "freqRL" and "freqAP".
You can see this explicitly on the console screenshot from series 14 of the DWI test. The Frequency Direction is set to R/L and the resulting 0018,1312 and BIDS values are
"PhaseEncodingDirection": "j-",
"InPlanePhaseEncodingDirectionDICOM": "COL",
This is equivalent to your AP phase direction Siemens data
"PhaseEncodingDirection": "j-",
"InPlanePhaseEncodingDirectionDICOM": "COL",

@leej3
Copy link
Contributor

leej3 commented Sep 18, 2018

The confusion may be that with Siemens one explicitly sets the phase-encode direction in the protocol whereas for GE one sets the frequency/readout direction.

@Alirezamnk
Copy link

Is there any possibility in the last version of dcm2niix to get the "SliceTiming" information (Single-/Multi-band) by looking at the output json file?

@neurolabusc
Copy link
Collaborator

To detect multi-band you should be able to simply count the number of occurrences of zero in the BIDS SliceTiming field. I have also uploaded a commit that should populate the MultibandAccelerationFactor field for GE sequences where the multiband is greater than one. I do not have any data to test this solution with, so please validate this for me.

@Alirezamnk
Copy link

I think this commit is just for the Multi-Band GE data. Is it true? If we have a single-band GE dataset, how we can extract the SliceTiming order? I run this commit for a single-band GE dataset, but I didn't find anything in the output json file. Is there any possibility to extract this information like Siemens DICOM file? I do not really need the times that each slice is acquired, just the sequence they are acquired with.

@neurolabusc
Copy link
Collaborator

@Alirezamnk the latest version of dcm2niix will report both the slice timing (which allows you to infer slice order) as well as multi-band factor for GE data. However, there is a caveat that the DICOM data must populate the RTIA_timer group/element (0021,105E). The inclusion of this information seems to be optional. For example, this dataset from 24_LX_MR_Software_release:DV24.0_R02_1607.b includes this tag, while the 27_LX_MR_Software_release:DV26.0_R01_1725.a dataset does not. I do not have GE hardware, so I can not describe how to ensure the RTIA data is stored.

Therefore, at the moment dcm2niix deciphers timing to the full extent understood by the scientific community. Please provide any suggestions you have, it is possible timing information is hidden somewhere in the GE proprietary headers. Please lobby your GE research collaboration manager to provide this important sequence information in their future software.

Assuming you have RTIA timer information, slice timing will be recording in the BIDS header generated by dcm2niix:

"SliceTiming": [
		0,
		0.0453999,
		0.0908999,
...

@neurolabusc
Copy link
Collaborator

Thanks to all the users who contributed data. It seems everyone is happy with the latest solutions. Hopefully in the future GE will release new software that provides richer information. At that stage we can revisit this. The dcm2niix GE support page summarizes the information investigated in this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests