Skip to content

Commit

Permalink
Philips enhanced with embedded real/imaginary images #189
Browse files Browse the repository at this point in the history
  • Loading branch information
neurolabusc committed May 23, 2018
1 parent f09d776 commit e5fbd34
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
24 changes: 24 additions & 0 deletions console/nii_dicom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,8 @@ struct TDICOMdata clear_dicom_data() {
//~ d.patientPositionSequentialRepeats = 0;
//~ d.patientPositionRepeats = 0;
d.isHasPhase = false;
d.isHasReal = false;
d.isHasImaginary = false;
d.isHasMagnitude = false;
//d.maxGradDynVol = -1; //PAR/REC only
d.sliceOrient = kSliceOrientUnknown;
Expand Down Expand Up @@ -1728,6 +1730,8 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
dti4D->intenScale[vol] = cols[kRS];
dti4D->intenScalePhilips[vol] = cols[kSS];
dti4D->isPhase[vol] = (cols[kImageType] != 0);
//dti4D->isReal[vol]; !Nice to have an example
//dti4D->isImaginary[vol]; !Nice to have an example
}
//if (slice == 1) printWarning("%d\n", (int)cols[kEcho]);
slice = slice + (vol * d.xyzDim[3]);
Expand Down Expand Up @@ -1923,6 +1927,8 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
if (dti4D->intenScale[i] != dti4D->intenScale[0]) d.isScaleOrTEVaries = true;
if (dti4D->intenScalePhilips[i] != dti4D->intenScalePhilips[0]) d.isScaleOrTEVaries = true;
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 (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 @@ -3215,6 +3221,8 @@ struct TDCMdim { //DimensionIndexValues
uint32_t diskPos;
float TE, intenScale, intenIntercept, intenScalePhilips;
bool isPhase;
bool isReal;
bool isImaginary;
};

int compareTDCMdim(void const *item1, void const *item2) {
Expand Down Expand Up @@ -3508,6 +3516,8 @@ double TE = 0.0; //most recent echo time recorded
float vAPPhilips = 0.0;
float vFHPhilips = 0.0;
bool isPhase = false;
bool isReal = false;
bool isImaginary = false;
bool isMagnitude = false;
float patientPositionPrivate[4] = {NAN, NAN, NAN, NAN};
float patientPosition[4] = {NAN, NAN, NAN, NAN}; //used to compute slice direction for Philips 4D
Expand Down Expand Up @@ -3791,13 +3801,21 @@ double TE = 0.0; //most recent echo time recorded
case kComplexImageComponent:
if (lLength < 2) break;
isPhase = false;
isReal = false;
isImaginary = false;
isMagnitude = false;
if ((buffer[lPos]=='R') && (toupper(buffer[lPos+1]) == 'E'))
isReal = true;
if ((buffer[lPos]=='I') && (toupper(buffer[lPos+1]) == 'M'))
isImaginary = true;
if ((buffer[lPos]=='P') && (toupper(buffer[lPos+1]) == 'H'))
isPhase = true;
if ((buffer[lPos]=='M') && (toupper(buffer[lPos+1]) == 'A'))
isMagnitude = true;
//not mutually exclusive: possible for Philips enhanced DICOM to store BOTH magnitude and phase in the same image
if (isPhase) d.isHasPhase = true;
if (isReal) d.isHasReal = true;
if (isImaginary) d.isHasImaginary = true;
if (isMagnitude) d.isHasMagnitude = true;
break;
case kAcquisitionTime :
Expand Down Expand Up @@ -4019,6 +4037,8 @@ double TE = 0.0; //most recent echo time recorded
dcmDim[numDimensionIndexValues].intenScale = d.intenScale;
dcmDim[numDimensionIndexValues].intenIntercept = d.intenIntercept;
dcmDim[numDimensionIndexValues].isPhase = isPhase;
dcmDim[numDimensionIndexValues].isReal = isReal;
dcmDim[numDimensionIndexValues].isImaginary = isImaginary;
dcmDim[numDimensionIndexValues].intenScalePhilips = d.intenScalePhilips;
numDimensionIndexValues ++;
//next: add diffusion if reported
Expand Down Expand Up @@ -4850,11 +4870,15 @@ if (d.isHasPhase)
dti4D->intenScale[i] = dcmDim[j+(i * d.xyzDim[3])].intenScale;
dti4D->intenIntercept[i] = dcmDim[j+(i * d.xyzDim[3])].intenIntercept;
dti4D->isPhase[i] = dcmDim[j+(i * d.xyzDim[3])].isPhase;
dti4D->isReal[i] = dcmDim[j+(i * d.xyzDim[3])].isReal;
dti4D->isImaginary[i] = dcmDim[j+(i * d.xyzDim[3])].isImaginary;
dti4D->intenScalePhilips[i] = dcmDim[j+(i * d.xyzDim[3])].intenScalePhilips;
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->isReal[i] != isReal) d.isScaleOrTEVaries = true;
if (dti4D->isImaginary[i] != isImaginary) d.isScaleOrTEVaries = true;
}
if((isScaleVaries) || (isTEvaries)) d.isScaleOrTEVaries = true;
if (isTEvaries) d.isMultiEcho = true;
Expand Down
4 changes: 3 additions & 1 deletion console/nii_dicom.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ static const uint8_t MAX_NUMBER_OF_DIMENSIONS = 8;
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], intenScale[kMaxDTI4D], intenIntercept[kMaxDTI4D], intenScalePhilips[kMaxDTI4D];
bool isReal[kMaxDTI4D];
bool isImaginary[kMaxDTI4D];
bool isPhase[kMaxDTI4D];
};

