Skip to content

Commit

Permalink
Better detection of TR for segmented 3D EPI sequences saved as PAR/RE…
Browse files Browse the repository at this point in the history
…C (Gilles de Hollander)
  • Loading branch information
neurolabusc committed Dec 6, 2017
1 parent 94f3129 commit 66cdf2d
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 7 deletions.
20 changes: 15 additions & 5 deletions console/nii_dicom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1376,8 +1376,9 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
#define kYmm 29
#define kTEcho 30
#define kDynTime 31
#define kGradientNumber 42
#define kbval 33
#define kInversionDelayMs 40
#define kGradientNumber 42
#define kv1 47
#define kv2 45
#define kv3 46
Expand All @@ -1387,6 +1388,8 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
float maxBValue = 0.0f;
float maxDynTime = 0.0f;
float minDynTime = 999999.0f;
int minDyn = 32767;
int maxDyn = 0;
bool ADCwarning = false;
int parVers = 0;
int maxEcho = 1;
Expand Down Expand Up @@ -1429,7 +1432,6 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
if (buff[0] == '.') { //tag
char Comment[8][50];
sscanf(buff, ". %s %s %s %s %s %s %s %s\n", Comment[0], Comment[1],Comment[2], Comment[3], Comment[4], Comment[5], Comment[6], Comment[7]);

if ((strcmp(Comment[0], "Acquisition") == 0) && (strcmp(Comment[1], "nr") == 0)) {
d.acquNum = atoi( Comment[3]);
d.seriesNum = d.acquNum;
Expand Down Expand Up @@ -1493,6 +1495,8 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
if (slice == 1) {
//for (int i = 0; i < nCols; i++)
// cols1[i] = cols[i]; //store first slice to see if dimensions or intensity scale varies between slices
//for (int i = 0; i < nCols; i++)
// printMessage("%d %g\n",i, cols[i]); //store first slice to see if dimensions or intensity scale varies between slices
d.xyzDim[1] = (int) cols[kXdim];
d.xyzDim[2] = (int) cols[kYdim];
d.xyzMM[1] = cols[kXmm];
Expand All @@ -1506,6 +1510,7 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
d.angulation[3] = cols[kAngulationFHs];
d.sliceOrient = (int) cols[kSliceOrients];
d.TE = cols[kTEcho];
d.TI = cols[kInversionDelayMs];
d.bitsAllocated = (int) cols[kBitsPerVoxel];
d.bitsStored = (int) cols[kBitsPerVoxel];
d.intenIntercept = cols[kRI];
Expand All @@ -1526,6 +1531,8 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
}
if (cols[kImageType] == 0) d.isHasMagnitude = true;
if (cols[kImageType] != 0) d.isHasPhase = true;
if (cols[kDyn] > maxDyn) maxDyn = (int) cols[kDyn];
if (cols[kDyn] < minDyn) minDyn = (int) cols[kDyn];
if (cols[kDynTime] > maxDynTime) maxDynTime = cols[kDynTime];
if (cols[kDynTime] < minDynTime) minDynTime = cols[kDynTime];
if (cols[kEcho] > maxEcho) maxEcho = cols[kEcho];
Expand Down Expand Up @@ -1554,7 +1561,8 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
ADCwarning = true;
}*/
//666: test (cols[kDyn] == 1)
if ((cols[kDyn] == 1) && (cols[kEcho] == 1) && (cols[kCardiac] == 1) && (cols[kSlice] == 1)) { //only first slice
//(cols[kImageType] == 0) means magnitude scan
if ((cols[kImageType] == 0) && (cols[kDyn] == 1) && (cols[kEcho] == 1) && (cols[kCardiac] == 1) && (cols[kSlice] == 1)) { //only first slice
d.CSA.numDti++;
int dir = d.CSA.numDti;
if (dir <= kMaxDTI4D) {
Expand Down Expand Up @@ -1671,8 +1679,10 @@ struct TDICOMdata nii_readParRec (char * parname, int isVerbose, struct TDTI4D
printError("Unable to convert DTI [increase kMaxDTI4D]\n");
d.CSA.numDti = 0;
};
if ((maxBValue <= 0.0f) && (maxDynTime > minDynTime) && (d.CSA.numDti > 1)) {
float TRms = 1000.0f * (maxDynTime - minDynTime) / (float)(d.CSA.numDti-1);
if ((maxBValue <= 0.0f) && (maxDyn > minDyn) && (maxDynTime > minDynTime)) { //use max vs min Dyn instead of && (d.CSA.numDti > 1)
int numDyn = maxDyn - minDyn;
float TRms = 1000.0f * (maxDynTime - minDynTime) / (float)numDyn;
//float TRms = 1000.0f * (maxDynTime - minDynTime) / (float)(d.CSA.numDti-1);
if (fabs(TRms - d.TR) > 0.005f)
printWarning("Reported TR=%gms, measured TR=%gms (prospect. motion corr.?)\n", d.TR, TRms);
d.TR = TRms;
Expand Down
6 changes: 4 additions & 2 deletions console/nii_dicom_batch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ void siemensCsaAscii(const char * filename, int csaOffset, int csaLength, float
char keyStr[] = "### ASCCONV BEGIN"; //skip to start of ASCII often "### ASCCONV BEGIN ###" but also "### ASCCONV BEGIN object=MrProtDataImpl@MrProtocolData"
char *keyPos = (char *)memmem(bufferTrim, csaLengthTrim, keyStr, strlen(keyStr));
if (keyPos) {
//We could detect multi-echo MPRAGE here, e.g. "lContrasts = 4"- but ideally we want an earlier detection
csaLengthTrim -= (keyPos-bufferTrim);
char keyStrEnd[] = "### ASCCONV END";
char *keyPosEnd = (char *)memmem(keyPos, csaLengthTrim, keyStrEnd, strlen(keyStrEnd));
Expand Down Expand Up @@ -2602,7 +2603,6 @@ TWarnings setWarnings() {

bool isSameSet (struct TDICOMdata d1, struct TDICOMdata d2, struct TDCMopts* opts, struct TWarnings* warnings, bool *isMultiEcho) {
//returns true if d1 and d2 should be stacked together as a single output
*isMultiEcho = false;
if (!d1.isValid) return false;
if (!d2.isValid) return false;
if (d1.modality != d2.modality) return false; //do not stack MR and CT data!
Expand Down Expand Up @@ -2965,13 +2965,14 @@ int nii_loadDir(struct TDCMopts* opts) {
if ((dcmList[i].converted2NII == 0) && (dcmList[i].isValid)) {
int nConvert = 0;
struct TWarnings warnings = setWarnings();
bool isMultiEcho;
bool isMultiEcho = false;
for (int j = i; j < (int)nDcm; j++)
if (isSameSet(dcmList[i], dcmList[j], opts, &warnings, &isMultiEcho ) )
nConvert++;
if (nConvert < 1) nConvert = 1; //prevents compiler warning for next line: never executed since j=i always causes nConvert ++
TDCMsort * dcmSort = (TDCMsort *)malloc(nConvert * sizeof(TDCMsort));
nConvert = 0;
isMultiEcho = false;
for (int j = i; j < (int)nDcm; j++)
if (isSameSet(dcmList[i], dcmList[j], opts, &warnings, &isMultiEcho)) {
dcmSort[nConvert].indx = j;
Expand All @@ -2983,6 +2984,7 @@ int nii_loadDir(struct TDCMopts* opts) {
dcmList[j].isMultiEcho = isMultiEcho;
}
qsort(dcmSort, nConvert, sizeof(struct TDCMsort), compareTDCMsort); //sort based on series and image numbers....
//dcmList[dcmSort[0].indx].isMultiEcho = isMultiEcho;
if (opts->isVerbose)
nConvert = removeDuplicatesVerbose(nConvert, dcmSort, &nameList);
else
Expand Down

0 comments on commit 66cdf2d

Please sign in to comment.