From 625a24788fe1fac745aafc6f07906c34159037db Mon Sep 17 00:00:00 2001 From: Jaemin Shin Date: Wed, 20 Jul 2022 15:55:45 -0400 Subject: [PATCH 1/2] GE Direct field mapping (TE1/TE2) (#617) --- console/nii_dicom.cpp | 8 ++++++++ console/nii_dicom.h | 4 ++-- console/nii_dicom_batch.cpp | 11 +++++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/console/nii_dicom.cpp b/console/nii_dicom.cpp index d663de2a..9c03232d 100644 --- a/console/nii_dicom.cpp +++ b/console/nii_dicom.cpp @@ -861,6 +861,7 @@ struct TDICOMdata clear_dicom_data() { d.isLittleEndian = true; //DICOM initially always little endian d.converted2NII = 0; d.numberOfDiffusionDirectionGE = -1; + d.velocityEncodeScaleGE = 1.0; d.phaseEncodingGE = kGE_PHASE_ENCODING_POLARITY_UNKNOWN; d.rtia_timerGE = -1.0; d.rawDataRunNumber = -1; @@ -4301,6 +4302,7 @@ const uint32_t kEffectiveTE = 0x0018 + (0x9082 << 16); #define kDiffusionDirectionGEY 0x0019 + (0x10BC << 16) //DS frequency diffusion direction #define kDiffusionDirectionGEZ 0x0019 + (0x10BD << 16) //DS slice diffusion direction #define kNumberOfDiffusionDirectionGE 0x0019 + (0x10E0 << 16) ///DS NumberOfDiffusionDirection:UserData24 +#define kVelocityEncodeScaleGE 0x0019 + (0x10E2 << 16) ///DS Velocity Encode Scale #define kStudyID 0x0020 + (0x0010 << 16) #define kSeriesNum 0x0020 + (0x0011 << 16) #define kAcquNum 0x0020 + (0x0012 << 16) @@ -5633,6 +5635,12 @@ const uint32_t kEffectiveTE = 0x0018 + (0x9082 << 16); d.numberOfDiffusionDirectionGE = round(f); break; } + case kVelocityEncodeScaleGE: { + if (d.manufacturer != kMANUFACTURER_GE) + break; + d.velocityEncodeScaleGE = dcmStrFloat(lLength, &buffer[lPos]); + break; + } case kLastScanLoc: d.lastScanLoc = dcmStrFloat(lLength, &buffer[lPos]); break; diff --git a/console/nii_dicom.h b/console/nii_dicom.h index dbdfb139..2458f75a 100644 --- a/console/nii_dicom.h +++ b/console/nii_dicom.h @@ -50,7 +50,7 @@ extern "C" { #define kCPUsuf " " //unknown CPU #endif -#define kDCMdate "v1.0.20220717" +#define kDCMdate "v1.0.20220720" #define kDCMvers kDCMdate " " kJP2suf kLSsuf kCCsuf kCPUsuf static const int kMaxEPI3D = 1024; //maximum number of EPI images in Siemens Mosaic @@ -224,7 +224,7 @@ static const uint8_t MAX_NUMBER_OF_DIMENSIONS = 8; uint32_t coilCrc, seriesUidCrc, instanceUidCrc; int overlayStart[kMaxOverlay]; int postLabelDelay, shimGradientX, shimGradientY, shimGradientZ, phaseNumber, spoiling, mtState, partialFourierDirection, interp3D, aslFlags, durationLabelPulseGE, epiVersionGE, internalepiVersionGE, maxEchoNumGE, rawDataRunNumber, numberOfImagesInGridUIH, numberOfDiffusionDirectionGE, phaseEncodingGE, protocolBlockStartGE, protocolBlockLengthGE, modality, dwellTime, effectiveEchoSpacingGE, phaseEncodingLines, phaseEncodingSteps, echoTrainLength, echoNum, sliceOrient, manufacturer, converted2NII, acquNum, imageNum, imageStart, imageBytes, bitsStored, bitsAllocated, samplesPerPixel,locationsInAcquisition, locationsInAcquisitionConflict, compressionScheme; - float xRayTubeCurrent, exposureTimeMs, numberOfExcitations, numberOfArms, numberOfPointsPerArm, groupDelay, decayFactor, percentSampling,waterFatShift, numberOfAverages, imagingFrequency, patientWeight, zSpacing, zThick, pixelBandwidth, SAR, phaseFieldofView, accelFactPE, accelFactOOP, flipAngle, fieldStrength, TE, TI, TR, intenScale, intenIntercept, intenScalePhilips, gantryTilt, lastScanLoc, angulation[4]; + float xRayTubeCurrent, exposureTimeMs, numberOfExcitations, numberOfArms, numberOfPointsPerArm, groupDelay, decayFactor, percentSampling,waterFatShift, numberOfAverages, imagingFrequency, patientWeight, zSpacing, zThick, pixelBandwidth, SAR, phaseFieldofView, accelFactPE, accelFactOOP, flipAngle, fieldStrength, TE, TI, TR, intenScale, intenIntercept, intenScalePhilips, gantryTilt, lastScanLoc, angulation[4], velocityEncodeScaleGE; float orient[7], patientPosition[4], patientPositionLast[4], xyzMM[4], stackOffcentre[4]; float rtia_timerGE, radionuclidePositronFraction, radionuclideTotalDose, radionuclideHalfLife, doseCalibrationFactor; //PET ISOTOPE MODULE ATTRIBUTES (C.8-57) float frameReferenceTime, frameDuration, ecat_isotope_halflife, ecat_dosage; diff --git a/console/nii_dicom_batch.cpp b/console/nii_dicom_batch.cpp index 83af5878..6e233315 100644 --- a/console/nii_dicom_batch.cpp +++ b/console/nii_dicom_batch.cpp @@ -1466,8 +1466,15 @@ tse3d: T2*/ json_Float(fp, "\t\"NumberOfAverages\": %g,\n", d.numberOfAverages); if ((d.echoNum > 1) || ((d.isMultiEcho) && (d.echoNum > 0))) fprintf(fp, "\t\"EchoNumber\": %d,\n", d.echoNum); - if ((d.TE > 0.0) && (!d.isXRay)) - fprintf(fp, "\t\"EchoTime\": %g,\n", d.TE / 1000.0); + if ((d.TE > 0.0) && (!d.isXRay)) { + if ((d.manufacturer == kMANUFACTURER_GE) && (d.isRealIsPhaseMapHz) && (d.velocityEncodeScaleGE < 0)) { //issue617, only set for GE fieldmaphz + json_Float(fp, "\t\"EchoTime1\": %g,\n", d.TE / 1000.0 ); + json_Float(fp, "\t\"EchoTime2\": %g,\n", d.TE / 1000.0 - 1/(2 * M_PI * d.velocityEncodeScaleGE)); + // delta TE = -1/(2 * pi * velocityEncodeScaleGE) + } + else + fprintf(fp, "\t\"EchoTime\": %g,\n", d.TE / 1000.0); + } //if ((d.TE2 > 0.0) && (!d.isXRay)) fprintf(fp, "\t\"EchoTime2\": %g,\n", d.TE2 / 1000.0 ); if (dti4D->frameDuration[0] < 0.0) //e.g. PET scans can have variable TR json_Float(fp, "\t\"RepetitionTime\": %g,\n", d.TR / 1000.0); From cfa4b98b4d8247ff84858c2182611976acd301a7 Mon Sep 17 00:00:00 2001 From: Jaemin Shin Date: Wed, 20 Jul 2022 16:36:21 -0400 Subject: [PATCH 2/2] GE Direct field mapping (TE1/TE2) (#617) --- console/nii_dicom_batch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/console/nii_dicom_batch.cpp b/console/nii_dicom_batch.cpp index 6e233315..5cfb3ad9 100644 --- a/console/nii_dicom_batch.cpp +++ b/console/nii_dicom_batch.cpp @@ -1469,7 +1469,7 @@ tse3d: T2*/ if ((d.TE > 0.0) && (!d.isXRay)) { if ((d.manufacturer == kMANUFACTURER_GE) && (d.isRealIsPhaseMapHz) && (d.velocityEncodeScaleGE < 0)) { //issue617, only set for GE fieldmaphz json_Float(fp, "\t\"EchoTime1\": %g,\n", d.TE / 1000.0 ); - json_Float(fp, "\t\"EchoTime2\": %g,\n", d.TE / 1000.0 - 1/(2 * M_PI * d.velocityEncodeScaleGE)); + json_Float(fp, "\t\"EchoTime2\": %g,\n", d.TE / 1000.0 - 1.0/(2.0 * M_PI * d.velocityEncodeScaleGE)); // delta TE = -1/(2 * pi * velocityEncodeScaleGE) } else