Expand Down Expand Up @@ -139,7 +141,7 @@ static const uint8_t MAX_NUMBER_OF_DIMENSIONS = 8;
uint32_t dimensionIndexValues[MAX_NUMBER_OF_DIMENSIONS];
struct TCSAdata CSA;
//isSlicesSpatiallySequentialPhilips
bool isSegamiOasis, isScaleOrTEVaries, isDerived, isXRay, isMultiEcho, isValid, is3DAcq, is2DAcq, isExplicitVR, isLittleEndian, isPlanarRGB, isSigned, isHasPhase,isHasMagnitude,isHasMixed, isFloat, isResampled, isLocalizer;
bool isSegamiOasis, isScaleOrTEVaries, isDerived, isXRay, isMultiEcho, isValid, is3DAcq, is2DAcq, isExplicitVR, isLittleEndian, isPlanarRGB, isSigned, isHasPhase, isHasImaginary, isHasReal, isHasMagnitude,isHasMixed, isFloat, isResampled, isLocalizer;
char phaseEncodingRC, patientSex;
//uint32_t *totalSlicesIn4DOrder; //Reordering array for Philips slices
};
Expand Down
16 changes: 12 additions & 4 deletions console/nii_dicom_batch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1705,6 +1705,12 @@ int nii_createFilename(struct TDICOMdata dcm, char * niiFilename, struct TDCMopt
sprintf(newstr, "_v%04d", dcm.gradDynVol+1); //+1 as indexed from zero
strcat (outname,newstr);
}*/
if (dcm.isHasImaginary) {
strcat (outname,"_imaginary"); //has phase map
}
if (dcm.isHasReal) {
strcat (outname,"_real"); //has phase map
}
if (dcm.isHasPhase) {
strcat (outname,"_ph"); //has phase map
if (dcm.isHasMagnitude)
Expand Down Expand Up @@ -2570,7 +2576,7 @@ int saveDcm2NiiCore(int nConvert, struct TDCMsort dcmSort[],struct TDICOMdata dc
printMessage("Ignoring 2D image of series %ld %s\n", dcmList[indx].seriesNum, nameList->str[indx]);
return EXIT_SUCCESS;
}
bool saveAs3D = dcmList[indx].isHasPhase;
bool saveAs3D = dcmList[indx].isHasPhase || dcmList[indx].isHasReal || dcmList[indx].isHasImaginary;
struct nifti_1_header hdr0;
unsigned char * img = nii_loadImgXL(nameList->str[indx], &hdr0,dcmList[indx], iVaries, opts.compressFlag, opts.isVerbose, dti4D);
if (strlen(opts.imageComments) > 0) {
Expand Down Expand Up @@ -2952,7 +2958,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->isPhase[i] == dti4D->isPhase[j]) && (dti4D->TE[i] == dti4D->TE[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]))
dti4D->gradDynVol[i] = dti4D->gradDynVol[j];
if (dti4D->gradDynVol[i] == 0) {
series++;
Expand All @@ -2968,6 +2974,8 @@ int saveDcm2Nii(int nConvert, struct TDCMsort dcmSort[],struct TDICOMdata dcmLis
dcmList[indx].intenScale = dti4D->intenScale[i];
dcmList[indx].intenIntercept = dti4D->intenIntercept[i];
dcmList[indx].isHasPhase = dti4D->isPhase[i];
dcmList[indx].isHasReal = dti4D->isReal[i];
dcmList[indx].isHasImaginary = dti4D->isImaginary[i];
dcmList[indx].intenScalePhilips = dti4D->intenScalePhilips[i];
dcmList[indx].isHasMagnitude = false;
dcmList[indx].echoNum = echoNum[i];
Expand Down Expand Up @@ -3113,9 +3121,9 @@ bool isSameSet (struct TDICOMdata d1, struct TDICOMdata d2, struct TDCMopts* opt
*isMultiEcho = true;
return true; //we will stack these images, even if they differ in the following attributes
}
if (d1.isHasPhase != d2.isHasPhase) {
if ((d1.isHasImaginary != d2.isHasImaginary) || (d1.isHasPhase != d2.isHasPhase) || ((d1.isHasReal != d2.isHasReal))) {
if (!warnings->phaseVaries)
printMessage("slices not stacked: some are phase maps, others are not. Use 'merge 2D slices' option to force stacking\n");
printMessage("slices not stacked: some are phase/real/imaginary maps, others are not. Use 'merge 2D slices' option to force stacking\n");
warnings->phaseVaries = true;
return false;
}
Expand Down

0 comments on commit e5fbd34

Please sign in to comment.