From 686a9a8219c218cb639efb0fbed34588977c3fc7 Mon Sep 17 00:00:00 2001 From: Chris Rorden Date: Wed, 11 Oct 2017 13:57:04 -0400 Subject: [PATCH] Add patient sex, weight, etc, https://www.nitrc.org/forum/message.php?msg_id=22567 --- console/nii_dicom.cpp | 20 ++++++++++++++++++++ console/nii_dicom.h | 6 +++--- console/nii_dicom_batch.cpp | 12 ++++++++---- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/console/nii_dicom.cpp b/console/nii_dicom.cpp index 9b2b0b80..37827a19 100644 --- a/console/nii_dicom.cpp +++ b/console/nii_dicom.cpp @@ -748,6 +748,10 @@ struct TDICOMdata clear_dicom_data() { d.isLittleEndian = true; //DICOM initially always little endian d.converted2NII = 0; d.phaseEncodingRC = '?'; + d.patientSex = '?'; + d.patientWeight = 0.0; + strcpy(d.patientBirthDate, ""); + strcpy(d.patientAge, ""); d.CSA.bandwidthPerPixelPhaseEncode = 0.0; d.CSA.mosaicSlices = 0; d.CSA.sliceNormV[1] = 1.0; @@ -2730,6 +2734,10 @@ struct TDICOMdata readDICOMv(char * fname, int isVerbose, int compressFlag, stru #define kComplexImageComponent (uint32_t) 0x0008+(0x9208 << 16 )//'0008' '9208' 'CS' 'ComplexImageComponent' #define kPatientName 0x0010+(0x0010 << 16 ) #define kPatientID 0x0010+(0x0020 << 16 ) +#define kPatientBirthDate 0x0010+(0x0030 << 16 ) +#define kPatientSex 0x0010+(0x0040 << 16 ) +#define kPatientAge 0x0010+(0x1010 << 16 ) +#define kPatientWeight 0x0010+(0x1030 << 16 ) #define kAnatomicalOrientationType 0x0010+(0x2210 << 16 ) #define kBodyPartExamined 0x0018+(0x0015 << 16) #define kScanningSequence 0x0018+(0x0020 << 16) @@ -3106,6 +3114,18 @@ uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define kUnnest2 0xFFFE +(0xE0DD case kPatientID : dcmStr (lLength, &buffer[lPos], d.patientID); break; + case kPatientBirthDate : + dcmStr (lLength, &buffer[lPos], d.patientBirthDate); + break; + case kPatientSex : + d.patientSex = toupper(buffer[lPos]); //first character is either 'R'ow or 'C'ol + break; + case kPatientAge : + dcmStr (lLength, &buffer[lPos], d.patientAge); + break; + case kPatientWeight : + d.patientWeight = dcmStrFloat(lLength, &buffer[lPos]); + break; case kStationName : dcmStr (lLength, &buffer[lPos], d.stationName); break; diff --git a/console/nii_dicom.h b/console/nii_dicom.h index 68875545..7391c44a 100644 --- a/console/nii_dicom.h +++ b/console/nii_dicom.h @@ -113,17 +113,17 @@ static const int kCompressRLE = 4; //run length encoding long seriesNum; int xyzDim[5]; int modality, dwellTime, effectiveEchoSpacingGE, phaseEncodingLines, phaseEncodingSteps, echoTrainLength, patientPositionNumPhilips, coilNum, echoNum, sliceOrient,numberOfDynamicScans, manufacturer, converted2NII, acquNum, imageNum, imageStart, imageBytes, bitsStored, bitsAllocated, samplesPerPixel,patientPositionSequentialRepeats,locationsInAcquisition, compressionScheme; - float zSpacing, zThick, pixelBandwidth, SAR, phaseFieldofView, accelFactPE, flipAngle, fieldStrength, TE, TI, TR, intenScale, intenIntercept, intenScalePhilips, gantryTilt, lastScanLoc, angulation[4]; + float patientWeight, zSpacing, zThick, pixelBandwidth, SAR, phaseFieldofView, accelFactPE, flipAngle, fieldStrength, TE, TI, TR, intenScale, intenIntercept, intenScalePhilips, gantryTilt, lastScanLoc, angulation[4]; float orient[7], patientPosition[4], patientPositionLast[4], xyzMM[4], stackOffcentre[4]; float radionuclidePositronFraction, radionuclideTotalDose, radionuclideHalfLife, doseCalibrationFactor; //PET ISOTOPE MODULE ATTRIBUTES (C.8-57) float ecat_isotope_halflife, ecat_dosage; double dateTime, acquisitionTime, acquisitionDate, bandwidthPerPixelPhaseEncode; //char mrAcquisitionType[kDICOMStr] - char scanOptions[kDICOMStr], stationName[kDICOMStr], softwareVersions[kDICOMStr], deviceSerialNumber[kDICOMStr], institutionAddress[kDICOMStr], institutionName[kDICOMStr], referringPhysicianName[kDICOMStr], seriesInstanceUID[kDICOMStr], studyInstanceUID[kDICOMStr], bodyPartExamined[kDICOMStr], procedureStepDescription[kDICOMStr], imageType[kDICOMStr], institutionalDepartmentName[kDICOMStr], manufacturersModelName[kDICOMStr], patientID[kDICOMStr], patientOrient[kDICOMStr], patientName[kDICOMStr],seriesDescription[kDICOMStr], studyID[kDICOMStr], sequenceName[kDICOMStr], protocolName[kDICOMStr],sequenceVariant[kDICOMStr],scanningSequence[kDICOMStr], birthDate[kDICOMStr], gender[kDICOMStr], age[kDICOMStr], studyDate[kDICOMStr],studyTime[kDICOMStr]; + char scanOptions[kDICOMStr], stationName[kDICOMStr], softwareVersions[kDICOMStr], deviceSerialNumber[kDICOMStr], institutionAddress[kDICOMStr], institutionName[kDICOMStr], referringPhysicianName[kDICOMStr], seriesInstanceUID[kDICOMStr], studyInstanceUID[kDICOMStr], bodyPartExamined[kDICOMStr], procedureStepDescription[kDICOMStr], imageType[kDICOMStr], institutionalDepartmentName[kDICOMStr], manufacturersModelName[kDICOMStr], patientID[kDICOMStr], patientOrient[kDICOMStr], patientName[kDICOMStr],seriesDescription[kDICOMStr], studyID[kDICOMStr], sequenceName[kDICOMStr], protocolName[kDICOMStr],sequenceVariant[kDICOMStr],scanningSequence[kDICOMStr], patientBirthDate[kDICOMStr], patientAge[kDICOMStr], studyDate[kDICOMStr],studyTime[kDICOMStr]; char imageComments[kDICOMStrLarge]; struct TCSAdata CSA; bool isSegamiOasis, isDerived, isXRay, isMultiEcho, isSlicesSpatiallySequentialPhilips, isValid, is3DAcq, is2DAcq, isExplicitVR, isLittleEndian, isPlanarRGB, isSigned, isHasPhase,isHasMagnitude,isHasMixed, isFloat, isResampled; - char phaseEncodingRC; + char phaseEncodingRC, patientSex; }; size_t nii_ImgBytes(struct nifti_1_header hdr); diff --git a/console/nii_dicom_batch.cpp b/console/nii_dicom_batch.cpp index fa55b753..c358c72e 100644 --- a/console/nii_dicom_batch.cpp +++ b/console/nii_dicom_batch.cpp @@ -338,9 +338,9 @@ void nii_SaveText(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts, strcat (txtname,".txt"); //printMessage("Saving text %s\n",txtname); FILE *fp = fopen(txtname, "w"); - fprintf(fp, "%s\tField Strength:\t%g\tProtocolName:\t%s\tScanningSequence00180020:\t%s\tTE:\t%g\tTR:\t%g\tSeriesNum:\t%ld\tAcquNum:\t%d\tImageNum:\t%d\tImageComments:\t%s\tDateTime:\t%f\tName:\t%s\tConvVers:\t%s\tDoB:\t%s\tGender:\t%s\tAge:\t%s\tDimXYZT:\t%d\t%d\t%d\t%d\tCoil:\t%d\tEchoNum:\t%d\tOrient(6)\t%g\t%g\t%g\t%g\t%g\t%g\tbitsAllocated\t%d\tInputName\t%s\n", + fprintf(fp, "%s\tField Strength:\t%g\tProtocolName:\t%s\tScanningSequence00180020:\t%s\tTE:\t%g\tTR:\t%g\tSeriesNum:\t%ld\tAcquNum:\t%d\tImageNum:\t%d\tImageComments:\t%s\tDateTime:\t%f\tName:\t%s\tConvVers:\t%s\tDoB:\t%s\tGender:\t%c\tAge:\t%s\tDimXYZT:\t%d\t%d\t%d\t%d\tCoil:\t%d\tEchoNum:\t%d\tOrient(6)\t%g\t%g\t%g\t%g\t%g\t%g\tbitsAllocated\t%d\tInputName\t%s\n", pathoutname, d.fieldStrength, d.protocolName, d.scanningSequence, d.TE, d.TR, d.seriesNum, d.acquNum, d.imageNum, d.imageComments, - d.dateTime, d.patientName, kDCMvers, d.birthDate, d.gender, d.age, h->dim[1], h->dim[2], h->dim[3], h->dim[4], + d.dateTime, d.patientName, kDCMvers, d.patientBirthDate, d.patientSex, d.patientAge, h->dim[1], h->dim[2], h->dim[3], h->dim[4], d.coilNum,d.echoNum, d.orient[1], d.orient[2], d.orient[3], d.orient[4], d.orient[5], d.orient[6], d.bitsAllocated, dcmname); fclose(fp); @@ -689,8 +689,12 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts, json_Str(fp, "\t\"ReferringPhysicianName\": \"%s\",\n", d.referringPhysicianName); json_Str(fp, "\t\"StudyID\": \"%s\",\n", d.studyID); //Next lines directly reveal patient identity - // json_Str(fp, "\t\"PatientName\": \"%s\",\n", d.patientName); - // json_Str(fp, "\t\"PatientID\": \"%s\",\n", d.patientID); + json_Str(fp, "\t\"PatientName\": \"%s\",\n", d.patientName); + json_Str(fp, "\t\"PatientID\": \"%s\",\n", d.patientID); + if (d.patientSex != '?') fprintf(fp, "\t\"PatientSex\": \"%c\",\n", d.patientSex); + json_Float(fp, "\t\"PatientWeight\": %g,\n", d.patientWeight); + //d.patientBirthDate //convert from DICOM YYYYMMDD to JSON + //d.patientAge //4-digit Age String: nnnD, nnnW, nnnM, nnnY; } json_Str(fp, "\t\"BodyPartExamined\": \"%s\",\n", d.bodyPartExamined); json_Str(fp, "\t\"PatientPosition\": \"%s\",\n", d.patientOrient); // 0018,5100 = PatientPosition in DICOM