Skip to content

Commit

Permalink
Segment Philips 4D images with multiple Cardiac Trigger times (0020,9…
Browse files Browse the repository at this point in the history
…153) #189
  • Loading branch information
neurolabusc committed May 29, 2018
1 parent 1dcebfc commit 429a049
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 3 deletions.
10 changes: 9 additions & 1 deletion console/nii_dicom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,7 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
#define kYmm 29
#define kTEcho 30
#define kDynTime 31
#define kTriggerTime 32
#define kbval 33
#define kInversionDelayMs 40
#define kGradientNumber 42
Expand Down Expand Up @@ -1742,6 +1743,7 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
// dti4D->S[vol].V[0] = cols[kbval];
//dti4D->gradDynVol[vol] = gradDynVol;
dti4D->TE[vol] = cols[kTEcho];
dti4D->triggerDelayTime[vol] = cols[kTriggerTime];
if (dti4D->TE[vol] < 0) dti4D->TE[vol] = 0; //used to detect sparse volumes
dti4D->intenIntercept[vol] = cols[kRI];
dti4D->intenScale[vol] = cols[kRS];
Expand Down Expand Up @@ -1801,6 +1803,7 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
for (int i = 0; i < kMaxDTI4D; i++) {
if (dti4D->TE[i] > -1.0) {
dti4D->TE[maxVol] = dti4D->TE[i];
dti4D->triggerDelayTime[maxVol] = dti4D->triggerDelayTime[i];
dti4D->intenIntercept[maxVol] = dti4D->intenIntercept[i];
dti4D->intenScale[maxVol] = dti4D->intenScale[i];
dti4D->intenScalePhilips[maxVol] = dti4D->intenScalePhilips[i];
Expand Down Expand Up @@ -1952,6 +1955,7 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
if (dti4D->isPhase[i] != dti4D->isPhase[0]) d.isScaleOrTEVaries = true;
if (dti4D->isReal[i] != dti4D->isReal[0]) d.isScaleOrTEVaries = true;
if (dti4D->isImaginary[i] != dti4D->isImaginary[0]) d.isScaleOrTEVaries = true;
if (dti4D->triggerDelayTime[i] != dti4D->triggerDelayTime[0]) d.isScaleOrTEVaries = true;
}
//if (d.isScaleOrTEVaries)
// printWarning("Varying dimensions (echoes, phase maps, intensity scaling) will require volumes to be saved separately (hint: you may prefer dicm2nii output)\n");
Expand Down Expand Up @@ -3242,7 +3246,7 @@ void _update_tvd(struct TVolumeDiffusion* ptvd) {
struct TDCMdim { //DimensionIndexValues
uint32_t dimIdx[MAX_NUMBER_OF_DIMENSIONS];
uint32_t diskPos;
float TE, intenScale, intenIntercept, intenScalePhilips, RWVScale, RWVIntercept;
float triggerDelayTime, TE, intenScale, intenIntercept, intenScalePhilips, RWVScale, RWVIntercept;
bool isPhase;
bool isReal;
bool isImaginary;
Expand Down Expand Up @@ -3653,6 +3657,7 @@ double TE = 0.0; //most recent echo time recorded
dcmDim[numDimensionIndexValues].intenScalePhilips = d.intenScalePhilips;
dcmDim[numDimensionIndexValues].RWVScale = d.RWVScale;
dcmDim[numDimensionIndexValues].RWVIntercept = d.RWVIntercept;
dcmDim[numDimensionIndexValues].triggerDelayTime = d.triggerDelayTime;
#ifdef DEBUG_READ_NOT_WRITE
if (numDimensionIndexValues < 19) {
printMessage("dimensionIndexValues0020x9157[%d] = [", numDimensionIndexValues);
Expand Down Expand Up @@ -4161,6 +4166,7 @@ double TE = 0.0; //most recent echo time recorded
printMessage("TriggerDelayTime varies %g %g\n", trigger, d.triggerDelayTime);
}
d.triggerDelayTime = trigger;
if (isSameFloatGE(d.triggerDelayTime, 0.0)) d.triggerDelayTime = 0.0; //double to single
break; }
case kDimensionIndexValues: { // kImageNum is not enough for 4D series from Philips 5.*.
if (lLength < 4) break;
Expand Down Expand Up @@ -4957,10 +4963,12 @@ if (d.isHasPhase)
dti4D->intenScalePhilips[i] = dcmDim[j+(i * d.xyzDim[3])].intenScalePhilips;
dti4D->RWVIntercept[i] = dcmDim[j+(i * d.xyzDim[3])].RWVIntercept;
dti4D->RWVScale[i] = dcmDim[j+(i * d.xyzDim[3])].RWVScale;
dti4D->triggerDelayTime[i] = dcmDim[j+(i * d.xyzDim[3])].triggerDelayTime;
if (dti4D->TE[i] != d.TE) isTEvaries = true;
if (dti4D->intenScale[i] != d.intenScale) isScaleVaries = true;
if (dti4D->intenIntercept[i] != d.intenIntercept) isScaleVaries = true;
if (dti4D->isPhase[i] != isPhase) d.isScaleOrTEVaries = true;
if (dti4D->triggerDelayTime[i] != d.triggerDelayTime) d.isScaleOrTEVaries = true;
if (dti4D->isReal[i] != isReal) d.isScaleOrTEVaries = true;
if (dti4D->isImaginary[i] != isImaginary) d.isScaleOrTEVaries = true;
}
Expand Down
2 changes: 1 addition & 1 deletion console/nii_dicom.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ static const uint8_t MAX_NUMBER_OF_DIMENSIONS = 8;
struct TDTI S[kMaxDTI4D];
int sliceOrder[kMaxSlice2D]; // [7,3,2] means the first slice on disk should be moved to 7th position
int gradDynVol[kMaxDTI4D]; //used to parse dimensions of Philips data, e.g. file with multiple dynamics, echoes, phase+magnitude
float TE[kMaxDTI4D], RWVScale[kMaxDTI4D], RWVIntercept[kMaxDTI4D], intenScale[kMaxDTI4D], intenIntercept[kMaxDTI4D], intenScalePhilips[kMaxDTI4D];
float triggerDelayTime[kMaxDTI4D], TE[kMaxDTI4D], RWVScale[kMaxDTI4D], RWVIntercept[kMaxDTI4D], intenScale[kMaxDTI4D], intenIntercept[kMaxDTI4D], intenScalePhilips[kMaxDTI4D];
bool isReal[kMaxDTI4D];
bool isImaginary[kMaxDTI4D];
bool isPhase[kMaxDTI4D];
Expand Down
7 changes: 6 additions & 1 deletion console/nii_dicom_batch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1722,6 +1722,10 @@ int nii_createFilename(struct TDICOMdata dcm, char * niiFilename, struct TDCMopt
if (dcm.isHasMagnitude)
strcat (outname,"Mag"); //Philips enhanced with BOTH phase and Magnitude in single file
}
if (dcm.triggerDelayTime >= 1) {
sprintf(newstr, "_t%d", (int)roundf(dcm.triggerDelayTime));
strcat (outname,newstr);
}
if (strlen(outname) < 1) strcpy(outname, "dcm2nii_invalidName");
if (outname[0] == '.') outname[0] = '_'; //make sure not a hidden file
//eliminate illegal characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
Expand Down Expand Up @@ -2977,7 +2981,7 @@ int saveDcm2Nii(int nConvert, struct TDCMsort dcmSort[],struct TDICOMdata dcmLis
dti4D->gradDynVol[0] = 1;
for (int i = 1; i < dcmList[indx].xyzDim[4]; i++) {
for (int j = 0; j < i; j++)
if ((dti4D->intenIntercept[i] == dti4D->intenIntercept[j]) && (dti4D->intenScale[i] == dti4D->intenScale[j]) && (dti4D->isReal[i] == dti4D->isReal[j]) && (dti4D->isImaginary[i] == dti4D->isImaginary[j]) && (dti4D->isPhase[i] == dti4D->isPhase[j]) && (dti4D->TE[i] == dti4D->TE[j]))
if (isSameFloatGE(dti4D->triggerDelayTime[i], dti4D->triggerDelayTime[j]) && (dti4D->intenIntercept[i] == dti4D->intenIntercept[j]) && (dti4D->intenScale[i] == dti4D->intenScale[j]) && (dti4D->isReal[i] == dti4D->isReal[j]) && (dti4D->isImaginary[i] == dti4D->isImaginary[j]) && (dti4D->isPhase[i] == dti4D->isPhase[j]) && (dti4D->TE[i] == dti4D->TE[j]))
dti4D->gradDynVol[i] = dti4D->gradDynVol[j];
if (dti4D->gradDynVol[i] == 0) {
series++;
Expand All @@ -2998,6 +3002,7 @@ int saveDcm2Nii(int nConvert, struct TDCMsort dcmSort[],struct TDICOMdata dcmLis
dcmList[indx].intenScalePhilips = dti4D->intenScalePhilips[i];
dcmList[indx].RWVScale = dti4D->RWVScale[i];
dcmList[indx].RWVIntercept = dti4D->RWVIntercept[i];
dcmList[indx].triggerDelayTime = dti4D->triggerDelayTime[i];
dcmList[indx].isHasMagnitude = false;
dcmList[indx].echoNum = echoNum[i];
break;
Expand Down

0 comments on commit 429a049

Please sign in to comment.