diff --git a/Siemens/README.md b/Siemens/README.md index d387031e..d4ccf048 100644 --- a/Siemens/README.md +++ b/Siemens/README.md @@ -38,6 +38,7 @@ The private `ICE_Dims` (0021,1106) tag can prove useful for parsing data. The li (0021,1106) LO [X_4_1_1_1_1_160_1_1_1_1_1_277] # ICE_Dims ``` +0. coi = [coil number](https://github.com/rordenlab/dcm2niix/issues/631) (X: combined from multiple coils) 1. eco = echo number 2. phs = phase encode 3. set = diff --git a/console/nii_dicom.cpp b/console/nii_dicom.cpp index 9c03232d..8d589d20 100644 --- a/console/nii_dicom.cpp +++ b/console/nii_dicom.cpp @@ -903,6 +903,7 @@ struct TDICOMdata clear_dicom_data() { d.CSA.multiBandFactor = 1; d.CSA.SeriesHeader_offset = 0; d.CSA.SeriesHeader_length = 0; + d.CSA.coilNumber = -1; return d; } //clear_dicom_data() @@ -1244,6 +1245,30 @@ float csaMultiFloat(unsigned char buff[], int nItems, float Floats[], int *Items return Floats[1]; } //csaMultiFloat() +int csaICEdims(unsigned char buff[]) { + //determine coil number from CSA header + //Combined images start with a letter: X_1_1_1_1_1_1_1_1_1_1_1_106 + //Coil data starts with coil number: 29_1_1_1_1_1_7_1_1_1_1_1_3000012 + TCSAitem itemCSA; + int lPos = 0; + memcpy(&itemCSA, &buff[lPos], sizeof(itemCSA)); + int coilNumber = -1; + if (itemCSA.xx2_Len > 0) { + lPos += sizeof(itemCSA); + char *cString = (char *)malloc(sizeof(char) * (itemCSA.xx2_Len)); + memcpy(cString, &buff[lPos], itemCSA.xx2_Len); //TPX memcpy(&cString, &buff[lPos], sizeof(cString)); + lPos += ((itemCSA.xx2_Len + 3) / 4) * 4; + char c = cString[0]; + if( c >= '0' && c <= '9' ){ + dcmStrDigitsOnly(cString); + char *end; + coilNumber = (int)strtol(cString, &end, 10); + } + free(cString); + } + return coilNumber; +} //csaICEdims() + bool csaIsPhaseMap(unsigned char buff[], int nItems) { //returns true if the tag "ImageHistory" has an item named "CC:ComplexAdd" TCSAitem itemCSA; @@ -1378,6 +1403,8 @@ int readCSAImageHeader(unsigned char *buff, int lLength, struct TCSAdata *CSA, i if (tagCSA.nitems > 0) { if (strcmp(tagCSA.name, "ImageHistory") == 0) CSA->isPhaseMap = csaIsPhaseMap(&buff[lPos], tagCSA.nitems); + else if (strcmp(tagCSA.name, "ICE_Dims") == 0) + CSA->coilNumber = csaICEdims(&buff[lPos]); else if (strcmp(tagCSA.name, "NumberOfImagesInMosaic") == 0) CSA->mosaicSlices = (int)round(csaMultiFloat(&buff[lPos], 1, lFloats, &itemsOK)); else if (strcmp(tagCSA.name, "B_value") == 0) { @@ -6706,6 +6733,12 @@ const uint32_t kEffectiveTE = 0x0018 + (0x9082 << 16); readCSAImageHeader(&buffer[lPos], lLength, &d.CSA, isVerbose, d.is3DAcq); //, dti4D); if (!d.isHasPhase) d.isHasPhase = d.CSA.isPhaseMap; + if ((d.CSA.coilNumber > 0) && (strlen(d.coilName) < 1)) { + sprintf(d.coilName, "%d", d.CSA.coilNumber); + //printf("issue631 coil name '%s'\n", d.coilName); + d.coilCrc = mz_crc32X((unsigned char *)&d.coilName, strlen(d.coilName)); + } + //okra break; case kCSASeriesHeaderInfo: if ((lPos + lLength) > fileLen) diff --git a/console/nii_dicom.h b/console/nii_dicom.h index 2458f75a..e6abc75c 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.20220720" +#define kDCMdate "v1.0.20220903" #define kDCMvers kDCMdate " " kJP2suf kLSsuf kCCsuf kCPUsuf static const int kMaxEPI3D = 1024; //maximum number of EPI images in Siemens Mosaic @@ -213,10 +213,9 @@ static const uint8_t MAX_NUMBER_OF_DIMENSIONS = 8; } TCSAitem; //Siemens csa item structure #endif struct TCSAdata { - float sliceTiming[kMaxEPI3D], dtiV[4], sliceNormV[4], bandwidthPerPixelPhaseEncode, sliceMeasurementDuration; - int numDti, SeriesHeader_offset, SeriesHeader_length, multiBandFactor, sliceOrder, slice_start, slice_end, mosaicSlices, protocolSliceNumber1, phaseEncodingDirectionPositive; - bool isPhaseMap; - + float sliceTiming[kMaxEPI3D], dtiV[4], sliceNormV[4], bandwidthPerPixelPhaseEncode, sliceMeasurementDuration; + int coilNumber, numDti, SeriesHeader_offset, SeriesHeader_length, multiBandFactor, sliceOrder, slice_start, slice_end, mosaicSlices, protocolSliceNumber1, phaseEncodingDirectionPositive; + bool isPhaseMap; }; struct TDICOMdata { long seriesNum;