From: <ts...@us...> - 2008-07-23 13:55:56
|
Revision: 3877 http://teem.svn.sourceforge.net/teem/?rev=3877&view=rev Author: tststs Date: 2008-07-23 13:56:05 +0000 (Wed, 23 Jul 2008) Log Message: ----------- Integrated code from "Using Eigenvalue Derivatives for Edge Detection in DT-MRI Data" (Schultz/Seidel, DAGM 2008). This introduces the following tengage items: tenGageCl1GradVec, tenGageCl1GradMag, tenGageCp1GradVec, tenGageCp1GradMag, tenGageCa1GradVec, tenGageCa1GradMag, tenGageTensorGradRotE for gradients of cl1, cp1, and ca1, respectively, as well as the full (third-order) tensor field gradient rotated to the tensor field's eigenframe E. Moreover, the existing item tenGageEvalGrads now avoids visual artifacts in edge maps previously caused by ill-conditioned eigenvectors. Modified Paths: -------------- teem/trunk/src/ten/enumsTen.c teem/trunk/src/ten/ten.h teem/trunk/src/ten/tenGage.c Modified: teem/trunk/src/ten/enumsTen.c =================================================================== --- teem/trunk/src/ten/enumsTen.c 2008-07-23 13:49:00 UTC (rev 3876) +++ teem/trunk/src/ten/enumsTen.c 2008-07-23 13:56:05 UTC (rev 3877) @@ -620,7 +620,14 @@ tenGageTensorLogEuclidean, tenGageTensorQuatGeoLoxK, tenGageTensorQuatGeoLoxR, - tenGageAniso + tenGageAniso, + tenGageCl1GradVec, + tenGageCl1GradMag, + tenGageCp1GradVec, + tenGageCp1GradMag, + tenGageCa1GradVec, + tenGageCa1GradMag, + tenGageTensorGradRotE }; char Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2008-07-23 13:49:00 UTC (rev 3876) +++ teem/trunk/src/ten/ten.h 2008-07-23 13:56:05 UTC (rev 3877) @@ -435,9 +435,19 @@ tenGageTensorQuatGeoLoxR, /* 149: QGL-R interpolation */ tenGageAniso, /* 150: "an", all anisos: [TEN_ANISO_MAX+1] */ + tenGageCl1GradVec, /* 151: gradient vector of cl1: [3] */ + tenGageCl1GradMag, /* 152: gradient magnitude of cl1: [1] */ + tenGageCp1GradVec, /* 153: gradient vector of cp1: [3] */ + tenGageCp1GradMag, /* 154: gradient magnitude of cp1: [1] */ + tenGageCa1GradVec, /* 155: gradient vector of ca1: [3] */ + tenGageCa1GradMag, /* 156: gradient magnitude of ca1: [1] */ + tenGageTensorGradRotE, /* 157: all tensor component gradients, + starting with confidence gradient. + Rotated such that eigenvalue + derivatives are on the diagonal: [21] */ tenGageLast }; -#define TEN_GAGE_ITEM_MAX 150 +#define TEN_GAGE_ITEM_MAX 157 /* ******** tenDwiGage* enum Modified: teem/trunk/src/ten/tenGage.c =================================================================== --- teem/trunk/src/ten/tenGage.c 2008-07-23 13:49:00 UTC (rev 3876) +++ teem/trunk/src/ten/tenGage.c 2008-07-23 13:56:05 UTC (rev 3877) @@ -227,7 +227,15 @@ {tenGageTensorQuatGeoLoxK, 7, 0, {0}, 0, 0, AIR_FALSE}, {tenGageTensorQuatGeoLoxR, 7, 0, {0}, 0, 0, AIR_FALSE}, - {tenGageAniso, TEN_ANISO_MAX+1, 0, {tenGageEval0, tenGageEval1, tenGageEval2}, 0, 0, AIR_FALSE} + {tenGageAniso, TEN_ANISO_MAX+1, 0, {tenGageEval0, tenGageEval1, tenGageEval2}, 0, 0, AIR_FALSE}, + + {tenGageCl1GradVec, 3, 1, {tenGageTrace, tenGageEval, tenGageEvalGrads}, 0, 0, AIR_FALSE}, + {tenGageCl1GradMag, 1, 1, {tenGageCl1GradVec}, 0, 0, AIR_FALSE}, + {tenGageCp1GradVec, 3, 1, {tenGageTrace, tenGageEval, tenGageEvalGrads}, 0, 0, AIR_FALSE}, + {tenGageCp1GradMag, 1, 1, {tenGageCp1GradVec}, 0, 0, AIR_FALSE}, + {tenGageCa1GradVec, 3, 1, {tenGageTrace, tenGageEval, tenGageEvalGrads}, 0, 0, AIR_FALSE}, + {tenGageCa1GradMag, 1, 1, {tenGageCa1GradVec}, 0, 0, AIR_FALSE}, + {tenGageTensorGradRotE, 21, 1, {tenGageTensorGrad, tenGageEval, tenGageEvec}, 0, 0, AIR_FALSE} }; void @@ -750,15 +758,65 @@ } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageEvalGrads)) { double matOut[9], tenOut[9]; + double tmpRes[9]; int evi; for (evi=0; evi<=2; evi++) { ELL_3MV_OUTER(matOut, evecAns + evi*3, evecAns + evi*3); TEN_M2T(tenOut, matOut); - ELL_3V_SET(pvl->directAnswer[tenGageEvalGrads] + evi*3, + ELL_3V_SET(tmpRes + evi*3, TEN_T_DOT(tenOut, gradDdXYZ + 0*7), TEN_T_DOT(tenOut, gradDdXYZ + 1*7), TEN_T_DOT(tenOut, gradDdXYZ + 2*7)); } + + /* Added 2008-06-27: In case there are duplicate eigenvalues, + * average their derivatives to avoid visible artifacs in edge + * maps. Provide a smooth transition to the ill-defined case */ + float eps=0.05; /* threshold at which we start the transition */ + + /* interpolation weights from relative eigenvalue distance */ + float rel1=(evalAns[0]-evalAns[1])/(evalAns[0]+evalAns[1]); + float rel2=(evalAns[1]-evalAns[2])/(evalAns[1]+evalAns[2]); + float w1=rel1/eps-1; + w1*=w1; + float w2=rel2/eps-1; + w2*=w2; + + if (rel1>eps) { + ELL_3V_COPY(pvl->directAnswer[tenGageEvalGrads], tmpRes); + } else { + if (rel2>eps) { + ELL_3V_SCALE_ADD2(pvl->directAnswer[tenGageEvalGrads], + 1-0.5*w1, tmpRes, 0.5*w1, tmpRes+3); + } else { + ELL_3V_SCALE_ADD3(pvl->directAnswer[tenGageEvalGrads], + 1-0.5*w1-w1*w2/6.0, tmpRes, + 0.5*w1-w1*w2/6.0, tmpRes+3, + w1*w2/3.0, tmpRes+6); + } + } + + if (rel2>eps) { + ELL_3V_COPY(pvl->directAnswer[tenGageEvalGrads]+6, tmpRes+6); + } else { + if (rel1>eps) { + ELL_3V_SCALE_ADD2(pvl->directAnswer[tenGageEvalGrads]+6, + 1-0.5*w2, tmpRes+6, 0.5*w2, tmpRes+3); + } else { + ELL_3V_SCALE_ADD3(pvl->directAnswer[tenGageEvalGrads]+6, + 1-0.5*w2-w1*w2/6.0, tmpRes+6, + 0.5*w2-w1*w2/6.0, tmpRes+3, + w1*w2/3.0, tmpRes); + } + } + + ELL_3V_ADD3(pvl->directAnswer[tenGageEvalGrads]+3, + tmpRes, tmpRes+3, tmpRes+6); + ELL_3V_ADD2(tmpRes, pvl->directAnswer[tenGageEvalGrads], + pvl->directAnswer[tenGageEvalGrads]+6); + ELL_3V_SUB(pvl->directAnswer[tenGageEvalGrads]+3, + pvl->directAnswer[tenGageEvalGrads]+3, + tmpRes); /* l2 = trace - l1 - l3 */ } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageRotTans)) { double phi1[7], phi2[7], phi3[7]; @@ -1367,6 +1425,218 @@ pvl->directAnswer[tenGageAniso][ci] = tenAnisoEval_d(evalAns, ci); } } + + /* --- cl/cp/ca gradients --- */ + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCl1GradVec)) { + vecTmp = pvl->directAnswer[tenGageCl1GradVec]; + + ELL_3V_SET(vecTmp, + (evalAns[0]*(-2*pvl->directAnswer[tenGageEvalGrads][3]-pvl->directAnswer[tenGageEvalGrads][6]) + +evalAns[1]*(2*pvl->directAnswer[tenGageEvalGrads][0]+pvl->directAnswer[tenGageEvalGrads][6]) + +evalAns[2]*(pvl->directAnswer[tenGageEvalGrads][0]-pvl->directAnswer[tenGageEvalGrads][3])) + /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0]), + (evalAns[0]*(-2*pvl->directAnswer[tenGageEvalGrads][4]-pvl->directAnswer[tenGageEvalGrads][7]) + +evalAns[1]*(2*pvl->directAnswer[tenGageEvalGrads][1]+pvl->directAnswer[tenGageEvalGrads][7]) + +evalAns[2]*(pvl->directAnswer[tenGageEvalGrads][1]-pvl->directAnswer[tenGageEvalGrads][4])) + /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0]), + (evalAns[0]*(-2*pvl->directAnswer[tenGageEvalGrads][5]-pvl->directAnswer[tenGageEvalGrads][8]) + +evalAns[1]*(2*pvl->directAnswer[tenGageEvalGrads][2]+pvl->directAnswer[tenGageEvalGrads][8]) + +evalAns[2]*(pvl->directAnswer[tenGageEvalGrads][2]-pvl->directAnswer[tenGageEvalGrads][5])) + /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0])); + } + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCl1GradMag)) { + pvl->directAnswer[tenGageCl1GradMag][0] = ELL_3V_LEN(vecTmp); + } + + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCp1GradVec)) { + vecTmp = pvl->directAnswer[tenGageCp1GradVec]; + + ELL_3V_SET(vecTmp, + 2*(evalAns[0]*(pvl->directAnswer[tenGageEvalGrads][3]-pvl->directAnswer[tenGageEvalGrads][6]) + +evalAns[1]*(-pvl->directAnswer[tenGageEvalGrads][0]-2*pvl->directAnswer[tenGageEvalGrads][6]) + +evalAns[2]*(pvl->directAnswer[tenGageEvalGrads][0]+2*pvl->directAnswer[tenGageEvalGrads][3])) + /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0]), + 2*(evalAns[0]*(pvl->directAnswer[tenGageEvalGrads][4]-pvl->directAnswer[tenGageEvalGrads][7]) + +evalAns[1]*(-pvl->directAnswer[tenGageEvalGrads][1]-2*pvl->directAnswer[tenGageEvalGrads][7]) + +evalAns[2]*(pvl->directAnswer[tenGageEvalGrads][1]+2*pvl->directAnswer[tenGageEvalGrads][4])) + /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0]), + 2*(evalAns[0]*(pvl->directAnswer[tenGageEvalGrads][5]-pvl->directAnswer[tenGageEvalGrads][8]) + +evalAns[1]*(-pvl->directAnswer[tenGageEvalGrads][2]-2*pvl->directAnswer[tenGageEvalGrads][8]) + +evalAns[2]*(pvl->directAnswer[tenGageEvalGrads][2]+2*pvl->directAnswer[tenGageEvalGrads][5])) + /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0])); + } + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCp1GradMag)) { + pvl->directAnswer[tenGageCp1GradMag][0] = ELL_3V_LEN(vecTmp); + } + + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCa1GradVec)) { + vecTmp = pvl->directAnswer[tenGageCa1GradVec]; + + ELL_3V_SET(vecTmp, + -3*((evalAns[0]+evalAns[1])*pvl->directAnswer[tenGageEvalGrads][6] + -evalAns[2]*(pvl->directAnswer[tenGageEvalGrads][0]+pvl->directAnswer[tenGageEvalGrads][3])) + /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0]), + -3*((evalAns[0]+evalAns[1])*pvl->directAnswer[tenGageEvalGrads][7] + -evalAns[2]*(pvl->directAnswer[tenGageEvalGrads][1]+pvl->directAnswer[tenGageEvalGrads][4])) + /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0]), + -3*((evalAns[0]+evalAns[1])*pvl->directAnswer[tenGageEvalGrads][8] + -evalAns[2]*(pvl->directAnswer[tenGageEvalGrads][2]+pvl->directAnswer[tenGageEvalGrads][5])) + /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0])); + } + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCa1GradMag)) { + pvl->directAnswer[tenGageCa1GradMag][0] = ELL_3V_LEN(vecTmp); + } + + /* --- tensor gradient, rotated into eigenframe of the tensor itself --- */ + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensorGradRotE)) { + /* confidence not affected by rotation */ + ELL_3V_COPY(pvl->directAnswer[tenGageTensorGradRotE], pvl->directAnswer[tenGageTensorGrad]); + + float evecsT[9], evecs[9], tmp[9], tmp2[9]; + + /* pre-compute relative eigenvalue differences to detect ill-conditioned case */ + float diff0=(evalAns[0]-evalAns[1])/(evalAns[0]+evalAns[1]); + float diff1=(evalAns[1]-evalAns[2])/(evalAns[1]+evalAns[2]); + float diff2=(evalAns[0]-evalAns[2])/(evalAns[0]+evalAns[2]); + float diffthresh=0.05; + + float rdiff0, rdiff1, rdiff2; + if (diff2>diffthresh) rdiff2=1.0; else rdiff2=diff2/diffthresh; + if (diff1>diffthresh) rdiff1=1.0; else rdiff1=diff1/diffthresh; + if (diff0>diffthresh) rdiff0=1.0; else rdiff0=diff0/diffthresh; + + ELL_3M_COPY(evecs,evecAns); + ELL_3M_TRANSPOSE(evecsT,evecs); + int i, k; + for (i=0; i<3; ++i) { + /* first, simply rotate derivatives into eigenframe of value */ + TEN_T2M(tmp,gradDdXYZ + i*7); + ell_3m_mul_f(tmp2,tmp,evecsT); + ell_3m_mul_f(tmp,evecs,tmp2); + + /* If necessary, perform a number of additional rotations to + * distribute eigenvalue derivatives equally in ill-defined + * cases. Explanation in Schultz and Seidel, "Using Eigenvalue + * Derivatives for Edge Detection in DT-MRI Data", DAGM 2008*/ + if (rdiff0<1.0) { + /* rotate around z axis */ + float phi=0.5*atan((tmp[0]-tmp[4])/(2*tmp[1])); + float R[9],RT[9]; + ELL_3M_ROTATE_Z_SET(R, (1.0-rdiff0)*phi); + ELL_3M_TRANSPOSE(RT,R); + ell_3m_mul_f(tmp2,tmp,RT); + ell_3m_mul_f(tmp,R,tmp2); + } + if (rdiff1<1.0) { + /* rotate around x axis */ + float phi=0.5*atan((tmp[4]-tmp[8])/(2*tmp[5])); + float R[9],RT[9]; + ELL_3M_ROTATE_X_SET(R, (1.0-rdiff1)*phi); + ELL_3M_TRANSPOSE(RT,R); + ell_3m_mul_f(tmp2,tmp,RT); + ell_3m_mul_f(tmp,R,tmp2); + } + if (rdiff2<1.0) { + float mean=(tmp[0]+tmp[4]+tmp[8])/3.0; + /* what's the median? */ + int midaxis=0; + if ((tmp[0]>tmp[4] && tmp[4]>tmp[8])|| + (tmp[0]<tmp[4] && tmp[4]<tmp[8])) + midaxis=1; + else if ((tmp[4]>tmp[8] && tmp[8]>tmp[0])|| + (tmp[4]<tmp[8] && tmp[8]<tmp[0])) + midaxis=2; + int axis; + float submatrix[3]; + int smallest=0; + /* do we first rotate around smallest or largest? */ + if (mean>tmp[4*midaxis]) + smallest=1; + + char sign=1; + if ((smallest && (tmp[0]<tmp[4] && tmp[0]<tmp[8])) || + (!smallest && (tmp[0]>tmp[4] && tmp[0]>tmp[8]))) { + axis=0; + submatrix[0]=tmp[4]; + submatrix[1]=tmp[5]; + submatrix[2]=tmp[8]; + if (midaxis!=1) sign=-1; + } else if ((smallest && (tmp[4]<tmp[0] && tmp[4]<tmp[8])) || + (!smallest && (tmp[4]>tmp[0] && tmp[4]>tmp[8]))) { + axis=1; + submatrix[0]=tmp[8]; + submatrix[1]=tmp[2]; + submatrix[2]=tmp[0]; + if (midaxis!=2) sign=-1; + } else { + axis=2; + submatrix[0]=tmp[0]; + submatrix[1]=tmp[1]; + submatrix[2]=tmp[4]; + if (midaxis!=0) sign=-1; + } + float isoPhi=0.0f; + float gamma=sign*(submatrix[0]-submatrix[2]); + float beta=-sign*2*submatrix[1]; + float A=sqrt(gamma*gamma+beta*beta); + float C=atan2(gamma,beta); + isoPhi=0.5*(asin(2.0/A*(mean-0.5*(submatrix[0]+submatrix[2])))-C); + /* make sure we use the minimal rotation */ + isoPhi=asin(2.0/A*(mean-0.5*(submatrix[0]+submatrix[2]))); + if (isoPhi>0) { + if (fabs(M_PI-isoPhi-C)<fabs(isoPhi-C)) + isoPhi=0.5*(M_PI-isoPhi-C); + else + isoPhi=0.5*(isoPhi-C); + } else if (isoPhi<0) { + if (fabs(-M_PI-isoPhi-C)<fabs(isoPhi-C)) + isoPhi=0.5*(-M_PI-isoPhi-C); + else + isoPhi=0.5*(isoPhi-C); + } + + /* perform the rotation */ + float R[9],RT[9]; + switch (axis) { + case 0: + ELL_3M_ROTATE_X_SET(R, (1.0-rdiff2)*isoPhi); + break; + case 1: + ELL_3M_ROTATE_Y_SET(R, (1.0-rdiff2)*isoPhi); + break; + default: + ELL_3M_ROTATE_Z_SET(R, (1.0-rdiff2)*isoPhi); + break; + } + ELL_3M_TRANSPOSE(RT,R); + ell_3m_mul_f(tmp2,tmp,RT); + ell_3m_mul_f(tmp,R,tmp2); + + /* rotate around the now corrected evec */ + axis=midaxis; + switch (midaxis) { + case 0: + ELL_3M_ROTATE_X_SET(R, (1.0-rdiff2)*0.5*atan((tmp[0]-tmp[4])/(2*tmp[1]))); + break; + case 1: + ELL_3M_ROTATE_Y_SET(R, (1.0-rdiff2)*0.5*atan((tmp[8]-tmp[0])/(2*tmp[2]))); + break; + case 2: + ELL_3M_ROTATE_Z_SET(R, (1.0-rdiff2)*0.5*atan((tmp[4]-tmp[8])/(2*tmp[5]))); + break; + } + ELL_3M_TRANSPOSE(RT,R); + ell_3m_mul_f(tmp2,tmp,RT); + ell_3m_mul_f(tmp,R,tmp2); + } + /* Now, we can set the answer */ + TEN_M2T(tmp2,tmp); + for (k=1; k<7; ++k) { + pvl->directAnswer[tenGageTensorGradRotE][3*k+i] = tmp2[k]; + } + } + } + return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ts...@us...> - 2008-08-01 08:33:48
|
Revision: 3882 http://teem.svn.sourceforge.net/teem/?rev=3882&view=rev Author: tststs Date: 2008-08-01 08:33:57 +0000 (Fri, 01 Aug 2008) Log Message: ----------- Declared the last two parameters of tenMakeSingle* "const" to avoid compiler warnings. --This line, and those below, will be ignored-- M ten/tensor.c M ten/ten.h Modified Paths: -------------- teem/trunk/src/ten/ten.h teem/trunk/src/ten/tensor.c Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2008-07-25 14:14:10 UTC (rev 3881) +++ teem/trunk/src/ten/ten.h 2008-08-01 08:33:57 UTC (rev 3882) @@ -1178,9 +1178,9 @@ TEN_EXPORT int tenEigensolve_d(double eval[3], double evec[9], const double ten[7]); TEN_EXPORT void tenMakeSingle_f(float ten[7], - float conf, float eval[3], float evec[9]); + float conf, const float eval[3], const float evec[9]); TEN_EXPORT void tenMakeSingle_d(double ten[7], - double conf, double eval[3], double evec[9]); + double conf, const double eval[3], const double evec[9]); TEN_EXPORT int tenMake(Nrrd *nout, const Nrrd *nconf, const Nrrd *neval, const Nrrd *nevec); TEN_EXPORT int tenSlice(Nrrd *nout, const Nrrd *nten, Modified: teem/trunk/src/ten/tensor.c =================================================================== --- teem/trunk/src/ten/tensor.c 2008-07-25 14:14:10 UTC (rev 3881) +++ teem/trunk/src/ten/tensor.c 2008-08-01 08:33:57 UTC (rev 3882) @@ -404,7 +404,7 @@ */ void -tenMakeSingle_f(float ten[7], float conf, float eval[3], float evec[9]) { +tenMakeSingle_f(float ten[7], float conf, const float eval[3], const float evec[9]) { double tmpMat1[9], tmpMat2[9], diag[9], evecT[9]; ELL_3M_ZERO_SET(diag); @@ -419,7 +419,7 @@ /* HEY: copy and paste! */ void -tenMakeSingle_d(double ten[7], double conf, double eval[3], double evec[9]) { +tenMakeSingle_d(double ten[7], double conf, const double eval[3], const double evec[9]) { double tmpMat1[9], tmpMat2[9], diag[9], evecT[9]; ELL_3M_ZERO_SET(diag); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2008-10-28 22:11:02
|
Revision: 3912 http://teem.svn.sourceforge.net/teem/?rev=3912&view=rev Author: kindlmann Date: 2008-10-28 22:10:57 +0000 (Tue, 28 Oct 2008) Log Message: ----------- added tenFiberStopAnisoSet, tenFiberStopDoubleSet, tenFiberStopUIntSet so that stop criteria can be set without using var-args Modified Paths: -------------- teem/trunk/src/ten/fiberMethods.c teem/trunk/src/ten/ten.h Modified: teem/trunk/src/ten/fiberMethods.c =================================================================== --- teem/trunk/src/ten/fiberMethods.c 2008-10-16 00:31:05 UTC (rev 3911) +++ teem/trunk/src/ten/fiberMethods.c 2008-10-28 22:10:57 UTC (rev 3912) @@ -527,6 +527,63 @@ return ret; } +/* to avoid var-args */ +int +tenFiberStopAnisoSet(tenFiberContext *tfx, int anisoType, double anisoThresh) { + char me[]="tenFiberStopAnisoSet", err[BIFF_STRLEN]; + + if (tenFiberStopSet(tfx, tenFiberStopAniso, anisoType, anisoThresh)) { + sprintf(err, "%s: trouble", me); + biffAdd(TEN, err); return 1; + } + return 0; +} + +/* to avoid var-args */ +int +tenFiberStopDoubleSet(tenFiberContext *tfx, int stop, double val) { + char me[]="tenFiberStopDoubleSet", err[BIFF_STRLEN]; + + switch (stop) { + case tenFiberStopLength: + case tenFiberStopMinLength: + case tenFiberStopConfidence: + case tenFiberStopRadius: + case tenFiberStopFraction: + if (tenFiberStopSet(tfx, stop, val)) { + sprintf(err, "%s: trouble", me); + biffAdd(TEN, err); return 1; + } + break; + default: + sprintf(err, "%s: given stop criterion %d (%s) isn't a double", me, + stop, airEnumStr(tenFiberStop, stop)); + biffAdd(TEN, err); return 1; + } + return 0; +} + +/* to avoid var-args */ +int +tenFiberStopUIntSet(tenFiberContext *tfx, int stop, unsigned int val) { + char me[]="tenFiberStopUIntSet", err[BIFF_STRLEN]; + + switch (stop) { + case tenFiberStopNumSteps: + case tenFiberStopMinNumSteps: + if (tenFiberStopSet(tfx, stop, val)) { + sprintf(err, "%s: trouble", me); + biffAdd(TEN, err); return 1; + } + break; + default: + sprintf(err, "%s: given stop criterion %d (%s) isn't an unsigned int", me, + stop, airEnumStr(tenFiberStop, stop)); + biffAdd(TEN, err); return 1; + } + return 0; +} + void tenFiberStopOn(tenFiberContext *tfx, int stop) { Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2008-10-16 00:31:05 UTC (rev 3911) +++ teem/trunk/src/ten/ten.h 2008-10-28 22:10:57 UTC (rev 3912) @@ -1365,6 +1365,12 @@ const double parm[NRRD_KERNEL_PARMS_NUM]); TEN_EXPORT int tenFiberIntgSet(tenFiberContext *tfx, int intg); TEN_EXPORT int tenFiberStopSet(tenFiberContext *tfx, int stop, ...); +TEN_EXPORT int tenFiberStopAnisoSet(tenFiberContext *tfx, + int anisoType, double anisoThresh); +TEN_EXPORT int tenFiberStopDoubleSet(tenFiberContext *tfx, + int stop, double val); +TEN_EXPORT int tenFiberStopUIntSet(tenFiberContext *tfx, + int stop, unsigned int val); TEN_EXPORT void tenFiberStopOn(tenFiberContext *tfx, int stop); TEN_EXPORT void tenFiberStopOff(tenFiberContext *tfx, int stop); TEN_EXPORT void tenFiberStopReset(tenFiberContext *tfx); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2008-11-03 23:22:03
|
Revision: 3917 http://teem.svn.sourceforge.net/teem/?rev=3917&view=rev Author: kindlmann Date: 2008-11-03 23:22:00 +0000 (Mon, 03 Nov 2008) Log Message: ----------- API NEW: added tenFiberMulti struct, tenFiberMultiNew(), tenFiberMultiNix(), and API CHANGE the use of tenFiberMultiTrace() and tenFiberMultiPolyData() Modified Paths: -------------- teem/trunk/src/ten/fiber.c teem/trunk/src/ten/ten.h teem/trunk/src/ten/tendFiber.c Modified: teem/trunk/src/ten/fiber.c =================================================================== --- teem/trunk/src/ten/fiber.c 2008-11-02 04:23:34 UTC (rev 3916) +++ teem/trunk/src/ten/fiber.c 2008-11-03 23:22:00 UTC (rev 3917) @@ -863,6 +863,34 @@ return 0; } +/* uses biff */ +tenFiberMulti * +tenFiberMultiNew() { + char me[]="tenFiberMultiNew", err[BIFF_STRLEN]; + tenFiberMulti *ret; + + ret = AIR_CAST(tenFiberMulti *, calloc(1, sizeof(tenFiberMulti))); + if (ret) { + ret->fiber = NULL; + ret->fiberNum = 0; + ret->fiberArr = airArrayNew(AIR_CAST(void **, &(ret->fiber)), + &(ret->fiberNum), + sizeof(tenFiberSingle), 512 /* incr */); + if (ret->fiberArr) { + airArrayStructCB(ret->fiberArr, + AIR_CAST(void (*)(void *), tenFiberSingleInit), + AIR_CAST(void (*)(void *), tenFiberSingleDone)); + } else { + sprintf(err, "%s: couldn't create airArray", me); + biffAdd(TEN, err); return NULL; + } + } else { + sprintf(err, "%s: couldn't create tenFiberMulti", me); + biffAdd(TEN, err); return NULL; + } + return ret; +} + int tenFiberMultiCheck(airArray *arr) { char me[]="tenFiberMultiCheck", err[BIFF_STRLEN]; @@ -883,36 +911,42 @@ return 0; } +tenFiberMulti * +tenFiberMultiNix(tenFiberMulti *tfm) { + + if (tfm) { + airArrayNuke(tfm->fiberArr); + airFree(tfm); + } + return NULL; +} + /* ******** tenFiberMultiTrace ** ** does tractography for a list of seedpoints ** -** "tfbsArr" is an airArray that the caller has already set up to be -** an array of tenFiberSingle pointers, with length set to represent -** the number of tenFiberSingle's that have already been allocated -** (and pointed to). +** tfml has been returned from tenFiberMultiNew() ** ** This is probably the first time that an airArray is being forced on ** Teem API users in this way, since other container structs/classes ** could probably be better here. Alas. */ int -tenFiberMultiTrace(tenFiberContext *tfx, airArray *tfbsArr, +tenFiberMultiTrace(tenFiberContext *tfx, tenFiberMulti *tfml, const Nrrd *_nseed) { char me[]="tenFiberMultiTrace", err[BIFF_STRLEN]; airArray *mop; const double *seedData; double seed[3]; unsigned int seedNum, seedIdx, fibrNum, dirNum, dirIdx; - tenFiberSingle *tfbs; Nrrd *nseed; - if (!(tfx && tfbsArr && _nseed)) { + if (!(tfx && tfml && _nseed)) { sprintf(err, "%s: got NULL pointer", me); biffAdd(TEN, err); return 1; } - if (tenFiberMultiCheck(tfbsArr)) { + if (tenFiberMultiCheck(tfml->fiberArr)) { sprintf(err, "%s: problem with fiber array", me); biffAdd(TEN, err); return 1; } @@ -940,7 +974,6 @@ /* HEY: the correctness of the use of the airArray here is quite subtle */ fibrNum = 0; - tfbs = AIR_CAST(tenFiberSingle *, tfbsArr->data); for (seedIdx=0; seedIdx<seedNum; seedIdx++) { dirNum = tenFiberDirectionNumber(tfx, seed); if (!dirNum) { @@ -951,35 +984,37 @@ for (dirIdx=0; dirIdx<dirNum; dirIdx++) { if (tfx->verbose > 1) { fprintf(stderr, "%s: dir %u/%u on seed %u/%u; len %u; # %u\n", - me, dirIdx, dirNum, seedIdx, seedNum, tfbsArr->len, fibrNum); + me, dirIdx, dirNum, seedIdx, seedNum, + tfml->fiberArr->len, fibrNum); } - /* tfbsArr->len can never be < fibrNum */ - if (tfbsArr->len == fibrNum) { - airArrayLenIncr(tfbsArr, 1); - tfbs = AIR_CAST(tenFiberSingle *, tfbsArr->data); + /* tfml->fiberArr->len can never be < fibrNum */ + if (tfml->fiberArr->len == fibrNum) { + airArrayLenIncr(tfml->fiberArr, 1); } - ELL_3V_COPY(tfbs[fibrNum].seedPos, seedData + 3*seedIdx); - tfbs[fibrNum].dirIdx = dirIdx; - tfbs[fibrNum].dirNum = dirNum; + ELL_3V_COPY(tfml->fiber[fibrNum].seedPos, seedData + 3*seedIdx); + tfml->fiber[fibrNum].dirIdx = dirIdx; + tfml->fiber[fibrNum].dirNum = dirNum; ELL_3V_COPY(seed, seedData + 3*seedIdx); - if (tenFiberSingleTrace(tfx, &(tfbs[fibrNum]), seed, dirIdx)) { + if (tenFiberSingleTrace(tfx, &(tfml->fiber[fibrNum]), seed, dirIdx)) { sprintf(err, "%s: trouble on seed (%g,%g,%g) %u/%u, dir %u/%u", me, seed[0], seed[1], seed[2], seedIdx, seedNum, dirIdx, dirNum); biffAdd(TEN, err); return 1; } if (tfx->verbose) { - if (tenFiberStopUnknown == tfbs[fibrNum].whyNowhere) { + if (tenFiberStopUnknown == tfml->fiber[fibrNum].whyNowhere) { fprintf(stderr, "%s: (%g,%g,%g) ->\n" " steps = %u,%u; len = %g,%g; whyStop = %s,%s\n", me, seed[0], seed[1], seed[2], - tfbs[fibrNum].stepNum[0], tfbs[fibrNum].stepNum[1], - tfbs[fibrNum].halfLen[0], tfbs[fibrNum].halfLen[1], - airEnumStr(tenFiberStop, tfbs[fibrNum].whyStop[0]), - airEnumStr(tenFiberStop, tfbs[fibrNum].whyStop[1])); + tfml->fiber[fibrNum].stepNum[0], + tfml->fiber[fibrNum].stepNum[1], + tfml->fiber[fibrNum].halfLen[0], + tfml->fiber[fibrNum].halfLen[1], + airEnumStr(tenFiberStop, tfml->fiber[fibrNum].whyStop[0]), + airEnumStr(tenFiberStop, tfml->fiber[fibrNum].whyStop[1])); } else { fprintf(stderr, "%s: (%g,%g,%g) -> whyNowhere: %s\n", me, seed[0], seed[1], seed[2], - airEnumStr(tenFiberStop, tfbs[fibrNum].whyNowhere)); + airEnumStr(tenFiberStop, tfml->fiber[fibrNum].whyNowhere)); } } fibrNum++; @@ -988,36 +1023,45 @@ /* if the airArray got to be its length only because of the work above, then the following will be a no-op. Otherwise, via the callbacks, it will clear out the tenFiberSingle's that we didn't create here */ - airArrayLenSet(tfbsArr, fibrNum); + airArrayLenSet(tfml->fiberArr, fibrNum); airMopOkay(mop); return 0; } +/* +******** tenFiberMultiPolyData +** +** converts tenFiberMulti to polydata. +** +** currently the tenFiberContext *tfx arg is not used, but it will +** probably be needed in the future as the way that parameters to the +** polydata creation process are passed. +*/ int tenFiberMultiPolyData(tenFiberContext *tfx, - limnPolyData *lpld, airArray *fiberArr) { + limnPolyData *lpld, tenFiberMulti *tfml) { char me[]="tenFiberMultiPolyData", err[BIFF_STRLEN]; - tenFiberSingle *fiber; unsigned int seedIdx, vertTotalNum, fiberNum, fiberIdx, vertTotalIdx; - if (!(tfx && lpld && fiberArr)) { + if (!(tfx && lpld && tfml)) { sprintf(err, "%s: got NULL pointer", me); biffAdd(TEN, err); return 1; } - if (tenFiberMultiCheck(fiberArr)) { + if (tenFiberMultiCheck(tfml->fiberArr)) { sprintf(err, "%s: problem with fiber array", me); biffAdd(TEN, err); return 1; } - fiber = AIR_CAST(tenFiberSingle *, fiberArr->data); + /* we have to count the real fibers that went somewhere, excluding + fibers that went nowhere (counted in tfml->fiberNum) */ vertTotalNum = 0; fiberNum = 0; - for (seedIdx=0; seedIdx<fiberArr->len; seedIdx++) { - if (!(tenFiberStopUnknown == fiber[seedIdx].whyNowhere)) { + for (seedIdx=0; seedIdx<tfml->fiberArr->len; seedIdx++) { + if (!(tenFiberStopUnknown == tfml->fiber[seedIdx].whyNowhere)) { continue; } - vertTotalNum += fiber[seedIdx].nvert->axis[1].size; + vertTotalNum += tfml->fiber[seedIdx].nvert->axis[1].size; fiberNum++; } @@ -1029,14 +1073,14 @@ fiberIdx = 0; vertTotalIdx = 0; - for (seedIdx=0; seedIdx<fiberArr->len; seedIdx++) { + for (seedIdx=0; seedIdx<tfml->fiberArr->len; seedIdx++) { double *vert; unsigned int vertIdx, vertNum; - if (!(tenFiberStopUnknown == fiber[seedIdx].whyNowhere)) { + if (!(tenFiberStopUnknown == tfml->fiber[seedIdx].whyNowhere)) { continue; } - vertNum = fiber[seedIdx].nvert->axis[1].size; - vert = AIR_CAST(double*, fiber[seedIdx].nvert->data); + vertNum = tfml->fiber[seedIdx].nvert->axis[1].size; + vert = AIR_CAST(double*, tfml->fiber[seedIdx].nvert->data); for (vertIdx=0; vertIdx<vertNum; vertIdx++) { ELL_3V_COPY_TT(lpld->xyzw + 4*vertTotalIdx, float, vert + 3*vertIdx); (lpld->xyzw + 4*vertTotalIdx)[3] = 1.0; Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2008-11-02 04:23:34 UTC (rev 3916) +++ teem/trunk/src/ten/ten.h 2008-11-03 23:22:00 UTC (rev 3917) @@ -816,7 +816,7 @@ /* ------- available for recording for reference, not used by ten */ double seedPos[3]; /* where was the seed point */ unsigned int dirIdx; /* which direction at seedpoint to follow */ - unsigned int dirNum; /* how many directions at seedpoint could be followed */ + unsigned int dirNum; /* how many directions at seedpnt could be followed */ /* ------- output ------- */ Nrrd *nvert; /* locations of tract vertices */ double halfLen[2]; /* (same as in tenFiberContext) */ @@ -829,6 +829,17 @@ } tenFiberSingle; /* +******** tenFiberMulti +** +** container for multiple fibers +*/ +typedef struct { + tenFiberSingle *fiber; + unsigned int fiberNum; + airArray *fiberArr; +} tenFiberMulti; + +/* ******** struct tenEmBimodalParm ** ** input and output parameters for tenEMBimodal (for fitting two @@ -1393,10 +1404,12 @@ double seed[3]); TEN_EXPORT int tenFiberSingleTrace(tenFiberContext *tfx, tenFiberSingle *tfbs, double seed[3], unsigned int which); -TEN_EXPORT int tenFiberMultiTrace(tenFiberContext *tfx, airArray *tfbsArr, +TEN_EXPORT tenFiberMulti *tenFiberMultiNew(void); +TEN_EXPORT tenFiberMulti *tenFiberMultiNix(tenFiberMulti *tfm); +TEN_EXPORT int tenFiberMultiTrace(tenFiberContext *tfx, tenFiberMulti *tfml, const Nrrd *nseed); TEN_EXPORT int tenFiberMultiPolyData(tenFiberContext *tfx, - limnPolyData *lpld, airArray *tfbsArr); + limnPolyData *lpld, tenFiberMulti *tfml); /* epireg.c */ TEN_EXPORT int _tenEpiRegThresholdFind(double *DWthrP, Nrrd **nin, Modified: teem/trunk/src/ten/tendFiber.c =================================================================== --- teem/trunk/src/ten/tendFiber.c 2008-11-02 04:23:34 UTC (rev 3916) +++ teem/trunk/src/ten/tendFiber.c 2008-11-03 23:22:00 UTC (rev 3917) @@ -37,7 +37,7 @@ char *outS; tenFiberContext *tfx; - tenFiberSingle *tfbs, *fiber; + tenFiberSingle *tfbs; NrrdKernelSpec *ksp; double start[3], step, *_stop, *stop; airEnum *ftypeEnum; @@ -47,7 +47,7 @@ Nrrd *nin, *nseed, *nmat, *_nmat; unsigned int si, stopLen, whichPath; double matx[16]={1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; - airArray *fiberArr; + tenFiberMulti *tfml; limnPolyData *fiberPld; hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nin, "-", @@ -259,16 +259,20 @@ fprintf(stderr, "%s: didn't get seed nrrd via \"-ns\"\n", me); airMopError(mop); return 1; } + tfml = tenFiberMultiNew(); + airMopAdd(mop, tfml, (airMopper)tenFiberMultiNix, airMopAlways); + /* fiberArr = airArrayNew(AIR_CAST(void **, &fiber), NULL, - sizeof(tenFiberSingle), 1024 /* incr */); + sizeof(tenFiberSingle), 1024); airArrayStructCB(fiberArr, AIR_CAST(void (*)(void *), tenFiberSingleInit), AIR_CAST(void (*)(void *), tenFiberSingleDone)); airMopAdd(mop, fiberArr, (airMopper)airArrayNuke, airMopAlways); + */ fiberPld = limnPolyDataNew(); airMopAdd(mop, fiberPld, (airMopper)limnPolyDataNix, airMopAlways); - if (tenFiberMultiTrace(tfx, fiberArr, nseed) - || tenFiberMultiPolyData(tfx, fiberPld, fiberArr)) { + if (tenFiberMultiTrace(tfx, tfml, nseed) + || tenFiberMultiPolyData(tfx, fiberPld, tfml)) { airMopAdd(mop, err = biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble:\n%s\n", me, err); airMopError(mop); return 1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2008-11-17 19:02:18
|
Revision: 3979 http://teem.svn.sourceforge.net/teem/?rev=3979&view=rev Author: kindlmann Date: 2008-11-17 19:02:12 +0000 (Mon, 17 Nov 2008) Log Message: ----------- The tend commands that take a 7-component tensor can now take a 6-component tensor and it will be silently padded out to 7 components, by a significantly hacked up PARSE() macro Modified Paths: -------------- teem/trunk/src/ten/privateTen.h teem/trunk/src/ten/tendAnplot.c teem/trunk/src/ten/tendAvg.c teem/trunk/src/ten/tendBmat.c teem/trunk/src/ten/tendEllipse.c teem/trunk/src/ten/tendEpireg.c teem/trunk/src/ten/tendEstim.c teem/trunk/src/ten/tendGlyph.c teem/trunk/src/ten/tendHelix.c teem/trunk/src/ten/tendMake.c teem/trunk/src/ten/tendSatin.c Modified: teem/trunk/src/ten/privateTen.h =================================================================== --- teem/trunk/src/ten/privateTen.h 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/privateTen.h 2008-11-17 19:02:12 UTC (rev 3979) @@ -30,8 +30,9 @@ #define TEND_CMD(name, info) \ unrrduCmd tend_##name##Cmd = { #name, info, tend_##name##Main } -/* USAGE, PARSE: both copied verbatim from unrrdu/privateUnrrdu.h */ - +/* USAGE, PARSE: both copied verbatim from unrrdu/privateUnrrdu.h, but +** then some hacking was added ... +*/ #define USAGE(info) \ if (!argc) { \ hestInfo(stderr, me, (info), hparm); \ @@ -41,20 +42,53 @@ return 2; \ } -#define PARSE() \ - if ((pret=hestParse(hopt, argc, argv, &perr, hparm))) { \ - if (1 == pret) { \ - fprintf(stderr, "%s: %s\n", me, perr); free(perr); \ - hestUsage(stderr, hopt, me, hparm); \ - airMopError(mop); \ - return 2; \ - } else { \ - /* ... like tears ... in rain. Time ... to die. */ \ - exit(1); \ - } \ +/* JUSTPARSE is called by the tend functions that do *not* take an +** input 7-component tensor volume +*/ +#define JUSTPARSE() \ + if ((pret=hestParse(hopt, argc, argv, &perr, hparm))) { \ + if (1 == pret) { \ + fprintf(stderr, "%s: %s\n", me, perr); free(perr); \ + hestUsage(stderr, hopt, me, hparm); \ + airMopError(mop); \ + return 2; \ + } else { \ + /* ... like tears ... in rain. Time ... to die. */ \ + exit(1); \ + } \ } - - + +/* +** PARSE is called by tend functions that do take a 7-component tensor +** volume, so that as a hack, we can process 6-component volumes as well, +** by padding on the confidence channel (fixed at 1.0) +*/ +#define PARSE() \ + JUSTPARSE(); \ + if (4 == nin->dim \ + && 6 == nin->axis[0].size \ + && nrrdTypeBlock != nin->type) { \ + ptrdiff_t min[4], max[4]; \ + Nrrd *ntmp; \ + /* create a confidence channel by padding on 1s */ \ + min[0] = -1; min[1] = min[2] = min[3] = 0; \ + max[0] = nin->axis[0].size-1; \ + max[1] = nin->axis[1].size-1; \ + max[2] = nin->axis[2].size-1; \ + max[3] = nin->axis[3].size-1; \ + ntmp = nrrdNew(); \ + if (nrrdPad_nva(ntmp, nin, min, max, nrrdBoundaryPad, 1.0) \ + || nrrdCopy(nin, ntmp)) { \ + char *err; \ + airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); \ + fprintf(stderr, "%s: can't pad 6-comp tensor:\n%s", me, err); \ + airMopError(mop); \ + nrrdNuke(ntmp); \ + return 2; \ + } \ + nrrdNuke(ntmp); \ + } + /* qseg.c: 2-tensor estimation */ extern void _tenQball(const double b, const int gradcount, const double svals[], const double grads[], Modified: teem/trunk/src/ten/tendAnplot.c =================================================================== --- teem/trunk/src/ten/tendAnplot.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendAnplot.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -68,7 +68,7 @@ mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_anplotInfoL); - PARSE(); + JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); Modified: teem/trunk/src/ten/tendAvg.c =================================================================== --- teem/trunk/src/ten/tendAvg.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendAvg.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -52,7 +52,7 @@ mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_avgInfoL); - PARSE(); + JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); Modified: teem/trunk/src/ten/tendBmat.c =================================================================== --- teem/trunk/src/ten/tendBmat.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendBmat.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -55,7 +55,7 @@ mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_bmatInfoL); - PARSE(); + JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); Modified: teem/trunk/src/ten/tendEllipse.c =================================================================== --- teem/trunk/src/ten/tendEllipse.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendEllipse.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -248,7 +248,7 @@ airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_ellipseInfoL); - PARSE(); + JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); if (npos) { Modified: teem/trunk/src/ten/tendEpireg.c =================================================================== --- teem/trunk/src/ten/tendEpireg.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendEpireg.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -116,7 +116,7 @@ mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_epiregInfoL); - PARSE(); + JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); if (strcmp("kvp", gradS)) { Modified: teem/trunk/src/ten/tendEstim.c =================================================================== --- teem/trunk/src/ten/tendEstim.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendEstim.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -212,7 +212,7 @@ mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_estimInfoL); - PARSE(); + JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); Modified: teem/trunk/src/ten/tendGlyph.c =================================================================== --- teem/trunk/src/ten/tendGlyph.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendGlyph.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -102,7 +102,7 @@ char *perr, *err; airArray *mop; - Nrrd *nten, *emap, *nraw, *npos, *nslc; + Nrrd *nin, *emap, *nraw, *npos, *nslc; char *outS; limnCamera *cam, *hackcams; limnObject *glyph; @@ -318,7 +318,7 @@ "don't mind me"); /* input/output */ - hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nten, "-", + hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nin, "-", "input diffusion tensor volume", NULL, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", "output file"); @@ -348,7 +348,7 @@ if (tenGlyphGen(doRT ? NULL : glyph, doRT ? scene : NULL, gparm, - nten, npos, nslc)) { + nin, npos, nslc)) { airMopAdd(mop, err = biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble generating glyphs:\n%s\n", me, err); airMopError(mop); return 1; Modified: teem/trunk/src/ten/tendHelix.c =================================================================== --- teem/trunk/src/ten/tendHelix.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendHelix.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -190,7 +190,7 @@ mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_helixInfoL); - PARSE(); + JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); Modified: teem/trunk/src/ten/tendMake.c =================================================================== --- teem/trunk/src/ten/tendMake.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendMake.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -48,7 +48,7 @@ mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_makeInfoL); - PARSE(); + JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); Modified: teem/trunk/src/ten/tendSatin.c =================================================================== --- teem/trunk/src/ten/tendSatin.c 2008-11-17 19:00:54 UTC (rev 3978) +++ teem/trunk/src/ten/tendSatin.c 2008-11-17 19:02:12 UTC (rev 3979) @@ -223,7 +223,7 @@ mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_satinInfoL); - PARSE(); + JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2008-11-19 04:49:51
|
Revision: 3992 http://teem.svn.sourceforge.net/teem/?rev=3992&view=rev Author: kindlmann Date: 2008-11-19 04:49:46 +0000 (Wed, 19 Nov 2008) Log Message: ----------- adding tend about, like unu about Modified Paths: -------------- teem/trunk/src/ten/GNUmakefile teem/trunk/src/ten/sources.cmake teem/trunk/src/ten/ten.h Added Paths: ----------- teem/trunk/src/ten/tendAbout.c Modified: teem/trunk/src/ten/GNUmakefile =================================================================== --- teem/trunk/src/ten/GNUmakefile 2008-11-18 17:25:00 UTC (rev 3991) +++ teem/trunk/src/ten/GNUmakefile 2008-11-19 04:49:46 UTC (rev 3992) @@ -51,7 +51,7 @@ $(L).OBJS = tensor.o chan.o aniso.o glyph.o enumsTen.o grads.o miscTen.o \ mod.o estimate.o tenGage.o tenDwiGage.o qseg.o path.o qglox.o \ fiberMethods.o fiber.o epireg.o defaultsTen.o bimod.o bvec.o \ - triple.o \ + triple.o tendAbout.o \ tendFlotsam.o tendGrads.o tendAnplot.o tendAnvol.o tendEval.o \ tendEvec.o tendSten.o tendExpand.o tendEvq.o tendPoint.o \ tendTriple.o tendTconv.o tendAvg.o \ Modified: teem/trunk/src/ten/sources.cmake =================================================================== --- teem/trunk/src/ten/sources.cmake 2008-11-18 17:25:00 UTC (rev 3991) +++ teem/trunk/src/ten/sources.cmake 2008-11-19 04:49:46 UTC (rev 3992) @@ -22,6 +22,7 @@ qseg.c path.c qglox.c + tendAbout.c tendAnhist.c tendAnplot.c tendAnscale.c Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2008-11-18 17:25:00 UTC (rev 3991) +++ teem/trunk/src/ten/ten.h 2008-11-19 04:49:46 UTC (rev 3992) @@ -1481,6 +1481,7 @@ #define TEND_LIST(C) &tend_##C##Cmd, /* removed from below (superseded by estim): F(calc) \ */ #define TEND_MAP(F) \ +F(about) \ F(grads) \ F(epireg) \ F(bmat) \ Added: teem/trunk/src/ten/tendAbout.c =================================================================== --- teem/trunk/src/ten/tendAbout.c (rev 0) +++ teem/trunk/src/ten/tendAbout.c 2008-11-19 04:49:46 UTC (rev 3992) @@ -0,0 +1,86 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +#define INFO "Information about this program and its use" +char *_tend_aboutInfoL = + (INFO + ". "); + +int +tend_aboutMain(int argc, char **argv, char *me, hestParm *hparm) { + char buff[AIR_STRLEN_MED], fmt[AIR_STRLEN_MED]; + char par1[] = "\t\t\t\t" + "\"tend\" is a command-line interface to much of the functionality " + "in \"ten\", a C library for diffusion image processing. Ten is one " + "library in the \"Teem\" collection of libraries. More information " + "about Teem is at <http://teem.sourceforge.net>.\n"; + char par2[] = "\t\t\t\t" + "Users are strongly encouraged to join the teem-users mailing list: " + "<http://lists.sourceforge.net/lists/listinfo/teem-users>. This is " + "the primary forum for feedback, questions, and feature requests.\n"; + char par3[] = "\t\t\t\t" + "Like \"unu\", another Teem command-line binary, it is often useful " + "to chain together invocations of tend with pipes, as in the " + "following, which estimates tensors from DWIs, takes a slice of the " + "tensor volume, computes the standard RGB colormap of the principal " + "eigenvector, and then quantizes it to an 8-bit PNG:\n"; + char par4[] = "\ttend estim -i dwi.nhdr -B kvp -knownB0 true \\\n " + " | tend slice -a 2 -p 30 \\\n " + " | tend evecrgb -c 0 -a cl2 -gam 1.2 \\\n " + " | unu quantize -b 8 -min 0 -max 1 -o z30-rgb.png\n"; + char par5[] = "\t\t\t\t" + "If tend repeatedly proves itself useful for your research, an " + "acknowledgment to that effect in your publication would be greatly " + "appreciated, such as (for LaTeX): " + "\"Dataset processing performed with the {\\tt tend} tool " + "part of the {\\tt Teem} toolkit available at " + "{\\tt\t$<$http://teem.sf.net$>$}\"\n "; + + AIR_UNUSED(argc); + AIR_UNUSED(argv); + AIR_UNUSED(me); + + fprintf(stdout, "\n"); + sprintf(buff, "--- tend: Diffusion Image Processing and Analysis ---"); + sprintf(fmt, "%%%ds\n", + (int)((hparm->columns-strlen(buff))/2 + strlen(buff) - 1)); + fprintf(stdout, fmt, buff); + sprintf(buff, "(Teem version %s, %s)", + airTeemVersion, airTeemReleaseDate); + sprintf(fmt, "%%%ds\n", + (int)((hparm->columns-strlen(buff))/2 + strlen(buff) - 1)); + fprintf(stdout, fmt, buff); + fprintf(stdout, "\n"); + + _hestPrintStr(stdout, 1, 0, 78, par1, AIR_FALSE); + _hestPrintStr(stdout, 1, 0, 78, par2, AIR_FALSE); + _hestPrintStr(stdout, 1, 0, 78, par3, AIR_FALSE); + _hestPrintStr(stdout, 2, 0, 78, par4, AIR_FALSE); + _hestPrintStr(stdout, 1, 0, 78, par5, AIR_FALSE); + + return 0; +} + +TEND_CMD(about, INFO); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2008-11-19 05:00:16
|
Revision: 3993 http://teem.svn.sourceforge.net/teem/?rev=3993&view=rev Author: kindlmann Date: 2008-11-19 05:00:12 +0000 (Wed, 19 Nov 2008) Log Message: ----------- usage information not generated by an error should go to stdout, not stderr Modified Paths: -------------- teem/trunk/src/ten/privateTen.h teem/trunk/src/ten/tendFlotsam.c Modified: teem/trunk/src/ten/privateTen.h =================================================================== --- teem/trunk/src/ten/privateTen.h 2008-11-19 04:49:46 UTC (rev 3992) +++ teem/trunk/src/ten/privateTen.h 2008-11-19 05:00:12 UTC (rev 3993) @@ -35,9 +35,9 @@ */ #define USAGE(info) \ if (!argc) { \ - hestInfo(stderr, me, (info), hparm); \ - hestUsage(stderr, hopt, me, hparm); \ - hestGlossary(stderr, hopt, hparm); \ + hestInfo(stdout, me, (info), hparm); \ + hestUsage(stdout, hopt, me, hparm); \ + hestGlossary(stdout, hopt, hparm); \ airMopError(mop); \ return 2; \ } Modified: teem/trunk/src/ten/tendFlotsam.c =================================================================== --- teem/trunk/src/ten/tendFlotsam.c 2008-11-19 04:49:46 UTC (rev 3992) +++ teem/trunk/src/ten/tendFlotsam.c 2008-11-19 05:00:12 UTC (rev 3993) @@ -51,10 +51,10 @@ maxlen = AIR_MAX(maxlen, (int)strlen(tendCmdList[i]->name)); } - sprintf(buff, "--- Diffusion Tensor Processing and Analysis ---"); + sprintf(buff, "--- Diffusion Image Processing and Analysis ---"); sprintf(fmt, "%%%ds\n", (int)((hparm->columns-strlen(buff))/2 + strlen(buff) - 1)); - fprintf(stderr, fmt, buff); + fprintf(stdout, fmt, buff); for (i=0; tendCmdList[i]; i++) { len = strlen(tendCmdList[i]->name); @@ -66,8 +66,8 @@ strcat(buff, tendCmdList[i]->name); strcat(buff, " ... "); len = strlen(buff); - fprintf(stderr, "%s", buff); - _hestPrintStr(stderr, len, len, hparm->columns, + fprintf(stdout, "%s", buff); + _hestPrintStr(stdout, len, len, hparm->columns, tendCmdList[i]->info, AIR_FALSE); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2008-12-09 11:02:03
|
Revision: 4035 http://teem.svn.sourceforge.net/teem/?rev=4035&view=rev Author: kindlmann Date: 2008-12-09 11:02:01 +0000 (Tue, 09 Dec 2008) Log Message: ----------- Integrating last fixes and changes from Arish Qazi based on his two-tensor tractography work: * If the single tensor is too planar (based on pvlData->levmarMinCp), then the two-tensor fit will not be computed * removed "ELL_3V_NORM(tfx->lastDir, tfx->lastDir, len);" from _tenFiberProbe in the case of two-tensor work; the reason why this works is not yet clear.... * the measurement frame is applied to the whole tensor, instead of just its eigenvectors Modified Paths: -------------- teem/trunk/src/ten/fiber.c teem/trunk/src/ten/tenDwiGage.c Modified: teem/trunk/src/ten/fiber.c =================================================================== --- teem/trunk/src/ten/fiber.c 2008-12-08 17:38:33 UTC (rev 4034) +++ teem/trunk/src/ten/fiber.c 2008-12-09 11:02:01 UTC (rev 4035) @@ -55,6 +55,7 @@ char me[]="_tenFiberProbe", err[BIFF_STRLEN]; double iPos[3]; int ret = 0; + double tens2[2][7]; gageShapeWtoI(tfx->gtx->shape, iPos, wPos); *gageRet = gageProbe(tfx->gtx, iPos[0], iPos[1], iPos[2]); @@ -82,7 +83,7 @@ airEnumStr(tenDwiFiberType, tfx->fiberType)); } switch (tfx->fiberType) { - double evec[2][9], eval[2][3], len; + double evec[2][9], eval[2][3]; case tenDwiFiberType1Evec0: if (tfx->mframeUse) { double matTmpA[9], matTmpB[9]; @@ -106,18 +107,27 @@ break; case tenDwiFiberType2Evec0: /* Estimate principal diffusion direction of each tensor */ - tenEigensolve_d(eval[0], evec[0], tfx->gageTen2 + 0); - tenEigensolve_d(eval[1], evec[1], tfx->gageTen2 + 7); + if (tfx->mframeUse) { + /* Transform both the tensors */ + double matTmpA[9], matTmpB[9]; - if (tfx->mframeUse) { - double vectmp[3]; - /* NOTE: only fixing first (of three) eigenvector, for both tensors */ - ELL_3MV_MUL(vectmp, tfx->mframe, evec[0]); - ELL_3V_COPY(evec[0], vectmp); - ELL_3MV_MUL(vectmp, tfx->mframe, evec[1]); - ELL_3V_COPY(evec[1], vectmp); + TEN_T2M(matTmpA, tfx->gageTen2 + 0); + ELL_3M_MUL(matTmpB, tfx->mframe, matTmpA); + ELL_3M_MUL(matTmpA, matTmpB, tfx->mframeT); + TEN_M2T(tens2[0], matTmpA); + /* new eigen values and vectors */ + tenEigensolve_d(eval[0], evec[0], tens2[0]); + + TEN_T2M(matTmpA, tfx->gageTen2 + 7); + ELL_3M_MUL(matTmpB, tfx->mframe, matTmpA); + ELL_3M_MUL(matTmpA, matTmpB, tfx->mframeT); + TEN_M2T(tens2[1], matTmpA); + tenEigensolve_d(eval[1], evec[1], tens2[1]); + } else { + tenEigensolve_d(eval[0], evec[0], tfx->gageTen2 + 0); + tenEigensolve_d(eval[1], evec[1], tfx->gageTen2 + 7); } - + /* set ten2Use */ if (seedProbe) { /* we're on the *very* 1st probe per tract, at the seed pt */ @@ -135,7 +145,11 @@ lastVec = tfx->seedEvec; } else { /* we're past the first step */ - ELL_3V_NORM(tfx->lastDir, tfx->lastDir, len); + /* Arish says: "Bug len has not been initialized and don't think + its needed". The first part is not a problem; "len" is in the + *output* argument of ELL_3V_NORM. The second part seems to be + true, even though Gordon can't currently see why! */ + /* ELL_3V_NORM(tfx->lastDir, tfx->lastDir, len); */ lastVec = tfx->lastDir; } dot[0] = ELL_3V_DOT(lastVec, evec[0]); @@ -158,11 +172,7 @@ /* based on ten2Use, set the rest of the needed fields */ if (tfx->mframeUse) { - double matTmpA[9], matTmpB[9]; - TEN_T2M(matTmpA, tfx->gageTen2 + 7*(tfx->ten2Use)); - ELL_3M_MUL(matTmpB, tfx->mframe, matTmpA); - ELL_3M_MUL(matTmpA, matTmpB, tfx->mframeT); - TEN_M2T(tfx->fiberTen, matTmpA); + TEN_T_COPY(tfx->fiberTen, tens2[tfx->ten2Use]); } else { TEN_T_COPY(tfx->fiberTen, tfx->gageTen2 + 7*(tfx->ten2Use)); } Modified: teem/trunk/src/ten/tenDwiGage.c =================================================================== --- teem/trunk/src/ten/tenDwiGage.c 2008-12-08 17:38:33 UTC (rev 4034) +++ teem/trunk/src/ten/tenDwiGage.c 2008-12-09 11:02:01 UTC (rev 4035) @@ -306,8 +306,8 @@ egrad += 3; for (ii=0; ii<nn; ii++) { double argA, argB, sigA, sigB; - argA = -pvlData->tec2->bValue*TEN_T3V_CONTR(tenA, egrad + 3*ii); - argB = -pvlData->tec2->bValue*TEN_T3V_CONTR(tenB, egrad + 3*ii); + argA = -pvlData->tec1->bValue*TEN_T3V_CONTR(tenA, egrad + 3*ii); + argB = -pvlData->tec1->bValue*TEN_T3V_CONTR(tenB, egrad + 3*ii); if (pvlData->levmarUseFastExp) { sigA = airFastExp(argA); sigB = airFastExp(argB); @@ -315,7 +315,7 @@ sigA = exp(argA); sigB = exp(argB); } - xx[ii] = pvlData->tec2->knownB0*(pp[1]*sigA + (1-pp[1])*sigB); + xx[ii] = pvlData->tec1->knownB0*(pp[1]*sigA + (1-pp[1])*sigB); } return; } @@ -580,106 +580,114 @@ /* Pointer to the location where the two tensor will be written */ twoTen = pvl->directAnswer[tenDwiGage2TensorPeled]; /* Estimate the DWI error, error is given as standard deviation */ - pvlData->tec2->recordErrorDwi = AIR_FALSE; + pvlData->tec1->recordErrorDwi = AIR_FALSE; /* Estimate the single tensor */ - tenEstimate1TensorSingle_d(pvlData->tec2, pvlData->ten1, dwiAll); + tenEstimate1TensorSingle_d(pvlData->tec1, pvlData->ten1, dwiAll); /* Get the eigenValues and eigen vectors for this tensor */ tenEigensolve_d(pvlData->ten1Eval, pvlData->ten1Evec, pvlData->ten1); /* Get westins Cp */ Cp = tenAnisoEval_d(pvlData->ten1Eval, tenAniso_Cp1); - /* Calculate the residual, need the variance to sqr it */ - /* residual = pvlData->tec2->errorDwi*pvlData->tec2->errorDwi; */ - /* Calculate the AIC for single tensor fit */ - /* AICSingFit = _tenComputeAIC(residual, pvlData->tec2->dwiNum, 6); */ + /* Only do two-tensor fitting if CP is greater or equal to than a + user-defined threshold */ + if (Cp >= pvlData->levmarMinCp) { + /* Calculate the residual, need the variance to sqr it */ + /* residual = pvlData->tec1->errorDwi*pvlData->tec1->errorDwi; */ + /* Calculate the AIC for single tensor fit */ + /* AICSingFit = _tenComputeAIC(residual, pvlData->tec1->dwiNum, 6); */ - /* the CP-based test is gone; caller's responsibility */ + /* the CP-based test is gone; caller's responsibility */ - /* rotate DW gradients by inverse of eigenvector column matrix - and place into pvlData->nten1EigenGrads (which has been - allocated by _tenDwiGagePvlDataNew()) */ - grad = AIR_CAST(double *, kindData->ngrad->data); - egrad = AIR_CAST(double *, pvlData->nten1EigenGrads->data); - for (gi=0; gi<kindData->ngrad->axis[1].size; gi++) { - /* yes, this is also transforming some zero-length (B0) gradients; - that's harmless */ - ELL_3MV_MUL(egrad, pvlData->ten1Evec, grad); - grad += 3; - egrad += 3; - } + /* rotate DW gradients by inverse of eigenvector column matrix + and place into pvlData->nten1EigenGrads (which has been + allocated by _tenDwiGagePvlDataNew()) */ + grad = AIR_CAST(double *, kindData->ngrad->data); + egrad = AIR_CAST(double *, pvlData->nten1EigenGrads->data); + for (gi=0; gi<kindData->ngrad->axis[1].size; gi++) { + /* yes, this is also transforming some zero-length (B0) gradients; + that's harmless */ + ELL_3MV_MUL(egrad, pvlData->ten1Evec, grad); + grad += 3; + egrad += 3; + } - /* Lower and upper bounds for the NLLS routine */ - loBnd[0] = 0.0; - loBnd[1] = 0.0; - loBnd[2] = -AIR_PI/2; - loBnd[3] = -AIR_PI/2; - upBnd[0] = pvlData->ten1Eval[0]*5; - upBnd[1] = 1.0; - upBnd[2] = AIR_PI/2; - upBnd[3] = AIR_PI/2; - /* Starting point for the NLLS */ - guess[0] = pvlData->ten1Eval[0]; - guess[1] = 0.5; + /* Lower and upper bounds for the NLLS routine */ + loBnd[0] = 0.0; + loBnd[1] = 0.0; + loBnd[2] = -AIR_PI/2; + loBnd[3] = -AIR_PI/2; + upBnd[0] = pvlData->ten1Eval[0]*5; + upBnd[1] = 1.0; + upBnd[2] = AIR_PI/2; + upBnd[3] = AIR_PI/2; + /* Starting point for the NLLS */ + guess[0] = pvlData->ten1Eval[0]; + guess[1] = 0.5; - guess[2] = AIR_PI/4; - guess[3] = -AIR_PI/4; - /* - guess[2] = AIR_AFFINE(0, airDrandMT_r(pvlData->randState), 1, - AIR_PI/6, AIR_PI/3); - guess[3] = AIR_AFFINE(0, airDrandMT_r(pvlData->randState), 1, - -AIR_PI/6, -AIR_PI/3); - */ - /* Fill in the constraints for the LM optimization, - the threshold of error difference */ - opts[0] = pvlData->levmarTau; - opts[1] = pvlData->levmarEps1; - opts[2] = pvlData->levmarEps2; - opts[3] = pvlData->levmarEps3; - /* Very imp to set this opt, note that only forward - differences are used to approx Jacobian */ - opts[4] = pvlData->levmarDelta; - - /* run NLLS, results are stored back into guess[] */ - pvlData->levmarUseFastExp = AIR_FALSE; - lmret = dlevmar_bc_dif(_tenLevmarPeledCB, guess, pvlData->tec2->dwi, - PARAMS, pvlData->tec2->dwiNum, loBnd, upBnd, - pvlData->levmarMaxIter, opts, - pvlData->levmarInfo, - NULL, NULL, pvlData); - if (-1 == lmret) { - ctx->errNum = 1; - sprintf(ctx->errStr, "%s: dlevmar_bc_dif() failed!", me); - } else { - /* Get the AIC for the two tensor fit, use the levmarinfo - to get the residual */ + guess[2] = AIR_PI/4; + guess[3] = -AIR_PI/4; /* - residual = pvlData->levmarInfo[1]/pvlData->tec2->dwiNum; - AICTwoFit = _tenComputeAIC(residual, pvlData->tec2->dwiNum, 12); + guess[2] = AIR_AFFINE(0, airDrandMT_r(pvlData->randState), 1, + AIR_PI/6, AIR_PI/3); + guess[3] = AIR_AFFINE(0, airDrandMT_r(pvlData->randState), 1, + -AIR_PI/6, -AIR_PI/3); */ - /* Form the tensors using the estimated pp, returned in guess */ - _tenPeledRotate2D(tenA, guess[0], pvlData->ten1Eval[2], guess[2]); - _tenPeledRotate2D(tenB, guess[0], pvlData->ten1Eval[2], guess[3]); - TEN_T2M(matA, tenA); - TEN_T2M(matB, tenB); + /* Fill in the constraints for the LM optimization, + the threshold of error difference */ + opts[0] = pvlData->levmarTau; + opts[1] = pvlData->levmarEps1; + opts[2] = pvlData->levmarEps2; + opts[3] = pvlData->levmarEps3; + /* Very imp to set this opt, note that only forward + differences are used to approx Jacobian */ + opts[4] = pvlData->levmarDelta; + + /* run NLLS, results are stored back into guess[] */ + pvlData->levmarUseFastExp = AIR_FALSE; + lmret = dlevmar_bc_dif(_tenLevmarPeledCB, guess, pvlData->tec1->dwi, + PARAMS, pvlData->tec1->dwiNum, loBnd, upBnd, + pvlData->levmarMaxIter, opts, + pvlData->levmarInfo, + NULL, NULL, pvlData); + if (-1 == lmret) { + ctx->errNum = 1; + sprintf(ctx->errStr, "%s: dlevmar_bc_dif() failed!", me); + } else { + /* Get the AIC for the two tensor fit, use the levmarinfo + to get the residual */ + /* + residual = pvlData->levmarInfo[1]/pvlData->tec1->dwiNum; + AICTwoFit = _tenComputeAIC(residual, pvlData->tec1->dwiNum, 12); + */ + /* Form the tensors using the estimated pp, returned in guess */ + _tenPeledRotate2D(tenA, guess[0], pvlData->ten1Eval[2], guess[2]); + _tenPeledRotate2D(tenB, guess[0], pvlData->ten1Eval[2], guess[3]); + TEN_T2M(matA, tenA); + TEN_T2M(matB, tenB); - ELL_3M_TRANSPOSE(rott, pvlData->ten1Evec); - ELL_3M_MUL(matTmp, matA, pvlData->ten1Evec); - ELL_3M_MUL(matA, rott, matTmp); - ELL_3M_MUL(matTmp, matB, pvlData->ten1Evec); - ELL_3M_MUL(matB, rott, matTmp); - - /* Copy two two tensors */ - /* guess[1] is population fraction of first tensor */ - if (guess[1] > 0.5) { - twoTen[7] = guess[1]; - TEN_M2T(twoTen + 0, matA); - TEN_M2T(twoTen + 7, matB); - } else { - twoTen[7] = 1 - guess[1]; - TEN_M2T(twoTen + 0, matB); - TEN_M2T(twoTen + 7, matA); + ELL_3M_TRANSPOSE(rott, pvlData->ten1Evec); + ELL_3M_MUL(matTmp, matA, pvlData->ten1Evec); + ELL_3M_MUL(matA, rott, matTmp); + ELL_3M_MUL(matTmp, matB, pvlData->ten1Evec); + ELL_3M_MUL(matB, rott, matTmp); + + /* Copy two two tensors */ + /* guess[1] is population fraction of first tensor */ + if (guess[1] > 0.5) { + twoTen[7] = guess[1]; + TEN_M2T(twoTen + 0, matA); + TEN_M2T(twoTen + 7, matB); + } else { + twoTen[7] = 1 - guess[1]; + TEN_M2T(twoTen + 0, matB); + TEN_M2T(twoTen + 7, matA); + } + twoTen[0] = 1; } - twoTen[0] = 1; + } else { + /* its too planar- just do single tensor fit */ + TEN_T_COPY(twoTen, pvlData->ten1); + TEN_T_SET(twoTen + 7, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); } #undef PARAMS #else @@ -700,7 +708,7 @@ if (info[1] > 0) { /* Returning the standard deviation */ pvl->directAnswer[tenDwiGage2TensorPeledError][0] = - sqrt(info[1]/pvlData->tec2->dwiNum); + sqrt(info[1]/pvlData->tec1->dwiNum); } } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGage2TensorPeledAndError)) { @@ -833,7 +841,7 @@ pvlData->levmarEps2 = 1E-8; pvlData->levmarEps3 = 1E-8; pvlData->levmarDelta = 1E-8; - pvlData->levmarMinCp = 0.08; + pvlData->levmarMinCp = 0.1; /* pvlData->levmarInfo[] is output; not initialized */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-03-23 06:05:52
|
Revision: 4208 http://teem.svn.sourceforge.net/teem/?rev=4208&view=rev Author: kindlmann Date: 2009-03-23 06:05:50 +0000 (Mon, 23 Mar 2009) Log Message: ----------- API NEW: added two more items to tenGage: tenGageFARidgeLineAlignment and tenGageFARidgeSurfaceAlignment for looking at the alignment between eigenvectors of the Hessian of FA, and of the tensor itself Modified Paths: -------------- teem/trunk/src/ten/enumsTen.c teem/trunk/src/ten/ten.h teem/trunk/src/ten/tenGage.c Modified: teem/trunk/src/ten/enumsTen.c =================================================================== --- teem/trunk/src/ten/enumsTen.c 2009-03-23 06:04:04 UTC (rev 4207) +++ teem/trunk/src/ten/enumsTen.c 2009-03-23 06:05:50 UTC (rev 4208) @@ -250,10 +250,12 @@ "FA hessian evec 0", "FA hessian evec 1", "FA hessian evec 2", - "FA ridge surface", - "FA valley surface", + "FA ridge surface strength", + "FA valley surface strength", "FA laplacian", "FA hessian eval mode", + "FA ridge line alignment", + "FA ridge surface alignment", "FA 2nd DD", "FA geometry tensor", @@ -415,6 +417,8 @@ "FA valley surface strength", "FA laplacian", "FA hessian eval mode", + "FA ridge line alignment", + "FA ridge surface alignment", "FA 2nd DD", "FA geometry tensor", "FA kappa1", @@ -570,6 +574,8 @@ tenGageFAValleySurfaceStrength, tenGageFALaplacian, tenGageFAHessianEvalMode, + tenGageFARidgeLineAlignment, + tenGageFARidgeSurfaceAlignment, tenGageFA2ndDD, tenGageFAGeomTens, tenGageFAKappa1, @@ -731,10 +737,12 @@ "fahessevec0", "fahessevec1", "fahessevec2", - "farsurf", - "favsurf", + "farsurfstrn", + "favsurfstrn", "falapl", "fahessevalmode", + "farlinealn", + "farsurfaln", "fa2d", "fa2dd", "fagten", "FA geometry tensor", "fak1", "FA kappa1", @@ -890,6 +898,8 @@ tenGageFAValleySurfaceStrength, tenGageFALaplacian, tenGageFAHessianEvalMode, + tenGageFARidgeLineAlignment, + tenGageFARidgeSurfaceAlignment, tenGageFA2ndDD, tenGageFA2ndDD, tenGageFAGeomTens, tenGageFAGeomTens, tenGageFAKappa1, tenGageFAKappa1, Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-03-23 06:04:04 UTC (rev 4207) +++ teem/trunk/src/ten/ten.h 2009-03-23 06:05:50 UTC (rev 4208) @@ -363,62 +363,64 @@ tenGageFAHessianEvec0, /* 93: "fahessevec0": [3] */ tenGageFAHessianEvec1, /* 94: "fahessevec1": [3] */ tenGageFAHessianEvec2, /* 95: "fahessevec2": [3] */ - tenGageFARidgeSurfaceStrength, /* 96: "farsurf": [1] */ - tenGageFAValleySurfaceStrength, /* 97: "favsurf": [1] */ + tenGageFARidgeSurfaceStrength, /* 96: "farsurfstrn": [1] */ + tenGageFAValleySurfaceStrength, /* 97: "favsurfstrn": [1] */ tenGageFALaplacian, /* 98: "falapl": [1] */ tenGageFAHessianEvalMode,/* 99: "fahessevalmode": [1] */ - tenGageFA2ndDD, /* 100: "fa2d": [1] */ + tenGageFARidgeLineAlignment, /* 100: "farlinealn": [1] */ + tenGageFARidgeSurfaceAlignment, /* 101: "farsurfaln": [1] */ + tenGageFA2ndDD, /* 102: "fa2d": [1] */ - tenGageFAGeomTens, /* 101: "fagten", sym. matx w/ evals {0, K1, K2} + tenGageFAGeomTens, /* 103: "fagten", sym. matx w/ evals {0, K1, K2} and evecs {grad, cdir0, cdir1}: [9] */ - tenGageFAKappa1, /* 102: "fak1", 1st princ curv: [1] */ - tenGageFAKappa2, /* 103: "fak2", 2nd princ curv (k2 <= k1): [1] */ - tenGageFATotalCurv, /* 104: "fatc", L2 norm(K1,K2): [1] */ - tenGageFAShapeIndex, /* 105: "fasi", Koen.'s shape index, ("S"): [1] */ - tenGageFAMeanCurv, /* 106: "famc", mean curvature (K1 + K2)/2: [1] */ - tenGageFAGaussCurv, /* 107: "fagc", gaussian curvature K1*K2: [1] */ - tenGageFACurvDir1, /* 108: "facdir1", 1st princ curv direction: [3] */ - tenGageFACurvDir2, /* 109: "facdir2", 2nd princ curv direction: [3] */ - tenGageFAFlowlineCurv, /* 110: "fafc", curv of normal streamline: [1] */ + tenGageFAKappa1, /* 104: "fak1", 1st princ curv: [1] */ + tenGageFAKappa2, /* 105: "fak2", 2nd princ curv (k2 <= k1): [1] */ + tenGageFATotalCurv, /* 106: "fatc", L2 norm(K1,K2): [1] */ + tenGageFAShapeIndex, /* 107: "fasi", Koen.'s shape index, ("S"): [1] */ + tenGageFAMeanCurv, /* 108: "famc", mean curvature (K1 + K2)/2: [1] */ + tenGageFAGaussCurv, /* 109: "fagc", gaussian curvature K1*K2: [1] */ + tenGageFACurvDir1, /* 110: "facdir1", 1st princ curv direction: [3] */ + tenGageFACurvDir2, /* 111: "facdir2", 2nd princ curv direction: [3] */ + tenGageFAFlowlineCurv, /* 112: "fafc", curv of normal streamline: [1] */ - tenGageRHessian, /* 111: "rhess": [9] */ + tenGageRHessian, /* 113: "rhess": [9] */ - tenGageModeHessian, /* 112: "mhess": [9] */ - tenGageModeHessianEval, /* 113: "mhesseval": [3] */ - tenGageModeHessianEval0, /* 114: "mhesseval0": [1] */ - tenGageModeHessianEval1, /* 115: "mhesseval1": [1] */ - tenGageModeHessianEval2, /* 116: "mhesseval2": [1] */ - tenGageModeHessianEvec, /* 117: "mhessevec": [9] */ - tenGageModeHessianEvec0, /* 118: "mhessevec0": [3] */ - tenGageModeHessianEvec1, /* 119: "mhessevec1": [3] */ - tenGageModeHessianEvec2, /* 120: "mhessevec2": [3] */ + tenGageModeHessian, /* 114: "mhess": [9] */ + tenGageModeHessianEval, /* 115: "mhesseval": [3] */ + tenGageModeHessianEval0, /* 116: "mhesseval0": [1] */ + tenGageModeHessianEval1, /* 117: "mhesseval1": [1] */ + tenGageModeHessianEval2, /* 118: "mhesseval2": [1] */ + tenGageModeHessianEvec, /* 119: "mhessevec": [9] */ + tenGageModeHessianEvec0, /* 120: "mhessevec0": [3] */ + tenGageModeHessianEvec1, /* 121: "mhessevec1": [3] */ + tenGageModeHessianEvec2, /* 122: "mhessevec2": [3] */ - tenGageOmegaHessian, /* 121: "omhess": [9] */ - tenGageOmegaHessianEval, /* 122: "omhesseval": [3] */ - tenGageOmegaHessianEval0,/* 123: "omhesseval0": [1] */ - tenGageOmegaHessianEval1,/* 124: "omhesseval1": [1] */ - tenGageOmegaHessianEval2,/* 125: "omhesseval2": [1] */ - tenGageOmegaHessianEvec, /* 126: "omhessevec": [9] */ - tenGageOmegaHessianEvec0,/* 127: "omhessevec0": [3] */ - tenGageOmegaHessianEvec1,/* 128: "omhessevec1": [3] */ - tenGageOmegaHessianEvec2,/* 129: "omhessevec2": [3] */ - tenGageOmegaLaplacian, /* 130: "omlapl": [1] */ - tenGageOmega2ndDD, /* 131: "om2d": [1] */ + tenGageOmegaHessian, /* 123: "omhess": [9] */ + tenGageOmegaHessianEval, /* 124: "omhesseval": [3] */ + tenGageOmegaHessianEval0,/* 125: "omhesseval0": [1] */ + tenGageOmegaHessianEval1,/* 126: "omhesseval1": [1] */ + tenGageOmegaHessianEval2,/* 127: "omhesseval2": [1] */ + tenGageOmegaHessianEvec, /* 128: "omhessevec": [9] */ + tenGageOmegaHessianEvec0,/* 129: "omhessevec0": [3] */ + tenGageOmegaHessianEvec1,/* 130: "omhessevec1": [3] */ + tenGageOmegaHessianEvec2,/* 131: "omhessevec2": [3] */ + tenGageOmegaLaplacian, /* 132: "omlapl": [1] */ + tenGageOmega2ndDD, /* 133: "om2d": [1] */ - tenGageTraceGradVecDotEvec0, /* 132: "trgvdotevec0": [1] */ - tenGageTraceDiffusionAlign, /* 133: "datr": [1] */ - tenGageTraceDiffusionFraction, /* 134: "dftr": [1] */ - tenGageFAGradVecDotEvec0, /* 135: "fagvdotevec0": [1] */ - tenGageFADiffusionAlign, /* 136: "dafa": [1] */ - tenGageFADiffusionFraction, /* 137: "dffa": [1] */ - tenGageOmegaGradVecDotEvec0, /* 138: "omgvdotevec0": [1] */ - tenGageOmegaDiffusionAlign, /* 139: "daom": [1] */ - tenGageOmegaDiffusionFraction, /* 140: "daom": [1] */ - tenGageConfGradVecDotEvec0, /* 141: "cnfgvdotevec0": [1] */ - tenGageConfDiffusionAlign, /* 142: "dacnf": [1] */ - tenGageConfDiffusionFraction, /* 143: "dfcnf": [1] */ + tenGageTraceGradVecDotEvec0, /* 134: "trgvdotevec0": [1] */ + tenGageTraceDiffusionAlign, /* 135: "datr": [1] */ + tenGageTraceDiffusionFraction, /* 136: "dftr": [1] */ + tenGageFAGradVecDotEvec0, /* 137: "fagvdotevec0": [1] */ + tenGageFADiffusionAlign, /* 138: "dafa": [1] */ + tenGageFADiffusionFraction, /* 139: "dffa": [1] */ + tenGageOmegaGradVecDotEvec0, /* 140: "omgvdotevec0": [1] */ + tenGageOmegaDiffusionAlign, /* 141: "daom": [1] */ + tenGageOmegaDiffusionFraction, /* 142: "daom": [1] */ + tenGageConfGradVecDotEvec0, /* 143: "cnfgvdotevec0": [1] */ + tenGageConfDiffusionAlign, /* 144: "dacnf": [1] */ + tenGageConfDiffusionFraction, /* 145: "dfcnf": [1] */ - tenGageCovariance, /* 144: "cov" 4rth order covariance tensor: [21] + tenGageCovariance, /* 146: "cov" 4rth order covariance tensor: [21] in order of appearance: 0:xxxx 1:xxxy 2:xxxz 3:xxyy 4:xxyz 5:xxzz 6:xyxy 7:xyxz 8:xyyy 9:xyyz 10:xyzz @@ -426,28 +428,28 @@ 15:yyyy 16:yyyz 17:yyzz 18:yzyz 19:yzzz 20:zzzz */ - tenGageCovarianceRGRT, /* 145: "covr" covariance tensor expressed in frame + tenGageCovarianceRGRT, /* 147: "covr" covariance tensor expressed in frame of R invariant gradients and rotation tangents */ - tenGageCovarianceKGRT, /* 146: "covk" covariance tensor expressed in frame + tenGageCovarianceKGRT, /* 148: "covk" covariance tensor expressed in frame of K invariant gradients and rotation tangents */ - tenGageTensorLogEuclidean, /* 147: log-euclidean interpolation */ - tenGageTensorQuatGeoLoxK, /* 148: QGL-K interpolation */ - tenGageTensorQuatGeoLoxR, /* 149: QGL-R interpolation */ + tenGageTensorLogEuclidean, /* 149: log-euclidean interpolation */ + tenGageTensorQuatGeoLoxK, /* 150: QGL-K interpolation */ + tenGageTensorQuatGeoLoxR, /* 152: QGL-R interpolation */ - tenGageAniso, /* 150: "an", all anisos: [TEN_ANISO_MAX+1] */ - tenGageCl1GradVec, /* 151: gradient vector of cl1: [3] */ - tenGageCl1GradMag, /* 152: gradient magnitude of cl1: [1] */ - tenGageCp1GradVec, /* 153: gradient vector of cp1: [3] */ - tenGageCp1GradMag, /* 154: gradient magnitude of cp1: [1] */ - tenGageCa1GradVec, /* 155: gradient vector of ca1: [3] */ - tenGageCa1GradMag, /* 156: gradient magnitude of ca1: [1] */ - tenGageTensorGradRotE, /* 157: all tensor component gradients, + tenGageAniso, /* 152: "an", all anisos: [TEN_ANISO_MAX+1] */ + tenGageCl1GradVec, /* 153: gradient vector of cl1: [3] */ + tenGageCl1GradMag, /* 154: gradient magnitude of cl1: [1] */ + tenGageCp1GradVec, /* 155: gradient vector of cp1: [3] */ + tenGageCp1GradMag, /* 156: gradient magnitude of cp1: [1] */ + tenGageCa1GradVec, /* 157: gradient vector of ca1: [3] */ + tenGageCa1GradMag, /* 158: gradient magnitude of ca1: [1] */ + tenGageTensorGradRotE, /* 159: all tensor component gradients, starting with confidence gradient. Rotated such that eigenvalue derivatives are on the diagonal: [21] */ tenGageLast }; -#define TEN_GAGE_ITEM_MAX 157 +#define TEN_GAGE_ITEM_MAX 159 /* ******** tenDwiGage* enum Modified: teem/trunk/src/ten/tenGage.c =================================================================== --- teem/trunk/src/ten/tenGage.c 2009-03-23 06:04:04 UTC (rev 4207) +++ teem/trunk/src/ten/tenGage.c 2009-03-23 06:05:50 UTC (rev 4208) @@ -158,6 +158,8 @@ {tenGageFAValleySurfaceStrength, 1, 2, {tenGageConfidence, tenGageFAHessianEval}, 0, 0, AIR_FALSE}, {tenGageFALaplacian, 1, 2, {tenGageFAHessian}, 0, 0, AIR_FALSE}, {tenGageFAHessianEvalMode, 1, 2, {tenGageFAHessianEval}, 0, 0, AIR_FALSE}, + {tenGageFARidgeLineAlignment, 1, 2, {tenGageEvec0, tenGageFAHessianEvec0, tenGageFAHessianEvalMode}, 0, 0, AIR_FALSE}, + {tenGageFARidgeSurfaceAlignment, 1, 2, {tenGageEvec0, tenGageFAHessianEvec2, tenGageFAHessianEvalMode}, 0, 0, AIR_FALSE}, {tenGageFA2ndDD, 1, 2, {tenGageFAHessian, tenGageFANormal}, 0, 0, AIR_FALSE}, {tenGageFAGeomTens, 9, 2, {tenGageFAHessian, tenGageFAGradMag, tenGageFANormal}, 0, 0, AIR_FALSE}, @@ -1030,6 +1032,24 @@ heval = pvl->directAnswer[tenGageFAHessianEval]; pvl->directAnswer[tenGageFAHessianEvalMode][0] = airMode3_d(heval); } + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageFARidgeLineAlignment)) { + double *hev0, *dev0, dot, mde; + hev0 = pvl->directAnswer[tenGageFAHessianEvec0]; + dev0 = pvl->directAnswer[tenGageEvec0]; + dot = ELL_3V_DOT(hev0, dev0); + mde = pvl->directAnswer[tenGageFAHessianEvalMode][0]; + mde = AIR_AFFINE(-1, mde, 1, 0, 1); + pvl->directAnswer[tenGageFARidgeLineAlignment][0] = mde*AIR_ABS(dot); + } + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageFARidgeSurfaceAlignment)) { + double *hev2, *dev0, dot, mde; + hev2 = pvl->directAnswer[tenGageFAHessianEvec2]; + dev0 = pvl->directAnswer[tenGageEvec0]; + dot = ELL_3V_DOT(hev2, dev0); + mde = pvl->directAnswer[tenGageFAHessianEvalMode][0]; + mde = AIR_AFFINE(-1, mde, 1, 1, 0); + pvl->directAnswer[tenGageFARidgeSurfaceAlignment][0]= mde*(1-AIR_ABS(dot)); + } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageFA2ndDD)) { double *hess, *norm, tmpv[3]; hess = pvl->directAnswer[tenGageFAHessian]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-06-29 01:22:17
|
Revision: 4234 http://teem.svn.sourceforge.net/teem/?rev=4234&view=rev Author: kindlmann Date: 2009-06-29 01:08:18 +0000 (Mon, 29 Jun 2009) Log Message: ----------- bringing ten up to date with increased strictness in gage Modified Paths: -------------- teem/trunk/src/ten/tendSatin.c teem/trunk/src/ten/tensor.c Modified: teem/trunk/src/ten/tendSatin.c =================================================================== --- teem/trunk/src/ten/tendSatin.c 2009-05-20 23:00:52 UTC (rev 4233) +++ teem/trunk/src/ten/tendSatin.c 2009-06-29 01:08:18 UTC (rev 4234) @@ -247,6 +247,17 @@ nrrdCenterCell, nrrdCenterCell); shape = gageShapeNew(); airMopAdd(mop, shape, (airMopper)gageShapeNix, airMopAlways); + /* this is a weird mix of new and legacy code. At some point + prior to Wed May 27 19:23:55 CDT 2009, it was okay to pass + in a volume to gageShapeSet that had absolutely no notion + of spacing or orientation. Then gageShapeSet was used to + get a plausible set of space directions and space origin. + Now, we're setting some spacings, so that gageShapeSet can + do its thing, then (below) nan-ing out those spacings so + that the nrrd is self-consistent */ + nout->axis[1].spacing = 1.0; + nout->axis[2].spacing = 1.0; + nout->axis[3].spacing = 1.0; if (gageShapeSet(shape, nout, tenGageKind->baseDim)) { airMopAdd(mop, err=biffGetDone(GAGE), airFree, airMopAlways); fprintf(stderr, "%s: trouble doing shape:\n%s\n", me, err); @@ -263,6 +274,9 @@ nrrdSpaceOriginSet(nout, orig); nrrdAxisInfoSet_va(nout, nrrdAxisInfoSpaceDirection, spd[0], spd[1], spd[2], spd[3]); + nout->axis[1].spacing = AIR_NAN; + nout->axis[2].spacing = AIR_NAN; + nout->axis[3].spacing = AIR_NAN; nrrdAxisInfoSet_va(nout, nrrdAxisInfoKind, nrrdKind3DMaskedSymMatrix, nrrdKindSpace, nrrdKindSpace, nrrdKindSpace); Modified: teem/trunk/src/ten/tensor.c =================================================================== --- teem/trunk/src/ten/tensor.c 2009-05-20 23:00:52 UTC (rev 4233) +++ teem/trunk/src/ten/tensor.c 2009-06-29 01:08:18 UTC (rev 4234) @@ -547,6 +547,7 @@ } nout->axis[0].label = (char *)airFree(nout->axis[0].label); nout->axis[0].label = airStrdup("tensor"); + nout->axis[0].kind = nrrdKind3DMaskedSymMatrix; if (nrrdBasicInfoCopy(nout, nconf, NRRD_BASIC_INFO_DATA_BIT | NRRD_BASIC_INFO_TYPE_BIT This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-11 19:37:12
|
Revision: 4277 http://teem.svn.sourceforge.net/teem/?rev=4277&view=rev Author: kindlmann Date: 2009-10-11 19:37:05 +0000 (Sun, 11 Oct 2009) Log Message: ----------- fixing longstanding bugs in the definition of tenGageKind (got out of sync with tenGage enum), and one field in tenDwiGage Modified Paths: -------------- teem/trunk/src/ten/enumsTen.c teem/trunk/src/ten/ten.h teem/trunk/src/ten/tenDwiGage.c teem/trunk/src/ten/tenGage.c Modified: teem/trunk/src/ten/enumsTen.c =================================================================== --- teem/trunk/src/ten/enumsTen.c 2009-10-11 19:31:36 UTC (rev 4276) +++ teem/trunk/src/ten/enumsTen.c 2009-10-11 19:37:05 UTC (rev 4277) @@ -314,6 +314,14 @@ "qglk", "qglr", + "cl1gv", + "cl1gm", + "cp1gv", + "cp1gm", + "ca1gv", + "ca1gm", + "tgrote", + "anisotropies" }; @@ -395,9 +403,11 @@ "linear anisotropy (1)", "planar anisotropy (1)", "linear+planar anisotropy (1)", + "min(linear,planar) anisotropy (1)", "linear anisotropy (2)", "planar anisotropy (2)", "linear+planar anisotropy (2)", + "min(linear,planar) anisotropy (2)", "hessian", "trace hessian", "B hessian", @@ -469,6 +479,15 @@ "log-euclidean", "QuatGeoLoxK", "QuatGeoLoxR", + "gradient vector of cl1", + "gradient magnitude of cl1", + "gradient vector of cp1", + "gradient magnitude of cp1", + "gradient vector of ca1", + "gradient magnitude of ca1", + "all tensor component gradients, starting with confidence gradient, " + /* !! CONCAT !! */ + "rotated such that eigenvalue derivatives are on the diagonal", "anisotropies" }; @@ -596,7 +615,7 @@ tenGageModeHessianEvec, tenGageModeHessianEvec0, tenGageModeHessianEvec1, - tenGageOmegaHessianEvec2, + tenGageModeHessianEvec2, tenGageOmegaHessian, tenGageOmegaHessianEval, tenGageOmegaHessianEval0, @@ -626,14 +645,14 @@ tenGageTensorLogEuclidean, tenGageTensorQuatGeoLoxK, tenGageTensorQuatGeoLoxR, - tenGageAniso, tenGageCl1GradVec, tenGageCl1GradMag, tenGageCp1GradVec, tenGageCp1GradMag, tenGageCa1GradVec, tenGageCa1GradMag, - tenGageTensorGradRotE + tenGageTensorGradRotE, + tenGageAniso, }; const char * @@ -784,12 +803,24 @@ "omgvdotevec0", "daom", "dfom", + "confgvdotevec0", + "daconf", + "dfconf", "cov", "covr", "covk", "logeuclidean", "logeuc", "quatgeoloxk", "qglk", "quatgeoloxr", "qglr", + + "cl1gv", + "cl1gm", + "cp1gv", + "cp1gm", + "ca1gv", + "ca1gm", + "tgrote", + "an", "aniso", "anisotropies", "" }; @@ -957,13 +988,21 @@ tenGageTensorQuatGeoLoxK, tenGageTensorQuatGeoLoxK, tenGageTensorQuatGeoLoxR, tenGageTensorQuatGeoLoxR, + tenGageCl1GradVec, + tenGageCl1GradMag, + tenGageCp1GradVec, + tenGageCp1GradMag, + tenGageCa1GradVec, + tenGageCa1GradMag, + tenGageTensorGradRotE, + tenGageAniso, tenGageAniso, tenGageAniso }; airEnum _tenGage = { "tenGage", - TEN_GAGE_ITEM_MAX+1, + TEN_GAGE_ITEM_MAX, _tenGageStr, _tenGageVal, _tenGageDesc, _tenGageStrEqv, _tenGageValEqv, Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-10-11 19:31:36 UTC (rev 4276) +++ teem/trunk/src/ten/ten.h 2009-10-11 19:37:05 UTC (rev 4277) @@ -415,10 +415,10 @@ tenGageFADiffusionFraction, /* 139: "dffa": [1] */ tenGageOmegaGradVecDotEvec0, /* 140: "omgvdotevec0": [1] */ tenGageOmegaDiffusionAlign, /* 141: "daom": [1] */ - tenGageOmegaDiffusionFraction, /* 142: "daom": [1] */ - tenGageConfGradVecDotEvec0, /* 143: "cnfgvdotevec0": [1] */ - tenGageConfDiffusionAlign, /* 144: "dacnf": [1] */ - tenGageConfDiffusionFraction, /* 145: "dfcnf": [1] */ + tenGageOmegaDiffusionFraction, /* 142: "dfom": [1] */ + tenGageConfGradVecDotEvec0, /* 143: "confgvdotevec0": [1] */ + tenGageConfDiffusionAlign, /* 144: "daconf": [1] */ + tenGageConfDiffusionFraction, /* 145: "dfconf": [1] */ tenGageCovariance, /* 146: "cov" 4rth order covariance tensor: [21] in order of appearance: @@ -432,21 +432,22 @@ of R invariant gradients and rotation tangents */ tenGageCovarianceKGRT, /* 148: "covk" covariance tensor expressed in frame of K invariant gradients and rotation tangents */ - tenGageTensorLogEuclidean, /* 149: log-euclidean interpolation */ - tenGageTensorQuatGeoLoxK, /* 150: QGL-K interpolation */ - tenGageTensorQuatGeoLoxR, /* 152: QGL-R interpolation */ + tenGageTensorLogEuclidean, /* 149: "logeuc" log-euclidean interp */ + tenGageTensorQuatGeoLoxK, /* 150: "qglk" QGL-K interpolation */ + tenGageTensorQuatGeoLoxR, /* 151: "qglr" QGL-R interpolation */ - tenGageAniso, /* 152: "an", all anisos: [TEN_ANISO_MAX+1] */ - tenGageCl1GradVec, /* 153: gradient vector of cl1: [3] */ - tenGageCl1GradMag, /* 154: gradient magnitude of cl1: [1] */ - tenGageCp1GradVec, /* 155: gradient vector of cp1: [3] */ - tenGageCp1GradMag, /* 156: gradient magnitude of cp1: [1] */ - tenGageCa1GradVec, /* 157: gradient vector of ca1: [3] */ - tenGageCa1GradMag, /* 158: gradient magnitude of ca1: [1] */ - tenGageTensorGradRotE, /* 159: all tensor component gradients, + tenGageCl1GradVec, /* 152: "cl1gv" gradient vector of cl1: [3] */ + tenGageCl1GradMag, /* 153: "cl1gm" gradient magnitude of cl1: [1] */ + tenGageCp1GradVec, /* 154: "cp1gv" gradient vector of cp1: [3] */ + tenGageCp1GradMag, /* 155: "cp1gm" gradient magnitude of cp1: [1] */ + tenGageCa1GradVec, /* 156: "ca1gv" gradient vector of ca1: [3] */ + tenGageCa1GradMag, /* 157: "ca1gm" gradient magnitude of ca1: [1] */ + tenGageTensorGradRotE, /* 158: "tgrote" all tensor component gradients, starting with confidence gradient. Rotated such that eigenvalue derivatives are on the diagonal: [21] */ + + tenGageAniso, /* 159: "an", all anisos: [TEN_ANISO_MAX+1] */ tenGageLast }; #define TEN_GAGE_ITEM_MAX 159 Modified: teem/trunk/src/ten/tenDwiGage.c =================================================================== --- teem/trunk/src/ten/tenDwiGage.c 2009-10-11 19:31:36 UTC (rev 4276) +++ teem/trunk/src/ten/tenDwiGage.c 2009-10-11 19:37:05 UTC (rev 4277) @@ -112,7 +112,7 @@ airEnum _tenDwiGage = { "tenDwiGage", - TEN_DWI_GAGE_ITEM_MAX+1, + TEN_DWI_GAGE_ITEM_MAX, _tenDwiGageStr, _tenDwiGageVal, NULL, NULL, NULL, Modified: teem/trunk/src/ten/tenGage.c =================================================================== --- teem/trunk/src/ten/tenGage.c 2009-10-11 19:31:36 UTC (rev 4276) +++ teem/trunk/src/ten/tenGage.c 2009-10-11 19:37:05 UTC (rev 4277) @@ -229,7 +229,6 @@ {tenGageTensorQuatGeoLoxK, 7, 0, {0}, 0, 0, AIR_FALSE}, {tenGageTensorQuatGeoLoxR, 7, 0, {0}, 0, 0, AIR_FALSE}, - {tenGageAniso, TEN_ANISO_MAX+1, 0, {tenGageEval0, tenGageEval1, tenGageEval2}, 0, 0, AIR_FALSE}, {tenGageCl1GradVec, 3, 1, {tenGageTrace, tenGageEval, tenGageEvalGrads}, 0, 0, AIR_FALSE}, {tenGageCl1GradMag, 1, 1, {tenGageCl1GradVec}, 0, 0, AIR_FALSE}, @@ -237,7 +236,8 @@ {tenGageCp1GradMag, 1, 1, {tenGageCp1GradVec}, 0, 0, AIR_FALSE}, {tenGageCa1GradVec, 3, 1, {tenGageTrace, tenGageEval, tenGageEvalGrads}, 0, 0, AIR_FALSE}, {tenGageCa1GradMag, 1, 1, {tenGageCa1GradVec}, 0, 0, AIR_FALSE}, - {tenGageTensorGradRotE, 21, 1, {tenGageTensorGrad, tenGageEval, tenGageEvec}, 0, 0, AIR_FALSE} + {tenGageTensorGradRotE, 21, 1, {tenGageTensorGrad, tenGageEval, tenGageEvec}, 0, 0, AIR_FALSE}, + {tenGageAniso, TEN_ANISO_MAX+1, 0, {tenGageEval0, tenGageEval1, tenGageEval2}, 0, 0, AIR_FALSE}, }; void This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-22 18:09:27
|
Revision: 4297 http://teem.svn.sourceforge.net/teem/?rev=4297&view=rev Author: kindlmann Date: 2009-10-22 18:09:18 +0000 (Thu, 22 Oct 2009) Log Message: ----------- adding more flexible modeling of DWI signals Added Paths: ----------- teem/trunk/src/ten/experSpec.c teem/trunk/src/ten/modelBall.c teem/trunk/src/ten/modelBall1Stick.c teem/trunk/src/ten/modelCylinder.c teem/trunk/src/ten/modelTen.c teem/trunk/src/ten/modelTensor2.c Added: teem/trunk/src/ten/experSpec.c =================================================================== --- teem/trunk/src/ten/experSpec.c (rev 0) +++ teem/trunk/src/ten/experSpec.c 2009-10-22 18:09:18 UTC (rev 4297) @@ -0,0 +1,307 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +static int +_experAlloc(tenExperSpec* espec, unsigned int num) { + static char me[]="_experAlloc"; + + espec->bval = airFree(espec->bval); + espec->grad = airFree(espec->grad); + espec->wght = airFree(espec->wght); + if (!num) { + biffAddf(TEN, "%s: need a non-zero number of images", me); + return 1; + } + espec->bval = AIR_CAST(double *, calloc(num, sizeof(double))); + espec->grad = AIR_CAST(double *, calloc(3*num, sizeof(double))); + espec->wght = AIR_CAST(double *, calloc(num, sizeof(double))); + if (!( espec->bval && espec->grad && espec->wght )) { + biffAddf(TEN, "%s: couldn't allocate for %u images", me, num); + return 1; + } + return 0; +} + +tenExperSpec* +tenExperSpecNew(void) { + tenExperSpec* espec; + + espec = AIR_CAST(tenExperSpec*, calloc(1, sizeof(tenExperSpec))); + espec->set = AIR_FALSE; + espec->imgNum = 0; + espec->bval = NULL; + espec->grad = NULL; + espec->wght = NULL; + return espec; +} + +int +tenExperSpecGradSingleBValSet(tenExperSpec *espec, + unsigned int imgNum, + double bval, + const double *grad) { + static const char me[]="tenExperSpecGradSingleBValSet"; + unsigned int ii; + + if (!espec) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + if (_experAlloc(espec, imgNum)) { + biffAddf(TEN, "%s: couldn't allocate", me); + return 1; + } + for (ii=0; ii<imgNum; ii++) { + espec->bval[ii] = bval; + ELL_3V_COPY(espec->grad + 3*ii, grad + 3*ii); + espec->wght[ii] = 1.0; + } + + return 0; +} + +int +tenExperSpecGradBValSet(tenExperSpec *espec, + unsigned int imgNum, + const double *bval, + const double *grad) { + static const char me[]="tenExperSpecGradBValSet"; + unsigned int ii; + + if (!espec) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + if (_experAlloc(espec, imgNum)) { + biffAddf(TEN, "%s: couldn't allocate", me); + return 1; + } + for (ii=0; ii<imgNum; ii++) { + espec->bval[ii] = bval[ii]; + ELL_3V_COPY(espec->grad + 3*ii, grad + 3*ii); + espec->wght[ii] = 1.0; + } + + return 0; +} + +int +tenExperSpecGradBValWghtSet(tenExperSpec *espec, + unsigned int imgNum, + const double *bval, + const double *grad, + const double *wght) { + static const char me[]="tenExperSpecGradBValWghtSet"; + unsigned int ii; + + if (!espec) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + if (_experAlloc(espec, imgNum)) { + biffAddf(TEN, "%s: couldn't allocate", me); + return 1; + } + for (ii=0; ii<imgNum; ii++) { + espec->bval[ii] = bval[ii]; + ELL_3V_COPY(espec->grad + 3*ii, grad + 3*ii); + espec->wght[ii] = wght[ii]; + } + + return 0; +} + +int +tenExperSpecFromKeyValueSet(tenExperSpec *espec, const Nrrd *ndwi) { + static const char me[]="tenExperSpecFromKeyValueSet"; + unsigned int *skip, skipNum, ii, imgNum; + Nrrd *ngrad, *nbmat; + airArray *mop; + double len, singleBval, *bval, *grad; + + if (tenDWMRIKeyValueParse(&ngrad, &nbmat, &singleBval, + &skip, &skipNum, ndwi)) { + biffAddf(TEN, "%s: trouble parsing DWI info from key/value pairs", me); + return 1; + } + mop = airMopNew(); + if (ngrad) { + airMopAdd(mop, ngrad, (airMopper)nrrdNuke, airMopAlways); + } + if (nbmat) { + airMopAdd(mop, nbmat, (airMopper)nrrdNuke, airMopAlways); + } + if (skip) { + airMopAdd(mop, skip, airFree, airMopAlways); + } + + if (nbmat) { + biffAddf(TEN, "%s: sorry, currently can't handle B-matrices here", me); + airMopError(mop); return 1; + } + if (skipNum) { + biffAddf(TEN, "%s: sorry, currently can't handle skipping (%u) here", me, + skipNum); + airMopError(mop); return 1; + } + + imgNum = ngrad->axis[1].size; + bval = AIR_CAST(double *, calloc(imgNum, sizeof(double))); + airMopAdd(mop, bval, airFree, airMopAlways); + grad = AIR_CAST(double *, ngrad->data); + for (ii=0; ii<imgNum; ii++) { + len = ELL_3V_LEN(grad + 3*ii); + bval[ii] = singleBval*len*len; + if (len) { + ELL_3V_SCALE(grad + 3*ii, 1/len, grad + 3*ii); + } else { + ELL_3V_SET(grad + 3*ii, 0, 0, -1); + } + } + if (tenExperSpecGradBValSet(espec, imgNum, bval, grad)) { + biffAddf(TEN, "%s: trouble", me); + airMopError(mop); return 1; + } + airMopOkay(mop); + return 0; +} + +tenExperSpec* +tenExperSpecNix(tenExperSpec *espec) { + + if (espec) { + espec->bval = airFree(espec->bval); + espec->grad = airFree(espec->grad); + espec->wght = airFree(espec->wght); + airFree(espec); + } + return NULL; +} + +double +_tenModel_sqe(const double *dwiMeas, const double *dwiSim, + const tenExperSpec *espec) { + unsigned int ii; + double sqe; + + sqe = 0; + for (ii=0; ii<espec->imgNum; ii++) { + double dd; + dd = dwiMeas[ii] - dwiSim[ii]; + sqe += dd*dd; + } + return sqe; +} + +double +_tenModel_nll(const double *dwiMeas, const double *dwiSim, + const tenExperSpec *espec, + int rician, double sigma) { + double nll; + unsigned int ii; + + nll = 0; + if (rician) { + for (ii=0; ii<espec->imgNum; ii++) { + nll += -airLogRician(dwiMeas[ii], dwiSim[ii], sigma); + } + } else { + double dd, ladd, denom; + ladd = log(sigma*sqrt(2*AIR_PI)); + denom = 1.0/(2*sigma*sigma); + for (ii=0; ii<espec->imgNum; ii++) { + dd = dwiMeas[ii] - dwiSim[ii]; + nll += dd*dd*denom + ladd; + } + } + return nll; +} + +int +tenDWMRIKeyValueFromExperSpecSet(Nrrd *ndwi, const tenExperSpec *espec) { + static char me[]="tenDWMRIKeyValueFromExperSpecSet"; + char keystr[AIR_STRLEN_MED], valstr[AIR_STRLEN_MED]; + + if (!(ndwi && espec)) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + + AIR_UNUSED(keystr); + AIR_UNUSED(valstr); + + /* + nrrdKeyValueAdd(ndwi, tenDWMRIModalityKey, tenDWMRIModalityVal); + sprintf(valstr, "%g", espec->); + nrrdKeyValueAdd(ndwi, tenDWMRIBValueKey, valstr); + if (tec->_ngrad) { + lup = nrrdDLookup[tec->_ngrad->type]; + for (allIdx=0; allIdx<tec->allNum; allIdx++) { + sprintf(keystr, tenDWMRIGradKeyFmt, allIdx); + sprintf(valstr, "%g %g %g", + lup(tec->_ngrad->data, 0 + 3*allIdx), + lup(tec->_ngrad->data, 1 + 3*allIdx), + lup(tec->_ngrad->data, 2 + 3*allIdx)); + nrrdKeyValueAdd(ndwi, keystr, valstr); + } + } else { + lup = nrrdDLookup[tec->_nbmat->type]; + for (allIdx=0; allIdx<tec->allNum; allIdx++) { + sprintf(keystr, tenDWMRIBmatKeyFmt, allIdx); + sprintf(valstr, "%g %g %g %g %g %g", + lup(tec->_nbmat->data, 0 + 6*allIdx), + lup(tec->_nbmat->data, 1 + 6*allIdx), + lup(tec->_nbmat->data, 2 + 6*allIdx), + lup(tec->_nbmat->data, 3 + 6*allIdx), + lup(tec->_nbmat->data, 4 + 6*allIdx), + lup(tec->_nbmat->data, 5 + 6*allIdx)); + nrrdKeyValueAdd(ndwi, keystr, valstr); + } + } + */ + + return 0; +} + +double +tenExperSpecKnownB0Get(const tenExperSpec *espec, const double *dwi) { + unsigned int ii, nb; + double b0; + + if (!( dwi && espec )) { + return AIR_NAN; + } + + nb = 0; + b0 = 0.0; + for (ii=0; ii<espec->imgNum; ii++) { + if (0 == espec->bval[ii]) { + b0 += dwi[ii]; + ++nb; + } + } + return b0/nb; +} + Added: teem/trunk/src/ten/modelBall.c =================================================================== --- teem/trunk/src/ten/modelBall.c (rev 0) +++ teem/trunk/src/ten/modelBall.c 2009-10-22 18:09:18 UTC (rev 4297) @@ -0,0 +1,104 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +#define PARM_NUM 2 + +static void +simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { + unsigned int ii; + double b0, diff; + + b0 = parm[0]; + diff = parm[1]; + for (ii=0; ii<espec->imgNum; ii++) { + dwiSim[ii] = b0*exp(-espec->bval[ii]*diff); + } + return; +} + +static double +sqe(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas) { + + simulate(dwiBuff, parm, espec); + return _tenModel_sqe(dwiMeas, dwiBuff, espec); +} + +static int +sqeFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +static double +nll(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma) { + + simulate(dwiBuff, parm, espec); + return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); +} + +static int +nllFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int rician, double sigma, int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +tenModel +_tenModelBall = { + "ball", + PARM_NUM, + { + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0} + }, + simulate, + sqe, + sqeFit, + nll, + nllFit +}; +const tenModel *const tenModelBall = &_tenModelBall; Added: teem/trunk/src/ten/modelBall1Stick.c =================================================================== --- teem/trunk/src/ten/modelBall1Stick.c (rev 0) +++ teem/trunk/src/ten/modelBall1Stick.c 2009-10-22 18:09:18 UTC (rev 4297) @@ -0,0 +1,116 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +#define PARM_NUM 6 + +static void +simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { + unsigned int ii; + double b0, diff, frac, vec[3]; + + b0 = parm[0]; + diff = parm[1]; + frac = parm[2]; + vec[0] = parm[3]; + vec[1] = parm[4]; + vec[2] = parm[5]; + for (ii=0; ii<espec->imgNum; ii++) { + double dwiBall, dwiStck, dot; + dwiBall = exp(-espec->bval[ii]*diff); + dot = ELL_3V_DOT(vec, espec->grad + 3*ii); + dwiStck = exp(-espec->bval[ii]*diff*dot*dot); + dwiSim[ii] = b0*((1-frac)*dwiBall + frac*dwiStck); + } + return; +} + +static double +sqe(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas) { + + simulate(dwiBuff, parm, espec); + return _tenModel_sqe(dwiMeas, dwiBuff, espec); +} + +static int +sqeFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +static double +nll(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma) { + + simulate(dwiBuff, parm, espec); + return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); +} + +static int +nllFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int rician, double sigma, int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +tenModel +_tenModelBall1Stick = { + "ball1stick", + PARM_NUM, + { + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"fraction", 0.0, 1.0, AIR_FALSE, 0}, + {"x", -1.0, 1.0, AIR_TRUE, 0}, + {"y", -1.0, 1.0, AIR_TRUE, 1}, + {"z", -1.0, 1.0, AIR_TRUE, 2}, + }, + simulate, + sqe, + sqeFit, + nll, + nllFit +}; +const tenModel *const tenModelBall1Stick = &_tenModelBall1Stick; Added: teem/trunk/src/ten/modelCylinder.c =================================================================== --- teem/trunk/src/ten/modelCylinder.c (rev 0) +++ teem/trunk/src/ten/modelCylinder.c 2009-10-22 18:09:18 UTC (rev 4297) @@ -0,0 +1,118 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +#define PARM_NUM 6 + +static void +simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { + unsigned int ii; + double b0, length, radius, vec[3], ten[7], + ident[7] = {1, 1, 0, 0, 1, 0, 1}; + + b0 = parm[0]; + length = parm[1]; + radius = parm[2]; + vec[0] = parm[3]; + vec[1] = parm[4]; + vec[2] = parm[5]; + TEN_T3V_OUTER(ten, vec); + TEN_T_SCALE_ADD2(ten, length - radius, ten, radius, ident); + for (ii=0; ii<espec->imgNum; ii++) { + double adc, bb; + bb = espec->bval[ii]; + adc = TEN_T3V_CONTR(ten, espec->grad + 3*ii); + dwiSim[ii] = b0*exp(-bb*adc); + } + return; +} + +static double +sqe(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas) { + + simulate(dwiBuff, parm, espec); + return _tenModel_sqe(dwiMeas, dwiBuff, espec); +} + +static int +sqeFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +static double +nll(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma) { + + simulate(dwiBuff, parm, espec); + return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); +} + +static int +nllFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int rician, double sigma, int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +tenModel +_tenModelCylinder = { + "cylinder", + PARM_NUM, + { + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + {"length", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"radius", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"x", -1.0, 1.0, AIR_TRUE, 0}, + {"y", -1.0, 1.0, AIR_TRUE, 1}, + {"z", -1.0, 1.0, AIR_TRUE, 2}, + }, + simulate, + sqe, + sqeFit, + nll, + nllFit +}; +const tenModel *const tenModelCylinder = &_tenModelCylinder; Added: teem/trunk/src/ten/modelTen.c =================================================================== --- teem/trunk/src/ten/modelTen.c (rev 0) +++ teem/trunk/src/ten/modelTen.c 2009-10-22 18:09:18 UTC (rev 4297) @@ -0,0 +1,268 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +static const tenModel * +str2model(const char *str) { + const tenModel *ret = NULL; + + if (!strcmp(str, "ball")) ret = tenModelBall; + + if (!strcmp(str, "ball1stick")) ret = tenModelBall1Stick; + + if (!strcmp(str, "cyl")) ret = tenModelCylinder; + if (!strcmp(str, "cylinder")) ret = tenModelCylinder; + + if (!strcmp(str, "tensor2")) ret = tenModelTensor2; + return ret; +} + +int +tenModelParse(const tenModel **model, int *plusB0, const char *_str) { + static const char me[]="tenModelParse"; + char *str, *modstr; + airArray *mop; + + if (!( model && plusB0 && _str)) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + str = airToLower(airStrdup(_str)); + if (!str) { + biffAddf(TEN, "%s: couldn't strdup", me); + return 1; + } + + mop = airMopNew(); + airMopAdd(mop, str, airFree, airMopAlways); + if ((modstr = strchr(str, '+'))) { + *modstr = '\0'; + ++modstr; + if (!strcmp(str, "b0")) { + *plusB0 = AIR_TRUE; + } else { + biffAddf(TEN, "%s: string (\"%s\") prior to \"+\" not \"b0\"", me, str); + airMopError(mop); + return 1; + } + } else { + *plusB0 = AIR_FALSE; + modstr = str; + } + if (!(*model = str2model(modstr))) { + biffAddf(TEN, "%s: didn't recognize \"%s\" as model", me, str); + airMopError(mop); + return 1; + } + airMopOkay(mop); + return 0; +} + +/* +** if nB0 is given, and if parm vector is short by one (seems to be +** missing B0), then use that instead. Otherwise parm vector has to +** be length that includes B0 +*/ +int +tenModelSimulate(Nrrd *ndwi, int typeOut, + tenExperSpec *espec, + const tenModel *model, + const Nrrd *_nB0, + const Nrrd *_nparm, + int keyValueSet) { + static const char me[]="tenModelSimulate"; + double *ddwi, *parm, (*ins)(void *v, size_t I, double d); + char *dwi; + size_t szOut[NRRD_DIM_MAX], II, numSamp; + const Nrrd *nB0, /* B0 as doubles */ + *ndparm, /* parm as doubles */ + *ndpparm, /* parm as doubles, padded */ + *nparm; /* final parm as doubles, padded, w/ correct B0 values */ + Nrrd *ntmp; /* non-const pointer for working */ + airArray *mop; + unsigned int gpsze, /* given parm size */ + ii; + int useB0, needPad; + + if (!(ndwi && espec && model /* _nB0 can be NULL */ && _nparm)) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + + gpsze = _nparm->axis[0].size; + if (model->parmNum - 1 == gpsze) { + /* got one less than needed parm #, see if we got B0 */ + if (!_nB0) { + biffAddf(TEN, "%s: got %u parms, need %u, but didn't get B0 vol", + me, gpsze, model->parmNum); + return 1; + } + useB0 = AIR_TRUE; + needPad = AIR_TRUE; + } else if (model->parmNum != gpsze) { + biffAddf(TEN, "%s: mismatch between getting %u parms, needing %u\n", + me, gpsze, model->parmNum); + return 1; + } else { + /* model->parmNum == gpsze */ + needPad = AIR_FALSE; + useB0 = !!_nB0; + } + + mop = airMopNew(); + /* get parms as doubles */ + if (nrrdTypeDouble == _nparm->type) { + ndparm = _nparm; + } else { + ntmp = nrrdNew(); + airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); + if (nrrdConvert(ntmp, _nparm, nrrdTypeDouble)) { + biffMovef(TEN, NRRD, "%s: couldn't convert parm to %s", me, + airEnumStr(nrrdType, nrrdTypeDouble)); + airMopError(mop); return 1; + } + ndparm = ntmp; + } + /* get parms the right length */ + if (!needPad) { + ndpparm = ndparm; + } else { + ptrdiff_t min[NRRD_DIM_MAX], max[NRRD_DIM_MAX]; + unsigned int ax; + + ntmp = nrrdNew(); + airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); + for (ax=0; ax<ndparm->dim; ax++) { + min[ax] = (!ax ? -1 : 0); + max[ax] = ndparm->axis[ax].size-1; + } + if (nrrdPad_nva(ntmp, ndparm, min, max, nrrdBoundaryBleed, 0.0)) { + biffMovef(TEN, NRRD, "%s: couldn't pad", me); + airMopError(mop); return 1; + } + ndpparm = ntmp; + } + /* put in B0 values if needed */ + if (!useB0) { + nparm = ndpparm; + } else { + if (nrrdTypeDouble == _nB0->type) { + nB0 = _nB0; + } else { + ntmp = nrrdNew(); + airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); + if (nrrdConvert(ntmp, _nB0, nrrdTypeDouble)) { + biffMovef(TEN, NRRD, "%s: couldn't convert B0 to %s", me, + airEnumStr(nrrdType, nrrdTypeDouble)); + airMopError(mop); return 1; + } + nB0 = ntmp; + } + /* HEY: this is mostly likely a waste of memory, + but its all complicated by const-correctness */ + ntmp = nrrdNew(); + airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); + if (nrrdSplice(ntmp, ndpparm, nB0, 0, 0)) { + biffMovef(TEN, NRRD, "%s: couldn't splice in B0", me); + airMopError(mop); return 1; + } + nparm = ntmp; + } + + /* allocate output */ + for (ii=0; ii<nparm->dim; ii++) { + szOut[ii] = (!ii + ? espec->imgNum + : nparm->axis[ii].size); + } + if (nrrdMaybeAlloc_nva(ndwi, typeOut, nparm->dim, szOut)) { + biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + airMopError(mop); return 1; + } + if (!(ddwi = AIR_CAST(double *, calloc(espec->imgNum, sizeof(double))))) { + biffAddf(TEN, "%s: couldn't allocate dwi buffer", me); + airMopError(mop); return 1; + } + airMopAdd(mop, ddwi, airFree, airMopAlways); + numSamp = nrrdElementNumber(nparm)/nparm->axis[0].size; + + /* set output */ + ins = nrrdDInsert[typeOut]; + parm = AIR_CAST(double *, nparm->data); + dwi = AIR_CAST(char *, ndwi->data); + for (II=0; II<numSamp; II++) { + model->simulate(ddwi, parm, espec); + for (ii=0; ii<espec->imgNum; ii++) { + ins(dwi, ii, ddwi[ii]); + } + parm += model->parmNum; + dwi += espec->imgNum*nrrdTypeSize[typeOut]; + } + + if (keyValueSet) { + if (tenDWMRIKeyValueFromExperSpecSet(ndwi, espec)) { + biffAddf(TEN, "%s: trouble", me); + airMopError(mop); return 1; + } + } + + /* set basic info */ + + airMopOkay(mop); + return 0; +} + +int +tenModelSqeFit(Nrrd *nparm, Nrrd **nsqeP, + const tenModel *model, + const tenExperSpec *espec, const Nrrd *ndwi, + int knownB0) { + + AIR_UNUSED(nparm); + AIR_UNUSED(nsqeP); + AIR_UNUSED(model); + AIR_UNUSED(espec); + AIR_UNUSED(ndwi); + AIR_UNUSED(knownB0); + + return 0; +} + +int +tenModelNllFit(Nrrd *nparm, Nrrd **nnllP, + const tenModel *model, + const tenExperSpec *espec, const Nrrd *ndwi, + int rician, double sigma, int knownB0) { + + AIR_UNUSED(nparm); + AIR_UNUSED(nnllP); + AIR_UNUSED(model); + AIR_UNUSED(espec); + AIR_UNUSED(ndwi); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + AIR_UNUSED(knownB0); + + return 0; +} Added: teem/trunk/src/ten/modelTensor2.c =================================================================== --- teem/trunk/src/ten/modelTensor2.c (rev 0) +++ teem/trunk/src/ten/modelTensor2.c 2009-10-22 18:09:18 UTC (rev 4297) @@ -0,0 +1,121 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +#define PARM_NUM 6 + +static void +simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { + unsigned int ii; + double b0, ten[7]; + + b0 = parm[0]; + ten[0] = 1; + ten[1] = parm[1]; + ten[2] = parm[2]; + ten[3] = parm[3]; + ten[4] = parm[4]; + ten[5] = parm[5]; + ten[6] = parm[6]; + for (ii=0; ii<espec->imgNum; ii++) { + double adc, bb; + bb = espec->bval[ii]; + adc = TEN_T3V_CONTR(ten, espec->grad + 3*ii); + dwiSim[ii] = b0*exp(-bb*adc); + } + return; +} + +static double +sqe(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas) { + + simulate(dwiBuff, parm, espec); + return _tenModel_sqe(dwiMeas, dwiBuff, espec); +} + +static int +sqeFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +static double +nll(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma) { + + simulate(dwiBuff, parm, espec); + return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); +} + +static int +nllFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int rician, double sigma, int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +/* 1/sqrt(2) */ +#define OST 0.70710678118654752440 + +tenModel +_tenModelTensor2 = { + "tensor2", + PARM_NUM, + { + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + {"Dxx", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"Dxy", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, + {"Dxz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, + {"Dyy", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"Dyz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, + {"Dzz", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + }, + simulate, + sqe, + sqeFit, + nll, + nllFit +}; +const tenModel *const tenModelTensor2 = &_tenModelTensor2; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-22 18:10:39
|
Revision: 4298 http://teem.svn.sourceforge.net/teem/?rev=4298&view=rev Author: kindlmann Date: 2009-10-22 18:10:31 +0000 (Thu, 22 Oct 2009) Log Message: ----------- adding const to airEnums, and adding more flexible modeling of DWI signals Modified Paths: -------------- teem/trunk/src/ten/GNUmakefile teem/trunk/src/ten/chan.c teem/trunk/src/ten/enumsTen.c teem/trunk/src/ten/estimate.c teem/trunk/src/ten/privateTen.h teem/trunk/src/ten/sources.cmake teem/trunk/src/ten/ten.h teem/trunk/src/ten/tendFiber.c Modified: teem/trunk/src/ten/GNUmakefile =================================================================== --- teem/trunk/src/ten/GNUmakefile 2009-10-22 18:09:18 UTC (rev 4297) +++ teem/trunk/src/ten/GNUmakefile 2009-10-22 18:10:31 UTC (rev 4298) @@ -51,7 +51,9 @@ $(L).OBJS = tensor.o chan.o aniso.o glyph.o enumsTen.o grads.o miscTen.o \ mod.o estimate.o tenGage.o tenDwiGage.o qseg.o path.o qglox.o \ fiberMethods.o fiber.o epireg.o defaultsTen.o bimod.o bvec.o \ - triple.o tendAbout.o \ + triple.o experSpec.o modelTen.o modelBall.o modelBall1Stick.o \ + modelCylinder.o modelTensor2.o \ + tendAbout.o \ tendFlotsam.o tendGrads.o tendAnplot.o tendAnvol.o tendEval.o \ tendEvec.o tendSten.o tendExpand.o tendEvq.o tendPoint.o \ tendTriple.o tendTconv.o tendAvg.o \ @@ -61,8 +63,8 @@ tendEvalpow.o tendEvalclamp.o tendEvaladd.o tendHelix.o tendBfit.o \ tendUnmf.o tendLog.o tendExp.o $(L).TESTS = test/roistat test/tg test/tt test/tem test/rotedge \ - test/tsoid test/odf-hist test/to test/tensorDotDat \ - test/igrt test/cntr test/geode test/taniso test/csim \ + test/tsoid test/odf-hist test/to test/tensorDotDat \ + test/igrt test/cntr test/geode test/taniso test/csim \ test/ttriple test/tqgl #### #### Modified: teem/trunk/src/ten/chan.c =================================================================== --- teem/trunk/src/ten/chan.c 2009-10-22 18:09:18 UTC (rev 4297) +++ teem/trunk/src/ten/chan.c 2009-10-22 18:10:31 UTC (rev 4298) @@ -53,8 +53,9 @@ ** Parses through key-value pairs in the NRRD header to determine the ** list of diffusion-sensitizing gradient directions, or B-matrices ** (depending to what was found), according the NAMIC conventions. -** This requires, among other things, that ndwi be have exactly one axis -** with kind nrrdKindList, which is taken to be the DWI axis. +** This requires, among other things, that ndwi be have exactly one +** axis with kind nrrdKindList (or nrrdKindVector), which is taken to +** be the DWI axis. ** ** Either *ngradP or *nbmatP is set to a newly- allocated nrrd ** containing this information, and the other one is set to NULL Modified: teem/trunk/src/ten/enumsTen.c =================================================================== --- teem/trunk/src/ten/enumsTen.c 2009-10-22 18:09:18 UTC (rev 4297) +++ teem/trunk/src/ten/enumsTen.c 2009-10-22 18:10:31 UTC (rev 4298) @@ -59,7 +59,7 @@ "eval2" }; -airEnum +const airEnum _tenAniso = { "anisotropy metric", TEN_ANISO_MAX, @@ -68,7 +68,7 @@ NULL, NULL, AIR_FALSE }; -airEnum * +const airEnum *const tenAniso = &_tenAniso; /* --------------------------------------------------------------------- */ @@ -117,7 +117,7 @@ tenInterpTypeQuatGeoLoxR, tenInterpTypeQuatGeoLoxR, }; -airEnum +const airEnum _tenInterpType = { "interp type", TEN_INTERP_TYPE_MAX, @@ -126,7 +126,7 @@ _tenInterpTypeStrEqv, _tenInterpTypeValEqv, AIR_FALSE }; -airEnum * +const airEnum *const tenInterpType = &_tenInterpType; /* --------------------------------------------------------------------- */ @@ -999,7 +999,7 @@ tenGageAniso, tenGageAniso, tenGageAniso }; -airEnum +const airEnum _tenGage = { "tenGage", TEN_GAGE_ITEM_MAX, @@ -1008,7 +1008,7 @@ _tenGageStrEqv, _tenGageValEqv, AIR_FALSE }; -airEnum * +const airEnum *const tenGage = &_tenGage; /* --------------------------------------------------------------------- */ @@ -1056,7 +1056,7 @@ tenFiberTypeZhukov, tenFiberTypeZhukov }; -airEnum +const airEnum _tenFiberType = { "tenFiberType", TEN_FIBER_TYPE_MAX, @@ -1065,7 +1065,7 @@ _tenFiberTypeStrEqv, _tenFiberTypeValEqv, AIR_FALSE }; -airEnum * +const airEnum *const tenFiberType = &_tenFiberType; /* --------------------------------------------------------------------- */ @@ -1101,7 +1101,7 @@ tenDwiFiberType12BlendEvec0, tenDwiFiberType12BlendEvec0 }; -airEnum +const airEnum _tenDwiFiberType = { "tenDwiFiberType", TEN_DWI_FIBER_TYPE_MAX, @@ -1110,7 +1110,7 @@ _tenDwiFiberTypeStrEqv, _tenDwiFiberTypeValEqv, AIR_FALSE }; -airEnum * +const airEnum *const tenDwiFiberType = &_tenDwiFiberType; /* ----------------------------------------------------------------------- */ @@ -1174,7 +1174,7 @@ "whole fiber has too few numbers of steps" }; -airEnum +const airEnum _tenFiberStop = { "fiber stopping criteria", TEN_FIBER_STOP_MAX, @@ -1183,7 +1183,7 @@ _tenFiberStopStrEqv, _tenFiberStopValEqv, AIR_FALSE }; -airEnum * +const airEnum *const tenFiberStop = &_tenFiberStop; /* ----------------------------------------------------------------------- */ @@ -1219,7 +1219,7 @@ "4rth order Runge-Kutta" }; -airEnum +const airEnum _tenFiberIntg = { "fiber integration method", TEN_FIBER_INTG_MAX, @@ -1228,7 +1228,7 @@ _tenFiberIntgStrEqv, _tenFiberIntgValEqv, AIR_FALSE }; -airEnum * +const airEnum *const tenFiberIntg = &_tenFiberIntg; /* ----------------------------------------------------------------------- */ @@ -1273,7 +1273,7 @@ "superquadric (superellipsoids)" }; -airEnum +const airEnum _tenGlyphType = { "tenGlyphType", TEN_GLYPH_TYPE_MAX, @@ -1282,7 +1282,7 @@ _tenGlyphTypeStrEqv, _tenGlyphTypeValEqv, AIR_FALSE }; -airEnum * +const airEnum *const tenGlyphType = &_tenGlyphType; /* ---------------------------------------------- */ @@ -1305,7 +1305,7 @@ "maximum likelihood estimate from DWI" }; -airEnum +const airEnum _tenEstimate1Method = { "single-tensor-estimation", TEN_ESTIMATE_1_METHOD_MAX, @@ -1314,7 +1314,7 @@ NULL, NULL, AIR_FALSE }; -airEnum * +const airEnum *const tenEstimate1Method= &_tenEstimate1Method; /* ---------------------------------------------- */ @@ -1333,7 +1333,7 @@ "Peled" }; -airEnum +const airEnum _tenEstimate2Method = { "two-tensor-estimation", TEN_ESTIMATE_2_METHOD_MAX, @@ -1342,7 +1342,7 @@ NULL, NULL, AIR_FALSE }; -airEnum * +const airEnum *const tenEstimate2Method= &_tenEstimate2Method; /* ---------------------------------------------- */ @@ -1402,7 +1402,7 @@ tenTripleTypeWheelParm, tenTripleTypeWheelParm }; -airEnum +const airEnum _tenTripleType = { "tenTripleType", TEN_TRIPLE_TYPE_MAX, @@ -1411,5 +1411,5 @@ _tenTripleTypeStrEqv, _tenTripleTypeValEqv, AIR_FALSE }; -airEnum * +const airEnum *const tenTripleType = &_tenTripleType; Modified: teem/trunk/src/ten/estimate.c =================================================================== --- teem/trunk/src/ten/estimate.c 2009-10-22 18:09:18 UTC (rev 4297) +++ teem/trunk/src/ten/estimate.c 2009-10-22 18:10:31 UTC (rev 4298) @@ -1001,7 +1001,6 @@ const Nrrd *nB0, const Nrrd *nten, int outType, int keyValueSet) { static const char me[]="tenEstimate1TensorSimulateVolume"; - char keystr[AIR_STRLEN_MED], valstr[AIR_STRLEN_MED]; size_t sizeTen, sizeX, sizeY, sizeZ, NN, II; double (*tlup)(const void *, size_t), (*blup)(const void *, size_t), (*lup)(const void *, size_t), ten_d[7], *dwi_d, B0; @@ -1098,6 +1097,8 @@ airMopError(mop); return 1; } if (keyValueSet) { + char keystr[AIR_STRLEN_MED], valstr[AIR_STRLEN_MED]; + nrrdKeyValueAdd(ndwi, tenDWMRIModalityKey, tenDWMRIModalityVal); sprintf(valstr, "%g", bValue); nrrdKeyValueAdd(ndwi, tenDWMRIBValueKey, valstr); Modified: teem/trunk/src/ten/privateTen.h =================================================================== --- teem/trunk/src/ten/privateTen.h 2009-10-22 18:09:18 UTC (rev 4297) +++ teem/trunk/src/ten/privateTen.h 2009-10-22 18:10:31 UTC (rev 4298) @@ -147,6 +147,15 @@ const double *wght, unsigned int NN, int ptype, tenInterpParm *tip); +/* modelUtil.c */ +TEN_EXPORT double _tenModel_sqe(const double *dwiMeas, + const double *dwiSim, + const tenExperSpec *espec); +TEN_EXPORT double _tenModel_nll(const double *dwiMeas, + const double *dwiSim, + const tenExperSpec *espec, + int rician, double sigma); + #ifdef __cplusplus } #endif Modified: teem/trunk/src/ten/sources.cmake =================================================================== --- teem/trunk/src/ten/sources.cmake 2009-10-22 18:09:18 UTC (rev 4297) +++ teem/trunk/src/ten/sources.cmake 2009-10-22 18:10:31 UTC (rev 4298) @@ -62,6 +62,12 @@ tendUnmf.c tensor.c triple.c + experSpec.c + modelTen.c + modelBall.c + modelBall1Stick.c + modelCylinder.c + modelTensor2.c ) ADD_TEEM_LIBRARY(ten ${TEN_SOURCES}) Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-10-22 18:09:18 UTC (rev 4297) +++ teem/trunk/src/ten/ten.h 2009-10-22 18:10:31 UTC (rev 4298) @@ -1075,6 +1075,68 @@ double lengthShape, lengthOrient; } tenInterpParm; +/* the idea is that there should be a uniform way of describing + DWI experiments, and as a result of calling one of the Set() + functions below, the information is set in tenExperSpec so that + combined with a diffusion model spec, DWIs can be simulated */ +typedef struct { + int set; /* has been set */ + unsigned imgNum; /* total number of images, dwi or not */ + double *bval, /* all b values: imgNum doubles */ + *wght, /* all weights: imgNum doubles */ + *grad; /* all gradients: 3 x imgNum doubles */ +} tenExperSpec; + +typedef struct { + char name[AIR_STRLEN_SMALL]; /* name */ + double min, max; /* bounds */ + int vec3; /* non-zero if this is one coeff of 3-vector */ + unsigned int idx; /* if 3-vector, index into it */ +} tenModelParmDesc; + +#define TEN_MODEL_PARM_MAXNUM 15 /* adjust as needed */ +#define TEN_MODEL_B0_MAX 65536 /* pretty arbitrary */ +#define TEN_MODEL_DIFF_MAX 0.004 /* in units of mm^2/sec */ + +/* +******** struct tenModel +** +** container for information about how DWI values arise, +** with functions that help in fitting and evaluating models +** +** NOTE: the current convention is to *always* have the non-DW +** T2 image value ("B0") be the first parameter in the model. +** The B0 value will probably be found by trivial means (i.e copied +** from the image data), or by a different method than the rest +** of the model parameters, but (1) its very handy to have in one +** place all the information that, when combined with the +** tenExperSpec, gives you a DWI value, and (2) sometimes B0 does +** have to be estimated at the same time as the rest of the model, +** and it would be dumb to double the number of models to be able +** to capture this. +*/ +typedef struct { + char name[AIR_STRLEN_SMALL]; + unsigned int parmNum; + tenModelParmDesc parmDesc[TEN_MODEL_PARM_MAXNUM]; + /* noise free simulation */ + void (*simulate)(double *dwiSim, const double *parm, + const tenExperSpec *espec); + /* "sqe" == squared error in DWI values */ + double (*sqe)(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas); + int (*sqeFit)(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int knownB0); + /* "nll" == negative log likelihood */ + double (*nll)(double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma); + int (*nllFit)(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int rician, double sigma, int knownB0); +} tenModel; + /* defaultsTen.c */ TEN_EXPORT const char *tenBiffKey; TEN_EXPORT const char tenDefFiberKernel[]; @@ -1125,18 +1187,18 @@ tenGradientParm *tgparm); /* enumsTen.c */ -TEN_EXPORT airEnum *tenAniso; -TEN_EXPORT airEnum *tenInterpType; -TEN_EXPORT airEnum _tenGage; -TEN_EXPORT airEnum *tenGage; -TEN_EXPORT airEnum *tenFiberType; -TEN_EXPORT airEnum *tenDwiFiberType; -TEN_EXPORT airEnum *tenFiberStop; -TEN_EXPORT airEnum *tenFiberIntg; -TEN_EXPORT airEnum *tenGlyphType; -TEN_EXPORT airEnum *tenEstimate1Method; -TEN_EXPORT airEnum *tenEstimate2Method; -TEN_EXPORT airEnum *tenTripleType; +TEN_EXPORT const airEnum *const tenAniso; +TEN_EXPORT const airEnum *const tenInterpType; +TEN_EXPORT const airEnum _tenGage; +TEN_EXPORT const airEnum *const tenGage; +TEN_EXPORT const airEnum *const tenFiberType; +TEN_EXPORT const airEnum *const tenDwiFiberType; +TEN_EXPORT const airEnum *const tenFiberStop; +TEN_EXPORT const airEnum *const tenFiberIntg; +TEN_EXPORT const airEnum *const tenGlyphType; +TEN_EXPORT const airEnum *const tenEstimate1Method; +TEN_EXPORT const airEnum *const tenEstimate2Method; +TEN_EXPORT const airEnum *const tenTripleType; /* path.c */ TEN_EXPORT tenInterpParm *tenInterpParmNew(); @@ -1435,6 +1497,58 @@ const NrrdKernel *kern, double *kparm, int progress, int verbose); +/* experspec.c */ +TEN_EXPORT tenExperSpec* tenExperSpecNew(void); +TEN_EXPORT int tenExperSpecGradSingleBValSet(tenExperSpec *espec, + unsigned int imgNum, + double bval, + const double *grad); +TEN_EXPORT int tenExperSpecGradBValSet(tenExperSpec *espec, + unsigned int imgNum, + const double *bval, + const double *grad); +TEN_EXPORT int tenExperSpecGradBValWghtSet(tenExperSpec *espec, + unsigned int imgNum, + const double *bval, + const double *grad, + const double *wght); +TEN_EXPORT int tenExperSpecFromKeyValueSet(tenExperSpec *espec, + const Nrrd *ndwi); +TEN_EXPORT tenExperSpec* tenExperSpecNix(tenExperSpec *espec); +TEN_EXPORT int tenDWMRIKeyValueFromExperSpecSet(Nrrd *ndwi, + const tenExperSpec *espec); +TEN_EXPORT double tenExperSpecKnownB0Get(const tenExperSpec *espec, + const double *dwi); + +/* modelTen.c */ +TEN_EXPORT int tenModelParse(const tenModel **model, int *plusB0, + const char *_str); +TEN_EXPORT int tenModelSimulate(Nrrd *ndwi, int typeOut, + tenExperSpec *espec, + const tenModel *model, + const Nrrd *nB0, /* maybe NULL */ + const Nrrd *nparm, + int keyValueSet); +TEN_EXPORT int tenModelSqeFit(Nrrd *nparm, Nrrd **nsqeP, + const tenModel *model, + const tenExperSpec *espec, const Nrrd *ndwi, + int knownB0); +TEN_EXPORT int tenModelNllFit(Nrrd *nparm, Nrrd **nnllP, + const tenModel *model, + const tenExperSpec *espec, const Nrrd *ndwi, + int rician, double sigma, int knownB0); + + +/* have to keep in sync with modelUtil.c/tenModelParse() */ +/* modelBall.c */ +TEN_EXPORT const tenModel *const tenModelBall; +/* modelBall1Stick.c */ +TEN_EXPORT const tenModel *const tenModelBall1Stick; +/* modelCylinder.c */ +TEN_EXPORT const tenModel *const tenModelCylinder; +/* modelTensor2.c */ +TEN_EXPORT const tenModel *const tenModelTensor2; + /* mod.c */ TEN_EXPORT int tenSizeNormalize(Nrrd *nout, const Nrrd *nin, double weight[3], double amount, double target); Modified: teem/trunk/src/ten/tendFiber.c =================================================================== --- teem/trunk/src/ten/tendFiber.c 2009-10-22 18:09:18 UTC (rev 4297) +++ teem/trunk/src/ten/tendFiber.c 2009-10-22 18:10:31 UTC (rev 4298) @@ -40,7 +40,7 @@ tenFiberSingle *tfbs; NrrdKernelSpec *ksp; double start[3], step, *_stop, *stop; - airEnum *ftypeEnum; + const airEnum *ftypeEnum; char *ftypeS; int E, intg, useDwi, allPaths, verbose, worldSpace, worldSpaceOut, ftype, ftypeDef; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-22 22:27:19
|
Revision: 4310 http://teem.svn.sourceforge.net/teem/?rev=4310&view=rev Author: kindlmann Date: 2009-10-22 22:27:12 +0000 (Thu, 22 Oct 2009) Log Message: ----------- improving tenModel code, added tend msim Modified Paths: -------------- teem/trunk/src/ten/GNUmakefile teem/trunk/src/ten/experSpec.c teem/trunk/src/ten/modelTen.c teem/trunk/src/ten/modelTensor2.c teem/trunk/src/ten/sources.cmake teem/trunk/src/ten/ten.h Modified: teem/trunk/src/ten/GNUmakefile =================================================================== --- teem/trunk/src/ten/GNUmakefile 2009-10-22 19:43:13 UTC (rev 4309) +++ teem/trunk/src/ten/GNUmakefile 2009-10-22 22:27:12 UTC (rev 4310) @@ -58,7 +58,7 @@ tendEvec.o tendSten.o tendExpand.o tendEvq.o tendPoint.o \ tendTriple.o tendTconv.o tendAvg.o \ tendAnhist.o tendMake.o tendSatin.o tendShrink.o tendGlyph.o \ - tendFiber.o tendEpireg.o tendBmat.o tendEstim.o tendSim.o \ + tendFiber.o tendEpireg.o tendBmat.o tendEstim.o tendSim.o tendMsim.o \ tendSlice.o tendEllipse.o tendEvecrgb.o tendNorm.o tendAnscale.o \ tendEvalpow.o tendEvalclamp.o tendEvaladd.o tendHelix.o tendBfit.o \ tendUnmf.o tendLog.o tendExp.o Modified: teem/trunk/src/ten/experSpec.c =================================================================== --- teem/trunk/src/ten/experSpec.c 2009-10-22 19:43:13 UTC (rev 4309) +++ teem/trunk/src/ten/experSpec.c 2009-10-22 22:27:12 UTC (rev 4310) @@ -34,6 +34,7 @@ biffAddf(TEN, "%s: need a non-zero number of images", me); return 1; } + espec->imgNum = num; espec->bval = AIR_CAST(double *, calloc(num, sizeof(double))); espec->grad = AIR_CAST(double *, calloc(3*num, sizeof(double))); espec->wght = AIR_CAST(double *, calloc(num, sizeof(double))); @@ -243,44 +244,27 @@ tenDWMRIKeyValueFromExperSpecSet(Nrrd *ndwi, const tenExperSpec *espec) { static char me[]="tenDWMRIKeyValueFromExperSpecSet"; char keystr[AIR_STRLEN_MED], valstr[AIR_STRLEN_MED]; + double maxb, bb; + unsigned int ii; if (!(ndwi && espec)) { biffAddf(TEN, "%s: got NULL pointer", me); return 1; } - AIR_UNUSED(keystr); - AIR_UNUSED(valstr); - - /* nrrdKeyValueAdd(ndwi, tenDWMRIModalityKey, tenDWMRIModalityVal); - sprintf(valstr, "%g", espec->); - nrrdKeyValueAdd(ndwi, tenDWMRIBValueKey, valstr); - if (tec->_ngrad) { - lup = nrrdDLookup[tec->_ngrad->type]; - for (allIdx=0; allIdx<tec->allNum; allIdx++) { - sprintf(keystr, tenDWMRIGradKeyFmt, allIdx); - sprintf(valstr, "%g %g %g", - lup(tec->_ngrad->data, 0 + 3*allIdx), - lup(tec->_ngrad->data, 1 + 3*allIdx), - lup(tec->_ngrad->data, 2 + 3*allIdx)); - nrrdKeyValueAdd(ndwi, keystr, valstr); - } - } else { - lup = nrrdDLookup[tec->_nbmat->type]; - for (allIdx=0; allIdx<tec->allNum; allIdx++) { - sprintf(keystr, tenDWMRIBmatKeyFmt, allIdx); - sprintf(valstr, "%g %g %g %g %g %g", - lup(tec->_nbmat->data, 0 + 6*allIdx), - lup(tec->_nbmat->data, 1 + 6*allIdx), - lup(tec->_nbmat->data, 2 + 6*allIdx), - lup(tec->_nbmat->data, 3 + 6*allIdx), - lup(tec->_nbmat->data, 4 + 6*allIdx), - lup(tec->_nbmat->data, 5 + 6*allIdx)); - nrrdKeyValueAdd(ndwi, keystr, valstr); - } - } - */ + maxb = tenExperSpecMaxBGet(espec); + sprintf(valstr, "%g", maxb); + nrrdKeyValueAdd(ndwi, tenDWMRIBValueKey, valstr); + for (ii=0; ii<espec->imgNum; ii++) { + double vec[3]; + sprintf(keystr, tenDWMRIGradKeyFmt, ii); + ELL_3V_COPY(vec, espec->grad + 3*ii); + bb = espec->bval[ii]; + ELL_3V_SCALE(vec, sqrt(bb/maxb), vec); + sprintf(valstr, "%g %g %g", vec[0], vec[1], vec[2]); + nrrdKeyValueAdd(ndwi, keystr, valstr); + } return 0; } @@ -305,3 +289,18 @@ return b0/nb; } +double +tenExperSpecMaxBGet(const tenExperSpec *espec) { + unsigned int ii; + double bval; + + if (!( espec )) { + return AIR_NAN; + } + + bval = -1; + for (ii=0; ii<espec->imgNum; ii++) { + bval = AIR_MAX(bval, espec->bval[ii]); + } + return bval; +} Modified: teem/trunk/src/ten/modelTen.c =================================================================== --- teem/trunk/src/ten/modelTen.c 2009-10-22 19:43:13 UTC (rev 4309) +++ teem/trunk/src/ten/modelTen.c 2009-10-22 22:27:12 UTC (rev 4310) @@ -79,10 +79,37 @@ return 0; } +int +tenModelFromAxisLearn(const tenModel **modelP, + const NrrdAxisInfo *axinfo) { + static const char me[]="tenModelFromAxisLearn"; + + if (!(modelP && axinfo)) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + /* first try to learn model from "kind" */ + if (nrrdKind3DSymMatrix == axinfo->kind + || nrrdKind3DMaskedSymMatrix == axinfo->kind) { + *modelP = tenModelTensor2; + } else if (airStrlen(axinfo->label)) { + /* try to parse from label */ + + } else { + biffAddf(TEN, "%s: don't have kind or label info to learn model", me); + *modelP = NULL; + return 1; + } + + return 0; +} + /* ** if nB0 is given, and if parm vector is short by one (seems to be ** missing B0), then use that instead. Otherwise parm vector has to ** be length that includes B0 +** +** basic and axis info is derived from _nparm */ int tenModelSimulate(Nrrd *ndwi, int typeOut, @@ -103,26 +130,32 @@ airArray *mop; unsigned int gpsze, /* given parm size */ ii; - int useB0, needPad; + int useB0, needPad, axmap[NRRD_DIM_MAX]; if (!(ndwi && espec && model /* _nB0 can be NULL */ && _nparm)) { biffAddf(TEN, "%s: got NULL pointer", me); return 1; } + if (!espec->imgNum) { + biffAddf(TEN, "%s: given espec wants 0 images, unset?", me); + return 1; + } gpsze = _nparm->axis[0].size; if (model->parmNum - 1 == gpsze) { /* got one less than needed parm #, see if we got B0 */ if (!_nB0) { - biffAddf(TEN, "%s: got %u parms, need %u, but didn't get B0 vol", - me, gpsze, model->parmNum); + biffAddf(TEN, "%s: got %u parms, need %u (for %s), " + "but didn't get B0 vol", + me, gpsze, model->parmNum, model->name); return 1; } useB0 = AIR_TRUE; needPad = AIR_TRUE; } else if (model->parmNum != gpsze) { - biffAddf(TEN, "%s: mismatch between getting %u parms, needing %u\n", - me, gpsze, model->parmNum); + biffAddf(TEN, "%s: mismatch between getting %u parms, " + "needing %u (for %s)\n", + me, gpsze, model->parmNum, model->name); return 1; } else { /* model->parmNum == gpsze */ @@ -190,11 +223,14 @@ nparm = ntmp; } - /* allocate output */ + /* allocate output (and set axmap) */ for (ii=0; ii<nparm->dim; ii++) { szOut[ii] = (!ii ? espec->imgNum : nparm->axis[ii].size); + axmap[ii] = (!ii + ? -1 + : AIR_CAST(int, ii)); } if (nrrdMaybeAlloc_nva(ndwi, typeOut, nparm->dim, szOut)) { biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); @@ -227,7 +263,20 @@ } } - /* set basic info */ + if (nrrdAxisInfoCopy(ndwi, _nparm, axmap, NRRD_AXIS_INFO_SIZE_BIT) + || nrrdBasicInfoCopy(ndwi, _nparm, + NRRD_BASIC_INFO_DATA_BIT + | NRRD_BASIC_INFO_TYPE_BIT + | NRRD_BASIC_INFO_BLOCKSIZE_BIT + | NRRD_BASIC_INFO_DIMENSION_BIT + | NRRD_BASIC_INFO_CONTENT_BIT + | NRRD_BASIC_INFO_COMMENTS_BIT + | (nrrdStateKeyValuePairsPropagate + ? 0 + : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { + biffMovef(TEN, NRRD, "%s: couldn't copy axis or basic info", me); + airMopError(mop); return 1; + } airMopOkay(mop); return 0; Modified: teem/trunk/src/ten/modelTensor2.c =================================================================== --- teem/trunk/src/ten/modelTensor2.c 2009-10-22 19:43:13 UTC (rev 4309) +++ teem/trunk/src/ten/modelTensor2.c 2009-10-22 22:27:12 UTC (rev 4310) @@ -23,7 +23,7 @@ #include "ten.h" #include "privateTen.h" -#define PARM_NUM 6 +#define PARM_NUM 7 static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { Modified: teem/trunk/src/ten/sources.cmake =================================================================== --- teem/trunk/src/ten/sources.cmake 2009-10-22 19:43:13 UTC (rev 4309) +++ teem/trunk/src/ten/sources.cmake 2009-10-22 22:27:12 UTC (rev 4310) @@ -55,6 +55,7 @@ tendSatin.c tendShrink.c tendSim.c + tendMsim.c tendSlice.c tendSten.c tendTconv.c Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-10-22 19:43:13 UTC (rev 4309) +++ teem/trunk/src/ten/ten.h 2009-10-22 22:27:12 UTC (rev 4310) @@ -1515,14 +1515,17 @@ TEN_EXPORT int tenExperSpecFromKeyValueSet(tenExperSpec *espec, const Nrrd *ndwi); TEN_EXPORT tenExperSpec* tenExperSpecNix(tenExperSpec *espec); +TEN_EXPORT double tenExperSpecKnownB0Get(const tenExperSpec *espec, + const double *dwi); +TEN_EXPORT double tenExperSpecMaxBGet(const tenExperSpec *espec); TEN_EXPORT int tenDWMRIKeyValueFromExperSpecSet(Nrrd *ndwi, const tenExperSpec *espec); -TEN_EXPORT double tenExperSpecKnownB0Get(const tenExperSpec *espec, - const double *dwi); /* modelTen.c */ TEN_EXPORT int tenModelParse(const tenModel **model, int *plusB0, const char *_str); +TEN_EXPORT int tenModelFromAxisLearn(const tenModel **model, + const NrrdAxisInfo *axinfo); TEN_EXPORT int tenModelSimulate(Nrrd *ndwi, int typeOut, tenExperSpec *espec, const tenModel *model, @@ -1538,7 +1541,6 @@ const tenExperSpec *espec, const Nrrd *ndwi, int rician, double sigma, int knownB0); - /* have to keep in sync with modelUtil.c/tenModelParse() */ /* modelBall.c */ TEN_EXPORT const tenModel *const tenModelBall; @@ -1605,6 +1607,7 @@ F(epireg) \ F(bmat) \ F(estim) \ +F(msim) \ F(sim) \ F(make) \ F(avg) \ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-23 04:36:55
|
Revision: 4314 http://teem.svn.sourceforge.net/teem/?rev=4314&view=rev Author: kindlmann Date: 2009-10-23 04:36:46 +0000 (Fri, 23 Oct 2009) Log Message: ----------- mv modelTen.c tenModel.c Added Paths: ----------- teem/trunk/src/ten/tenModel.c Removed Paths: ------------- teem/trunk/src/ten/modelTen.c Deleted: teem/trunk/src/ten/modelTen.c =================================================================== --- teem/trunk/src/ten/modelTen.c 2009-10-23 04:36:21 UTC (rev 4313) +++ teem/trunk/src/ten/modelTen.c 2009-10-23 04:36:46 UTC (rev 4314) @@ -1,335 +0,0 @@ -/* - Teem: Tools to process and visualize scientific data and images - Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann - Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - (LGPL) as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - The terms of redistributing and/or modifying this software also - include exceptions to the LGPL that facilitate static linking. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this library; if not, write to Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "ten.h" -#include "privateTen.h" - -const char * -tenModelPrefixStr = "DWMRI_model"; - -static const tenModel * -str2model(const char *str) { - const tenModel *ret = NULL; - - if (!strcmp(str, TEN_MODEL_STR_BALL)) ret = tenModelBall; - if (!strcmp(str, TEN_MODEL_STR_1STICK)) ret = tenModel1Stick; - if (!strcmp(str, TEN_MODEL_STR_BALL1STICK)) ret = tenModelBall1Stick; - if (!strcmp(str, TEN_MODEL_STR_CYLINDER)) ret = tenModelCylinder; - if (!strcmp(str, TEN_MODEL_STR_TENSOR2)) ret = tenModelTensor2; - return ret; -} - -int -tenModelParse(const tenModel **model, int *plusB0, - int requirePrefix, const char *_str) { - static const char me[]="tenModelParse"; - char *str, *modstr, prefix[AIR_STRLEN_MED], *pre; - airArray *mop; - - if (!( model && plusB0 && _str)) { - biffAddf(TEN, "%s: got NULL pointer", me); - return 1; - } - str = airToLower(airStrdup(_str)); - if (!str) { - biffAddf(TEN, "%s: couldn't strdup", me); - return 1; - } - mop = airMopNew(); - airMopAdd(mop, str, airFree, airMopAlways); - sprintf(prefix, "%s:", tenModelPrefixStr); - pre = strstr(str, prefix); - if (pre) { - str += strlen(prefix); - } else { - if (requirePrefix) { - biffAddf(TEN, "%s: didn't see prefix \"%s\" in \"%s\"", me, - prefix, _str); - airMopError(mop); return 1; - } - } - - if ((modstr = strchr(str, '+'))) { - *modstr = '\0'; - ++modstr; - if (!strcmp(str, "b0")) { - *plusB0 = AIR_TRUE; - } else { - biffAddf(TEN, "%s: string (\"%s\") prior to \"+\" not \"b0\"", me, str); - airMopError(mop); - return 1; - } - } else { - *plusB0 = AIR_FALSE; - modstr = str; - } - if (!(*model = str2model(modstr))) { - biffAddf(TEN, "%s: didn't recognize \"%s\" as model", me, str); - airMopError(mop); - return 1; - } - airMopOkay(mop); - return 0; -} - -int -tenModelFromAxisLearn(const tenModel **modelP, - int *plusB0, - const NrrdAxisInfo *axinfo) { - static const char me[]="tenModelFromAxisLearn"; - - if (!(modelP && plusB0 && axinfo)) { - biffAddf(TEN, "%s: got NULL pointer", me); - return 1; - } - *plusB0 = AIR_FALSE; - /* first try to learn model from "kind" */ - if (nrrdKind3DSymMatrix == axinfo->kind - || nrrdKind3DMaskedSymMatrix == axinfo->kind) { - *modelP = tenModelTensor2; - } else if (airStrlen(axinfo->label)) { - /* try to parse from label */ - if (tenModelParse(modelP, plusB0, AIR_TRUE, axinfo->label)) { - biffAddf(TEN, "%s: couldn't parse label \"%s\"", me, axinfo->label); - *modelP = NULL; - return 1; - } - } else { - biffAddf(TEN, "%s: don't have kind or label info to learn model", me); - *modelP = NULL; - return 1; - } - - return 0; -} - -/* -** if nB0 is given, and if parm vector is short by one (seems to be -** missing B0), then use that instead. Otherwise parm vector has to -** be length that includes B0 -** -** basic and axis info is derived from _nparm -*/ -int -tenModelSimulate(Nrrd *ndwi, int typeOut, - tenExperSpec *espec, - const tenModel *model, - const Nrrd *_nB0, - const Nrrd *_nparm, - int keyValueSet) { - static const char me[]="tenModelSimulate"; - double *ddwi, *parm, (*ins)(void *v, size_t I, double d); - char *dwi; - size_t szOut[NRRD_DIM_MAX], II, numSamp; - const Nrrd *nB0, /* B0 as doubles */ - *ndparm, /* parm as doubles */ - *ndpparm, /* parm as doubles, padded */ - *nparm; /* final parm as doubles, padded, w/ correct B0 values */ - Nrrd *ntmp; /* non-const pointer for working */ - airArray *mop; - unsigned int gpsze, /* given parm size */ - ii; - int useB0, needPad, axmap[NRRD_DIM_MAX]; - - if (!(ndwi && espec && model /* _nB0 can be NULL */ && _nparm)) { - biffAddf(TEN, "%s: got NULL pointer", me); - return 1; - } - if (!espec->imgNum) { - biffAddf(TEN, "%s: given espec wants 0 images, unset?", me); - return 1; - } - - gpsze = _nparm->axis[0].size; - if (model->parmNum - 1 == gpsze) { - /* got one less than needed parm #, see if we got B0 */ - if (!_nB0) { - biffAddf(TEN, "%s: got %u parms, need %u (for %s), " - "but didn't get B0 vol", - me, gpsze, model->parmNum, model->name); - return 1; - } - useB0 = AIR_TRUE; - needPad = AIR_TRUE; - } else if (model->parmNum != gpsze) { - biffAddf(TEN, "%s: mismatch between getting %u parms, " - "needing %u (for %s)\n", - me, gpsze, model->parmNum, model->name); - return 1; - } else { - /* model->parmNum == gpsze */ - needPad = AIR_FALSE; - useB0 = !!_nB0; - } - - mop = airMopNew(); - /* get parms as doubles */ - if (nrrdTypeDouble == _nparm->type) { - ndparm = _nparm; - } else { - ntmp = nrrdNew(); - airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); - if (nrrdConvert(ntmp, _nparm, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: couldn't convert parm to %s", me, - airEnumStr(nrrdType, nrrdTypeDouble)); - airMopError(mop); return 1; - } - ndparm = ntmp; - } - /* get parms the right length */ - if (!needPad) { - ndpparm = ndparm; - } else { - ptrdiff_t min[NRRD_DIM_MAX], max[NRRD_DIM_MAX]; - unsigned int ax; - - ntmp = nrrdNew(); - airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); - for (ax=0; ax<ndparm->dim; ax++) { - min[ax] = (!ax ? -1 : 0); - max[ax] = ndparm->axis[ax].size-1; - } - if (nrrdPad_nva(ntmp, ndparm, min, max, nrrdBoundaryBleed, 0.0)) { - biffMovef(TEN, NRRD, "%s: couldn't pad", me); - airMopError(mop); return 1; - } - ndpparm = ntmp; - } - /* put in B0 values if needed */ - if (!useB0) { - nparm = ndpparm; - } else { - if (nrrdTypeDouble == _nB0->type) { - nB0 = _nB0; - } else { - ntmp = nrrdNew(); - airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); - if (nrrdConvert(ntmp, _nB0, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: couldn't convert B0 to %s", me, - airEnumStr(nrrdType, nrrdTypeDouble)); - airMopError(mop); return 1; - } - nB0 = ntmp; - } - /* HEY: this is mostly likely a waste of memory, - but its all complicated by const-correctness */ - ntmp = nrrdNew(); - airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); - if (nrrdSplice(ntmp, ndpparm, nB0, 0, 0)) { - biffMovef(TEN, NRRD, "%s: couldn't splice in B0", me); - airMopError(mop); return 1; - } - nparm = ntmp; - } - - /* allocate output (and set axmap) */ - for (ii=0; ii<nparm->dim; ii++) { - szOut[ii] = (!ii - ? espec->imgNum - : nparm->axis[ii].size); - axmap[ii] = (!ii - ? -1 - : AIR_CAST(int, ii)); - } - if (nrrdMaybeAlloc_nva(ndwi, typeOut, nparm->dim, szOut)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); - airMopError(mop); return 1; - } - if (!(ddwi = AIR_CAST(double *, calloc(espec->imgNum, sizeof(double))))) { - biffAddf(TEN, "%s: couldn't allocate dwi buffer", me); - airMopError(mop); return 1; - } - airMopAdd(mop, ddwi, airFree, airMopAlways); - numSamp = nrrdElementNumber(nparm)/nparm->axis[0].size; - - /* set output */ - ins = nrrdDInsert[typeOut]; - parm = AIR_CAST(double *, nparm->data); - dwi = AIR_CAST(char *, ndwi->data); - for (II=0; II<numSamp; II++) { - model->simulate(ddwi, parm, espec); - for (ii=0; ii<espec->imgNum; ii++) { - ins(dwi, ii, ddwi[ii]); - } - parm += model->parmNum; - dwi += espec->imgNum*nrrdTypeSize[typeOut]; - } - - if (keyValueSet) { - if (tenDWMRIKeyValueFromExperSpecSet(ndwi, espec)) { - biffAddf(TEN, "%s: trouble", me); - airMopError(mop); return 1; - } - } - - if (nrrdAxisInfoCopy(ndwi, _nparm, axmap, NRRD_AXIS_INFO_SIZE_BIT) - || nrrdBasicInfoCopy(ndwi, _nparm, - NRRD_BASIC_INFO_DATA_BIT - | NRRD_BASIC_INFO_TYPE_BIT - | NRRD_BASIC_INFO_BLOCKSIZE_BIT - | NRRD_BASIC_INFO_DIMENSION_BIT - | NRRD_BASIC_INFO_CONTENT_BIT - | NRRD_BASIC_INFO_COMMENTS_BIT - | (nrrdStateKeyValuePairsPropagate - ? 0 - : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { - biffMovef(TEN, NRRD, "%s: couldn't copy axis or basic info", me); - airMopError(mop); return 1; - } - - airMopOkay(mop); - return 0; -} - -int -tenModelSqeFit(Nrrd *nparm, Nrrd **nsqeP, - const tenModel *model, - const tenExperSpec *espec, const Nrrd *ndwi, - int knownB0) { - - AIR_UNUSED(nparm); - AIR_UNUSED(nsqeP); - AIR_UNUSED(model); - AIR_UNUSED(espec); - AIR_UNUSED(ndwi); - AIR_UNUSED(knownB0); - - return 0; -} - -int -tenModelNllFit(Nrrd *nparm, Nrrd **nnllP, - const tenModel *model, - const tenExperSpec *espec, const Nrrd *ndwi, - int rician, double sigma, int knownB0) { - - AIR_UNUSED(nparm); - AIR_UNUSED(nnllP); - AIR_UNUSED(model); - AIR_UNUSED(espec); - AIR_UNUSED(ndwi); - AIR_UNUSED(rician); - AIR_UNUSED(sigma); - AIR_UNUSED(knownB0); - - return 0; -} Copied: teem/trunk/src/ten/tenModel.c (from rev 4313, teem/trunk/src/ten/modelTen.c) =================================================================== --- teem/trunk/src/ten/tenModel.c (rev 0) +++ teem/trunk/src/ten/tenModel.c 2009-10-23 04:36:46 UTC (rev 4314) @@ -0,0 +1,335 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +const char * +tenModelPrefixStr = "DWMRI_model"; + +static const tenModel * +str2model(const char *str) { + const tenModel *ret = NULL; + + if (!strcmp(str, TEN_MODEL_STR_BALL)) ret = tenModelBall; + if (!strcmp(str, TEN_MODEL_STR_1STICK)) ret = tenModel1Stick; + if (!strcmp(str, TEN_MODEL_STR_BALL1STICK)) ret = tenModelBall1Stick; + if (!strcmp(str, TEN_MODEL_STR_CYLINDER)) ret = tenModelCylinder; + if (!strcmp(str, TEN_MODEL_STR_TENSOR2)) ret = tenModelTensor2; + return ret; +} + +int +tenModelParse(const tenModel **model, int *plusB0, + int requirePrefix, const char *_str) { + static const char me[]="tenModelParse"; + char *str, *modstr, prefix[AIR_STRLEN_MED], *pre; + airArray *mop; + + if (!( model && plusB0 && _str)) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + str = airToLower(airStrdup(_str)); + if (!str) { + biffAddf(TEN, "%s: couldn't strdup", me); + return 1; + } + mop = airMopNew(); + airMopAdd(mop, str, airFree, airMopAlways); + sprintf(prefix, "%s:", tenModelPrefixStr); + pre = strstr(str, prefix); + if (pre) { + str += strlen(prefix); + } else { + if (requirePrefix) { + biffAddf(TEN, "%s: didn't see prefix \"%s\" in \"%s\"", me, + prefix, _str); + airMopError(mop); return 1; + } + } + + if ((modstr = strchr(str, '+'))) { + *modstr = '\0'; + ++modstr; + if (!strcmp(str, "b0")) { + *plusB0 = AIR_TRUE; + } else { + biffAddf(TEN, "%s: string (\"%s\") prior to \"+\" not \"b0\"", me, str); + airMopError(mop); + return 1; + } + } else { + *plusB0 = AIR_FALSE; + modstr = str; + } + if (!(*model = str2model(modstr))) { + biffAddf(TEN, "%s: didn't recognize \"%s\" as model", me, str); + airMopError(mop); + return 1; + } + airMopOkay(mop); + return 0; +} + +int +tenModelFromAxisLearn(const tenModel **modelP, + int *plusB0, + const NrrdAxisInfo *axinfo) { + static const char me[]="tenModelFromAxisLearn"; + + if (!(modelP && plusB0 && axinfo)) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + *plusB0 = AIR_FALSE; + /* first try to learn model from "kind" */ + if (nrrdKind3DSymMatrix == axinfo->kind + || nrrdKind3DMaskedSymMatrix == axinfo->kind) { + *modelP = tenModelTensor2; + } else if (airStrlen(axinfo->label)) { + /* try to parse from label */ + if (tenModelParse(modelP, plusB0, AIR_TRUE, axinfo->label)) { + biffAddf(TEN, "%s: couldn't parse label \"%s\"", me, axinfo->label); + *modelP = NULL; + return 1; + } + } else { + biffAddf(TEN, "%s: don't have kind or label info to learn model", me); + *modelP = NULL; + return 1; + } + + return 0; +} + +/* +** if nB0 is given, and if parm vector is short by one (seems to be +** missing B0), then use that instead. Otherwise parm vector has to +** be length that includes B0 +** +** basic and axis info is derived from _nparm +*/ +int +tenModelSimulate(Nrrd *ndwi, int typeOut, + tenExperSpec *espec, + const tenModel *model, + const Nrrd *_nB0, + const Nrrd *_nparm, + int keyValueSet) { + static const char me[]="tenModelSimulate"; + double *ddwi, *parm, (*ins)(void *v, size_t I, double d); + char *dwi; + size_t szOut[NRRD_DIM_MAX], II, numSamp; + const Nrrd *nB0, /* B0 as doubles */ + *ndparm, /* parm as doubles */ + *ndpparm, /* parm as doubles, padded */ + *nparm; /* final parm as doubles, padded, w/ correct B0 values */ + Nrrd *ntmp; /* non-const pointer for working */ + airArray *mop; + unsigned int gpsze, /* given parm size */ + ii; + int useB0, needPad, axmap[NRRD_DIM_MAX]; + + if (!(ndwi && espec && model /* _nB0 can be NULL */ && _nparm)) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + if (!espec->imgNum) { + biffAddf(TEN, "%s: given espec wants 0 images, unset?", me); + return 1; + } + + gpsze = _nparm->axis[0].size; + if (model->parmNum - 1 == gpsze) { + /* got one less than needed parm #, see if we got B0 */ + if (!_nB0) { + biffAddf(TEN, "%s: got %u parms, need %u (for %s), " + "but didn't get B0 vol", + me, gpsze, model->parmNum, model->name); + return 1; + } + useB0 = AIR_TRUE; + needPad = AIR_TRUE; + } else if (model->parmNum != gpsze) { + biffAddf(TEN, "%s: mismatch between getting %u parms, " + "needing %u (for %s)\n", + me, gpsze, model->parmNum, model->name); + return 1; + } else { + /* model->parmNum == gpsze */ + needPad = AIR_FALSE; + useB0 = !!_nB0; + } + + mop = airMopNew(); + /* get parms as doubles */ + if (nrrdTypeDouble == _nparm->type) { + ndparm = _nparm; + } else { + ntmp = nrrdNew(); + airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); + if (nrrdConvert(ntmp, _nparm, nrrdTypeDouble)) { + biffMovef(TEN, NRRD, "%s: couldn't convert parm to %s", me, + airEnumStr(nrrdType, nrrdTypeDouble)); + airMopError(mop); return 1; + } + ndparm = ntmp; + } + /* get parms the right length */ + if (!needPad) { + ndpparm = ndparm; + } else { + ptrdiff_t min[NRRD_DIM_MAX], max[NRRD_DIM_MAX]; + unsigned int ax; + + ntmp = nrrdNew(); + airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); + for (ax=0; ax<ndparm->dim; ax++) { + min[ax] = (!ax ? -1 : 0); + max[ax] = ndparm->axis[ax].size-1; + } + if (nrrdPad_nva(ntmp, ndparm, min, max, nrrdBoundaryBleed, 0.0)) { + biffMovef(TEN, NRRD, "%s: couldn't pad", me); + airMopError(mop); return 1; + } + ndpparm = ntmp; + } + /* put in B0 values if needed */ + if (!useB0) { + nparm = ndpparm; + } else { + if (nrrdTypeDouble == _nB0->type) { + nB0 = _nB0; + } else { + ntmp = nrrdNew(); + airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); + if (nrrdConvert(ntmp, _nB0, nrrdTypeDouble)) { + biffMovef(TEN, NRRD, "%s: couldn't convert B0 to %s", me, + airEnumStr(nrrdType, nrrdTypeDouble)); + airMopError(mop); return 1; + } + nB0 = ntmp; + } + /* HEY: this is mostly likely a waste of memory, + but its all complicated by const-correctness */ + ntmp = nrrdNew(); + airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); + if (nrrdSplice(ntmp, ndpparm, nB0, 0, 0)) { + biffMovef(TEN, NRRD, "%s: couldn't splice in B0", me); + airMopError(mop); return 1; + } + nparm = ntmp; + } + + /* allocate output (and set axmap) */ + for (ii=0; ii<nparm->dim; ii++) { + szOut[ii] = (!ii + ? espec->imgNum + : nparm->axis[ii].size); + axmap[ii] = (!ii + ? -1 + : AIR_CAST(int, ii)); + } + if (nrrdMaybeAlloc_nva(ndwi, typeOut, nparm->dim, szOut)) { + biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + airMopError(mop); return 1; + } + if (!(ddwi = AIR_CAST(double *, calloc(espec->imgNum, sizeof(double))))) { + biffAddf(TEN, "%s: couldn't allocate dwi buffer", me); + airMopError(mop); return 1; + } + airMopAdd(mop, ddwi, airFree, airMopAlways); + numSamp = nrrdElementNumber(nparm)/nparm->axis[0].size; + + /* set output */ + ins = nrrdDInsert[typeOut]; + parm = AIR_CAST(double *, nparm->data); + dwi = AIR_CAST(char *, ndwi->data); + for (II=0; II<numSamp; II++) { + model->simulate(ddwi, parm, espec); + for (ii=0; ii<espec->imgNum; ii++) { + ins(dwi, ii, ddwi[ii]); + } + parm += model->parmNum; + dwi += espec->imgNum*nrrdTypeSize[typeOut]; + } + + if (keyValueSet) { + if (tenDWMRIKeyValueFromExperSpecSet(ndwi, espec)) { + biffAddf(TEN, "%s: trouble", me); + airMopError(mop); return 1; + } + } + + if (nrrdAxisInfoCopy(ndwi, _nparm, axmap, NRRD_AXIS_INFO_SIZE_BIT) + || nrrdBasicInfoCopy(ndwi, _nparm, + NRRD_BASIC_INFO_DATA_BIT + | NRRD_BASIC_INFO_TYPE_BIT + | NRRD_BASIC_INFO_BLOCKSIZE_BIT + | NRRD_BASIC_INFO_DIMENSION_BIT + | NRRD_BASIC_INFO_CONTENT_BIT + | NRRD_BASIC_INFO_COMMENTS_BIT + | (nrrdStateKeyValuePairsPropagate + ? 0 + : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { + biffMovef(TEN, NRRD, "%s: couldn't copy axis or basic info", me); + airMopError(mop); return 1; + } + + airMopOkay(mop); + return 0; +} + +int +tenModelSqeFit(Nrrd *nparm, Nrrd **nsqeP, + const tenModel *model, + const tenExperSpec *espec, const Nrrd *ndwi, + int knownB0) { + + AIR_UNUSED(nparm); + AIR_UNUSED(nsqeP); + AIR_UNUSED(model); + AIR_UNUSED(espec); + AIR_UNUSED(ndwi); + AIR_UNUSED(knownB0); + + return 0; +} + +int +tenModelNllFit(Nrrd *nparm, Nrrd **nnllP, + const tenModel *model, + const tenExperSpec *espec, const Nrrd *ndwi, + int rician, double sigma, int knownB0) { + + AIR_UNUSED(nparm); + AIR_UNUSED(nnllP); + AIR_UNUSED(model); + AIR_UNUSED(espec); + AIR_UNUSED(ndwi); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + AIR_UNUSED(knownB0); + + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-26 22:40:16
|
Revision: 4321 http://teem.svn.sourceforge.net/teem/?rev=4321&view=rev Author: kindlmann Date: 2009-10-26 22:40:09 +0000 (Mon, 26 Oct 2009) Log Message: ----------- under construction Modified Paths: -------------- teem/trunk/src/ten/GNUmakefile teem/trunk/src/ten/experSpec.c teem/trunk/src/ten/modelBall.c teem/trunk/src/ten/modelBall1Stick.c teem/trunk/src/ten/modelCylinder.c teem/trunk/src/ten/modelTensor2.c teem/trunk/src/ten/privateTen.h teem/trunk/src/ten/sources.cmake teem/trunk/src/ten/ten.h teem/trunk/src/ten/tenModel.c teem/trunk/src/ten/tendEstim.c Added Paths: ----------- teem/trunk/src/ten/model1Stick.c teem/trunk/src/ten/tendMfit.c Modified: teem/trunk/src/ten/GNUmakefile =================================================================== --- teem/trunk/src/ten/GNUmakefile 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/GNUmakefile 2009-10-26 22:40:09 UTC (rev 4321) @@ -51,14 +51,15 @@ $(L).OBJS = tensor.o chan.o aniso.o glyph.o enumsTen.o grads.o miscTen.o \ mod.o estimate.o tenGage.o tenDwiGage.o qseg.o path.o qglox.o \ fiberMethods.o fiber.o epireg.o defaultsTen.o bimod.o bvec.o \ - triple.o experSpec.o modelTen.o modelBall.o modelBall1Stick.o \ - modelCylinder.o modelTensor2.o \ + triple.o experSpec.o tenModel.o modelBall.o model1Stick.o \ + modelBall1Stick.o modelCylinder.o modelTensor2.o \ tendAbout.o \ tendFlotsam.o tendGrads.o tendAnplot.o tendAnvol.o tendEval.o \ tendEvec.o tendSten.o tendExpand.o tendEvq.o tendPoint.o \ tendTriple.o tendTconv.o tendAvg.o \ tendAnhist.o tendMake.o tendSatin.o tendShrink.o tendGlyph.o \ - tendFiber.o tendEpireg.o tendBmat.o tendEstim.o tendSim.o tendMsim.o \ + tendFiber.o tendEpireg.o tendBmat.o tendEstim.o tendSim.o \ + tendMsim.o tendMfit.o \ tendSlice.o tendEllipse.o tendEvecrgb.o tendNorm.o tendAnscale.o \ tendEvalpow.o tendEvalclamp.o tendEvaladd.o tendHelix.o tendBfit.o \ tendUnmf.o tendLog.o tendExp.o Modified: teem/trunk/src/ten/experSpec.c =================================================================== --- teem/trunk/src/ten/experSpec.c 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/experSpec.c 2009-10-26 22:40:09 UTC (rev 4321) @@ -137,11 +137,35 @@ int tenExperSpecFromKeyValueSet(tenExperSpec *espec, const Nrrd *ndwi) { static const char me[]="tenExperSpecFromKeyValueSet"; - unsigned int *skip, skipNum, ii, imgNum; + unsigned int *skip, skipNum, ii, imgNum, dwiax; Nrrd *ngrad, *nbmat; airArray *mop; double len, singleBval, *bval, *grad; + for (dwiax=0; dwiax<ndwi->dim; dwiax++) { + if (nrrdKindList == ndwi->axis[dwiax].kind + || nrrdKindVector == ndwi->axis[dwiax].kind) { + break; + } + } + if (0 != dwiax) { + biffAddf(TEN, "%s: need dwis (kind %s or %s) along axis 0, not %u", me, + airEnumStr(nrrdKind, nrrdKindList), + airEnumStr(nrrdKind, nrrdKindVector), dwiax); + return 1; + } + for (ii=dwiax+1; ii<ndwi->dim; ii++) { + if (nrrdKindList == ndwi->axis[ii].kind + || nrrdKindVector == ndwi->axis[ii].kind) { + break; + } + } + if (ii < ndwi->dim) { + biffAddf(TEN, "%s: saw on %u another %s or %s kind axis, after 0", me, + ii, airEnumStr(nrrdKind, nrrdKindList), + airEnumStr(nrrdKind, nrrdKindVector)); + return 1; + } if (tenDWMRIKeyValueParse(&ngrad, &nbmat, &singleBval, &skip, &skipNum, ndwi)) { biffAddf(TEN, "%s: trouble parsing DWI info from key/value pairs", me); Added: teem/trunk/src/ten/model1Stick.c =================================================================== --- teem/trunk/src/ten/model1Stick.c (rev 0) +++ teem/trunk/src/ten/model1Stick.c 2009-10-26 22:40:09 UTC (rev 4321) @@ -0,0 +1,158 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +#define PARM_NUM 5 +#define PARM_DESC \ + { \ + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ + {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ + {"x", -1.0, 1.0, AIR_TRUE, 0}, \ + {"y", -1.0, 1.0, AIR_TRUE, 1}, \ + {"z", -1.0, 1.0, AIR_TRUE, 2}, \ + } +static const tenModelParmDesc +const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; + +static void +simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { + unsigned int ii; + double b0, diff, vec[3]; + + b0 = parm[0]; + diff = parm[1]; + vec[0] = parm[2]; + vec[1] = parm[3]; + vec[2] = parm[4]; + for (ii=0; ii<espec->imgNum; ii++) { + double dot; + dot = ELL_3V_DOT(vec, espec->grad + 3*ii); + dwiSim[ii] = b0*exp(-espec->bval[ii]*diff*dot*dot); + } + return; +} + +static void +prand(double *parm, airRandMTState *rng) { + unsigned int ii; + + for (ii=0; ii<PARM_NUM; ii++) { + if (pdesc[ii].vec3) { + /* its unit vector */ + double xx, yy, zz, theta, rr; + + zz = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, -1.0, 1.0); + theta = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, 0.0, 2*AIR_PI); + rr = sqrt(1 - zz*zz); + xx = rr*cos(theta); + yy = rr*sin(theta); + parm[ii + 0] = xx; + parm[ii + 1] = yy; + parm[ii + 2] = zz; + /* bump ii by 2; next for loop will increment past */ + ii += 2; + } else { + parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, + pdesc[ii].min, pdesc[ii].max); + } + } + return; +} + +SQE; + +static void +sqeGrad(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas) { + + AIR_UNUSED(grad); + AIR_UNUSED(parm); + AIR_UNUSED(espec); + AIR_UNUSED(dwiBuff); + AIR_UNUSED(dwiMeas); + return; +} + +static int +sqeFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +NLL; + +static void +nllGrad(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma) { + + AIR_UNUSED(grad); + AIR_UNUSED(parm); + AIR_UNUSED(espec); + AIR_UNUSED(dwiBuff); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + return; +} + +static int +nllFit(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int rician, double sigma, int knownB0) { + unsigned int pp; + + AIR_UNUSED(espec); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + AIR_UNUSED(knownB0); + for (pp=0; pp<PARM_NUM; pp++) { + parm[pp] = parmInit[pp]; + } + return 0; +} + +tenModel +_tenModel1Stick = { + TEN_MODEL_STR_1STICK, + PARM_NUM, + PARM_DESC, + simulate, + prand, + sqe, sqeGrad, sqeFit, + nll, nllGrad, nllFit +}; +const tenModel *const tenModel1Stick = &_tenModel1Stick; Modified: teem/trunk/src/ten/modelBall.c =================================================================== --- teem/trunk/src/ten/modelBall.c 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/modelBall.c 2009-10-26 22:40:09 UTC (rev 4321) @@ -24,6 +24,13 @@ #include "privateTen.h" #define PARM_NUM 2 +#define PARM_DESC \ + { \ + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ + {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0} \ + } +static const tenModelParmDesc +const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { @@ -38,14 +45,29 @@ return; } -static double -sqe(double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas) { +static void +prand(double *parm, airRandMTState *rng) { - simulate(dwiBuff, parm, espec); - return _tenModel_sqe(dwiMeas, dwiBuff, espec); + parm[0] = AIR_AFFINE(0, airDrandMT_r(rng), 1, pdesc[0].min, pdesc[0].max); + parm[1] = AIR_AFFINE(0, airDrandMT_r(rng), 1, pdesc[1].min, pdesc[1].max); + return; } +SQE; + +static void +sqeGrad(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas) { + + AIR_UNUSED(grad); + AIR_UNUSED(parm); + AIR_UNUSED(espec); + AIR_UNUSED(dwiBuff); + AIR_UNUSED(dwiMeas); + return; +} + static int sqeFit(double *parm, const tenExperSpec *espec, const double *dwiMeas, const double *parmInit, @@ -61,13 +83,22 @@ return 0; } -static double -nll(double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - int rician, double sigma) { +NLL; - simulate(dwiBuff, parm, espec); - return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); +static void +nllGrad(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma) { + + AIR_UNUSED(grad); + AIR_UNUSED(parm); + AIR_UNUSED(espec); + AIR_UNUSED(dwiBuff); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + return; } static int @@ -89,16 +120,12 @@ tenModel _tenModelBall = { - "ball", + TEN_MODEL_STR_BALL, PARM_NUM, - { - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, - {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0} - }, + PARM_DESC, simulate, - sqe, - sqeFit, - nll, - nllFit + prand, + sqe, sqeGrad, sqeFit, + nll, nllGrad, nllFit }; const tenModel *const tenModelBall = &_tenModelBall; Modified: teem/trunk/src/ten/modelBall1Stick.c =================================================================== --- teem/trunk/src/ten/modelBall1Stick.c 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/modelBall1Stick.c 2009-10-26 22:40:09 UTC (rev 4321) @@ -24,6 +24,17 @@ #include "privateTen.h" #define PARM_NUM 6 +#define PARM_DESC \ + { \ + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ + {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ + {"fraction", 0.0, 1.0, AIR_FALSE, 0}, \ + {"x", -1.0, 1.0, AIR_TRUE, 0}, \ + {"y", -1.0, 1.0, AIR_TRUE, 1}, \ + {"z", -1.0, 1.0, AIR_TRUE, 2} \ + } +static const tenModelParmDesc +const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { @@ -46,14 +57,48 @@ return; } -static double -sqe(double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas) { +static void +prand(double *parm, airRandMTState *rng) { + unsigned int ii; - simulate(dwiBuff, parm, espec); - return _tenModel_sqe(dwiMeas, dwiBuff, espec); + for (ii=0; ii<PARM_NUM; ii++) { + if (pdesc[ii].vec3) { + /* its unit vector */ + double xx, yy, zz, theta, rr; + + zz = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, -1.0, 1.0); + theta = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, 0.0, 2*AIR_PI); + rr = sqrt(1 - zz*zz); + xx = rr*cos(theta); + yy = rr*sin(theta); + parm[ii + 0] = xx; + parm[ii + 1] = yy; + parm[ii + 2] = zz; + /* bump ii by 2, anticipating completion of this for-loop iter */ + ii += 2; + } else { + parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, + pdesc[ii].min, pdesc[ii].max); + } + } + return; } +SQE; + +static void +sqeGrad(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas) { + + AIR_UNUSED(grad); + AIR_UNUSED(parm); + AIR_UNUSED(espec); + AIR_UNUSED(dwiBuff); + AIR_UNUSED(dwiMeas); + return; +} + static int sqeFit(double *parm, const tenExperSpec *espec, const double *dwiMeas, const double *parmInit, @@ -69,13 +114,22 @@ return 0; } -static double -nll(double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - int rician, double sigma) { +NLL; - simulate(dwiBuff, parm, espec); - return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); +static void +nllGrad(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma) { + + AIR_UNUSED(grad); + AIR_UNUSED(parm); + AIR_UNUSED(espec); + AIR_UNUSED(dwiBuff); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + return; } static int @@ -97,20 +151,12 @@ tenModel _tenModelBall1Stick = { - "ball1stick", + TEN_MODEL_STR_BALL1STICK, PARM_NUM, - { - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, - {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - {"fraction", 0.0, 1.0, AIR_FALSE, 0}, - {"x", -1.0, 1.0, AIR_TRUE, 0}, - {"y", -1.0, 1.0, AIR_TRUE, 1}, - {"z", -1.0, 1.0, AIR_TRUE, 2}, - }, + PARM_DESC, simulate, - sqe, - sqeFit, - nll, - nllFit + prand, + sqe, sqeGrad, sqeFit, + nll, nllGrad, nllFit }; const tenModel *const tenModelBall1Stick = &_tenModelBall1Stick; Modified: teem/trunk/src/ten/modelCylinder.c =================================================================== --- teem/trunk/src/ten/modelCylinder.c 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/modelCylinder.c 2009-10-26 22:40:09 UTC (rev 4321) @@ -24,6 +24,17 @@ #include "privateTen.h" #define PARM_NUM 6 +#define PARM_DESC \ + { \ + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ + {"length", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ + {"radius", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ + {"x", -1.0, 1.0, AIR_TRUE, 0}, \ + {"y", -1.0, 1.0, AIR_TRUE, 1}, \ + {"z", -1.0, 1.0, AIR_TRUE, 2}, \ + } +static const tenModelParmDesc +const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { @@ -48,14 +59,48 @@ return; } -static double -sqe(double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas) { +static void +prand(double *parm, airRandMTState *rng) { + unsigned int ii; - simulate(dwiBuff, parm, espec); - return _tenModel_sqe(dwiMeas, dwiBuff, espec); + for (ii=0; ii<PARM_NUM; ii++) { + if (pdesc[ii].vec3) { + /* its unit vector */ + double xx, yy, zz, theta, rr; + + zz = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, -1.0, 1.0); + theta = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, 0.0, 2*AIR_PI); + rr = sqrt(1 - zz*zz); + xx = rr*cos(theta); + yy = rr*sin(theta); + parm[ii + 0] = xx; + parm[ii + 1] = yy; + parm[ii + 2] = zz; + /* bump ii by 2, anticipating completion of this for-loop iter */ + ii += 2; + } else { + parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, + pdesc[ii].min, pdesc[ii].max); + } + } + return; } +SQE; + +static void +sqeGrad(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas) { + + AIR_UNUSED(grad); + AIR_UNUSED(parm); + AIR_UNUSED(espec); + AIR_UNUSED(dwiBuff); + AIR_UNUSED(dwiMeas); + return; +} + static int sqeFit(double *parm, const tenExperSpec *espec, const double *dwiMeas, const double *parmInit, @@ -71,13 +116,22 @@ return 0; } -static double -nll(double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - int rician, double sigma) { +NLL; - simulate(dwiBuff, parm, espec); - return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); +static void +nllGrad(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma) { + + AIR_UNUSED(grad); + AIR_UNUSED(parm); + AIR_UNUSED(espec); + AIR_UNUSED(dwiBuff); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + return; } static int @@ -99,20 +153,12 @@ tenModel _tenModelCylinder = { - "cylinder", + TEN_MODEL_STR_CYLINDER, PARM_NUM, - { - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, - {"length", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - {"radius", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - {"x", -1.0, 1.0, AIR_TRUE, 0}, - {"y", -1.0, 1.0, AIR_TRUE, 1}, - {"z", -1.0, 1.0, AIR_TRUE, 2}, - }, + PARM_DESC, simulate, - sqe, - sqeFit, - nll, - nllFit + prand, + sqe, sqeGrad, sqeFit, + nll, nllGrad, nllFit }; const tenModel *const tenModelCylinder = &_tenModelCylinder; Modified: teem/trunk/src/ten/modelTensor2.c =================================================================== --- teem/trunk/src/ten/modelTensor2.c 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/modelTensor2.c 2009-10-26 22:40:09 UTC (rev 4321) @@ -24,6 +24,20 @@ #include "privateTen.h" #define PARM_NUM 7 +/* 1/sqrt(2) */ +#define OST 0.70710678118654752440 +#define PARM_DESC \ + { \ + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ + {"Dxx", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ + {"Dxy", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, \ + {"Dxz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, \ + {"Dyy", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ + {"Dyz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, \ + {"Dzz", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ + } +static const tenModelParmDesc +const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { @@ -47,38 +61,166 @@ return; } -static double -sqe(double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas) { +static void +prand(double *parm, airRandMTState *rng) { + unsigned int ii; - simulate(dwiBuff, parm, espec); - return _tenModel_sqe(dwiMeas, dwiBuff, espec); + for (ii=0; ii<PARM_NUM; ii++) { + if (pdesc[ii].vec3) { + /* its unit vector */ + double xx, yy, zz, theta, rr; + + zz = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, -1.0, 1.0); + theta = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, 0.0, 2*AIR_PI); + rr = sqrt(1 - zz*zz); + xx = rr*cos(theta); + yy = rr*sin(theta); + parm[ii + 0] = xx; + parm[ii + 1] = yy; + parm[ii + 2] = zz; + /* bump ii by 2, anticipating completion of this for-loop iter */ + ii += 2; + } else { + parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, + pdesc[ii].min, pdesc[ii].max); + } + } + return; } -static int -sqeFit(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int knownB0) { - unsigned int pp; +SQE; - AIR_UNUSED(espec); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(knownB0); - for (pp=0; pp<PARM_NUM; pp++) { - parm[pp] = parmInit[pp]; +static void +sqeGrad(double *grad, const double *parm0, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int knownB0) { + double parm1[PARM_NUM], sqe0, sqe1, dp; + unsigned int ii, i0; + + i0 = knownB0 ? 1 : 0; + for (ii=i0; ii<PARM_NUM; ii++) { + parm1[ii] = parm0[ii]; } - return 0; + sqe0 = sqe(parm0, espec, dwiBuff, dwiMeas); + for (ii=i0; ii<PARM_NUM; ii++) { + dp = (pdesc[ii].max - pdesc[ii].min)/3000; + parm1[ii] += dp; + sqe1 = sqe(parm1, espec, dwiBuff, dwiMeas); + grad[ii] = (sqe1 - sqe0)/dp; + parm1[ii] = parm0[ii]; + } + if (knownB0) { + grad[ii] = 0; + } + return; } +static void +parmAdd(double *parm1, const double scl, + const double *grad, const double *parm0) { + unsigned int ii; + + for (ii=0; ii<PARM_NUM; ii++) { + parm1[ii] = scl*grad[ii] + parm0[ii]; + parm1[ii] = AIR_CLAMP(pdesc[ii].min, parm1[ii], pdesc[ii].max); + } +} + static double -nll(double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - int rician, double sigma) { +parmDist(const double *parmA, const double *parmB) { + unsigned int ii; + double dist, dd; - simulate(dwiBuff, parm, espec); - return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); + dist = 0; + for (ii=0; ii<PARM_NUM; ii++) { + dd = (parmA[ii] - parmB[ii])/(pdesc[ii].max - pdesc[ii].min); + dist += dd*dd; + } + return sqrt(dist); } +static char * +parmSprint(char str[AIR_STRLEN_MED], double *parm) { + sprintf(str, "(%g) [%g %g %g; %g %g; %g]", parm[0], + parm[1], parm[2], parm[3], + parm[4], parm[5], + parm[6]); + return str; +} + +#define PARM_COPY(A, B) \ + { \ + unsigned int pidx; \ + for (pidx=0; pidx<PARM_NUM; pidx++) { \ + A[pidx] = B[pidx]; \ + } \ + } + +static double +sqeFit(double *parm, double *convFrac, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + const double *parmInit, int knownB0, + unsigned int maxIter, double convEps) { + static const char me[]= TEN_MODEL_STR_TENSOR2 ":sqeFit"; + unsigned int ii, i0, iter; + double step, bak, opp, val, tval, + dist, tparm[PARM_NUM], grad[PARM_NUM]; + char str[AIR_STRLEN_MED]; + + i0 = knownB0 ? 1 : 0; + PARM_COPY(parm, parmInit); + val = sqe(parm, espec, dwiBuff, dwiMeas); + sqeGrad(grad, parm, espec, dwiBuff, dwiMeas, knownB0); + step = 0; + for (ii=i0; ii<PARM_NUM; ii++) { + step += (pdesc[ii].max - pdesc[ii].min)/(10*grad[ii]); + } + step /= (PARM_NUM - i0); + fprintf(stderr, "!%s: at %s\n", me, parmSprint(str, parm)); + fprintf(stderr, "!%s: initial step = %g\n", me, step); + + opp = 1.5; + bak = 0.1; + iter = 0; + do { + do { + parmAdd(tparm, -step, grad, parm); + tval = sqe(tparm, espec, dwiBuff, dwiMeas); + if (tval > val) { + step *= bak; + } + } while (tval > val); + fprintf(stderr, "!%s: step %g got to tval %g at %s\n", me, + step, tval, parmSprint(str, tparm)); + dist = parmDist(tparm, parm); + val = tval; + PARM_COPY(parm, tparm); + step *= opp; + iter++; + } while ((iter < maxIter) && (dist > convEps)); + *convFrac = dist/convEps; + return val; +} + +NLL; + +static void +nllGrad(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma) { + + AIR_UNUSED(grad); + AIR_UNUSED(parm); + AIR_UNUSED(espec); + AIR_UNUSED(dwiBuff); + AIR_UNUSED(dwiMeas); + AIR_UNUSED(rician); + AIR_UNUSED(sigma); + return; +} + static int nllFit(double *parm, const tenExperSpec *espec, const double *dwiMeas, const double *parmInit, @@ -96,26 +238,14 @@ return 0; } -/* 1/sqrt(2) */ -#define OST 0.70710678118654752440 - tenModel _tenModelTensor2 = { - "tensor2", + TEN_MODEL_STR_TENSOR2, PARM_NUM, - { - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, - {"Dxx", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - {"Dxy", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, - {"Dxz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, - {"Dyy", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - {"Dyz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, - {"Dzz", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - }, + PARM_DESC, simulate, - sqe, - sqeFit, - nll, - nllFit + prand, + sqe, sqeGrad, sqeFit, + nll, nllGrad, nllFit }; const tenModel *const tenModelTensor2 = &_tenModelTensor2; Modified: teem/trunk/src/ten/privateTen.h =================================================================== --- teem/trunk/src/ten/privateTen.h 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/privateTen.h 2009-10-26 22:40:09 UTC (rev 4321) @@ -156,6 +156,35 @@ const tenExperSpec *espec, int rician, double sigma); +/* model*.c */ +/* +** NOTE: these functions rely on the "simulate" function defined +** per-model (which is why these functions can't all use the same +** underlying function definition, unless the simulate function +** was passed as a callback, which would incur some more function +** call overhead) +*/ +#define SQE \ +static double \ +sqe(const double *parm, const tenExperSpec *espec, \ + double *dwiBuff, const double *dwiMeas) { \ + \ + simulate(dwiBuff, parm, espec); \ + return _tenModel_sqe(dwiMeas, dwiBuff, espec); \ +} + +#define NLL \ +static double \ +nll(const double *parm, const tenExperSpec *espec, \ + double *dwiBuff, const double *dwiMeas, \ + int rician, double sigma) { \ + \ + simulate(dwiBuff, parm, espec); \ + return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); \ +} + + + #ifdef __cplusplus } #endif Modified: teem/trunk/src/ten/sources.cmake =================================================================== --- teem/trunk/src/ten/sources.cmake 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/sources.cmake 2009-10-26 22:40:09 UTC (rev 4321) @@ -56,6 +56,7 @@ tendShrink.c tendSim.c tendMsim.c + tendMfit.c tendSlice.c tendSten.c tendTconv.c @@ -64,8 +65,9 @@ tensor.c triple.c experSpec.c - modelTen.c + tenModel.c modelBall.c + model1Stick.c modelBall1Stick.c modelCylinder.c modelTensor2.c Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/ten.h 2009-10-26 22:40:09 UTC (rev 4321) @@ -1122,16 +1122,26 @@ /* noise free simulation */ void (*simulate)(double *dwiSim, const double *parm, const tenExperSpec *espec); + /* random parameter vector */ + void (*random)(double *parm, airRandMTState *rng); /* "sqe" == squared error in DWI values */ - double (*sqe)(double *parm, const tenExperSpec *espec, + double (*sqe)(const double *parm, const tenExperSpec *espec, double *dwiBuff, const double *dwiMeas); - int (*sqeFit)(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int knownB0); + void (*sqeGrad)(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas); + int (*sqeFit)(double *parm, double *convFrac, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + const double *parmInit, int knownB0, + unsigned int maxIter, double convEps); /* "nll" == negative log likelihood */ - double (*nll)(double *parm, const tenExperSpec *espec, + double (*nll)(const double *parm, const tenExperSpec *espec, double *dwiBuff, const double *dwiMeas, int rician, double sigma); + void (*nllGrad)(double *grad, const double *parm, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + int rician, double sigma); int (*nllFit)(double *parm, const tenExperSpec *espec, const double *dwiMeas, const double *parmInit, int rician, double sigma, int knownB0); @@ -1521,10 +1531,11 @@ TEN_EXPORT int tenDWMRIKeyValueFromExperSpecSet(Nrrd *ndwi, const tenExperSpec *espec); -/* modelTen.c */ +/* tenModel.c */ +TEN_EXPORT const char *tenModelPrefixStr; TEN_EXPORT int tenModelParse(const tenModel **model, int *plusB0, - const char *_str); -TEN_EXPORT int tenModelFromAxisLearn(const tenModel **model, + int requirePrefix, const char *_str); +TEN_EXPORT int tenModelFromAxisLearn(const tenModel **model, int *plusB0, const NrrdAxisInfo *axinfo); TEN_EXPORT int tenModelSimulate(Nrrd *ndwi, int typeOut, tenExperSpec *espec, @@ -1535,20 +1546,28 @@ TEN_EXPORT int tenModelSqeFit(Nrrd *nparm, Nrrd **nsqeP, const tenModel *model, const tenExperSpec *espec, const Nrrd *ndwi, - int knownB0); + int knownB0, int saveB0, int typeOut, + unsigned int maxIter, double convEps); TEN_EXPORT int tenModelNllFit(Nrrd *nparm, Nrrd **nnllP, const tenModel *model, const tenExperSpec *espec, const Nrrd *ndwi, int rician, double sigma, int knownB0); -/* have to keep in sync with modelUtil.c/tenModelParse() */ +/* have to keep in sync with modelTen.c/tenModelParse() */ /* modelBall.c */ +#define TEN_MODEL_STR_BALL "ball" TEN_EXPORT const tenModel *const tenModelBall; +/* model1Stick.c */ +#define TEN_MODEL_STR_1STICK "1stick" +TEN_EXPORT const tenModel *const tenModel1Stick; /* modelBall1Stick.c */ +#define TEN_MODEL_STR_BALL1STICK "ball1stick" TEN_EXPORT const tenModel *const tenModelBall1Stick; /* modelCylinder.c */ +#define TEN_MODEL_STR_CYLINDER "cylinder" TEN_EXPORT const tenModel *const tenModelCylinder; /* modelTensor2.c */ +#define TEN_MODEL_STR_TENSOR2 "tensor2" TEN_EXPORT const tenModel *const tenModelTensor2; /* mod.c */ @@ -1607,8 +1626,9 @@ F(epireg) \ F(bmat) \ F(estim) \ +F(sim) \ +F(mfit) \ F(msim) \ -F(sim) \ F(make) \ F(avg) \ F(helix) \ Modified: teem/trunk/src/ten/tenModel.c =================================================================== --- teem/trunk/src/ten/tenModel.c 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/tenModel.c 2009-10-26 22:40:09 UTC (rev 4321) @@ -75,8 +75,7 @@ *plusB0 = AIR_TRUE; } else { biffAddf(TEN, "%s: string (\"%s\") prior to \"+\" not \"b0\"", me, str); - airMopError(mop); - return 1; + airMopError(mop); return 1; } } else { *plusB0 = AIR_FALSE; @@ -84,8 +83,7 @@ } if (!(*model = str2model(modstr))) { biffAddf(TEN, "%s: didn't recognize \"%s\" as model", me, str); - airMopError(mop); - return 1; + airMopError(mop); return 1; } airMopOkay(mop); return 0; @@ -304,15 +302,94 @@ tenModelSqeFit(Nrrd *nparm, Nrrd **nsqeP, const tenModel *model, const tenExperSpec *espec, const Nrrd *ndwi, - int knownB0) { + int knownB0, int saveB0, int typeOut, + unsigned int maxIter, double convEps) { + static const char me[]="tenModelSqeFit"; + double *ddwi, *dwibuff, dparm[TEN_MODEL_PARM_MAXNUM], + (*ins)(void *v, size_t I, double d), + (*lup)(const void *v, size_t I); + airArray *mop; + unsigned int saveParmNum, dwiNum, ii; + size_t szOut[NRRD_DIM_MAX], II, numSamp; + int axmap[NRRD_DIM_MAX]; + const char *dwi; + char *parm; - AIR_UNUSED(nparm); - AIR_UNUSED(nsqeP); - AIR_UNUSED(model); - AIR_UNUSED(espec); - AIR_UNUSED(ndwi); - AIR_UNUSED(knownB0); + if (!( nparm && model && espec && ndwi )) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + if (!( nrrdTypeFloat == typeOut || nrrdTypeDouble == typeOut )) { + biffAddf(TEN, "%s: typeOut must be %s or %s, not %s", me, + airEnumStr(nrrdType, nrrdTypeFloat), + airEnumStr(nrrdType, nrrdTypeDouble), + airEnumStr(nrrdType, typeOut)); + return 1; + } + dwiNum = ndwi->axis[0].size; + if (!( espec->imgNum != dwiNum )) { + biffAddf(TEN, "%s: espec expects %u images but dwi has %u on axis 0", + me, espec->imgNum, AIR_CAST(unsigned int, dwiNum)); + return 1; + } + + /* allocate output (and set axmap) */ + saveParmNum = saveB0 ? model->parmNum : model->parmNum-1; + for (ii=0; ii<nparm->dim; ii++) { + szOut[ii] = (!ii + ? saveParmNum + : ndwi->axis[ii].size); + axmap[ii] = (!ii + ? -1 + : AIR_CAST(int, ii)); + } + if (nrrdMaybeAlloc_nva(nparm, typeOut, ndwi->dim, szOut)) { + biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + airMopError(mop); return 1; + } + ddwi = AIR_CAST(double *, calloc(espec->imgNum, sizeof(double))); + dwibuff = AIR_CAST(double *, calloc(espec->imgNum, sizeof(double))); + if (!(ddwi && dwibuff)) { + biffAddf(TEN, "%s: couldn't allocate dwi buffers", me); + airMopError(mop); return 1; + } + airMopAdd(mop, ddwi, airFree, airMopAlways); + airMopAdd(mop, dwibuff, airFree, airMopAlways); + /* set output */ + numSamp = nrrdElementNumber(ndwi)/ndwi->axis[0].size; + ins = nrrdDInsert[typeOut]; + lup = nrrdDLookup[ndwi->type]; + parm = AIR_CAST(char *, nparm->data); + dwi = AIR_CAST(char *, ndwi->data); + for (II=0; II<numSamp; II++) { + for (ii=0; ii<dwiNum; ii++) { + ddwi[ii] = lup(dwi, ii); + } + /* fit to dparm */ + for (ii=0; ii<saveParmNum; ii++) { + ins(parm, ii, dparm[ii]); + } + parm += saveParmNum*nrrdTypeSize[typeOut]; + dwi += espec->imgNum*nrrdTypeSize[ndwi->type]; + } + + if (nrrdAxisInfoCopy(nparm, ndwi, axmap, NRRD_AXIS_INFO_SIZE_BIT) + || nrrdBasicInfoCopy(nparm, ndwi, + NRRD_BASIC_INFO_DATA_BIT + | NRRD_BASIC_INFO_TYPE_BIT + | NRRD_BASIC_INFO_BLOCKSIZE_BIT + | NRRD_BASIC_INFO_DIMENSION_BIT + | NRRD_BASIC_INFO_CONTENT_BIT + | NRRD_BASIC_INFO_COMMENTS_BIT + | (nrrdStateKeyValuePairsPropagate + ? 0 + : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { + biffMovef(TEN, NRRD, "%s: couldn't copy axis or basic info", me); + airMopError(mop); return 1; + } + + airMopOkay(mop); return 0; } Modified: teem/trunk/src/ten/tendEstim.c =================================================================== --- teem/trunk/src/ten/tendEstim.c 2009-10-26 22:39:34 UTC (rev 4320) +++ teem/trunk/src/ten/tendEstim.c 2009-10-26 22:40:09 UTC (rev 4321) @@ -27,7 +27,7 @@ char *_tend_estimInfoL = (INFO ". The tensor coefficient weightings associated with " - "each of the DWIs, the B-matrix, is given either as a seperate array, " + "each of the DWIs, the B-matrix, is given either as a separate array, " "(see \"tend bmat\" usage info for details), or by the key-value pairs " "in the DWI nrrd header. A \"confidence\" value is computed with the " "tensor, based on a soft thresholding of the sum of all the DWIs, " @@ -193,7 +193,7 @@ hestOptAdd(&hopt, "b", "b", airTypeDouble, 1, 1, &bval, "nan", "\"b\" diffusion-weighting factor (units of sec/mm^2)"); hestOptAdd(&hopt, "knownB0", "bool", airTypeBool, 1, 1, &knownB0, NULL, - "Determines of the B=0 non-diffusion-weighted reference image " + "Indicates if the B=0 non-diffusion-weighted reference image " "is known, or if it has to be estimated along with the tensor " "elements.\n " "\b\bo if \"true\": in the given list of diffusion gradients or " @@ -203,7 +203,7 @@ "images among the input; the B=0 image value is going to be " "estimated along with the diffusion model"); hestOptAdd(&hopt, "i", "dwi0 dwi1", airTypeOther, 1, -1, &nin, "-", - "all the diffusion-weighted images (DWIs), as seperate 3D nrrds, " + "all the diffusion-weighted images (DWIs), as separate 3D nrrds, " "**OR**: One 4D nrrd of all DWIs stacked along axis 0", &ninLen, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", Added: teem/trunk/src/ten/tendMfit.c =================================================================== --- teem/trunk/src/ten/tendMfit.c (rev 0) +++ teem/trunk/src/ten/tendMfit.c 2009-10-26 22:40:09 UTC (rev 4321) @@ -0,0 +1,101 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +#define INFO "Estimate models from a set of DW images" +char *_tend_mfitInfoL = + (INFO + ". More docs here."); + +int +tend_mfitMain(int argc, char **argv, char *me, hestParm *hparm) { + int pret; + hestOpt *hopt = NULL; + char *perr, *err; + airArray *mop; + + Nrrd *nin, *nout; + char *outS; + int EE, knownB0, verbose, mlfit; + unsigned int maxIter; + double valueMin, thresh, sigma; + const tenModel *model; + + hestOptAdd(&hopt, "v", "verbose", airTypeInt, 1, 1, &verbose, "0", + "verbosity level"); + hestOptAdd(&hopt, "ml", NULL, airTypeInt, 0, 0, &mlfit, NULL, + "do ML fitting, rather than least-squares, which also " + "requires setting \"-sigma\""); + hestOptAdd(&hopt, "sigma", "sigma", airTypeDouble, 1, 1, &sigma, "nan", + "Rician noise parameter"); + hestOptAdd(&hopt, "maxi", "max iters", airTypeUInt, 1, 1, &maxIter, "10", + "maximum allowable iterations for fitting."); + hestOptAdd(&hopt, "knownB0", "bool", airTypeBool, 1, 1, &knownB0, NULL, + "Indicates if the B=0 non-diffusion-weighted reference image " + "is known (\"true\"), or if it has to be estimated along with " + "the other model parameters (\"false\")"); + hestOptAdd(&hopt, "i", "dwi", airTypeOther, 1, 1, &nin, "-", + "all the diffusion-weighted images in one 4D nrrd", + NULL, NULL, nrrdHestNrrd); + hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", + "output tensor volume"); + + mop = airMopNew(); + airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); + USAGE(_tend_mfitInfoL); + JUSTPARSE(); + airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); + + nout = nrrdNew(); + airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); + + /* + if (tenModelSqeFit(nout, NULL, + const tenModel *model, + const tenExperSpec *espec, const Nrrd *ndwi, + int knownB0, int saveB0, int typeOut, + unsigned int maxIter, double convEps); + + if (tenEstimate1TensorVolume4D(tec, nout, &nB0, + airStrlen(terrS) + ? &nterr + : NULL, + nin4d, nrrdTypeFloat)) { + airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); + fprintf(stderr, "%s: trouble doing estimation:\n%s\n", me, err); + airMopError(mop); return 1; + } + + */ + if (nrrdSave(outS, nout, NULL)) { + airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); + fprintf(stderr, "%s: trouble writing:\n%s\n", me, err); + airMopError(mop); return 1; + } + + airMopOkay(mop); + return 0; +} +/* TEND_CMD(mfit, INFO); */ +unrrduCmd tend_mfitCmd = { "mfit", INFO, tend_mfitMain }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-27 20:23:41
|
Revision: 4323 http://teem.svn.sourceforge.net/teem/?rev=4323&view=rev Author: kindlmann Date: 2009-10-27 20:23:29 +0000 (Tue, 27 Oct 2009) Log Message: ----------- tenModel stuff still under construction Modified Paths: -------------- teem/trunk/src/ten/experSpec.c teem/trunk/src/ten/model1Stick.c teem/trunk/src/ten/modelBall.c teem/trunk/src/ten/modelBall1Stick.c teem/trunk/src/ten/modelCylinder.c teem/trunk/src/ten/modelTensor2.c teem/trunk/src/ten/privateTen.h teem/trunk/src/ten/ten.h teem/trunk/src/ten/tenModel.c teem/trunk/src/ten/tendMfit.c Modified: teem/trunk/src/ten/experSpec.c =================================================================== --- teem/trunk/src/ten/experSpec.c 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/experSpec.c 2009-10-27 20:23:29 UTC (rev 4323) @@ -29,7 +29,7 @@ espec->bval = airFree(espec->bval); espec->grad = airFree(espec->grad); - espec->wght = airFree(espec->wght); + /* espec->wght = airFree(espec->wght); */ if (!num) { biffAddf(TEN, "%s: need a non-zero number of images", me); return 1; @@ -37,8 +37,8 @@ espec->imgNum = num; espec->bval = AIR_CAST(double *, calloc(num, sizeof(double))); espec->grad = AIR_CAST(double *, calloc(3*num, sizeof(double))); - espec->wght = AIR_CAST(double *, calloc(num, sizeof(double))); - if (!( espec->bval && espec->grad && espec->wght )) { + /* espec->wght = AIR_CAST(double *, calloc(num, sizeof(double))); */ + if (!( espec->bval && espec->grad /* && espec->wght */ )) { biffAddf(TEN, "%s: couldn't allocate for %u images", me, num); return 1; } @@ -54,7 +54,7 @@ espec->imgNum = 0; espec->bval = NULL; espec->grad = NULL; - espec->wght = NULL; + /* espec->wght = NULL; */ return espec; } @@ -77,7 +77,7 @@ for (ii=0; ii<imgNum; ii++) { espec->bval[ii] = bval; ELL_3V_COPY(espec->grad + 3*ii, grad + 3*ii); - espec->wght[ii] = 1.0; + /* espec->wght[ii] = 1.0; */ } return 0; @@ -102,12 +102,13 @@ for (ii=0; ii<imgNum; ii++) { espec->bval[ii] = bval[ii]; ELL_3V_COPY(espec->grad + 3*ii, grad + 3*ii); - espec->wght[ii] = 1.0; + /* espec->wght[ii] = 1.0; */ } return 0; } +/* int tenExperSpecGradBValWghtSet(tenExperSpec *espec, unsigned int imgNum, @@ -133,6 +134,7 @@ return 0; } +*/ int tenExperSpecFromKeyValueSet(tenExperSpec *espec, const Nrrd *ndwi) { @@ -219,37 +221,51 @@ if (espec) { espec->bval = airFree(espec->bval); espec->grad = airFree(espec->grad); - espec->wght = airFree(espec->wght); + /* espec->wght = airFree(espec->wght); */ airFree(espec); } return NULL; } double -_tenModel_sqe(const double *dwiMeas, const double *dwiSim, - const tenExperSpec *espec) { +_tenExperSpec_sqe(const double *dwiMeas, const double *dwiSim, + const tenExperSpec *espec, int knownB0) { unsigned int ii; double sqe; sqe = 0; - for (ii=0; ii<espec->imgNum; ii++) { - double dd; - dd = dwiMeas[ii] - dwiSim[ii]; - sqe += dd*dd; + if (knownB0) { + for (ii=0; ii<espec->imgNum; ii++) { + double dd; + if (!espec->bval[ii]) { + continue; + } + dd = dwiMeas[ii] - dwiSim[ii]; + sqe += dd*dd; + } + } else { + for (ii=0; ii<espec->imgNum; ii++) { + double dd; + dd = dwiMeas[ii] - dwiSim[ii]; + sqe += dd*dd; + } } return sqe; } double -_tenModel_nll(const double *dwiMeas, const double *dwiSim, - const tenExperSpec *espec, - int rician, double sigma) { +_tenExperSpec_nll(const double *dwiMeas, const double *dwiSim, + const tenExperSpec *espec, + int rician, double sigma, int knownB0) { double nll; unsigned int ii; nll = 0; if (rician) { for (ii=0; ii<espec->imgNum; ii++) { + if (knownB0 && !espec->bval[ii]) { + continue; + } nll += -airLogRician(dwiMeas[ii], dwiSim[ii], sigma); } } else { @@ -257,6 +273,9 @@ ladd = log(sigma*sqrt(2*AIR_PI)); denom = 1.0/(2*sigma*sigma); for (ii=0; ii<espec->imgNum; ii++) { + if (knownB0 && !espec->bval[ii]) { + continue; + } dd = dwiMeas[ii] - dwiSim[ii]; nll += dd*dd*denom + ladd; } Modified: teem/trunk/src/ten/model1Stick.c =================================================================== --- teem/trunk/src/ten/model1Stick.c 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/model1Stick.c 2009-10-27 20:23:29 UTC (rev 4323) @@ -53,106 +53,29 @@ return; } -static void -prand(double *parm, airRandMTState *rng) { - unsigned int ii; - - for (ii=0; ii<PARM_NUM; ii++) { - if (pdesc[ii].vec3) { - /* its unit vector */ - double xx, yy, zz, theta, rr; - - zz = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, -1.0, 1.0); - theta = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, 0.0, 2*AIR_PI); - rr = sqrt(1 - zz*zz); - xx = rr*cos(theta); - yy = rr*sin(theta); - parm[ii + 0] = xx; - parm[ii + 1] = yy; - parm[ii + 2] = zz; - /* bump ii by 2; next for loop will increment past */ - ii += 2; - } else { - parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, - pdesc[ii].min, pdesc[ii].max); - } - } - return; +static char * +parmSprint(char str[AIR_STRLEN_MED], const double *parm) { + sprintf(str, "(%g) %g (%g,%g,%g)", parm[0], parm[1], + parm[2], parm[3], parm[4]); + return str; } -SQE; +_TEN_PARM_RAND +_TEN_PARM_STEP +_TEN_PARM_DIST +_TEN_PARM_COPY -static void -sqeGrad(double *grad, const double *parm, - const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas) { - - AIR_UNUSED(grad); - AIR_UNUSED(parm); - AIR_UNUSED(espec); - AIR_UNUSED(dwiBuff); - AIR_UNUSED(dwiMeas); - return; -} +_TEN_SQE +_TEN_SQE_GRAD_STUB +_TEN_SQE_FIT_STUB -static int -sqeFit(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int knownB0) { - unsigned int pp; +_TEN_NLL +_TEN_NLL_GRAD_STUB +_TEN_NLL_FIT_STUB - AIR_UNUSED(espec); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(knownB0); - for (pp=0; pp<PARM_NUM; pp++) { - parm[pp] = parmInit[pp]; - } - return 0; -} - -NLL; - -static void -nllGrad(double *grad, const double *parm, - const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - int rician, double sigma) { - - AIR_UNUSED(grad); - AIR_UNUSED(parm); - AIR_UNUSED(espec); - AIR_UNUSED(dwiBuff); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(rician); - AIR_UNUSED(sigma); - return; -} - -static int -nllFit(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int rician, double sigma, int knownB0) { - unsigned int pp; - - AIR_UNUSED(espec); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(rician); - AIR_UNUSED(sigma); - AIR_UNUSED(knownB0); - for (pp=0; pp<PARM_NUM; pp++) { - parm[pp] = parmInit[pp]; - } - return 0; -} - tenModel _tenModel1Stick = { TEN_MODEL_STR_1STICK, - PARM_NUM, - PARM_DESC, - simulate, - prand, - sqe, sqeGrad, sqeFit, - nll, nllGrad, nllFit + _TEN_MODEL_FIELDS }; const tenModel *const tenModel1Stick = &_tenModel1Stick; Modified: teem/trunk/src/ten/modelBall.c =================================================================== --- teem/trunk/src/ten/modelBall.c 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/modelBall.c 2009-10-27 20:23:29 UTC (rev 4323) @@ -45,46 +45,23 @@ return; } -static void -prand(double *parm, airRandMTState *rng) { - - parm[0] = AIR_AFFINE(0, airDrandMT_r(rng), 1, pdesc[0].min, pdesc[0].max); - parm[1] = AIR_AFFINE(0, airDrandMT_r(rng), 1, pdesc[1].min, pdesc[1].max); - return; +static char * +parmSprint(char str[AIR_STRLEN_MED], const double *parm) { + sprintf(str, "(%g) %g", parm[0], parm[1]); + return str; } -SQE; +_TEN_PARM_RAND +_TEN_PARM_STEP +_TEN_PARM_DIST +_TEN_PARM_COPY -static void -sqeGrad(double *grad, const double *parm, - const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas) { - - AIR_UNUSED(grad); - AIR_UNUSED(parm); - AIR_UNUSED(espec); - AIR_UNUSED(dwiBuff); - AIR_UNUSED(dwiMeas); - return; -} +_TEN_SQE +_TEN_SQE_GRAD_STUB +_TEN_SQE_FIT_STUB -static int -sqeFit(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int knownB0) { - unsigned int pp; +_TEN_NLL - AIR_UNUSED(espec); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(knownB0); - for (pp=0; pp<PARM_NUM; pp++) { - parm[pp] = parmInit[pp]; - } - return 0; -} - -NLL; - static void nllGrad(double *grad, const double *parm, const tenExperSpec *espec, @@ -101,7 +78,7 @@ return; } -static int +static double nllFit(double *parm, const tenExperSpec *espec, const double *dwiMeas, const double *parmInit, int rician, double sigma, int knownB0) { @@ -121,11 +98,6 @@ tenModel _tenModelBall = { TEN_MODEL_STR_BALL, - PARM_NUM, - PARM_DESC, - simulate, - prand, - sqe, sqeGrad, sqeFit, - nll, nllGrad, nllFit + _TEN_MODEL_FIELDS }; const tenModel *const tenModelBall = &_tenModelBall; Modified: teem/trunk/src/ten/modelBall1Stick.c =================================================================== --- teem/trunk/src/ten/modelBall1Stick.c 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/modelBall1Stick.c 2009-10-27 20:23:29 UTC (rev 4323) @@ -57,106 +57,29 @@ return; } -static void -prand(double *parm, airRandMTState *rng) { - unsigned int ii; - - for (ii=0; ii<PARM_NUM; ii++) { - if (pdesc[ii].vec3) { - /* its unit vector */ - double xx, yy, zz, theta, rr; - - zz = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, -1.0, 1.0); - theta = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, 0.0, 2*AIR_PI); - rr = sqrt(1 - zz*zz); - xx = rr*cos(theta); - yy = rr*sin(theta); - parm[ii + 0] = xx; - parm[ii + 1] = yy; - parm[ii + 2] = zz; - /* bump ii by 2, anticipating completion of this for-loop iter */ - ii += 2; - } else { - parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, - pdesc[ii].min, pdesc[ii].max); - } - } - return; +static char * +parmSprint(char str[AIR_STRLEN_MED], const double *parm) { + sprintf(str, "(%g) %g * (%g + %g*(%g,%g,%g))", parm[0], + parm[1], 1-parm[2], parm[2], parm[3], parm[4], parm[5]); + return str; } -SQE; +_TEN_PARM_RAND +_TEN_PARM_STEP +_TEN_PARM_DIST +_TEN_PARM_COPY -static void -sqeGrad(double *grad, const double *parm, - const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas) { - - AIR_UNUSED(grad); - AIR_UNUSED(parm); - AIR_UNUSED(espec); - AIR_UNUSED(dwiBuff); - AIR_UNUSED(dwiMeas); - return; -} +_TEN_SQE +_TEN_SQE_GRAD_STUB +_TEN_SQE_FIT_STUB -static int -sqeFit(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int knownB0) { - unsigned int pp; +_TEN_NLL +_TEN_NLL_GRAD_STUB +_TEN_NLL_FIT_STUB - AIR_UNUSED(espec); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(knownB0); - for (pp=0; pp<PARM_NUM; pp++) { - parm[pp] = parmInit[pp]; - } - return 0; -} - -NLL; - -static void -nllGrad(double *grad, const double *parm, - const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - int rician, double sigma) { - - AIR_UNUSED(grad); - AIR_UNUSED(parm); - AIR_UNUSED(espec); - AIR_UNUSED(dwiBuff); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(rician); - AIR_UNUSED(sigma); - return; -} - -static int -nllFit(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int rician, double sigma, int knownB0) { - unsigned int pp; - - AIR_UNUSED(espec); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(rician); - AIR_UNUSED(sigma); - AIR_UNUSED(knownB0); - for (pp=0; pp<PARM_NUM; pp++) { - parm[pp] = parmInit[pp]; - } - return 0; -} - tenModel _tenModelBall1Stick = { TEN_MODEL_STR_BALL1STICK, - PARM_NUM, - PARM_DESC, - simulate, - prand, - sqe, sqeGrad, sqeFit, - nll, nllGrad, nllFit + _TEN_MODEL_FIELDS }; const tenModel *const tenModelBall1Stick = &_tenModelBall1Stick; Modified: teem/trunk/src/ten/modelCylinder.c =================================================================== --- teem/trunk/src/ten/modelCylinder.c 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/modelCylinder.c 2009-10-27 20:23:29 UTC (rev 4323) @@ -59,106 +59,29 @@ return; } -static void -prand(double *parm, airRandMTState *rng) { - unsigned int ii; +_TEN_PARM_RAND +_TEN_PARM_STEP +_TEN_PARM_DIST +_TEN_PARM_COPY - for (ii=0; ii<PARM_NUM; ii++) { - if (pdesc[ii].vec3) { - /* its unit vector */ - double xx, yy, zz, theta, rr; - - zz = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, -1.0, 1.0); - theta = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, 0.0, 2*AIR_PI); - rr = sqrt(1 - zz*zz); - xx = rr*cos(theta); - yy = rr*sin(theta); - parm[ii + 0] = xx; - parm[ii + 1] = yy; - parm[ii + 2] = zz; - /* bump ii by 2, anticipating completion of this for-loop iter */ - ii += 2; - } else { - parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, - pdesc[ii].min, pdesc[ii].max); - } - } - return; +static char * +parmSprint(char str[AIR_STRLEN_MED], const double *parm) { + sprintf(str, "(%g) %g x %g (%g,%g,%g)", parm[0], + parm[1], parm[2], parm[3], parm[4], parm[5]); + return str; } -SQE; +_TEN_SQE +_TEN_SQE_GRAD_STUB +_TEN_SQE_FIT_STUB -static void -sqeGrad(double *grad, const double *parm, - const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas) { - - AIR_UNUSED(grad); - AIR_UNUSED(parm); - AIR_UNUSED(espec); - AIR_UNUSED(dwiBuff); - AIR_UNUSED(dwiMeas); - return; -} +_TEN_NLL +_TEN_NLL_GRAD_STUB +_TEN_NLL_FIT_STUB -static int -sqeFit(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int knownB0) { - unsigned int pp; - - AIR_UNUSED(espec); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(knownB0); - for (pp=0; pp<PARM_NUM; pp++) { - parm[pp] = parmInit[pp]; - } - return 0; -} - -NLL; - -static void -nllGrad(double *grad, const double *parm, - const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - int rician, double sigma) { - - AIR_UNUSED(grad); - AIR_UNUSED(parm); - AIR_UNUSED(espec); - AIR_UNUSED(dwiBuff); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(rician); - AIR_UNUSED(sigma); - return; -} - -static int -nllFit(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int rician, double sigma, int knownB0) { - unsigned int pp; - - AIR_UNUSED(espec); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(rician); - AIR_UNUSED(sigma); - AIR_UNUSED(knownB0); - for (pp=0; pp<PARM_NUM; pp++) { - parm[pp] = parmInit[pp]; - } - return 0; -} - tenModel _tenModelCylinder = { TEN_MODEL_STR_CYLINDER, - PARM_NUM, - PARM_DESC, - simulate, - prand, - sqe, sqeGrad, sqeFit, - nll, nllGrad, nllFit + _TEN_MODEL_FIELDS }; const tenModel *const tenModelCylinder = &_tenModelCylinder; Modified: teem/trunk/src/ten/modelTensor2.c =================================================================== --- teem/trunk/src/ten/modelTensor2.c 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/modelTensor2.c 2009-10-27 20:23:29 UTC (rev 4323) @@ -61,35 +61,22 @@ return; } -static void -prand(double *parm, airRandMTState *rng) { - unsigned int ii; - - for (ii=0; ii<PARM_NUM; ii++) { - if (pdesc[ii].vec3) { - /* its unit vector */ - double xx, yy, zz, theta, rr; - - zz = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, -1.0, 1.0); - theta = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, 0.0, 2*AIR_PI); - rr = sqrt(1 - zz*zz); - xx = rr*cos(theta); - yy = rr*sin(theta); - parm[ii + 0] = xx; - parm[ii + 1] = yy; - parm[ii + 2] = zz; - /* bump ii by 2, anticipating completion of this for-loop iter */ - ii += 2; - } else { - parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, - pdesc[ii].min, pdesc[ii].max); - } - } - return; +static char * +parmSprint(char str[AIR_STRLEN_MED], const double *parm) { + sprintf(str, "(%g) [%g %g %g; %g %g; %g]", parm[0], + parm[1], parm[2], parm[3], + parm[4], parm[5], + parm[6]); + return str; } -SQE; +_TEN_PARM_RAND +_TEN_PARM_STEP +_TEN_PARM_DIST +_TEN_PARM_COPY +_TEN_SQE + static void sqeGrad(double *grad, const double *parm0, const tenExperSpec *espec, @@ -102,11 +89,11 @@ for (ii=i0; ii<PARM_NUM; ii++) { parm1[ii] = parm0[ii]; } - sqe0 = sqe(parm0, espec, dwiBuff, dwiMeas); + sqe0 = sqe(parm0, espec, dwiBuff, dwiMeas, knownB0); for (ii=i0; ii<PARM_NUM; ii++) { - dp = (pdesc[ii].max - pdesc[ii].min)/3000; + dp = (pdesc[ii].max - pdesc[ii].min)*_TEN_PARM_GRAD_EPS; parm1[ii] += dp; - sqe1 = sqe(parm1, espec, dwiBuff, dwiMeas); + sqe1 = sqe(parm1, espec, dwiBuff, dwiMeas, knownB0); grad[ii] = (sqe1 - sqe0)/dp; parm1[ii] = parm0[ii]; } @@ -116,136 +103,64 @@ return; } -static void -parmAdd(double *parm1, const double scl, - const double *grad, const double *parm0) { - unsigned int ii; - - for (ii=0; ii<PARM_NUM; ii++) { - parm1[ii] = scl*grad[ii] + parm0[ii]; - parm1[ii] = AIR_CLAMP(pdesc[ii].min, parm1[ii], pdesc[ii].max); - } -} - static double -parmDist(const double *parmA, const double *parmB) { - unsigned int ii; - double dist, dd; - - dist = 0; - for (ii=0; ii<PARM_NUM; ii++) { - dd = (parmA[ii] - parmB[ii])/(pdesc[ii].max - pdesc[ii].min); - dist += dd*dd; - } - return sqrt(dist); -} - -static char * -parmSprint(char str[AIR_STRLEN_MED], double *parm) { - sprintf(str, "(%g) [%g %g %g; %g %g; %g]", parm[0], - parm[1], parm[2], parm[3], - parm[4], parm[5], - parm[6]); - return str; -} - -#define PARM_COPY(A, B) \ - { \ - unsigned int pidx; \ - for (pidx=0; pidx<PARM_NUM; pidx++) { \ - A[pidx] = B[pidx]; \ - } \ - } - -static double sqeFit(double *parm, double *convFrac, const tenExperSpec *espec, double *dwiBuff, const double *dwiMeas, const double *parmInit, int knownB0, - unsigned int maxIter, double convEps) { + unsigned int minIter, unsigned int maxIter, double convEps) { static const char me[]= TEN_MODEL_STR_TENSOR2 ":sqeFit"; - unsigned int ii, i0, iter; + unsigned int i0, iter; double step, bak, opp, val, tval, dist, tparm[PARM_NUM], grad[PARM_NUM]; char str[AIR_STRLEN_MED]; + int done; i0 = knownB0 ? 1 : 0; - PARM_COPY(parm, parmInit); - val = sqe(parm, espec, dwiBuff, dwiMeas); + parmCopy(parm, parmInit); + val = sqe(parm, espec, dwiBuff, dwiMeas, knownB0); sqeGrad(grad, parm, espec, dwiBuff, dwiMeas, knownB0); - step = 0; - for (ii=i0; ii<PARM_NUM; ii++) { - step += (pdesc[ii].max - pdesc[ii].min)/(10*grad[ii]); - } - step /= (PARM_NUM - i0); - fprintf(stderr, "!%s: at %s\n", me, parmSprint(str, parm)); - fprintf(stderr, "!%s: initial step = %g\n", me, step); + step = 10; + fprintf(stderr, "!%s: -------- at %s\n", me, parmSprint(str, parm)); + fprintf(stderr, "!%s: initial step = %g, convEps = %g\n", + me, step, convEps); - opp = 1.5; + opp = 1.1; bak = 0.1; iter = 0; do { do { - parmAdd(tparm, -step, grad, parm); - tval = sqe(tparm, espec, dwiBuff, dwiMeas); + parmStep(tparm, -step, grad, parm); + tval = sqe(tparm, espec, dwiBuff, dwiMeas, knownB0); if (tval > val) { step *= bak; + fprintf(stderr, "!%s(%u): tval %g > val %g ==> step -> %g\n", + me, iter, tval, val, step); } } while (tval > val); - fprintf(stderr, "!%s: step %g got to tval %g at %s\n", me, - step, tval, parmSprint(str, tparm)); dist = parmDist(tparm, parm); + fprintf(stderr, "!%s(%u): step %g (dist %g) -> %g @ %s\n", me, iter, + step, dist, tval, parmSprint(str, tparm)); val = tval; - PARM_COPY(parm, tparm); + parmCopy(parm, tparm); + sqeGrad(grad, parm, espec, dwiBuff, dwiMeas, knownB0); step *= opp; iter++; - } while ((iter < maxIter) && (dist > convEps)); + done = (iter < minIter + ? AIR_FALSE + : (iter > maxIter) || dist < convEps); + } while (!done); *convFrac = dist/convEps; return val; } -NLL; +_TEN_NLL +_TEN_NLL_GRAD_STUB +_TEN_NLL_FIT_STUB -static void -nllGrad(double *grad, const double *parm, - const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - int rician, double sigma) { - AIR_UNUSED(grad); - AIR_UNUSED(parm); - AIR_UNUSED(espec); - AIR_UNUSED(dwiBuff); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(rician); - AIR_UNUSED(sigma); - return; -} - -static int -nllFit(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int rician, double sigma, int knownB0) { - unsigned int pp; - - AIR_UNUSED(espec); - AIR_UNUSED(dwiMeas); - AIR_UNUSED(rician); - AIR_UNUSED(sigma); - AIR_UNUSED(knownB0); - for (pp=0; pp<PARM_NUM; pp++) { - parm[pp] = parmInit[pp]; - } - return 0; -} - tenModel _tenModelTensor2 = { TEN_MODEL_STR_TENSOR2, - PARM_NUM, - PARM_DESC, - simulate, - prand, - sqe, sqeGrad, sqeFit, - nll, nllGrad, nllFit + _TEN_MODEL_FIELDS }; const tenModel *const tenModelTensor2 = &_tenModelTensor2; Modified: teem/trunk/src/ten/privateTen.h =================================================================== --- teem/trunk/src/ten/privateTen.h 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/privateTen.h 2009-10-27 20:23:29 UTC (rev 4323) @@ -147,44 +147,197 @@ const double *wght, unsigned int NN, int ptype, tenInterpParm *tip); -/* modelUtil.c */ -TEN_EXPORT double _tenModel_sqe(const double *dwiMeas, - const double *dwiSim, - const tenExperSpec *espec); -TEN_EXPORT double _tenModel_nll(const double *dwiMeas, - const double *dwiSim, - const tenExperSpec *espec, - int rician, double sigma); +/* experSpec.c */ +TEN_EXPORT double _tenExperSpec_sqe(const double *dwiMeas, + const double *dwiSim, + const tenExperSpec *espec, + int knownB0); +TEN_EXPORT double _tenExperSpec_nll(const double *dwiMeas, + const double *dwiSim, + const tenExperSpec *espec, + int rician, double sigma, + int knownB0); /* model*.c */ + +#define _TEN_PARM_GRAD_EPS 0.0001 + /* -** NOTE: these functions rely on the "simulate" function defined -** per-model (which is why these functions can't all use the same -** underlying function definition, unless the simulate function -** was passed as a callback, which would incur some more function -** call overhead) +** NOTE: these functions rely on per-model information (like PARM_NUM) +** or functions (like "simulate"), which is why these functions can't +** all use same common underlying function, since more information would +** have to be passed (annoying for rapid hacking), and the function +** call overhead might be doubled */ -#define SQE \ -static double \ -sqe(const double *parm, const tenExperSpec *espec, \ - double *dwiBuff, const double *dwiMeas) { \ - \ - simulate(dwiBuff, parm, espec); \ - return _tenModel_sqe(dwiMeas, dwiBuff, espec); \ +#define _TEN_PARM_RAND \ +static void \ +parmRand(double *parm, airRandMTState *rng, int knownB0) { \ + unsigned int ii; \ + \ + for (ii=knownB0 ? 1 : 0; ii<PARM_NUM; ii++) { \ + if (pdesc[ii].vec3) { \ + /* its unit vector */ \ + double xx, yy, zz, theta, rr; \ + \ + zz = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, -1.0, 1.0); \ + theta = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, 0.0, 2*AIR_PI); \ + rr = sqrt(1 - zz*zz); \ + xx = rr*cos(theta); \ + yy = rr*sin(theta); \ + parm[ii + 0] = xx; \ + parm[ii + 1] = yy; \ + parm[ii + 2] = zz; \ + /* bump ii by 2, anticipating end of this for-loop iteration */ \ + ii += 2; \ + } else { \ + parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, \ + pdesc[ii].min, pdesc[ii].max); \ + } \ + } \ + return; \ } -#define NLL \ +#define _TEN_PARM_STEP \ +static void \ +parmStep(double *parm1, const double scl, \ + const double *grad, const double *parm0) { \ + unsigned int ii; \ + \ + for (ii=0; ii<PARM_NUM; ii++) { \ + parm1[ii] = scl*grad[ii] + parm0[ii]; \ + parm1[ii] = AIR_CLAMP(pdesc[ii].min, parm1[ii], pdesc[ii].max); \ + if (pdesc[ii].vec3 && 2 == pdesc[ii].vecIdx) { \ + double len; \ + ELL_3V_NORM(parm1 + ii - 2, parm1 + ii - 2, len); \ + } \ + } \ +} + +#define _TEN_PARM_DIST \ +static double \ +parmDist(const double *parmA, const double *parmB) { \ + unsigned int ii; \ + double dist, dd; \ + \ + dist = 0; \ + for (ii=0; ii<PARM_NUM; ii++) { \ + dd = (parmA[ii] - parmB[ii])/(pdesc[ii].max - pdesc[ii].min); \ + dist += dd*dd; \ + } \ + return sqrt(dist); \ +} + +#define _TEN_PARM_COPY \ +static void \ +parmCopy(double *parmA, const double *parmB) { \ + unsigned int ii; \ + \ + for (ii=0; ii<PARM_NUM; ii++) { \ + parmA[ii] = parmB[ii]; \ + } \ + return; \ +} + +#define _TEN_SQE \ static double \ -nll(const double *parm, const tenExperSpec *espec, \ - double *dwiBuff, const double *dwiMeas, \ - int rician, double sigma) { \ +sqe(const double *parm, const tenExperSpec *espec, \ + double *dwiBuff, const double *dwiMeas, int knownB0) { \ \ simulate(dwiBuff, parm, espec); \ - return _tenModel_nll(dwiMeas, dwiBuff, espec, rician, sigma); \ + return _tenExperSpec_sqe(dwiMeas, dwiBuff, espec, knownB0); \ } +#define _TEN_SQE_GRAD_STUB \ +static void \ +sqeGrad(double *grad, const double *parm, \ + const tenExperSpec *espec, \ + double *dwiBuff, const double *dwiMeas, \ + int knownB0) { \ + \ + AIR_UNUSED(grad); \ + AIR_UNUSED(parm); \ + AIR_UNUSED(espec); \ + AIR_UNUSED(dwiBuff); \ + AIR_UNUSED(dwiMeas); \ + AIR_UNUSED(knownB0); \ + return; \ +} +#define _TEN_SQE_FIT_STUB \ +static double \ +sqeFit(double *parm, double *convFrac, const tenExperSpec *espec, \ + double *dwiBuff, const double *dwiMeas, \ + const double *parmInit, int knownB0, \ + unsigned int minIter, unsigned int maxIter, double convEps) { \ + unsigned int pp; \ + \ + AIR_UNUSED(convFrac); \ + AIR_UNUSED(espec); \ + AIR_UNUSED(dwiBuff); \ + AIR_UNUSED(dwiMeas); \ + AIR_UNUSED(knownB0); \ + AIR_UNUSED(minIter); \ + AIR_UNUSED(maxIter); \ + AIR_UNUSED(convEps); \ + for (pp=0; pp<PARM_NUM; pp++) { \ + parm[pp] = parmInit[pp]; \ + } \ + return 0; \ +} +#define _TEN_NLL \ + static double \ +nll(const double *parm, const tenExperSpec *espec, \ + double *dwiBuff, const double *dwiMeas, \ + int rician, double sigma, int knownB0) { \ + \ + simulate(dwiBuff, parm, espec); \ + return _tenExperSpec_nll(dwiMeas, dwiBuff, espec, \ + rician, sigma, knownB0); \ +} + +#define _TEN_NLL_GRAD_STUB \ +static void \ +nllGrad(double *grad, const double *parm, \ + const tenExperSpec *espec, \ + double *dwiBuff, const double *dwiMeas, \ + int rician, double sigma) { \ + \ + AIR_UNUSED(grad); \ + AIR_UNUSED(parm); \ + AIR_UNUSED(espec); \ + AIR_UNUSED(dwiBuff); \ + AIR_UNUSED(dwiMeas); \ + AIR_UNUSED(rician); \ + AIR_UNUSED(sigma); \ + return; \ +} + +#define _TEN_NLL_FIT_STUB \ +static double \ +nllFit(double *parm, const tenExperSpec *espec, \ + const double *dwiMeas, const double *parmInit, \ + int rician, double sigma, int knownB0) { \ + unsigned int pp; \ + \ + AIR_UNUSED(espec); \ + AIR_UNUSED(dwiMeas); \ + AIR_UNUSED(rician); \ + AIR_UNUSED(sigma); \ + AIR_UNUSED(knownB0); \ + for (pp=0; pp<PARM_NUM; pp++) { \ + parm[pp] = parmInit[pp]; \ + } \ + return 0; \ +} + +#define _TEN_MODEL_FIELDS \ + PARM_NUM, PARM_DESC, \ + simulate, \ + parmSprint, parmRand, parmStep, parmDist, parmCopy, \ + sqe, sqeGrad, sqeFit, \ + nll, nllGrad, nllFit + #ifdef __cplusplus } #endif Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/ten.h 2009-10-27 20:23:29 UTC (rev 4323) @@ -1083,7 +1083,7 @@ int set; /* has been set */ unsigned imgNum; /* total number of images, dwi or not */ double *bval, /* all b values: imgNum doubles */ - *wght, /* all weights: imgNum doubles */ + /* *wght, all weights, but not yet used */ *grad; /* all gradients: 3 x imgNum doubles */ } tenExperSpec; @@ -1091,11 +1091,11 @@ char name[AIR_STRLEN_SMALL]; /* name */ double min, max; /* bounds */ int vec3; /* non-zero if this is one coeff of 3-vector */ - unsigned int idx; /* if 3-vector, index into it */ + unsigned int vecIdx; /* if 3-vector, index into it */ } tenModelParmDesc; #define TEN_MODEL_PARM_MAXNUM 15 /* adjust as needed */ -#define TEN_MODEL_B0_MAX 65536 /* pretty arbitrary */ +#define TEN_MODEL_B0_MAX 10000 /* HEY: completely arbitrary! */ #define TEN_MODEL_DIFF_MAX 0.004 /* in units of mm^2/sec */ /* @@ -1122,29 +1122,37 @@ /* noise free simulation */ void (*simulate)(double *dwiSim, const double *parm, const tenExperSpec *espec); - /* random parameter vector */ - void (*random)(double *parm, airRandMTState *rng); + /* parameter vector operations */ + char *(*sprint)(char str[AIR_STRLEN_MED], const double *parm); + void (*rand)(double *parm, airRandMTState *rng, int knownB0); + void (*step)(double *parm1, const double scl, + const double *grad, const double *parm0); + double (*dist)(const double *parmA, const double *parmB); + void (*copy)(double *parmA, const double *parmB); + /* "sqe" == squared error in DWI values */ double (*sqe)(const double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas); + double *dwiBuff, const double *dwiMeas, int knownB0); void (*sqeGrad)(double *grad, const double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas); - int (*sqeFit)(double *parm, double *convFrac, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - const double *parmInit, int knownB0, - unsigned int maxIter, double convEps); + double *dwiBuff, const double *dwiMeas, + int knownB0); + double (*sqeFit)(double *parm, double *convFrac, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + const double *parmInit, int knownB0, + unsigned int minIter, unsigned int maxIter, + double convEps); /* "nll" == negative log likelihood */ double (*nll)(const double *parm, const tenExperSpec *espec, double *dwiBuff, const double *dwiMeas, - int rician, double sigma); + int rician, double sigma, int knownB0); void (*nllGrad)(double *grad, const double *parm, const tenExperSpec *espec, double *dwiBuff, const double *dwiMeas, int rician, double sigma); - int (*nllFit)(double *parm, const tenExperSpec *espec, - const double *dwiMeas, const double *parmInit, - int rician, double sigma, int knownB0); + double (*nllFit)(double *parm, const tenExperSpec *espec, + const double *dwiMeas, const double *parmInit, + int rician, double sigma, int knownB0); } tenModel; /* defaultsTen.c */ @@ -1517,11 +1525,13 @@ unsigned int imgNum, const double *bval, const double *grad); +/* TEN_EXPORT int tenExperSpecGradBValWghtSet(tenExperSpec *espec, unsigned int imgNum, const double *bval, const double *grad, const double *wght); +*/ TEN_EXPORT int tenExperSpecFromKeyValueSet(tenExperSpec *espec, const Nrrd *ndwi); TEN_EXPORT tenExperSpec* tenExperSpecNix(tenExperSpec *espec); @@ -1547,7 +1557,9 @@ const tenModel *model, const tenExperSpec *espec, const Nrrd *ndwi, int knownB0, int saveB0, int typeOut, - unsigned int maxIter, double convEps); + unsigned int minIter, unsigned int maxIter, + unsigned int starts, double convEps, + airRandMTState *rng); TEN_EXPORT int tenModelNllFit(Nrrd *nparm, Nrrd **nnllP, const tenModel *model, const tenExperSpec *espec, const Nrrd *ndwi, Modified: teem/trunk/src/ten/tenModel.c =================================================================== --- teem/trunk/src/ten/tenModel.c 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/tenModel.c 2009-10-27 20:23:29 UTC (rev 4323) @@ -303,22 +303,30 @@ const tenModel *model, const tenExperSpec *espec, const Nrrd *ndwi, int knownB0, int saveB0, int typeOut, - unsigned int maxIter, double convEps) { + unsigned int minIter, unsigned int maxIter, + unsigned int starts, double convEps, airRandMTState *_rng) { static const char me[]="tenModelSqeFit"; - double *ddwi, *dwibuff, dparm[TEN_MODEL_PARM_MAXNUM], + double *ddwi, *dwibuff, sqe, sqeBest, convFrac, + dparm[TEN_MODEL_PARM_MAXNUM], + dparmBest[TEN_MODEL_PARM_MAXNUM], (*ins)(void *v, size_t I, double d), (*lup)(const void *v, size_t I); airArray *mop; - unsigned int saveParmNum, dwiNum, ii; + unsigned int saveParmNum, dwiNum, ii, lablen; size_t szOut[NRRD_DIM_MAX], II, numSamp; int axmap[NRRD_DIM_MAX]; const char *dwi; char *parm; + airRandMTState *rng; if (!( nparm && model && espec && ndwi )) { biffAddf(TEN, "%s: got NULL pointer", me); return 1; } + if (!( starts > 0 )) { + biffAddf(TEN, "%s: need non-zero starts", me); + return 1; + } if (!( nrrdTypeFloat == typeOut || nrrdTypeDouble == typeOut )) { biffAddf(TEN, "%s: typeOut must be %s or %s, not %s", me, airEnumStr(nrrdType, nrrdTypeFloat), @@ -327,15 +335,16 @@ return 1; } dwiNum = ndwi->axis[0].size; - if (!( espec->imgNum != dwiNum )) { + if (espec->imgNum != dwiNum) { biffAddf(TEN, "%s: espec expects %u images but dwi has %u on axis 0", me, espec->imgNum, AIR_CAST(unsigned int, dwiNum)); return 1; } /* allocate output (and set axmap) */ + mop = airMopNew(); saveParmNum = saveB0 ? model->parmNum : model->parmNum-1; - for (ii=0; ii<nparm->dim; ii++) { + for (ii=0; ii<ndwi->dim; ii++) { szOut[ii] = (!ii ? saveParmNum : ndwi->axis[ii].size); @@ -357,19 +366,46 @@ airMopAdd(mop, dwibuff, airFree, airMopAlways); /* set output */ + airRandMTStateGlobalInit(); + rng = _rng ? _rng : airRandMTStateGlobal; numSamp = nrrdElementNumber(ndwi)/ndwi->axis[0].size; + lup = nrrdDLookup[ndwi->type]; ins = nrrdDInsert[typeOut]; - lup = nrrdDLookup[ndwi->type]; parm = AIR_CAST(char *, nparm->data); dwi = AIR_CAST(char *, ndwi->data); for (II=0; II<numSamp; II++) { + char pstr[AIR_STRLEN_MED]; + unsigned int ss; for (ii=0; ii<dwiNum; ii++) { ddwi[ii] = lup(dwi, ii); } - /* fit to dparm */ + sqeBest = DBL_MAX; + for (ss=0; ss<starts; ss++) { + fprintf(stderr, "!%s: II %u ss %u -------\n", + me, AIR_CAST(unsigned int, II), ss); + if (knownB0) { + dparm[0] = tenExperSpecKnownB0Get(espec, ddwi); + fprintf(stderr, "!%s: b0 = %g\n", me, dparm[0]); + } + model->rand(dparm, rng, knownB0); + fprintf(stderr, "!%s: rand -> %s\n", me, + model->sprint(pstr, dparm)); + sqe = model->sqeFit(dparm, &convFrac, espec, dwibuff, ddwi, + dparm, knownB0, minIter, maxIter, convEps); + if (sqe < sqeBest) { + fprintf(stderr, "!%s: %g < %g --> %s\n", me, + sqe, sqeBest, model->sprint(pstr, dparm)); + sqeBest = sqe; + model->copy(dparmBest, dparm); + } + } for (ii=0; ii<saveParmNum; ii++) { - ins(parm, ii, dparm[ii]); + ins(parm, ii, saveB0 ? dparmBest[ii] : dparmBest[ii+1]); + fprintf(stderr, "!%s: saving parm[%u] = %g\n", me, + saveB0 ? ii : ii+1, + saveB0 ? dparmBest[ii] : dparmBest[ii+1]); } + /* possibly save sqeBest */ parm += saveParmNum*nrrdTypeSize[typeOut]; dwi += espec->imgNum*nrrdTypeSize[ndwi->type]; } @@ -388,6 +424,16 @@ biffMovef(TEN, NRRD, "%s: couldn't copy axis or basic info", me); airMopError(mop); return 1; } + lablen = (strlen(tenModelPrefixStr) + + strlen(":") + + (saveB0 ? strlen("B0+") : 0) + + strlen(model->name) + + 1); + nparm->axis[0].label = AIR_CAST(char *, calloc(lablen, sizeof(char))); + sprintf(nparm->axis[0].label, "%s:%s%s", + tenModelPrefixStr, + saveB0 ? "B0+" : "", + model->name); airMopOkay(mop); return 0; Modified: teem/trunk/src/ten/tendMfit.c =================================================================== --- teem/trunk/src/ten/tendMfit.c 2009-10-27 20:22:33 UTC (rev 4322) +++ teem/trunk/src/ten/tendMfit.c 2009-10-27 20:23:29 UTC (rev 4323) @@ -36,25 +36,39 @@ airArray *mop; Nrrd *nin, *nout; - char *outS; - int EE, knownB0, verbose, mlfit; - unsigned int maxIter; - double valueMin, thresh, sigma; + char *outS, *modS; + int knownB0, saveB0, verbose, mlfit, typeOut; + unsigned int maxIter, minIter, starts; + double sigma, eps; const tenModel *model; + tenExperSpec *espec; hestOptAdd(&hopt, "v", "verbose", airTypeInt, 1, 1, &verbose, "0", "verbosity level"); + hestOptAdd(&hopt, "m", "model", airTypeString, 1, 1, &modS, NULL, + "which model to fit. Use optional \"b0+\" prefix to " + "indicate that the B0 image should also be saved."); + hestOptAdd(&hopt, "ns", "# starts", airTypeUInt, 1, 1, &starts, "1", + "number of random starting points at which to initialize " + "fitting"); hestOptAdd(&hopt, "ml", NULL, airTypeInt, 0, 0, &mlfit, NULL, "do ML fitting, rather than least-squares, which also " "requires setting \"-sigma\""); hestOptAdd(&hopt, "sigma", "sigma", airTypeDouble, 1, 1, &sigma, "nan", "Rician noise parameter"); - hestOptAdd(&hopt, "maxi", "max iters", airTypeUInt, 1, 1, &maxIter, "10", - "maximum allowable iterations for fitting."); + hestOptAdd(&hopt, "eps", "eps", airTypeDouble, 1, 1, &eps, "0.01", + "convergence epsilon"); + hestOptAdd(&hopt, "mini", "min iters", airTypeUInt, 1, 1, &minIter, "3", + "minimum required # iterations for fitting."); + hestOptAdd(&hopt, "maxi", "max iters", airTypeUInt, 1, 1, &maxIter, "100", + "maximum allowable # iterations for fitting."); hestOptAdd(&hopt, "knownB0", "bool", airTypeBool, 1, 1, &knownB0, NULL, "Indicates if the B=0 non-diffusion-weighted reference image " "is known (\"true\"), or if it has to be estimated along with " "the other model parameters (\"false\")"); + hestOptAdd(&hopt, "t", "type", airTypeEnum, 1, 1, &typeOut, "float", + "output type of DWIs", + NULL, nrrdType); hestOptAdd(&hopt, "i", "dwi", airTypeOther, 1, 1, &nin, "-", "all the diffusion-weighted images in one 4D nrrd", NULL, NULL, nrrdHestNrrd); @@ -67,27 +81,28 @@ JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); + espec = tenExperSpecNew(); + airMopAdd(mop, espec, (airMopper)tenExperSpecNix, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); - - /* - if (tenModelSqeFit(nout, NULL, - const tenModel *model, - const tenExperSpec *espec, const Nrrd *ndwi, - int knownB0, int saveB0, int typeOut, - unsigned int maxIter, double convEps); - - if (tenEstimate1TensorVolume4D(tec, nout, &nB0, - airStrlen(terrS) - ? &nterr - : NULL, - nin4d, nrrdTypeFloat)) { + if (tenModelParse(&model, &saveB0, AIR_FALSE, modS)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); - fprintf(stderr, "%s: trouble doing estimation:\n%s\n", me, err); + fprintf(stderr, "%s: trouble parsing model \"%s\":\n%s\n", me, modS, err); airMopError(mop); return 1; } + if (tenExperSpecFromKeyValueSet(espec, nin)) { + airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); + fprintf(stderr, "%s: trouble getting exper from kvp:\n%s\n", me, err); + airMopError(mop); return 1; + } + if (tenModelSqeFit(nout, NULL, model, espec, nin, + knownB0, saveB0, typeOut, + minIter, maxIter, starts, eps, NULL)) { + airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); + fprintf(stderr, "%s: trouble fitting:\n%s\n", me, err); + airMopError(mop); return 1; + } - */ if (nrrdSave(outS, nout, NULL)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble writing:\n%s\n", me, err); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-28 02:41:11
|
Revision: 4327 http://teem.svn.sourceforge.net/teem/?rev=4327&view=rev Author: kindlmann Date: 2009-10-28 02:41:05 +0000 (Wed, 28 Oct 2009) Log Message: ----------- tenModel still under construction Modified Paths: -------------- teem/trunk/src/ten/experSpec.c teem/trunk/src/ten/model1Stick.c teem/trunk/src/ten/modelBall.c teem/trunk/src/ten/modelBall1Stick.c teem/trunk/src/ten/modelCylinder.c teem/trunk/src/ten/modelTensor2.c teem/trunk/src/ten/privateTen.h teem/trunk/src/ten/ten.h teem/trunk/src/ten/tenMacros.h teem/trunk/src/ten/tenModel.c Modified: teem/trunk/src/ten/experSpec.c =================================================================== --- teem/trunk/src/ten/experSpec.c 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/experSpec.c 2009-10-28 02:41:05 UTC (rev 4327) @@ -242,6 +242,10 @@ } dd = dwiMeas[ii] - dwiSim[ii]; sqe += dd*dd; + /* + fprintf(stderr, "!%s: dwi[%u]: %g - %g -> %g\n", "_tenExperSpec_sqe", + ii, dwiMeas[ii], dwiSim[ii], sqe); + */ } } else { for (ii=0; ii<espec->imgNum; ii++) { Modified: teem/trunk/src/ten/model1Stick.c =================================================================== --- teem/trunk/src/ten/model1Stick.c 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/model1Stick.c 2009-10-28 02:41:05 UTC (rev 4327) @@ -24,16 +24,14 @@ #include "privateTen.h" #define PARM_NUM 5 -#define PARM_DESC \ - { \ - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ - {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ - {"x", -1.0, 1.0, AIR_TRUE, 0}, \ - {"y", -1.0, 1.0, AIR_TRUE, 1}, \ - {"z", -1.0, 1.0, AIR_TRUE, 2}, \ - } static const tenModelParmDesc -const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; +const parmDesc[] = { + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"x", -1.0, 1.0, AIR_TRUE, 0}, + {"y", -1.0, 1.0, AIR_TRUE, 1}, + {"z", -1.0, 1.0, AIR_TRUE, 2} +}; static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { Modified: teem/trunk/src/ten/modelBall.c =================================================================== --- teem/trunk/src/ten/modelBall.c 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/modelBall.c 2009-10-28 02:41:05 UTC (rev 4327) @@ -24,13 +24,11 @@ #include "privateTen.h" #define PARM_NUM 2 -#define PARM_DESC \ - { \ - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ - {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0} \ - } static const tenModelParmDesc -const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; +const parmDesc[] = { + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0} +}; static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { Modified: teem/trunk/src/ten/modelBall1Stick.c =================================================================== --- teem/trunk/src/ten/modelBall1Stick.c 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/modelBall1Stick.c 2009-10-28 02:41:05 UTC (rev 4327) @@ -24,17 +24,15 @@ #include "privateTen.h" #define PARM_NUM 6 -#define PARM_DESC \ - { \ - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ - {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ - {"fraction", 0.0, 1.0, AIR_FALSE, 0}, \ - {"x", -1.0, 1.0, AIR_TRUE, 0}, \ - {"y", -1.0, 1.0, AIR_TRUE, 1}, \ - {"z", -1.0, 1.0, AIR_TRUE, 2} \ - } static const tenModelParmDesc -const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; +const parmDesc[] = { + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"fraction", 0.0, 1.0, AIR_FALSE, 0}, + {"x", -1.0, 1.0, AIR_TRUE, 0}, + {"y", -1.0, 1.0, AIR_TRUE, 1}, + {"z", -1.0, 1.0, AIR_TRUE, 2} +}; static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { Modified: teem/trunk/src/ten/modelCylinder.c =================================================================== --- teem/trunk/src/ten/modelCylinder.c 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/modelCylinder.c 2009-10-28 02:41:05 UTC (rev 4327) @@ -24,17 +24,15 @@ #include "privateTen.h" #define PARM_NUM 6 -#define PARM_DESC \ - { \ - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ - {"length", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ - {"radius", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ - {"x", -1.0, 1.0, AIR_TRUE, 0}, \ - {"y", -1.0, 1.0, AIR_TRUE, 1}, \ - {"z", -1.0, 1.0, AIR_TRUE, 2}, \ - } static const tenModelParmDesc -const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; +const parmDesc[] = { + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + {"length", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"radius", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"x", -1.0, 1.0, AIR_TRUE, 0}, + {"y", -1.0, 1.0, AIR_TRUE, 1}, + {"z", -1.0, 1.0, AIR_TRUE, 2} +}; static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { Modified: teem/trunk/src/ten/modelTensor2.c =================================================================== --- teem/trunk/src/ten/modelTensor2.c 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/modelTensor2.c 2009-10-28 02:41:05 UTC (rev 4327) @@ -26,36 +26,28 @@ #define PARM_NUM 7 /* 1/sqrt(2) */ #define OST 0.70710678118654752440 -#define PARM_DESC \ - { \ - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, \ - {"Dxx", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ - {"Dxy", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, \ - {"Dxz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, \ - {"Dyy", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ - {"Dyz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, \ - {"Dzz", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, \ - } static const tenModelParmDesc -const pdesc[TEN_MODEL_PARM_MAXNUM] = PARM_DESC; +const parmDesc[] = { + {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + {"Dxx", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"Dxy", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, + {"Dxz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, + {"Dyy", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + {"Dyz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, + {"Dzz", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0} +}; static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { unsigned int ii; - double b0, ten[7]; + double b0; b0 = parm[0]; - ten[0] = 1; - ten[1] = parm[1]; - ten[2] = parm[2]; - ten[3] = parm[3]; - ten[4] = parm[4]; - ten[5] = parm[5]; - ten[6] = parm[6]; for (ii=0; ii<espec->imgNum; ii++) { double adc, bb; bb = espec->bval[ii]; - adc = TEN_T3V_CONTR(ten, espec->grad + 3*ii); + /* safe because TEN_T3V_CONTR never looks at parm[0] */ + adc = TEN_T3V_CONTR(parm, espec->grad + 3*ii); dwiSim[ii] = b0*exp(-bb*adc); } return; @@ -75,30 +67,40 @@ _TEN_PARM_DIST _TEN_PARM_COPY -_TEN_SQE +static double +sqe(const double *parm, const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, int knownB0) { + simulate(dwiBuff, parm, espec); + return _tenExperSpec_sqe(dwiBuff, dwiMeas, espec, knownB0); +} + static void sqeGrad(double *grad, const double *parm0, const tenExperSpec *espec, double *dwiBuff, const double *dwiMeas, int knownB0) { - double parm1[PARM_NUM], sqe0, sqe1, dp; + double parm1[PARM_NUM], sqeForw, sqeBack, dp; unsigned int ii, i0; i0 = knownB0 ? 1 : 0; - for (ii=i0; ii<PARM_NUM; ii++) { + for (ii=0; ii<PARM_NUM; ii++) { + /* have to copy all parms, even B0 with knownB0, and even if we + aren't going to diddle these values, because the + simulation depends on knowing the values */ parm1[ii] = parm0[ii]; } - sqe0 = sqe(parm0, espec, dwiBuff, dwiMeas, knownB0); for (ii=i0; ii<PARM_NUM; ii++) { - dp = (pdesc[ii].max - pdesc[ii].min)*_TEN_PARM_GRAD_EPS; - parm1[ii] += dp; - sqe1 = sqe(parm1, espec, dwiBuff, dwiMeas, knownB0); - grad[ii] = (sqe1 - sqe0)/dp; + dp = (parmDesc[ii].max - parmDesc[ii].min)*TEN_MODEL_PARM_GRAD_EPS; + parm1[ii] = parm0[ii] + dp; + sqeForw = sqe(parm1, espec, dwiBuff, dwiMeas, knownB0); + parm1[ii] = parm0[ii] - dp; + sqeBack = sqe(parm1, espec, dwiBuff, dwiMeas, knownB0); + grad[ii] = (sqeForw - sqeBack)/(2*dp); parm1[ii] = parm0[ii]; } if (knownB0) { - grad[ii] = 0; + grad[0] = 0; } return; } @@ -108,40 +110,31 @@ double *dwiBuff, const double *dwiMeas, const double *parmInit, int knownB0, unsigned int minIter, unsigned int maxIter, double convEps) { - static const char me[]= TEN_MODEL_STR_TENSOR2 ":sqeFit"; - unsigned int i0, iter; - double step, bak, opp, val, tval, - dist, tparm[PARM_NUM], grad[PARM_NUM]; - char str[AIR_STRLEN_MED]; + /* static const char me[]= TEN_MODEL_STR_TENSOR2 ":sqeFit"; */ + unsigned int iter; + double step, bak, opp, val, testval, + dist, testparm[PARM_NUM], grad[PARM_NUM]; int done; - i0 = knownB0 ? 1 : 0; + step = 1; parmCopy(parm, parmInit); val = sqe(parm, espec, dwiBuff, dwiMeas, knownB0); sqeGrad(grad, parm, espec, dwiBuff, dwiMeas, knownB0); - step = 10; - fprintf(stderr, "!%s: -------- at %s\n", me, parmSprint(str, parm)); - fprintf(stderr, "!%s: initial step = %g, convEps = %g\n", - me, step, convEps); - opp = 1.1; + opp = 2; bak = 0.1; iter = 0; do { do { - parmStep(tparm, -step, grad, parm); - tval = sqe(tparm, espec, dwiBuff, dwiMeas, knownB0); - if (tval > val) { + parmStep(testparm, -step, grad, parm); + testval = sqe(testparm, espec, dwiBuff, dwiMeas, knownB0); + if (testval > val) { step *= bak; - fprintf(stderr, "!%s(%u): tval %g > val %g ==> step -> %g\n", - me, iter, tval, val, step); } - } while (tval > val); - dist = parmDist(tparm, parm); - fprintf(stderr, "!%s(%u): step %g (dist %g) -> %g @ %s\n", me, iter, - step, dist, tval, parmSprint(str, tparm)); - val = tval; - parmCopy(parm, tparm); + } while (testval > val); + dist = parmDist(testparm, parm); + val = testval; + parmCopy(parm, testparm); sqeGrad(grad, parm, espec, dwiBuff, dwiMeas, knownB0); step *= opp; iter++; Modified: teem/trunk/src/ten/privateTen.h =================================================================== --- teem/trunk/src/ten/privateTen.h 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/privateTen.h 2009-10-28 02:41:05 UTC (rev 4327) @@ -159,9 +159,6 @@ int knownB0); /* model*.c */ - -#define _TEN_PARM_GRAD_EPS 0.0001 - /* ** NOTE: these functions rely on per-model information (like PARM_NUM) ** or functions (like "simulate"), which is why these functions can't @@ -175,7 +172,7 @@ unsigned int ii; \ \ for (ii=knownB0 ? 1 : 0; ii<PARM_NUM; ii++) { \ - if (pdesc[ii].vec3) { \ + if (parmDesc[ii].vec3) { \ /* its unit vector */ \ double xx, yy, zz, theta, rr; \ \ @@ -191,7 +188,7 @@ ii += 2; \ } else { \ parm[ii] = AIR_AFFINE(0.0, airDrandMT_r(rng), 1.0, \ - pdesc[ii].min, pdesc[ii].max); \ + parmDesc[ii].min, parmDesc[ii].max); \ } \ } \ return; \ @@ -205,8 +202,8 @@ \ for (ii=0; ii<PARM_NUM; ii++) { \ parm1[ii] = scl*grad[ii] + parm0[ii]; \ - parm1[ii] = AIR_CLAMP(pdesc[ii].min, parm1[ii], pdesc[ii].max); \ - if (pdesc[ii].vec3 && 2 == pdesc[ii].vecIdx) { \ + parm1[ii] = AIR_CLAMP(parmDesc[ii].min, parm1[ii], parmDesc[ii].max); \ + if (parmDesc[ii].vec3 && 2 == parmDesc[ii].vecIdx) { \ double len; \ ELL_3V_NORM(parm1 + ii - 2, parm1 + ii - 2, len); \ } \ @@ -221,7 +218,7 @@ \ dist = 0; \ for (ii=0; ii<PARM_NUM; ii++) { \ - dd = (parmA[ii] - parmB[ii])/(pdesc[ii].max - pdesc[ii].min); \ + dd = (parmA[ii] - parmB[ii])/(parmDesc[ii].max - parmDesc[ii].min); \ dist += dd*dd; \ } \ return sqrt(dist); \ @@ -332,7 +329,7 @@ } #define _TEN_MODEL_FIELDS \ - PARM_NUM, PARM_DESC, \ + PARM_NUM, parmDesc, \ simulate, \ parmSprint, parmRand, parmStep, parmDist, parmCopy, \ sqe, sqeGrad, sqeFit, \ Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/ten.h 2009-10-28 02:41:05 UTC (rev 4327) @@ -1094,9 +1094,9 @@ unsigned int vecIdx; /* if 3-vector, index into it */ } tenModelParmDesc; -#define TEN_MODEL_PARM_MAXNUM 15 /* adjust as needed */ -#define TEN_MODEL_B0_MAX 10000 /* HEY: completely arbitrary! */ -#define TEN_MODEL_DIFF_MAX 0.004 /* in units of mm^2/sec */ +#define TEN_MODEL_B0_MAX 10000 /* HEY: completely arbitrary! */ +#define TEN_MODEL_DIFF_MAX 0.004 /* in units of mm^2/sec */ +#define TEN_MODEL_PARM_GRAD_EPS 0.00002 /* for gradient calculations */ /* ******** struct tenModel @@ -1118,7 +1118,7 @@ typedef struct { char name[AIR_STRLEN_SMALL]; unsigned int parmNum; - tenModelParmDesc parmDesc[TEN_MODEL_PARM_MAXNUM]; + const tenModelParmDesc *parmDesc; /* noise free simulation */ void (*simulate)(double *dwiSim, const double *parm, const tenExperSpec *espec); Modified: teem/trunk/src/ten/tenMacros.h =================================================================== --- teem/trunk/src/ten/tenMacros.h 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/tenMacros.h 2009-10-28 02:41:05 UTC (rev 4327) @@ -241,6 +241,7 @@ (t)[4] = (a)[1]*(a)[1], (t)[5] = (a)[1]*(a)[2], \ (t)[6] = (a)[2]*(a)[2]) +/* NOTE: never looks at (t)[0] */ #define TEN_T3V_CONTR(t, v) ( \ (v)[0]*(t)[1]*(v)[0] + (v)[0]*(t)[2]*(v)[1] + (v)[0]*(t)[3]*(v)[2] \ + (v)[1]*(t)[2]*(v)[0] + (v)[1]*(t)[4]*(v)[1] + (v)[1]*(t)[5]*(v)[2] \ Modified: teem/trunk/src/ten/tenModel.c =================================================================== --- teem/trunk/src/ten/tenModel.c 2009-10-27 20:26:24 UTC (rev 4326) +++ teem/trunk/src/ten/tenModel.c 2009-10-28 02:41:05 UTC (rev 4327) @@ -307,8 +307,7 @@ unsigned int starts, double convEps, airRandMTState *_rng) { static const char me[]="tenModelSqeFit"; double *ddwi, *dwibuff, sqe, sqeBest, convFrac, - dparm[TEN_MODEL_PARM_MAXNUM], - dparmBest[TEN_MODEL_PARM_MAXNUM], + *dparm, *dparmBest, (*ins)(void *v, size_t I, double d), (*lup)(const void *v, size_t I); airArray *mop; @@ -342,7 +341,15 @@ } /* allocate output (and set axmap) */ + dparm = AIR_CAST(double *, calloc(model->parmNum, sizeof(double))); + dparmBest = AIR_CAST(double *, calloc(model->parmNum, sizeof(double))); + if (!( dparm && dparmBest )) { + biffAddf(TEN, "%s: couldn't allocate parm vecs", me); + return 1; + } mop = airMopNew(); + airMopAdd(mop, dparm, airFree, airMopAlways); + airMopAdd(mop, dparmBest, airFree, airMopAlways); saveParmNum = saveB0 ? model->parmNum : model->parmNum-1; for (ii=0; ii<ndwi->dim; ii++) { szOut[ii] = (!ii @@ -381,29 +388,19 @@ } sqeBest = DBL_MAX; for (ss=0; ss<starts; ss++) { - fprintf(stderr, "!%s: II %u ss %u -------\n", - me, AIR_CAST(unsigned int, II), ss); if (knownB0) { dparm[0] = tenExperSpecKnownB0Get(espec, ddwi); - fprintf(stderr, "!%s: b0 = %g\n", me, dparm[0]); } model->rand(dparm, rng, knownB0); - fprintf(stderr, "!%s: rand -> %s\n", me, - model->sprint(pstr, dparm)); sqe = model->sqeFit(dparm, &convFrac, espec, dwibuff, ddwi, dparm, knownB0, minIter, maxIter, convEps); if (sqe < sqeBest) { - fprintf(stderr, "!%s: %g < %g --> %s\n", me, - sqe, sqeBest, model->sprint(pstr, dparm)); sqeBest = sqe; model->copy(dparmBest, dparm); } } for (ii=0; ii<saveParmNum; ii++) { ins(parm, ii, saveB0 ? dparmBest[ii] : dparmBest[ii+1]); - fprintf(stderr, "!%s: saving parm[%u] = %g\n", me, - saveB0 ? ii : ii+1, - saveB0 ? dparmBest[ii] : dparmBest[ii+1]); } /* possibly save sqeBest */ parm += saveParmNum*nrrdTypeSize[typeOut]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-28 13:36:08
|
Revision: 4328 http://teem.svn.sourceforge.net/teem/?rev=4328&view=rev Author: kindlmann Date: 2009-10-28 13:35:58 +0000 (Wed, 28 Oct 2009) Log Message: ----------- still hacking tenModel Modified Paths: -------------- teem/trunk/src/ten/GNUmakefile teem/trunk/src/ten/model1Stick.c teem/trunk/src/ten/modelBall.c teem/trunk/src/ten/modelBall1Stick.c teem/trunk/src/ten/modelCylinder.c teem/trunk/src/ten/modelTensor2.c teem/trunk/src/ten/privateTen.h teem/trunk/src/ten/sources.cmake teem/trunk/src/ten/ten.h teem/trunk/src/ten/tenModel.c Added Paths: ----------- teem/trunk/src/ten/tendMconv.c Modified: teem/trunk/src/ten/GNUmakefile =================================================================== --- teem/trunk/src/ten/GNUmakefile 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/GNUmakefile 2009-10-28 13:35:58 UTC (rev 4328) @@ -59,7 +59,7 @@ tendTriple.o tendTconv.o tendAvg.o \ tendAnhist.o tendMake.o tendSatin.o tendShrink.o tendGlyph.o \ tendFiber.o tendEpireg.o tendBmat.o tendEstim.o tendSim.o \ - tendMsim.o tendMfit.o \ + tendMsim.o tendMfit.o tendMconv.o \ tendSlice.o tendEllipse.o tendEvecrgb.o tendNorm.o tendAnscale.o \ tendEvalpow.o tendEvalclamp.o tendEvaladd.o tendHelix.o tendBfit.o \ tendUnmf.o tendLog.o tendExp.o Modified: teem/trunk/src/ten/model1Stick.c =================================================================== --- teem/trunk/src/ten/model1Stick.c 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/model1Stick.c 2009-10-28 13:35:58 UTC (rev 4328) @@ -26,11 +26,11 @@ #define PARM_NUM 5 static const tenModelParmDesc const parmDesc[] = { - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, - {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - {"x", -1.0, 1.0, AIR_TRUE, 0}, - {"y", -1.0, 1.0, AIR_TRUE, 1}, - {"z", -1.0, 1.0, AIR_TRUE, 2} + /* 0 */ {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + /* 1 */ {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + /* 2 */ {"x", -1.0, 1.0, AIR_TRUE, 0}, + /* 3 */ {"y", -1.0, 1.0, AIR_TRUE, 1}, + /* 4 */ {"z", -1.0, 1.0, AIR_TRUE, 2} }; static void @@ -58,14 +58,40 @@ return str; } +_TEN_PARM_ALLOC _TEN_PARM_RAND _TEN_PARM_STEP _TEN_PARM_DIST _TEN_PARM_COPY +static int +parmConvert(double *parmDst, const double *parmSrc, + const tenModel *modelSrc) { + int lossy; + + parmDst[0] = parmSrc[0]; + if (modelSrc == tenModelBall) { + + } else if (modelSrc == tenModel1Stick) { + + } else if (modelSrc == tenModelBall1Stick) { + + } else if (modelSrc == tenModelCylinder) { + + } else if (modelSrc == tenModelTensor2) { + + } else { + unsigned int ii; + for (ii=0; ii<PARM_NUM; ii++) { + parmDst[ii] = AIR_NAN; + } + } + return lossy; +} + _TEN_SQE -_TEN_SQE_GRAD_STUB -_TEN_SQE_FIT_STUB +_TEN_SQE_GRAD_CENTDIFF +_TEN_SQE_FIT(tenModel1Stick) _TEN_NLL _TEN_NLL_GRAD_STUB Modified: teem/trunk/src/ten/modelBall.c =================================================================== --- teem/trunk/src/ten/modelBall.c 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/modelBall.c 2009-10-28 13:35:58 UTC (rev 4328) @@ -26,8 +26,8 @@ #define PARM_NUM 2 static const tenModelParmDesc const parmDesc[] = { - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, - {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0} + /* 0 */ {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + /* 1 */ {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0} }; static void @@ -49,14 +49,41 @@ return str; } +_TEN_PARM_ALLOC _TEN_PARM_RAND _TEN_PARM_STEP _TEN_PARM_DIST _TEN_PARM_COPY +static int +parmConvert(double *parmDst, const double *parmSrc, + const tenModel *modelSrc) { + int ret; + + parmDst[0] = parmSrc[0]; + if (modelSrc == tenModelBall) { + + } else if (modelSrc == tenModel1Stick) { + + } else if (modelSrc == tenModelBall1Stick) { + + } else if (modelSrc == tenModelCylinder) { + + } else if (modelSrc == tenModelTensor2) { + + } else { + unsigned int ii; + for (ii=0; ii<PARM_NUM; ii++) { + parmDst[ii] = AIR_NAN; + } + ret = 2; + } + return ret; +} + _TEN_SQE -_TEN_SQE_GRAD_STUB -_TEN_SQE_FIT_STUB +_TEN_SQE_GRAD_CENTDIFF +_TEN_SQE_FIT(tenModelBall) _TEN_NLL Modified: teem/trunk/src/ten/modelBall1Stick.c =================================================================== --- teem/trunk/src/ten/modelBall1Stick.c 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/modelBall1Stick.c 2009-10-28 13:35:58 UTC (rev 4328) @@ -26,12 +26,12 @@ #define PARM_NUM 6 static const tenModelParmDesc const parmDesc[] = { - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, - {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - {"fraction", 0.0, 1.0, AIR_FALSE, 0}, - {"x", -1.0, 1.0, AIR_TRUE, 0}, - {"y", -1.0, 1.0, AIR_TRUE, 1}, - {"z", -1.0, 1.0, AIR_TRUE, 2} + /* 0 */ {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + /* 1 */ {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + /* 2 */ {"fraction", 0.0, 1.0, AIR_FALSE, 0}, + /* 3 */ {"x", -1.0, 1.0, AIR_TRUE, 0}, + /* 4 */ {"y", -1.0, 1.0, AIR_TRUE, 1}, + /* 5 */ {"z", -1.0, 1.0, AIR_TRUE, 2} }; static void @@ -62,14 +62,40 @@ return str; } +_TEN_PARM_ALLOC _TEN_PARM_RAND _TEN_PARM_STEP _TEN_PARM_DIST _TEN_PARM_COPY +static int +parmConvert(double *parmDst, const double *parmSrc, + const tenModel *modelSrc) { + int lossy; + + parmDst[0] = parmSrc[0]; + if (modelSrc == tenModelBall) { + + } else if (modelSrc == tenModel1Stick) { + + } else if (modelSrc == tenModelBall1Stick) { + + } else if (modelSrc == tenModelCylinder) { + + } else if (modelSrc == tenModelTensor2) { + + } else { + unsigned int ii; + for (ii=0; ii<PARM_NUM; ii++) { + parmDst[ii] = AIR_NAN; + } + } + return lossy; +} + _TEN_SQE -_TEN_SQE_GRAD_STUB -_TEN_SQE_FIT_STUB +_TEN_SQE_GRAD_CENTDIFF +_TEN_SQE_FIT(tenModelBall1Stick) _TEN_NLL _TEN_NLL_GRAD_STUB Modified: teem/trunk/src/ten/modelCylinder.c =================================================================== --- teem/trunk/src/ten/modelCylinder.c 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/modelCylinder.c 2009-10-28 13:35:58 UTC (rev 4328) @@ -26,12 +26,12 @@ #define PARM_NUM 6 static const tenModelParmDesc const parmDesc[] = { - {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, - {"length", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - {"radius", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, - {"x", -1.0, 1.0, AIR_TRUE, 0}, - {"y", -1.0, 1.0, AIR_TRUE, 1}, - {"z", -1.0, 1.0, AIR_TRUE, 2} + /* 0 */ {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, + /* 1 */ {"length", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + /* 2 */ {"radius", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, + /* 3 */ {"x", -1.0, 1.0, AIR_TRUE, 0}, + /* 4 */ {"y", -1.0, 1.0, AIR_TRUE, 1}, + /* 5 */ {"z", -1.0, 1.0, AIR_TRUE, 2} }; static void @@ -57,6 +57,7 @@ return; } +_TEN_PARM_ALLOC _TEN_PARM_RAND _TEN_PARM_STEP _TEN_PARM_DIST @@ -69,9 +70,34 @@ return str; } +static int +parmConvert(double *parmDst, const double *parmSrc, + const tenModel *modelSrc) { + int lossy; + + parmDst[0] = parmSrc[0]; + if (modelSrc == tenModelBall) { + + } else if (modelSrc == tenModel1Stick) { + + } else if (modelSrc == tenModelBall1Stick) { + + } else if (modelSrc == tenModelCylinder) { + + } else if (modelSrc == tenModelTensor2) { + + } else { + unsigned int ii; + for (ii=0; ii<PARM_NUM; ii++) { + parmDst[ii] = AIR_NAN; + } + } + return lossy; +} + _TEN_SQE -_TEN_SQE_GRAD_STUB -_TEN_SQE_FIT_STUB +_TEN_SQE_GRAD_CENTDIFF +_TEN_SQE_FIT(tenModelCylinder) _TEN_NLL _TEN_NLL_GRAD_STUB Modified: teem/trunk/src/ten/modelTensor2.c =================================================================== --- teem/trunk/src/ten/modelTensor2.c 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/modelTensor2.c 2009-10-28 13:35:58 UTC (rev 4328) @@ -62,90 +62,66 @@ return str; } +_TEN_PARM_ALLOC _TEN_PARM_RAND _TEN_PARM_STEP _TEN_PARM_DIST _TEN_PARM_COPY -static double -sqe(const double *parm, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, int knownB0) { +static int +parmConvert(double *parmDst, const double *parmSrc, + const tenModel *modelSrc) { + int ret; - simulate(dwiBuff, parm, espec); - return _tenExperSpec_sqe(dwiBuff, dwiMeas, espec, knownB0); -} - -static void -sqeGrad(double *grad, const double *parm0, - const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - int knownB0) { - double parm1[PARM_NUM], sqeForw, sqeBack, dp; - unsigned int ii, i0; - - i0 = knownB0 ? 1 : 0; - for (ii=0; ii<PARM_NUM; ii++) { - /* have to copy all parms, even B0 with knownB0, and even if we - aren't going to diddle these values, because the - simulation depends on knowing the values */ - parm1[ii] = parm0[ii]; + if (modelSrc == tenModelBall) { + TEN_T_SET(parmDst, parmSrc[0], + parmSrc[1], 0, 0, + parmSrc[1], 0, + parmSrc[1]); + ret = 0; + } else if (modelSrc == tenModel1Stick) { + double ten[7]; + TEN_T3V_OUTER(ten, parmSrc + 2); + TEN_T_SCALE(parmDst, parmSrc[1], ten); + parmDst[0] = parmSrc[0]; + ret = 0; + } else if (modelSrc == tenModelBall1Stick) { + double stick[7], ball[7], diff, frac; + diff = parmSrc[1]; + frac = parmSrc[2]; + TEN_T3V_OUTER(stick, parmSrc + 3); + TEN_T_SCALE(stick, diff, stick); + TEN_T_SET(ball, 1, diff, 0, 0, diff, 0, diff); + TEN_T_LERP(parmDst, frac, ball, stick); + parmDst[0] = parmSrc[0]; + ret = 1; + } else if (modelSrc == tenModelCylinder) { + double stick[7], ball[7], len, rad; + len = parmSrc[1]; + rad = parmSrc[2]; + TEN_T3V_OUTER(stick, parmSrc + 3); + TEN_T_SCALE(stick, len, stick); + TEN_T_SET(ball, 1, rad, 0, 0, rad, 0, rad); + TEN_T_ADD(parmDst, ball, stick); + parmDst[0] = parmSrc[0]; + ret = 0; + } else if (modelSrc == tenModelTensor2) { + parmCopy(parmDst, parmSrc); + ret = 0; + } else { + unsigned int ii; + for (ii=0; ii<PARM_NUM; ii++) { + parmDst[ii] = AIR_NAN; + } + ret = 2; } - for (ii=i0; ii<PARM_NUM; ii++) { - dp = (parmDesc[ii].max - parmDesc[ii].min)*TEN_MODEL_PARM_GRAD_EPS; - parm1[ii] = parm0[ii] + dp; - sqeForw = sqe(parm1, espec, dwiBuff, dwiMeas, knownB0); - parm1[ii] = parm0[ii] - dp; - sqeBack = sqe(parm1, espec, dwiBuff, dwiMeas, knownB0); - grad[ii] = (sqeForw - sqeBack)/(2*dp); - parm1[ii] = parm0[ii]; - } - if (knownB0) { - grad[0] = 0; - } - return; + return ret; } -static double -sqeFit(double *parm, double *convFrac, const tenExperSpec *espec, - double *dwiBuff, const double *dwiMeas, - const double *parmInit, int knownB0, - unsigned int minIter, unsigned int maxIter, double convEps) { - /* static const char me[]= TEN_MODEL_STR_TENSOR2 ":sqeFit"; */ - unsigned int iter; - double step, bak, opp, val, testval, - dist, testparm[PARM_NUM], grad[PARM_NUM]; - int done; +_TEN_SQE +_TEN_SQE_GRAD_CENTDIFF +_TEN_SQE_FIT(tenModelTensor2) - step = 1; - parmCopy(parm, parmInit); - val = sqe(parm, espec, dwiBuff, dwiMeas, knownB0); - sqeGrad(grad, parm, espec, dwiBuff, dwiMeas, knownB0); - - opp = 2; - bak = 0.1; - iter = 0; - do { - do { - parmStep(testparm, -step, grad, parm); - testval = sqe(testparm, espec, dwiBuff, dwiMeas, knownB0); - if (testval > val) { - step *= bak; - } - } while (testval > val); - dist = parmDist(testparm, parm); - val = testval; - parmCopy(parm, testparm); - sqeGrad(grad, parm, espec, dwiBuff, dwiMeas, knownB0); - step *= opp; - iter++; - done = (iter < minIter - ? AIR_FALSE - : (iter > maxIter) || dist < convEps); - } while (!done); - *convFrac = dist/convEps; - return val; -} - _TEN_NLL _TEN_NLL_GRAD_STUB _TEN_NLL_FIT_STUB Modified: teem/trunk/src/ten/privateTen.h =================================================================== --- teem/trunk/src/ten/privateTen.h 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/privateTen.h 2009-10-28 13:35:58 UTC (rev 4328) @@ -158,14 +158,35 @@ int rician, double sigma, int knownB0); +/* tenModel.c */ +TEN_EXPORT double _tenModelSqeFitSingle(const tenModel *model, + double *testParm, double *grad, + double *parm, double *convFrac, + const tenExperSpec *espec, + double *dwiBuff, + const double *dwiMeas, + const double *parmInit, + int knownB0, + unsigned int minIter, + unsigned int maxIter, + double convEps); + /* model*.c */ /* ** NOTE: these functions rely on per-model information (like PARM_NUM) -** or functions (like "simulate"), which is why these functions can't -** all use same common underlying function, since more information would +** or functions (like "simulate"), which is why these functions don't +** all use some common underlying function: more information would ** have to be passed (annoying for rapid hacking), and the function ** call overhead might be doubled */ + +#define _TEN_PARM_ALLOC \ +static double * \ +parmAlloc(void) { \ + \ + return AIR_CAST(double *, calloc(PARM_NUM, sizeof(double))); \ +} + #define _TEN_PARM_RAND \ static void \ parmRand(double *parm, airRandMTState *rng, int knownB0) { \ @@ -244,22 +265,61 @@ return _tenExperSpec_sqe(dwiMeas, dwiBuff, espec, knownB0); \ } -#define _TEN_SQE_GRAD_STUB \ -static void \ -sqeGrad(double *grad, const double *parm, \ - const tenExperSpec *espec, \ - double *dwiBuff, const double *dwiMeas, \ - int knownB0) { \ - \ - AIR_UNUSED(grad); \ - AIR_UNUSED(parm); \ - AIR_UNUSED(espec); \ - AIR_UNUSED(dwiBuff); \ - AIR_UNUSED(dwiMeas); \ - AIR_UNUSED(knownB0); \ - return; \ +#define _TEN_SQE_GRAD_CENTDIFF \ +static void \ +sqeGrad(double *grad, const double *parm0, \ + const tenExperSpec *espec, \ + double *dwiBuff, const double *dwiMeas, \ + int knownB0) { \ + double parm1[PARM_NUM], sqeForw, sqeBack, dp; \ + unsigned int ii, i0; \ + \ + i0 = knownB0 ? 1 : 0; \ + for (ii=0; ii<PARM_NUM; ii++) { \ + /* have to copy all parms, even B0 with knownB0, and even if we \ + aren't going to diddle these values, because the \ + simulation depends on knowing the values */ \ + parm1[ii] = parm0[ii]; \ + } \ + for (ii=i0; ii<PARM_NUM; ii++) { \ + dp = (parmDesc[ii].max - parmDesc[ii].min)*TEN_MODEL_PARM_GRAD_EPS; \ + parm1[ii] = parm0[ii] + dp; \ + sqeForw = sqe(parm1, espec, dwiBuff, dwiMeas, knownB0); \ + parm1[ii] = parm0[ii] - dp; \ + sqeBack = sqe(parm1, espec, dwiBuff, dwiMeas, knownB0); \ + grad[ii] = (sqeForw - sqeBack)/(2*dp); \ + parm1[ii] = parm0[ii]; \ + if (parmDesc[ii].vec3 && 2 == parmDesc[ii].vecIdx) { \ + double dot, *gg; \ + const double *vv; \ + gg = grad + ii - 2; \ + vv = parm0 + ii - 2; \ + dot = ELL_3V_DOT(gg, vv); \ + ELL_3V_SCALE_INCR(gg, -dot, vv); \ + } \ + } \ + if (knownB0) { \ + grad[0] = 0; \ + } \ + return; \ } +#define _TEN_SQE_FIT(model) \ +static double \ +sqeFit(double *parm, double *convFrac, const tenExperSpec *espec, \ + double *dwiBuff, const double *dwiMeas, \ + const double *parmInit, int knownB0, \ + unsigned int minIter, unsigned int maxIter, double convEps) { \ + double testparm[PARM_NUM], grad[PARM_NUM]; \ + \ + return _tenModelSqeFitSingle((model), \ + testparm, grad, \ + parm, convFrac, \ + espec, dwiBuff, dwiMeas, \ + parmInit, knownB0, \ + minIter, maxIter, convEps); \ +} + #define _TEN_SQE_FIT_STUB \ static double \ sqeFit(double *parm, double *convFrac, const tenExperSpec *espec, \ @@ -328,12 +388,13 @@ return 0; \ } -#define _TEN_MODEL_FIELDS \ - PARM_NUM, parmDesc, \ - simulate, \ - parmSprint, parmRand, parmStep, parmDist, parmCopy, \ - sqe, sqeGrad, sqeFit, \ - nll, nllGrad, nllFit +#define _TEN_MODEL_FIELDS \ + PARM_NUM, parmDesc, \ + simulate, \ + parmSprint, parmAlloc, parmRand, \ + parmStep, parmDist, parmCopy, parmConvert, \ + sqe, sqeGrad, sqeFit, \ + nll, nllGrad, nllFit #ifdef __cplusplus } Modified: teem/trunk/src/ten/sources.cmake =================================================================== --- teem/trunk/src/ten/sources.cmake 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/sources.cmake 2009-10-28 13:35:58 UTC (rev 4328) @@ -57,6 +57,7 @@ tendSim.c tendMsim.c tendMfit.c + tendMconv.c tendSlice.c tendSten.c tendTconv.c Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/ten.h 2009-10-28 13:35:58 UTC (rev 4328) @@ -1115,7 +1115,7 @@ ** and it would be dumb to double the number of models to be able ** to capture this. */ -typedef struct { +typedef struct tenModel_t { char name[AIR_STRLEN_SMALL]; unsigned int parmNum; const tenModelParmDesc *parmDesc; @@ -1124,11 +1124,14 @@ const tenExperSpec *espec); /* parameter vector operations */ char *(*sprint)(char str[AIR_STRLEN_MED], const double *parm); + double *(*alloc)(void); void (*rand)(double *parm, airRandMTState *rng, int knownB0); void (*step)(double *parm1, const double scl, const double *grad, const double *parm0); double (*dist)(const double *parmA, const double *parmB); void (*copy)(double *parmA, const double *parmB); + int (*convert)(double *parmDst, const double *parmSrc, + const struct tenModel_t *modelSrc); /* "sqe" == squared error in DWI values */ double (*sqe)(const double *parm, const tenExperSpec *espec, @@ -1564,8 +1567,16 @@ const tenModel *model, const tenExperSpec *espec, const Nrrd *ndwi, int rician, double sigma, int knownB0); - -/* have to keep in sync with modelTen.c/tenModelParse() */ +TEN_EXPORT int tenModelConvert(Nrrd *nparmDst, int *convRet, + const tenModel *modelDst, + const Nrrd *nparmSrc, + const tenModel *modelSrc); + +/* +** Have to keep this list of model declarations in sync with: +** * modelTen.c/tenModelParse() +** * all model*.c/parmConvert() +*/ /* modelBall.c */ #define TEN_MODEL_STR_BALL "ball" TEN_EXPORT const tenModel *const tenModelBall; @@ -1640,6 +1651,7 @@ F(estim) \ F(sim) \ F(mfit) \ +F(mconv) \ F(msim) \ F(make) \ F(avg) \ Modified: teem/trunk/src/ten/tenModel.c =================================================================== --- teem/trunk/src/ten/tenModel.c 2009-10-28 02:41:05 UTC (rev 4327) +++ teem/trunk/src/ten/tenModel.c 2009-10-28 13:35:58 UTC (rev 4328) @@ -24,7 +24,7 @@ #include "privateTen.h" const char * -tenModelPrefixStr = "DWMRI_model"; +tenModelPrefixStr = "DWMRI_model:"; static const tenModel * str2model(const char *str) { @@ -42,31 +42,31 @@ tenModelParse(const tenModel **model, int *plusB0, int requirePrefix, const char *_str) { static const char me[]="tenModelParse"; - char *str, *modstr, prefix[AIR_STRLEN_MED], *pre; + char *str, *modstr, *pre; airArray *mop; if (!( model && plusB0 && _str)) { biffAddf(TEN, "%s: got NULL pointer", me); return 1; } - str = airToLower(airStrdup(_str)); + str = airStrdup(_str); if (!str) { biffAddf(TEN, "%s: couldn't strdup", me); return 1; } mop = airMopNew(); airMopAdd(mop, str, airFree, airMopAlways); - sprintf(prefix, "%s:", tenModelPrefixStr); - pre = strstr(str, prefix); + pre = strstr(str, tenModelPrefixStr); if (pre) { - str += strlen(prefix); + str += strlen(tenModelPrefixStr); } else { if (requirePrefix) { biffAddf(TEN, "%s: didn't see prefix \"%s\" in \"%s\"", me, - prefix, _str); + tenModelPrefixStr, _str); airMopError(mop); return 1; } } + airToLower(str); if ((modstr = strchr(str, '+'))) { *modstr = '\0'; @@ -100,7 +100,8 @@ return 1; } *plusB0 = AIR_FALSE; - /* first try to learn model from "kind" */ + /* first try to learn model from axis "kind" */ + /* HEY should probably also support 3 vector for stick? */ if (nrrdKind3DSymMatrix == axinfo->kind || nrrdKind3DMaskedSymMatrix == axinfo->kind) { *modelP = tenModelTensor2; @@ -298,6 +299,58 @@ return 0; } +/* +** _tenModelSqeFitSingle +** +** callable function (as opposed to tenModel method) for doing +** sqe fitting. Requires PARM_NUM length buffers testParm and grad +*/ +double +_tenModelSqeFitSingle(const tenModel *model, + double *testParm, double *grad, + double *parm, double *convFrac, + const tenExperSpec *espec, + double *dwiBuff, const double *dwiMeas, + const double *parmInit, int knownB0, + unsigned int minIter, unsigned int maxIter, + double convEps) { + /* static const char me[]="_tenModelSqeFitSingle"; */ + unsigned int iter; + double step, bak, opp, val, testval, dist, td; + int done; + + step = 1; + model->copy(parm, parmInit); + val = model->sqe(parm, espec, dwiBuff, dwiMeas, knownB0); + model->sqeGrad(grad, parm, espec, dwiBuff, dwiMeas, knownB0); + + opp = 2; + bak = 0.1; + iter = 0; + dist = convEps*8; + do { + do { + model->step(testParm, -step, grad, parm); + testval = model->sqe(testParm, espec, dwiBuff, dwiMeas, knownB0); + if (testval > val) { + step *= bak; + } + } while (testval > val); + td = model->dist(testParm, parm); + dist = (td + dist)/2; + val = testval; + model->copy(parm, testParm); + model->sqeGrad(grad, parm, espec, dwiBuff, dwiMeas, knownB0); + step *= opp; + iter++; + done = (iter < minIter + ? AIR_FALSE + : (iter > maxIter) || dist < convEps); + } while (!done); + *convFrac = dist/convEps; + return val; +} + int tenModelSqeFit(Nrrd *nparm, Nrrd **nsqeP, const tenModel *model, @@ -422,12 +475,11 @@ airMopError(mop); return 1; } lablen = (strlen(tenModelPrefixStr) - + strlen(":") + (saveB0 ? strlen("B0+") : 0) + strlen(model->name) + 1); nparm->axis[0].label = AIR_CAST(char *, calloc(lablen, sizeof(char))); - sprintf(nparm->axis[0].label, "%s:%s%s", + sprintf(nparm->axis[0].label, "%s%s%s", tenModelPrefixStr, saveB0 ? "B0+" : "", model->name); @@ -453,3 +505,124 @@ return 0; } + +/* +** copy the B0 info if we have it +** use the same type on the way out. +*/ +int +tenModelConvert(Nrrd *nparmDst, int *convRetP, const tenModel *modelDst, + const Nrrd *nparmSrc, const tenModel *_modelSrc) { + static char me[]="tenModelConvert"; + const tenModel *modelSrc; + double *dpdst, *dpsrc, (*lup)(const void *v, size_t I), + (*ins)(void *v, size_t I, double d); + size_t szOut[NRRD_DIM_MAX], II, NN, tsize; + airArray *mop; + int withB0, axmap[NRRD_DIM_MAX], convRet; + unsigned int parmNumDst, parmNumSrc, ii, lablen; + const char *parmSrc; + char *parmDst; + + if (!( nparmDst && modelDst && nparmSrc )) { + biffAddf(TEN, "%s: got NULL pointer", me); + return 1; + } + if (!_modelSrc) { + /* we have to try to learn the source model from the nrrd */ + if (tenModelFromAxisLearn(&modelSrc, &withB0, nparmSrc->axis + 0)) { + biffAddf(TEN, "%s: couldn't learn model from src nparm", me); + return 1; + } + } else { + modelSrc = _modelSrc; + if (modelSrc->parmNum == nparmSrc->axis[0].size) { + withB0 = AIR_TRUE; + } if (modelSrc->parmNum-1 == nparmSrc->axis[0].size) { + withB0 = AIR_FALSE; + } else { + biffAddf(TEN, "%s: axis[0].size %u is not \"%s\" parmnum %u or 1 less", + me, AIR_CAST(unsigned int, nparmSrc->axis[0].size), + modelSrc->name, modelSrc->parmNum); + return 1; + } + } + + mop = airMopNew(); + dpdst = modelDst->alloc(); + airMopAdd(mop, dpdst, airFree, airMopAlways); + dpsrc = modelSrc->alloc(); + airMopAdd(mop, dpsrc, airFree, airMopAlways); + lup = nrrdDLookup[nparmSrc->type]; + ins = nrrdDInsert[nparmSrc->type]; + parmNumDst = withB0 ? modelDst->parmNum : modelDst->parmNum-1; + parmNumSrc = nparmSrc->axis[0].size; + for (ii=0; ii<nparmSrc->dim; ii++) { + szOut[ii] = (!ii + ? parmNumDst + : nparmSrc->axis[ii].size); + axmap[ii] = (!ii + ? -1 + : AIR_CAST(int, ii)); + } + if (nrrdMaybeAlloc_nva(nparmDst, nparmSrc->type, nparmSrc->dim, szOut)) { + biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + airMopError(mop); return 1; + } + + NN = nrrdElementNumber(nparmSrc)/nparmSrc->axis[0].size; + tsize = nrrdTypeSize[nparmSrc->type]; + parmSrc = AIR_CAST(char *, nparmSrc->data); + parmDst = AIR_CAST(char *, nparmDst->data); + if (!withB0) { + dpsrc[0] = 0; + } + /* do first one for error check */ + for (II=0; II<NN; II++) { + for (ii=0; ii<parmNumSrc; ii++) { + dpsrc[withB0 ? ii : ii+1] = lup(parmSrc, ii); + } + convRet = modelDst->convert(dpdst, dpsrc, modelSrc); + if (2 == convRet) { /* HEY should be enum for this value */ + biffAddf(TEN, "%s: error converting from \"%s\" to \"%s\"", me, + modelSrc->name, modelDst->name); + airMopError(mop); return 1; + } + for (ii=0; ii<parmNumDst; ii++) { + ins(parmDst, ii, dpdst[ii]); + } + parmSrc += parmNumSrc*tsize; + parmDst += parmNumDst*tsize; + } + if (convRetP) { + *convRetP = convRet; + } + + if (nrrdAxisInfoCopy(nparmDst, nparmSrc, axmap, NRRD_AXIS_INFO_SIZE_BIT) + || nrrdBasicInfoCopy(nparmDst, nparmSrc, + NRRD_BASIC_INFO_DATA_BIT + | NRRD_BASIC_INFO_TYPE_BIT + | NRRD_BASIC_INFO_BLOCKSIZE_BIT + | NRRD_BASIC_INFO_DIMENSION_BIT + | NRRD_BASIC_INFO_CONTENT_BIT + | NRRD_BASIC_INFO_COMMENTS_BIT + | (nrrdStateKeyValuePairsPropagate + ? 0 + : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { + biffMovef(TEN, NRRD, "%s: couldn't copy axis or basic info", me); + airMopError(mop); return 1; + } + /* HEY: COPY AND PASTE! from above. perhaps make helper functions? */ + lablen = (strlen(tenModelPrefixStr) + + (withB0 ? strlen("B0+") : 0) + + strlen(modelDst->name) + + 1); + nparmDst->axis[0].label = AIR_CAST(char *, calloc(lablen, sizeof(char))); + sprintf(nparmDst->axis[0].label, "%s%s%s", + tenModelPrefixStr, + withB0 ? "B0+" : "", + modelDst->name); + + airMopOkay(mop); + return 0; +} Added: teem/trunk/src/ten/tendMconv.c =================================================================== --- teem/trunk/src/ten/tendMconv.c (rev 0) +++ teem/trunk/src/ten/tendMconv.c 2009-10-28 13:35:58 UTC (rev 4328) @@ -0,0 +1,97 @@ +/* + Teem: Tools to process and visualize scientific data and images + Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann + Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + (LGPL) as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The terms of redistributing and/or modifying this software also + include exceptions to the LGPL that facilitate static linking. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ten.h" +#include "privateTen.h" + +#define INFO "convert from one model to another" +char *_tend_mconvInfoL = + (INFO + ". More docs here."); + +int +tend_mconvMain(int argc, char **argv, char *me, hestParm *hparm) { + int pret; + hestOpt *hopt = NULL; + char *perr, *err; + airArray *mop; + + Nrrd *nin, *nout; + char *outS, *modelSrcS, *modelDstS; + const tenModel *modelDst, *modelSrc; + int saveB0; + + hestOptAdd(&hopt, "mo", "model", airTypeString, 1, 1, &modelDstS, NULL, + "which model to convert to"); + hestOptAdd(&hopt, "mi", "model", airTypeString, 1, 1, &modelSrcS, "", + "model converting from; if not set, will try to determine " + "from input nrrd"); + hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nin, "-", + "input nrrd of model parms", + NULL, NULL, nrrdHestNrrd); + hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", + "output nrrd of model parms"); + + mop = airMopNew(); + airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); + USAGE(_tend_mconvInfoL); + JUSTPARSE(); + airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); + + nout = nrrdNew(); + airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); + if (tenModelParse(&modelDst, &saveB0, AIR_FALSE, modelDstS)) { + airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); + fprintf(stderr, "%s: trouble parsing model \"%s\":\n%s\n", me, + modelDstS, err); + airMopError(mop); return 1; + } + if (saveB0) { + printf("%s: warning: saving B0 is determined by input nrrd " + "having B0 info.\n", me); + } + if (airStrlen(modelSrcS)) { + if (tenModelParse(&modelSrc, &saveB0, AIR_FALSE, modelSrcS)) { + airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); + fprintf(stderr, "%s: trouble parsing model \"%s\":\n%s\n", me, + modelSrcS, err); + airMopError(mop); return 1; + } + } else { + modelSrc = NULL; + } + if (tenModelConvert(nout, NULL, modelDst, nin, modelSrc)) { + airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); + fprintf(stderr, "%s: trouble converting:\n%s\n", me, err); + airMopError(mop); return 1; + } + if (nrrdSave(outS, nout, NULL)) { + airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); + fprintf(stderr, "%s: trouble writing:\n%s\n", me, err); + airMopError(mop); return 1; + } + + airMopOkay(mop); + return 0; +} +/* TEND_CMD(mconv, INFO); */ +unrrduCmd tend_mconvCmd = { "mconv", INFO, tend_mconvMain }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-29 12:08:24
|
Revision: 4338 http://teem.svn.sourceforge.net/teem/?rev=4338&view=rev Author: kindlmann Date: 2009-10-29 12:08:18 +0000 (Thu, 29 Oct 2009) Log Message: ----------- comments Modified Paths: -------------- teem/trunk/src/ten/ten.h teem/trunk/src/ten/tenModel.c Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-10-29 12:08:04 UTC (rev 4337) +++ teem/trunk/src/ten/ten.h 2009-10-29 12:08:18 UTC (rev 4338) @@ -1090,8 +1090,9 @@ typedef struct { char name[AIR_STRLEN_SMALL]; /* name */ double min, max; /* bounds */ - int vec3; /* non-zero if this is one coeff of 3-vector */ - unsigned int vecIdx; /* if 3-vector, index into it */ + int vec3; /* non-zero if this is a coefficient + of a UNIT-LENGTH 3-vector */ + unsigned int vecIdx; /* if part of vector, index into it */ } tenModelParmDesc; #define TEN_MODEL_B0_MAX 10000 /* HEY: completely arbitrary! */ Modified: teem/trunk/src/ten/tenModel.c =================================================================== --- teem/trunk/src/ten/tenModel.c 2009-10-29 12:08:04 UTC (rev 4337) +++ teem/trunk/src/ten/tenModel.c 2009-10-29 12:08:18 UTC (rev 4338) @@ -576,7 +576,6 @@ if (!withB0) { dpsrc[0] = 0; } - /* do first one for error check */ for (II=0; II<NN; II++) { for (ii=0; ii<parmNumSrc; ii++) { dpsrc[withB0 ? ii : ii+1] = lup(parmSrc, ii); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-10-30 13:42:42
|
Revision: 4339 http://teem.svn.sourceforge.net/teem/?rev=4339&view=rev Author: kindlmann Date: 2009-10-30 13:42:36 +0000 (Fri, 30 Oct 2009) Log Message: ----------- fixing warning message while tenModel->convert is still largely unimplemented Modified Paths: -------------- teem/trunk/src/ten/model1Stick.c teem/trunk/src/ten/modelBall.c teem/trunk/src/ten/modelBall1Stick.c teem/trunk/src/ten/modelCylinder.c teem/trunk/src/ten/modelTensor2.c Modified: teem/trunk/src/ten/model1Stick.c =================================================================== --- teem/trunk/src/ten/model1Stick.c 2009-10-29 12:08:18 UTC (rev 4338) +++ teem/trunk/src/ten/model1Stick.c 2009-10-30 13:42:36 UTC (rev 4339) @@ -25,7 +25,7 @@ #define PARM_NUM 5 static const tenModelParmDesc -const parmDesc[] = { +parmDesc[] = { /* 0 */ {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, /* 1 */ {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, /* 2 */ {"x", -1.0, 1.0, AIR_TRUE, 0}, @@ -67,8 +67,9 @@ static int parmConvert(double *parmDst, const double *parmSrc, const tenModel *modelSrc) { - int lossy; + int ret; + ret = 0; parmDst[0] = parmSrc[0]; if (modelSrc == tenModelBall) { @@ -85,8 +86,9 @@ for (ii=0; ii<PARM_NUM; ii++) { parmDst[ii] = AIR_NAN; } + ret = 2; } - return lossy; + return ret; } _TEN_SQE Modified: teem/trunk/src/ten/modelBall.c =================================================================== --- teem/trunk/src/ten/modelBall.c 2009-10-29 12:08:18 UTC (rev 4338) +++ teem/trunk/src/ten/modelBall.c 2009-10-30 13:42:36 UTC (rev 4339) @@ -25,7 +25,7 @@ #define PARM_NUM 2 static const tenModelParmDesc -const parmDesc[] = { +parmDesc[] = { /* 0 */ {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, /* 1 */ {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0} }; @@ -60,6 +60,7 @@ const tenModel *modelSrc) { int ret; + ret = 0; parmDst[0] = parmSrc[0]; if (modelSrc == tenModelBall) { Modified: teem/trunk/src/ten/modelBall1Stick.c =================================================================== --- teem/trunk/src/ten/modelBall1Stick.c 2009-10-29 12:08:18 UTC (rev 4338) +++ teem/trunk/src/ten/modelBall1Stick.c 2009-10-30 13:42:36 UTC (rev 4339) @@ -25,7 +25,7 @@ #define PARM_NUM 6 static const tenModelParmDesc -const parmDesc[] = { +parmDesc[] = { /* 0 */ {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, /* 1 */ {"diffusivity", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, /* 2 */ {"fraction", 0.0, 1.0, AIR_FALSE, 0}, @@ -71,8 +71,9 @@ static int parmConvert(double *parmDst, const double *parmSrc, const tenModel *modelSrc) { - int lossy; + int ret; + ret = 0; parmDst[0] = parmSrc[0]; if (modelSrc == tenModelBall) { @@ -89,8 +90,9 @@ for (ii=0; ii<PARM_NUM; ii++) { parmDst[ii] = AIR_NAN; } + ret = 2; } - return lossy; + return ret; } _TEN_SQE Modified: teem/trunk/src/ten/modelCylinder.c =================================================================== --- teem/trunk/src/ten/modelCylinder.c 2009-10-29 12:08:18 UTC (rev 4338) +++ teem/trunk/src/ten/modelCylinder.c 2009-10-30 13:42:36 UTC (rev 4339) @@ -25,7 +25,7 @@ #define PARM_NUM 6 static const tenModelParmDesc -const parmDesc[] = { +parmDesc[] = { /* 0 */ {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, /* 1 */ {"length", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, /* 2 */ {"radius", 0.0, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, @@ -73,8 +73,9 @@ static int parmConvert(double *parmDst, const double *parmSrc, const tenModel *modelSrc) { - int lossy; + int ret; + ret = 0; parmDst[0] = parmSrc[0]; if (modelSrc == tenModelBall) { @@ -91,8 +92,9 @@ for (ii=0; ii<PARM_NUM; ii++) { parmDst[ii] = AIR_NAN; } + ret = 2; } - return lossy; + return ret; } _TEN_SQE Modified: teem/trunk/src/ten/modelTensor2.c =================================================================== --- teem/trunk/src/ten/modelTensor2.c 2009-10-29 12:08:18 UTC (rev 4338) +++ teem/trunk/src/ten/modelTensor2.c 2009-10-30 13:42:36 UTC (rev 4339) @@ -27,7 +27,7 @@ /* 1/sqrt(2) */ #define OST 0.70710678118654752440 static const tenModelParmDesc -const parmDesc[] = { +parmDesc[] = { {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, 0}, {"Dxx", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, 0}, {"Dxy", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, 0}, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ts...@us...> - 2009-11-04 03:29:37
|
Revision: 4352 http://teem.svn.sourceforge.net/teem/?rev=4352&view=rev Author: tststs Date: 2009-11-04 03:29:26 +0000 (Wed, 04 Nov 2009) Log Message: ----------- Integrated code that implements tenGage kinds to compute Hessian of cl/cp/ca. Needed to implement the linearity and planarity ridges from Schultz/Theisel/Seidel: "Crease Surfaces: From Theory to Extraction and Application to Diffusion Tensor MRI." IEEE TVCG 2010. Modified Paths: -------------- teem/trunk/src/ten/enumsTen.c teem/trunk/src/ten/ten.h teem/trunk/src/ten/tenGage.c Modified: teem/trunk/src/ten/enumsTen.c =================================================================== --- teem/trunk/src/ten/enumsTen.c 2009-11-03 20:26:11 UTC (rev 4351) +++ teem/trunk/src/ten/enumsTen.c 2009-11-04 03:29:26 UTC (rev 4352) @@ -316,12 +316,42 @@ "cl1gv", "cl1gm", + "cl1gn", "cp1gv", "cp1gm", + "cp1gn", "ca1gv", "ca1gm", + "ca1gn", "tgrote", - + "eval hessian", + "cl1 hessian", + "cl1 hessian evals", + "cl1 hessian eval 0", + "cl1 hessian eval 1", + "cl1 hessian eval 2", + "cl1 hessian evecs", + "cl1 hessian evec 0", + "cl1 hessian evec 1", + "cl1 hessian evec 2", + "cp1 hessian", + "cp1 hessian evals", + "cp1 hessian eval 0", + "cp1 hessian eval 1", + "cp1 hessian eval 2", + "cp1 hessian evecs", + "cp1 hessian evec 0", + "cp1 hessian evec 1", + "cp1 hessian evec 2", + "ca1 hessian", + "ca1 hessian evals", + "ca1 hessian eval 0", + "ca1 hessian eval 1", + "ca1 hessian eval 2", + "ca1 hessian evecs", + "ca1 hessian evec 0", + "ca1 hessian evec 1", + "ca1 hessian evec 2", "anisotropies" }; @@ -481,13 +511,44 @@ "QuatGeoLoxR", "gradient vector of cl1", "gradient magnitude of cl1", + "normal of cl1", "gradient vector of cp1", "gradient magnitude of cp1", + "normal of cp1", "gradient vector of ca1", "gradient magnitude of ca1", + "normal of ca1", "all tensor component gradients, starting with confidence gradient, " /* !! CONCAT !! */ "rotated such that eigenvalue derivatives are on the diagonal", + "eigenvalue hessians", + "cl1 hessian", + "cl1 hessian evals", + "cl1 hessian eval 0", + "cl1 hessian eval 1", + "cl1 hessian eval 2", + "cl1 hessian evecs", + "cl1 hessian evec 0", + "cl1 hessian evec 1", + "cl1 hessian evec 2", + "cp1 hessian", + "cp1 hessian evals", + "cp1 hessian eval 0", + "cp1 hessian eval 1", + "cp1 hessian eval 2", + "cp1 hessian evecs", + "cp1 hessian evec 0", + "cp1 hessian evec 1", + "cp1 hessian evec 2", + "ca1 hessian", + "ca1 hessian evals", + "ca1 hessian eval 0", + "ca1 hessian eval 1", + "ca1 hessian eval 2", + "ca1 hessian evecs", + "ca1 hessian evec 0", + "ca1 hessian evec 1", + "ca1 hessian evec 2", "anisotropies" }; @@ -647,11 +708,42 @@ tenGageTensorQuatGeoLoxR, tenGageCl1GradVec, tenGageCl1GradMag, + tenGageCl1Normal, tenGageCp1GradVec, tenGageCp1GradMag, + tenGageCp1Normal, tenGageCa1GradVec, tenGageCa1GradMag, + tenGageCa1Normal, tenGageTensorGradRotE, + tenGageEvalHessian, /* Hessian of the eigenvalues: [27] */ + tenGageCl1Hessian, /* Hessian of cl1: [9] */ + tenGageCl1HessianEval, /* Hessian eigenvalues of cl1: [3] */ + tenGageCl1HessianEval0, /* First Hessian eigenvalue of cl1: [1] */ + tenGageCl1HessianEval1, /* Second Hessian eigenvalue of cl1: [1] */ + tenGageCl1HessianEval2, /* Third Hessian eigenvalue of cl1: [1] */ + tenGageCl1HessianEvec, /* Hessian eigenvectors of cl1: [9] */ + tenGageCl1HessianEvec0, /* First Hessian eigenvector of cl1: [3] */ + tenGageCl1HessianEvec1, /* Second Hessian eigenvector of cl1: [3] */ + tenGageCl1HessianEvec2, /* Third Hessian eigenvector of cl1: [3] */ + tenGageCp1Hessian, /* Hessian of cp1: [9] */ + tenGageCp1HessianEval, /* Hessian eigenvalues of cp1: [3] */ + tenGageCp1HessianEval0, /* First Hessian eigenvalue of cp1: [1] */ + tenGageCp1HessianEval1, /* Second Hessian eigenvalue of cp1: [1] */ + tenGageCp1HessianEval2, /* Third Hessian eigenvalue of cp1: [1] */ + tenGageCp1HessianEvec, /* Hessian eigenvectors of cp1: [9] */ + tenGageCp1HessianEvec0, /* First Hessian eigenvector of cp1: [3] */ + tenGageCp1HessianEvec1, /* Second Hessian eigenvector of cp1: [3] */ + tenGageCp1HessianEvec2, /* Third Hessian eigenvector of cp1: [3] */ + tenGageCa1Hessian, /* Hessian of cp1: [9] */ + tenGageCa1HessianEval, /* Hessian eigenvalues of cp1: [3] */ + tenGageCa1HessianEval0, /* First Hessian eigenvalue of cp1: [1] */ + tenGageCa1HessianEval1, /* Second Hessian eigenvalue of cp1: [1] */ + tenGageCa1HessianEval2, /* Third Hessian eigenvalue of cp1: [1] */ + tenGageCa1HessianEvec, /* Hessian eigenvectors of cp1: [9] */ + tenGageCa1HessianEvec0, /* First Hessian eigenvector of cp1: [3] */ + tenGageCa1HessianEvec1, /* Second Hessian eigenvector of cp1: [3] */ + tenGageCa1HessianEvec2, /* Third Hessian eigenvector of cp1: [3] */ tenGageAniso, }; @@ -815,12 +907,42 @@ "cl1gv", "cl1gm", + "cl1gn", "cp1gv", "cp1gm", + "cp1gn", "ca1gv", "ca1gm", + "ca1gn", "tgrote", - + "evalhess", + "cl1hess", + "cl1hesseval", + "cl1hesseval1", + "cl1hesseval2", + "cl1hesseval3", + "cl1hessevec", + "cl1hessevec1", + "cl1hessevec2", + "cl1hessevec3", + "cp1hess", + "cp1hesseval", + "cp1hesseval1", + "cp1hesseval2", + "cp1hesseval3", + "cp1hessevec", + "cp1hessevec1", + "cp1hessevec2", + "cp1hessevec3", + "ca1hess", + "ca1hesseval", + "ca1hesseval1", + "ca1hesseval2", + "ca1hesseval3", + "ca1hessevec", + "ca1hessevec1", + "ca1hessevec2", + "ca1hessevec3", "an", "aniso", "anisotropies", "" }; @@ -987,15 +1109,45 @@ tenGageTensorLogEuclidean, tenGageTensorLogEuclidean, tenGageTensorQuatGeoLoxK, tenGageTensorQuatGeoLoxK, tenGageTensorQuatGeoLoxR, tenGageTensorQuatGeoLoxR, - + tenGageCl1GradVec, tenGageCl1GradMag, + tenGageCl1Normal, tenGageCp1GradVec, tenGageCp1GradMag, + tenGageCp1Normal, tenGageCa1GradVec, tenGageCa1GradMag, + tenGageCa1Normal, tenGageTensorGradRotE, - + tenGageEvalHessian, + tenGageCl1Hessian, + tenGageCl1HessianEval, + tenGageCl1HessianEval0, + tenGageCl1HessianEval1, + tenGageCl1HessianEval2, + tenGageCl1HessianEvec, + tenGageCl1HessianEvec0, + tenGageCl1HessianEvec1, + tenGageCl1HessianEvec2, + tenGageCp1Hessian, + tenGageCp1HessianEval, + tenGageCp1HessianEval0, + tenGageCp1HessianEval1, + tenGageCp1HessianEval2, + tenGageCp1HessianEvec, + tenGageCp1HessianEvec0, + tenGageCp1HessianEvec1, + tenGageCp1HessianEvec2, + tenGageCa1Hessian, + tenGageCa1HessianEval, + tenGageCa1HessianEval0, + tenGageCa1HessianEval1, + tenGageCa1HessianEval2, + tenGageCa1HessianEvec, + tenGageCa1HessianEvec0, + tenGageCa1HessianEvec1, + tenGageCa1HessianEvec2, tenGageAniso, tenGageAniso, tenGageAniso }; Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-11-03 20:26:11 UTC (rev 4351) +++ teem/trunk/src/ten/ten.h 2009-11-04 03:29:26 UTC (rev 4352) @@ -438,19 +438,50 @@ tenGageCl1GradVec, /* 152: "cl1gv" gradient vector of cl1: [3] */ tenGageCl1GradMag, /* 153: "cl1gm" gradient magnitude of cl1: [1] */ - tenGageCp1GradVec, /* 154: "cp1gv" gradient vector of cp1: [3] */ - tenGageCp1GradMag, /* 155: "cp1gm" gradient magnitude of cp1: [1] */ - tenGageCa1GradVec, /* 156: "ca1gv" gradient vector of ca1: [3] */ - tenGageCa1GradMag, /* 157: "ca1gm" gradient magnitude of ca1: [1] */ - tenGageTensorGradRotE, /* 158: "tgrote" all tensor component gradients, + tenGageCl1Normal, /* 154: "cl1gn" normal of cl1: [3] */ + tenGageCp1GradVec, /* 155: "cp1gv" gradient vector of cp1: [3] */ + tenGageCp1GradMag, /* 156: "cp1gm" gradient magnitude of cp1: [1] */ + tenGageCp1Normal, /* 157: "cl1gn" normal of cp1: [3] */ + tenGageCa1GradVec, /* 158: "ca1gv" gradient vector of ca1: [3] */ + tenGageCa1GradMag, /* 159: "ca1gm" gradient magnitude of ca1: [1] */ + tenGageCa1Normal, /* 160: "cl1gn" normal of ca1: [3] */ + tenGageTensorGradRotE, /* 161: "tgrote" all tensor component gradients, starting with confidence gradient. Rotated such that eigenvalue derivatives are on the diagonal: [21] */ + tenGageEvalHessian, /* 162: "evalhess" Hessian of the eigenvalues: [27] */ + tenGageCl1Hessian, /* 163: "cl1hess" Hessian of cl1: [9] */ + tenGageCl1HessianEval, /* 164: "cl1hesseval" Hessian evals of cl1: [3] */ + tenGageCl1HessianEval0,/* 165: "cl1hesseval1" First Hess eval of cl1: [1] */ + tenGageCl1HessianEval1,/* 166: "cl1hesseval2" Second Hess eval of cl1: [1] */ + tenGageCl1HessianEval2,/* 167: "cl1hesseval3" Third Hess eval of cl1: [1] */ + tenGageCl1HessianEvec, /* 168: "cl1hessevec" Hessian evecs of cl1: [9] */ + tenGageCl1HessianEvec0,/* 169: "cl1hessevec1" First Hess evec of cl1: [3] */ + tenGageCl1HessianEvec1,/* 170: "cl1hessevec2" Second Hess evec of cl1: [3] */ + tenGageCl1HessianEvec2,/* 171: "cl1hessevec3" Third Hess evec of cl1: [3] */ + tenGageCp1Hessian, /* 172: "cp1hess" Hessian of cp1: [9] */ + tenGageCp1HessianEval, /* 173: "cp1hesseval" Hessian evals of cp1: [3] */ + tenGageCp1HessianEval0,/* 174: "cp1hesseval1" First Hess eval of cp1: [1] */ + tenGageCp1HessianEval1,/* 175: "cp1hesseval2" Second Hess eval of cp1: [1] */ + tenGageCp1HessianEval2,/* 176: "cp1hesseval3" Third Hess eval of cp1: [1] */ + tenGageCp1HessianEvec, /* 177: "cp1hessevec" Hessian evecs of cp1: [9] */ + tenGageCp1HessianEvec0,/* 178: "cp1hessevec1" First Hess evec of cp1: [3] */ + tenGageCp1HessianEvec1,/* 179: "cp1hessevec2" Second Hess evec of cp1: [3] */ + tenGageCp1HessianEvec2,/* 180: "cp1hessevec3" Third Hess evec of cp1: [3] */ + tenGageCa1Hessian, /* 181: "ca1hess" Hessian of ca1: [9] */ + tenGageCa1HessianEval, /* 182: "ca1hesseval" Hessian evals of ca1: [3] */ + tenGageCa1HessianEval0,/* 183: "ca1hesseval1" First Hess eval of ca1: [1] */ + tenGageCa1HessianEval1,/* 184: "ca1hesseval2" Second Hess eval of ca1: [1] */ + tenGageCa1HessianEval2,/* 185: "ca1hesseval3" Third Hess eval of ca1: [1] */ + tenGageCa1HessianEvec, /* 186: "ca1hessevec" Hessian evecs of ca1: [9] */ + tenGageCa1HessianEvec0,/* 187: "ca1hessevec1" First Hess evec of ca1: [3] */ + tenGageCa1HessianEvec1,/* 188: "ca1hessevec2" Second Hess evec of ca1: [3] */ + tenGageCa1HessianEvec2,/* 189: "ca1hessevec3" Third Hess evec of ca1: [3] */ - tenGageAniso, /* 159: "an", all anisos: [TEN_ANISO_MAX+1] */ + tenGageAniso, /* 190: "an", all anisos: [TEN_ANISO_MAX+1] */ tenGageLast }; -#define TEN_GAGE_ITEM_MAX 159 +#define TEN_GAGE_ITEM_MAX 190 /* ******** tenDwiGage* enum Modified: teem/trunk/src/ten/tenGage.c =================================================================== --- teem/trunk/src/ten/tenGage.c 2009-11-03 20:26:11 UTC (rev 4351) +++ teem/trunk/src/ten/tenGage.c 2009-11-04 03:29:26 UTC (rev 4352) @@ -228,16 +228,45 @@ {tenGageTensorLogEuclidean, 7, 0, {0}, 0, 0, AIR_FALSE}, {tenGageTensorQuatGeoLoxK, 7, 0, {0}, 0, 0, AIR_FALSE}, {tenGageTensorQuatGeoLoxR, 7, 0, {0}, 0, 0, AIR_FALSE}, - - {tenGageCl1GradVec, 3, 1, {tenGageTrace, tenGageEval, tenGageEvalGrads}, 0, 0, AIR_FALSE}, {tenGageCl1GradMag, 1, 1, {tenGageCl1GradVec}, 0, 0, AIR_FALSE}, + {tenGageCl1Normal, 3, 1, {tenGageCl1GradVec, tenGageCl1GradMag}, 0, 0, AIR_FALSE}, {tenGageCp1GradVec, 3, 1, {tenGageTrace, tenGageEval, tenGageEvalGrads}, 0, 0, AIR_FALSE}, {tenGageCp1GradMag, 1, 1, {tenGageCp1GradVec}, 0, 0, AIR_FALSE}, + {tenGageCp1Normal, 3, 1, {tenGageCp1GradVec, tenGageCp1GradMag}, 0, 0, AIR_FALSE}, {tenGageCa1GradVec, 3, 1, {tenGageTrace, tenGageEval, tenGageEvalGrads}, 0, 0, AIR_FALSE}, {tenGageCa1GradMag, 1, 1, {tenGageCa1GradVec}, 0, 0, AIR_FALSE}, + {tenGageCa1Normal, 3, 1, {tenGageCa1GradVec, tenGageCa1GradMag}, 0, 0, AIR_FALSE}, {tenGageTensorGradRotE, 21, 1, {tenGageTensorGrad, tenGageEval, tenGageEvec}, 0, 0, AIR_FALSE}, - {tenGageAniso, TEN_ANISO_MAX+1, 0, {tenGageEval0, tenGageEval1, tenGageEval2}, 0, 0, AIR_FALSE}, + {tenGageEvalHessian, 27, 2, {tenGageTensorGradRotE, tenGageHessian, tenGageEval}, 0, 0, AIR_FALSE }, + {tenGageCl1Hessian, 9, 2, {tenGageTensorGradRotE, tenGageEvalHessian}, 0, 0, AIR_FALSE }, + {tenGageCl1HessianEval, 3, 2, {tenGageCl1Hessian}, 0, 0, AIR_FALSE }, + {tenGageCl1HessianEval0, 1, 2, {tenGageCl1HessianEval}, tenGageCl1HessianEval, 0, AIR_FALSE}, + {tenGageCl1HessianEval1, 1, 2, {tenGageCl1HessianEval}, tenGageCl1HessianEval, 1, AIR_FALSE}, + {tenGageCl1HessianEval2, 1, 2, {tenGageCl1HessianEval}, tenGageCl1HessianEval, 2, AIR_FALSE}, + {tenGageCl1HessianEvec, 9, 2, {tenGageCl1Hessian}, 0, 0, AIR_FALSE }, + {tenGageCl1HessianEvec0, 3, 2, {tenGageCl1HessianEvec}, tenGageCl1HessianEvec, 0, AIR_FALSE}, + {tenGageCl1HessianEvec1, 3, 2, {tenGageCl1HessianEvec}, tenGageCl1HessianEvec, 3, AIR_FALSE}, + {tenGageCl1HessianEvec2, 3, 2, {tenGageCl1HessianEvec}, tenGageCl1HessianEvec, 6, AIR_FALSE}, + {tenGageCp1Hessian, 9, 2, {tenGageTensorGradRotE, tenGageEvalHessian}, 0, 0, AIR_FALSE }, + {tenGageCp1HessianEval, 3, 2, {tenGageCp1Hessian}, 0, 0, AIR_FALSE }, + {tenGageCp1HessianEval0, 1, 2, {tenGageCp1HessianEval}, tenGageCp1HessianEval, 0, AIR_FALSE}, + {tenGageCp1HessianEval1, 1, 2, {tenGageCp1HessianEval}, tenGageCp1HessianEval, 1, AIR_FALSE}, + {tenGageCp1HessianEval2, 1, 2, {tenGageCp1HessianEval}, tenGageCp1HessianEval, 2, AIR_FALSE}, + {tenGageCp1HessianEvec, 9, 2, {tenGageCp1Hessian}, 0, 0, AIR_FALSE }, + {tenGageCp1HessianEvec0, 3, 2, {tenGageCp1HessianEvec}, tenGageCp1HessianEvec, 0, AIR_FALSE}, + {tenGageCp1HessianEvec1, 3, 2, {tenGageCp1HessianEvec}, tenGageCp1HessianEvec, 3, AIR_FALSE}, + {tenGageCp1HessianEvec2, 3, 2, {tenGageCp1HessianEvec}, tenGageCp1HessianEvec, 6, AIR_FALSE}, + {tenGageCa1Hessian, 9, 2, {tenGageTensorGradRotE, tenGageEvalHessian}, 0, 0, AIR_FALSE }, + {tenGageCa1HessianEval, 3, 2, {tenGageCa1Hessian}, 0, 0, AIR_FALSE }, + {tenGageCa1HessianEval0, 1, 2, {tenGageCa1HessianEval}, tenGageCa1HessianEval, 0, AIR_FALSE}, + {tenGageCa1HessianEval1, 1, 2, {tenGageCa1HessianEval}, tenGageCa1HessianEval, 1, AIR_FALSE}, + {tenGageCa1HessianEval2, 1, 2, {tenGageCa1HessianEval}, tenGageCa1HessianEval, 2, AIR_FALSE}, + {tenGageCa1HessianEvec, 9, 2, {tenGageCa1Hessian}, 0, 0, AIR_FALSE }, + {tenGageCa1HessianEvec0, 3, 2, {tenGageCa1HessianEvec}, tenGageCa1HessianEvec, 0, AIR_FALSE}, + {tenGageCa1HessianEvec1, 3, 2, {tenGageCa1HessianEvec}, tenGageCa1HessianEvec, 3, AIR_FALSE}, + {tenGageCa1HessianEvec2, 3, 2, {tenGageCa1HessianEvec}, tenGageCa1HessianEvec, 6, AIR_FALSE}, + {tenGageAniso, TEN_ANISO_MAX+1, 0, {tenGageEval0, tenGageEval1, tenGageEval2}, 0, 0, AIR_FALSE} }; void @@ -998,16 +1027,12 @@ ELL_3M_SCALE(matTmp, 3.0/2, matTmp); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageFAHessianEvec)) { - /* HEY: cut-and-paste from tenGageEvec, with minimal changes */ - double fakeTen[7]; - TEN_M2T(fakeTen, pvl->directAnswer[tenGageFAHessian]); - tenEigensolve_d(pvl->directAnswer[tenGageFAHessianEval], - pvl->directAnswer[tenGageFAHessianEvec], fakeTen); + ell_3m_eigensolve_d(pvl->directAnswer[tenGageFAHessianEval], + pvl->directAnswer[tenGageFAHessianEvec], + pvl->directAnswer[tenGageFAHessian], AIR_TRUE); } else if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageFAHessianEval)) { - double fakeTen[7]; - TEN_M2T(fakeTen, pvl->directAnswer[tenGageFAHessian]); - /* else eigenvectors are NOT needed, but eigenvalues ARE needed */ - tenEigensolve_d(pvl->directAnswer[tenGageFAHessianEval], NULL, fakeTen); + ell_3m_eigenvalues_d(pvl->directAnswer[tenGageFAHessianEval], + pvl->directAnswer[tenGageFAHessian], AIR_TRUE); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageFARidgeSurfaceStrength)) { double ev; @@ -1170,16 +1195,12 @@ ELL_3M_SCALE(matTmp, tmp0, matTmp); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageModeHessianEvec)) { - /* HEY: cut-and-paste from tenGageFAHessianEvec */ - double fakeTen[7]; - TEN_M2T(fakeTen, pvl->directAnswer[tenGageModeHessian]); - tenEigensolve_d(pvl->directAnswer[tenGageModeHessianEval], - pvl->directAnswer[tenGageModeHessianEvec], fakeTen); + ell_3m_eigensolve_d(pvl->directAnswer[tenGageModeHessianEval], + pvl->directAnswer[tenGageModeHessianEvec], + pvl->directAnswer[tenGageModeHessian], AIR_TRUE); } else if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageModeHessianEval)) { - double fakeTen[7]; - TEN_M2T(fakeTen, pvl->directAnswer[tenGageModeHessian]); - /* else eigenvectors are NOT needed, but eigenvalues ARE needed */ - tenEigensolve_d(pvl->directAnswer[tenGageModeHessianEval], NULL, fakeTen); + ell_3m_eigenvalues_d(pvl->directAnswer[tenGageModeHessianEval], + pvl->directAnswer[tenGageModeHessian], AIR_TRUE); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageOmegaHessian)) { @@ -1198,16 +1219,12 @@ ELL_3MV_SCALE_OUTER_INCR(matTmp, 0.5, faGrad, modeGrad); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageOmegaHessianEvec)) { - /* HEY: cut-and-paste from tenGageFAHessianEvec */ - double fakeTen[7]; - TEN_M2T(fakeTen, pvl->directAnswer[tenGageOmegaHessian]); - tenEigensolve_d(pvl->directAnswer[tenGageOmegaHessianEval], - pvl->directAnswer[tenGageOmegaHessianEvec], fakeTen); + ell_3m_eigensolve_d(pvl->directAnswer[tenGageOmegaHessianEval], + pvl->directAnswer[tenGageOmegaHessianEvec], + pvl->directAnswer[tenGageOmegaHessian], AIR_TRUE); } else if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageOmegaHessianEval)) { - double fakeTen[7]; - TEN_M2T(fakeTen, pvl->directAnswer[tenGageOmegaHessian]); - /* else eigenvectors are NOT needed, but eigenvalues ARE needed */ - tenEigensolve_d(pvl->directAnswer[tenGageOmegaHessianEval], NULL, fakeTen); + ell_3m_eigenvalues_d(pvl->directAnswer[tenGageOmegaHessianEval], + pvl->directAnswer[tenGageOmegaHessian], AIR_TRUE); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageOmegaLaplacian)) { double *hess; @@ -1465,8 +1482,12 @@ /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0])); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCl1GradMag)) { - pvl->directAnswer[tenGageCl1GradMag][0] = ELL_3V_LEN(vecTmp); + magTmp = pvl->directAnswer[tenGageCl1GradMag][0] = ELL_3V_LEN(vecTmp); } + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCl1Normal)) { + ELL_3V_SCALE(pvl->directAnswer[tenGageCl1Normal], + magTmp ? 1/magTmp : 0, vecTmp); + } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCp1GradVec)) { vecTmp = pvl->directAnswer[tenGageCp1GradVec]; @@ -1486,8 +1507,12 @@ /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0])); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCp1GradMag)) { - pvl->directAnswer[tenGageCp1GradMag][0] = ELL_3V_LEN(vecTmp); + magTmp = pvl->directAnswer[tenGageCp1GradMag][0] = ELL_3V_LEN(vecTmp); } + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCp1Normal)) { + ELL_3V_SCALE(pvl->directAnswer[tenGageCp1Normal], + magTmp ? 1/magTmp : 0, vecTmp); + } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCa1GradVec)) { vecTmp = pvl->directAnswer[tenGageCa1GradVec]; @@ -1504,8 +1529,12 @@ /(pvl->directAnswer[tenGageTrace][0]*pvl->directAnswer[tenGageTrace][0])); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCa1GradMag)) { - pvl->directAnswer[tenGageCa1GradMag][0] = ELL_3V_LEN(vecTmp); + magTmp = pvl->directAnswer[tenGageCa1GradMag][0] = ELL_3V_LEN(vecTmp); } + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCa1Normal)) { + ELL_3V_SCALE(pvl->directAnswer[tenGageCa1Normal], + magTmp ? 1/magTmp : 0, vecTmp); + } /* --- tensor gradient, rotated into eigenframe of the tensor itself --- */ if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensorGradRotE)) { @@ -1680,6 +1709,240 @@ } } + /* --- Eigenvalue Hessians: rotate partial second derivatives into + * eigenframe and take into account correction factor based on + * eigenvector derivatives --- */ + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageEvalHessian)) { + /* some aliases for convenience: */ + double *thess = pvl->directAnswer[tenGageHessian]; + double *evhess = pvl->directAnswer[tenGageEvalHessian]; + double *tgradE = pvl->directAnswer[tenGageTensorGradRotE]; + int dira, dirb; /* directions of first/second partial derivative */ + int k; /* number of the eigenvalue */ + double evecsT[9], tmp[9]; + /* HEY: some copy-paste from tenGageEvalGrads */ + double eps=0.05; /* treshold for handling degeneracies */ + double rel1, rel2, rel3, w1, w2; + /* interpolation weights from relative eigenvalue distance */ + rel1=evalAns[0]*evalAns[0]+evalAns[1]*evalAns[1]; + if (rel1>1e-10) + rel1=(evalAns[0]-evalAns[1])*(evalAns[0]-evalAns[1])/rel1; + rel2=evalAns[0]*evalAns[0]+evalAns[2]*evalAns[2]; + if (rel2>1e-10) + rel2=(evalAns[0]-evalAns[2])*(evalAns[0]-evalAns[2])/rel2; + rel3=evalAns[1]*evalAns[1]+evalAns[2]*evalAns[2]; + if (rel3>1e-10) + rel3=(evalAns[1]-evalAns[2])*(evalAns[1]-evalAns[2])/rel3; + w1=rel1/eps-1; + w1*=w1; + w2=rel2/eps-1; + w2*=w2; + + ELL_3M_TRANSPOSE(evecsT,evecAns); + for (dira=0; dira<3; dira++) { + for (dirb=0; dirb<=dira; dirb++) { /* exploit symmetry of Hessian */ + double rdiff1,rdiff2; + double l1res, l2res, l3res; + /* collect second partial derivatives in dira,dirb */ + double H[9]; + ELL_3V_SET(H, thess[9+3*dirb+dira], thess[18+3*dirb+dira], + thess[27+3*dirb+dira]); + ELL_3V_SET(H+3, thess[18+3*dirb+dira], thess[36+3*dirb+dira], + thess[45+3*dirb+dira]); + ELL_3V_SET(H+6, thess[27+3*dirb+dira], thess[45+3*dirb+dira], + thess[54+3*dirb+dira]); + /* rotate into eigenframe of value */ + ell_3m_mul_d(tmp,H,evecsT); + ell_3m_mul_d(H,evecAns,tmp); + + /* we have to divide by rdiff=lambda_1-lambda_2; the following + * is a heuristic to avoid numerical problems in case rdiff is + * near zero */ + if (rel1>eps) rdiff1=1.0/(evalAns[0]-evalAns[1]); + else if (rel1>1e-10) rdiff1=(rel1/eps)/(evalAns[0]-evalAns[1]); + else rdiff1=0; + + if (rel2>eps) rdiff2=1.0/(evalAns[0]-evalAns[2]); + else if (rel2>1e-10) rdiff2=(rel2/eps)/(evalAns[0]-evalAns[2]); + else rdiff2=0; + + l1res=H[0]+2*(tgradE[6+dira]*tgradE[6+dirb]*rdiff1+ + tgradE[9+dira]*tgradE[9+dirb]*rdiff2); + + if (rel1>eps) rdiff1=1.0/(evalAns[1]-evalAns[0]); + else if (rel1>1e-10) rdiff1=(rel1/eps)/(evalAns[1]-evalAns[0]); + else rdiff1=0; + + if (rel3>eps) rdiff2=1.0/(evalAns[1]-evalAns[2]); + else if (rel3>1e-10) rdiff2=(rel3/eps)/(evalAns[1]-evalAns[2]); + else rdiff2=0; + l2res=H[4]+2*(tgradE[6+dira]*tgradE[6+dirb]*rdiff1+ + tgradE[15+dira]*tgradE[15+dirb]*rdiff2); + + if (rel2>eps) rdiff1=1.0/(evalAns[2]-evalAns[0]); + else if (rel2>1e-10) rdiff1=(rel2/eps)/(evalAns[2]-evalAns[0]); + else rdiff1=0; + + if (rel3>eps) rdiff2=1.0/(evalAns[2]-evalAns[1]); + else if (rel3>1e-10) rdiff2=(rel3/eps)/(evalAns[2]-evalAns[1]); + else rdiff2=0; + + l3res=H[8]+2*(tgradE[9+dira]*tgradE[9+dirb]*rdiff1+ + tgradE[15+dira]*tgradE[15+dirb]*rdiff2); + + if (rel1>eps) + evhess[3*dirb+dira]=l1res; + else { + if (rel2>eps) + evhess[3*dirb+dira]=(1-0.5*w1)*l1res+0.5*w1*l2res; + else + evhess[3*dirb+dira]=(1-0.5*w1-w1*w2/6.0)*l1res+ + (0.5*w1-w1*w2/6.0)*l2res+ + w1*w2/3.0*l3res; + } + + if (rel2>eps) + evhess[18+3*dirb+dira]=l3res; + else { + if (rel1>eps) + evhess[18+3*dirb+dira]=(1-0.5*w2)*l3res+0.5*w2*l2res; + else + evhess[18+3*dirb+dira]=(1-0.5*w2-w1*w2/6.0)*l3res+ + (0.5*w2-w1*w2/6.0)*l2res+ + w1*w2/3.0*l1res; + } + evhess[9+3*dirb+dira]=l1res+l2res+l3res - evhess[3*dirb+dira] - + evhess[18+3*dirb+dira]; + } + } + for (dira=0; dira<2; dira++) { + for (dirb=dira+1; dirb<3; dirb++) { /* copy over symmetric values */ + for (k=0; k<3; k++) { + evhess[9*k+3*dirb+dira]=evhess[9*k+3*dira+dirb]; + } + } + } + } + + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCl1Hessian)) { + int dira, dirb; + double *cl1hess = pvl->directAnswer[tenGageCl1Hessian]; + double *tgradE = pvl->directAnswer[tenGageTensorGradRotE]; + double *evhess = pvl->directAnswer[tenGageEvalHessian]; + /* A and B come out of the quotient rule; cf. appendix of Schultz + * et al., TVCG 2010 for more details */ + double B = (evalAns[0]+evalAns[1]+evalAns[2])* + (evalAns[0]+evalAns[1]+evalAns[2]); + for (dira=0; dira<3; dira++) { + for (dirb=0; dirb<=dira; dirb++) { /* again, exploit Hessian symmetry */ + double A = evalAns[0]*(-2*tgradE[12+dira]-tgradE[18+dira])+ + evalAns[1]*(2*tgradE[3+dira]+tgradE[18+dira])+ + evalAns[2]*(tgradE[3+dira]-tgradE[12+dira]); + double Ad = tgradE[3+dirb]*(-2*tgradE[12+dira]-tgradE[18+dira])+ + evalAns[0]*(-2*evhess[9+3*dirb+dira]-evhess[18+3*dirb+dira])+ + tgradE[12+dirb]*(2*tgradE[3+dira]+tgradE[18+dira])+ + evalAns[1]*(2*evhess[3*dirb+dira]+evhess[18+3*dirb+dira])+ + tgradE[18+dirb]*(tgradE[3+dira]-tgradE[12+dira])+ + evalAns[2]*(evhess[3*dirb+dira]-evhess[9+3*dirb+dira]); + double Bd = 2*(evalAns[0]+evalAns[1]+evalAns[2])* + (tgradE[3+dirb]+tgradE[12+dirb]+tgradE[18+dirb]); + cl1hess[3*dirb+dira]=Ad/B-A/B*Bd/B; + } + } + for (dira=0; dira<2; dira++) { + for (dirb=dira+1; dirb<3; dirb++) { /* copy over symmetric values */ + cl1hess[3*dirb+dira]=cl1hess[3*dira+dirb]; + } + } + } + + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCl1HessianEvec)) { + ell_3m_eigensolve_d(pvl->directAnswer[tenGageCl1HessianEval], + pvl->directAnswer[tenGageCl1HessianEvec], + pvl->directAnswer[tenGageCl1Hessian], AIR_TRUE); + } else if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCl1HessianEval)) { + ell_3m_eigenvalues_d(pvl->directAnswer[tenGageCl1HessianEval], + pvl->directAnswer[tenGageCl1Hessian], AIR_TRUE); + } + + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCp1Hessian)) { + int dira, dirb; + double *cp1hess = pvl->directAnswer[tenGageCp1Hessian]; + double *tgradE = pvl->directAnswer[tenGageTensorGradRotE]; + double *evhess = pvl->directAnswer[tenGageEvalHessian]; + double B = (evalAns[0]+evalAns[1]+evalAns[2])* + (evalAns[0]+evalAns[1]+evalAns[2]); + for (dira=0; dira<3; dira++) { + for (dirb=0; dirb<=dira; dirb++) { /* again, exploit Hessian symmetry */ + double A = 2*(evalAns[0]*(tgradE[12+dira]-tgradE[18+dira])+ + evalAns[1]*(-tgradE[3+dira]-2*tgradE[18+dira])+ + evalAns[2]*(tgradE[3+dira]+2*tgradE[12+dira])); + double Ad=2*(evalAns[0]*(evhess[9+3*dirb+dira]-evhess[18+3*dirb+dira])+ + evalAns[1]*(-evhess[3*dirb+dira]-2*evhess[18+3*dirb+dira])+ + evalAns[2]*(evhess[3*dirb+dira]+2*evhess[9+3*dirb+dira])+ + tgradE[3+dirb]*(tgradE[12+dira]-tgradE[18+dira])+ + tgradE[12+dirb]*(-tgradE[3+dira]-2*tgradE[18+dira])+ + tgradE[18+dirb]*(tgradE[3+dira]+2*tgradE[12+dira])); + double Bd = 2*(evalAns[0]+evalAns[1]+evalAns[2])* + (tgradE[3+dirb]+tgradE[12+dirb]+tgradE[18+dirb]); + cp1hess[3*dirb+dira]=Ad/B-A/B*Bd/B; + } + } + for (dira=0; dira<2; dira++) { + for (dirb=dira+1; dirb<3; dirb++) { /* copy over symmetric values */ + cp1hess[3*dirb+dira]=cp1hess[3*dira+dirb]; + } + } + } + + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCp1HessianEvec)) { + ell_3m_eigensolve_d(pvl->directAnswer[tenGageCp1HessianEval], + pvl->directAnswer[tenGageCp1HessianEvec], + pvl->directAnswer[tenGageCp1Hessian], AIR_TRUE); + } else if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCp1HessianEval)) { + ell_3m_eigenvalues_d(pvl->directAnswer[tenGageCp1HessianEval], + pvl->directAnswer[tenGageCp1Hessian], AIR_TRUE); + } + + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCa1Hessian)) { + int dira, dirb; + double *ca1hess = pvl->directAnswer[tenGageCa1Hessian]; + double *tgradE = pvl->directAnswer[tenGageTensorGradRotE]; + double *evhess = pvl->directAnswer[tenGageEvalHessian]; + double B = (evalAns[0]+evalAns[1]+evalAns[2])* + (evalAns[0]+evalAns[1]+evalAns[2]); + for (dira=0; dira<3; dira++) { + for (dirb=0; dirb<=dira; dirb++) { /* again, exploit Hessian symmetry */ + double A = 3*(evalAns[0]*tgradE[18+dira]+evalAns[1]*tgradE[18+dira]+ + evalAns[2]*(-tgradE[3+dira]-tgradE[12+dira])); + double Ad = 3*(tgradE[3+dirb]*tgradE[18+dira]+ + tgradE[12+dirb]*tgradE[18+dira]+ + tgradE[18+dirb]*(-tgradE[3+dira]-tgradE[12+dira])+ + evalAns[0]*evhess[18+3*dirb+dira]+ + evalAns[1]*evhess[18+3*dirb+dira]+ + evalAns[2]*(-evhess[3*dirb+dira]-evhess[9+3*dirb+dira])); + double Bd = 2*(evalAns[0]+evalAns[1]+evalAns[2])* + (tgradE[3+dirb]+tgradE[12+dirb]+tgradE[18+dirb]); + /* above formulas are true for cs, so flip sign here */ + ca1hess[3*dirb+dira]=-Ad/B+A/B*Bd/B; + } + } + for (dira=0; dira<2; dira++) { + for (dirb=dira+1; dirb<3; dirb++) { /* copy over symmetric values */ + ca1hess[3*dirb+dira]=ca1hess[3*dira+dirb]; + } + } + } + + if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCa1HessianEvec)) { + ell_3m_eigensolve_d(pvl->directAnswer[tenGageCa1HessianEval], + pvl->directAnswer[tenGageCa1HessianEvec], + pvl->directAnswer[tenGageCa1Hessian], AIR_TRUE); + } else if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageCa1HessianEval)) { + ell_3m_eigenvalues_d(pvl->directAnswer[tenGageCa1HessianEval], + pvl->directAnswer[tenGageCa1Hessian], AIR_TRUE); + } + return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-11-13 22:48:41
|
Revision: 4370 http://teem.svn.sourceforge.net/teem/?rev=4370&view=rev Author: kindlmann Date: 2009-11-13 22:48:33 +0000 (Fri, 13 Nov 2009) Log Message: ----------- biff rewrite: _f -> _va and new biffMove_va Modified Paths: -------------- teem/trunk/src/ten/aniso.c teem/trunk/src/ten/bimod.c teem/trunk/src/ten/bvec.c teem/trunk/src/ten/chan.c teem/trunk/src/ten/epireg.c teem/trunk/src/ten/estimate.c teem/trunk/src/ten/fiber.c teem/trunk/src/ten/fiberMethods.c teem/trunk/src/ten/glyph.c teem/trunk/src/ten/grads.c teem/trunk/src/ten/miscTen.c teem/trunk/src/ten/mod.c teem/trunk/src/ten/path.c teem/trunk/src/ten/qglox.c teem/trunk/src/ten/tenDwiGage.c teem/trunk/src/ten/tenModel.c teem/trunk/src/ten/tendEstim.c teem/trunk/src/ten/tendSatin.c teem/trunk/src/ten/tensor.c teem/trunk/src/ten/test/csim.c teem/trunk/src/ten/triple.c Modified: teem/trunk/src/ten/aniso.c =================================================================== --- teem/trunk/src/ten/aniso.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/aniso.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -995,7 +995,7 @@ } if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 2, AIR_CAST(size_t, res), AIR_CAST(size_t, res))) { - biffMovef(TEN, NRRD, "%s: ", me); + biffMove_va(TEN, NRRD, "%s: ", me); return 1; } out = (float *)nout->data; @@ -1058,7 +1058,7 @@ size[2] = sz = nin->axis[3].size; N = sx*sy*sz; if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 3, sx, sy, sz)) { - biffMovef(TEN, NRRD, "%s: trouble", me); + biffMove_va(TEN, NRRD, "%s: trouble", me); return 1; } out = (float *)nout->data; @@ -1101,7 +1101,7 @@ } ELL_3V_SET(map, 1, 2, 3); if (nrrdAxisInfoCopy(nout, nin, map, NRRD_AXIS_INFO_SIZE_BIT)) { - biffMovef(TEN, NRRD, "%s: trouble", me); + biffMove_va(TEN, NRRD, "%s: trouble", me); return 1; } if (nrrdBasicInfoCopy(nout, nin, @@ -1129,7 +1129,7 @@ } if (nwght) { if (nrrdCheck(nwght)) { - biffMovef(TEN, NRRD, "%s: trouble with weighting nrrd", me); + biffMove_va(TEN, NRRD, "%s: trouble with weighting nrrd", me); return 1; } if (nrrdElementNumber(nwght) @@ -1161,7 +1161,7 @@ } if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 2, AIR_CAST(size_t, res), AIR_CAST(size_t, yres))) { - biffMovef(TEN, NRRD, "%s: ", me); + biffMove_va(TEN, NRRD, "%s: ", me); return 1; } out = (float *)nout->data; Modified: teem/trunk/src/ten/bimod.c =================================================================== --- teem/trunk/src/ten/bimod.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/bimod.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -76,7 +76,7 @@ airMopAdd(mop, nhisto, (airMopper)nrrdNuke, airMopOnError); airMopAdd(mop, nhisto, (airMopper)nrrdNix, airMopOnOkay); if (nrrdConvert(nhisto, _nhisto, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: trouble converting histogram to double", me); + biffMove_va(TEN, NRRD, "%s: trouble converting histogram to double", me); airMopError(mop); return 1; } biparm->N = nhisto->axis[0].size; @@ -100,8 +100,8 @@ biparm->histo[i] /= sum; } if (!AIR_EXISTS(medianD)) { - biffMovef(TEN, NRRD, - "%s: got empty histogram? (median calculation failed)", me); + biffMove_va(TEN, NRRD, + "%s: got empty histogram? (median calculation failed)", me); airMopError(mop); return 1; } median = (int)medianD; Modified: teem/trunk/src/ten/bvec.c =================================================================== --- teem/trunk/src/ten/bvec.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/bvec.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -128,7 +128,7 @@ nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, size); size[0] = 3; if (nrrdMaybeAlloc_nva(nout, nrrdTypeDouble, nin->dim, size)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); return 1; } for (ii=1; ii<nin->dim; ii++) { @@ -136,10 +136,10 @@ } map[0] = -1; if (nrrdAxisInfoCopy(nout, nin, map, NRRD_AXIS_INFO_NONE)) { - biffMovef(TEN, NRRD, "%s: couldn't copy axis info", me); + biffMove_va(TEN, NRRD, "%s: couldn't copy axis info", me); return 1; } - + /* process all b vectors */ vecSize = nin->axis[0].size*nrrdTypeSize[nin->type]; vecNum = nrrdElementNumber(nin)/nin->axis[0].size; Modified: teem/trunk/src/ten/chan.c =================================================================== --- teem/trunk/src/ten/chan.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/chan.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -166,7 +166,7 @@ if (nrrdMaybeAlloc_va(ninfo, nrrdTypeDouble, 2, AIR_CAST(size_t, valNum), AIR_CAST(size_t, dwiNum))) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); return 1; } info = (double *)(ninfo->data); @@ -352,10 +352,10 @@ if (nrrdConvert(ngrad, _ngrad, nrrdTypeDouble) || nrrdMaybeAlloc_va(nbmat, nrrdTypeDouble, 2, AIR_CAST(size_t, 6), ngrad->axis[1].size)) { - biffMovef(TEN, NRRD, "%s: trouble", me); + biffMove_va(TEN, NRRD, "%s: trouble", me); airMopError(mop); return 1; } - + DD = ngrad->axis[1].size; G = (double*)(ngrad->data); bmat = (double*)(nbmat->data); @@ -398,19 +398,19 @@ airMopAdd(mop, nbmat=nrrdNew(), (airMopper)nrrdNuke, airMopAlways); if (knownB0) { if (nrrdConvert(nbmat, _nbmat, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: couldn't convert given bmat to doubles", me); + biffMove_va(TEN, NRRD, "%s: couldn't convert given bmat to doubles", me); airMopError(mop); return 1; } } else { airMopAdd(mop, ntmp=nrrdNew(), (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(ntmp, _nbmat, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: couldn't convert given bmat to doubles", me); + biffMove_va(TEN, NRRD, "%s: couldn't convert given bmat to doubles", me); airMopError(mop); return 1; } ELL_2V_SET(padmin, 0, 0); ELL_2V_SET(padmax, 6, _nbmat->axis[1].size-1); if (nrrdPad_nva(nbmat, ntmp, padmin, padmax, nrrdBoundaryPad, -1)) { - biffMovef(TEN, NRRD, "%s: couldn't pad given bmat", me); + biffMove_va(TEN, NRRD, "%s: couldn't pad given bmat", me); airMopError(mop); return 1; } } @@ -423,7 +423,7 @@ bmat += nbmat->axis[0].size; } if (ell_Nm_pseudo_inv(nemat, nbmat)) { - biffMovef(TEN, ELL, "%s: trouble pseudo-inverting B-matrix", me); + biffMove_va(TEN, ELL, "%s: trouble pseudo-inverting B-matrix", me); airMopError(mop); return 1; } airMopOkay(mop); @@ -588,10 +588,10 @@ ndwi = nrrdNew(); airMopAdd(mop, ndwi, (airMopper)nrrdNuke, airMopAlways); if (nrrdJoin(ndwi, (const Nrrd**)_ndwi, dwiLen, 0, AIR_TRUE)) { - biffMovef(TEN, NRRD, "%s: trouble joining inputs", me); + biffMove_va(TEN, NRRD, "%s: trouble joining inputs", me); airMopError(mop); return 1; } - + nrrdAxisInfoCopy(ndwi, _ndwi[0], amap, NRRD_AXIS_INFO_NONE); if (tenEstimateLinear4D(nten, nterrP, nB0P, ndwi, _nbmat, knownB0, thresh, soft, b)) { @@ -668,7 +668,7 @@ mop = airMopNew(); airMopAdd(mop, nbmat=nrrdNew(), (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(nbmat, _nbmat, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: trouble converting to doubles", me); + biffMove_va(TEN, NRRD, "%s: trouble converting to doubles", me); airMopError(mop); return 1; } airMopAdd(mop, nemat=nrrdNew(), (airMopper)nrrdNuke, airMopAlways); @@ -699,8 +699,8 @@ (int)AIR_MIN(1024, range->max - range->min + 1), nrrdTypeFloat); if (E) { - biffMovef(TEN, NRRD, - "%s: trouble histograming to find DW threshold", me); + biffMove_va(TEN, NRRD, + "%s: trouble histograming to find DW threshold", me); airMopError(mop); return 1; } if (_tenFindValley(&thresh, nhist, 0.75, AIR_FALSE)) { @@ -711,7 +711,7 @@ } if (nrrdMaybeAlloc_va(nten, nrrdTypeFloat, 4, AIR_CAST(size_t, 7), sx, sy, sz)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); airMopError(mop); return 1; } if (nterrP) { @@ -875,7 +875,7 @@ mop = airMopNew(); airMopAdd(mop, nbmat=nrrdNew(), (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(nbmat, _nbmat, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: couldn't convert B matrix", me); + biffMove_va(TEN, NRRD, "%s: couldn't convert B matrix", me); return 1; } @@ -897,7 +897,7 @@ } if (nrrdMaybeAlloc_va(ndwi, nrrdTypeFloat, 4, AIR_CAST(size_t, DD), sx, sy, sz)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); return 1; } dwi = (float*)(ndwi->data); @@ -1049,7 +1049,7 @@ sz = nin->axis[3].size; if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 4, AIR_CAST(size_t, 7), sx, sy, sz)) { - biffMovef(TEN, NRRD, "%s: couldn't alloc output", me); + biffMove_va(TEN, NRRD, "%s: couldn't alloc output", me); return 1; } nout->axis[0].label = airStrdup("c,Dxx,Dxy,Dxz,Dyy,Dyz,Dzz"); Modified: teem/trunk/src/ten/epireg.c =================================================================== --- teem/trunk/src/ten/epireg.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/epireg.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -36,12 +36,12 @@ } else { airMopAdd(mop, nout=nrrdNew(), (airMopper)nrrdNuke, airMopAlways); if (nrrdJoin(nout, (const Nrrd**)nmulti, len, 0, AIR_TRUE)) { - biffMovef(TEN, NRRD, "%s: couldn't join %s for output", me, desc); + biffMove_va(TEN, NRRD, "%s: couldn't join %s for output", me, desc); airMopError(mop); return 1; } } if (nrrdSave(fname, nout, NULL)) { - biffMovef(TEN, NRRD, "%s: trouble saving %s to \"%s\"", me, desc, fname); + biffMove_va(TEN, NRRD, "%s: trouble saving %s to \"%s\"", me, desc, fname); airMopError(mop); return 1; } fprintf(stderr, "%s: saved %s to \"%s\"\n", me, desc, fname); @@ -79,12 +79,12 @@ return 1; } if (nrrdCheck(ndwi[ni])) { - biffMovef(TEN, NRRD, - "%s: basic nrrd validity failed on ndwi[%d]", me, ni); + biffMove_va(TEN, NRRD, + "%s: basic nrrd validity failed on ndwi[%d]", me, ni); return 1; } if (!nrrdSameSize(ndwi[0], ndwi[ni], AIR_TRUE)) { - biffMovef(TEN, NRRD, "%s: ndwi[%d] is different from ndwi[0]", me, ni); + biffMove_va(TEN, NRRD, "%s: ndwi[%d] is different from ndwi[0]", me, ni); return 1; } } @@ -132,8 +132,8 @@ fprintf(stderr, "%2u ", (unsigned int)ni); fflush(stderr); } if (nrrdCopy(nblur[ni], ndwi[ni])) { - biffMovef(TEN, NRRD, "%s: trouble copying ndwi[%u]", - me, (unsigned int)ni); + biffMove_va(TEN, NRRD, "%s: trouble copying ndwi[%u]", + me, (unsigned int)ni); return 1; } } @@ -183,8 +183,8 @@ ndwi[ni]->axis[0].min = 0; ndwi[ni]->axis[0].max = sx-1; ndwi[ni]->axis[1].min = 0; ndwi[ni]->axis[1].max = sy-1; if (nrrdSpatialResample(nblur[ni], ndwi[ni], rinfo)) { - biffMovef(TEN, NRRD, "%s: trouble blurring ndwi[%u]", - me, (unsigned int)ni); + biffMove_va(TEN, NRRD, "%s: trouble blurring ndwi[%u]", + me, (unsigned int)ni); airMopError(mop); return 1; } ndwi[ni]->axis[0].min = savemin[0]; ndwi[ni]->axis[0].max = savemax[0]; @@ -227,7 +227,8 @@ ntmp->axis[0].max = max; for (ni=0; ni<ninLen; ni++) { if (nrrdHisto(ntmp, nin[ni], NULL, NULL, bins, nrrdTypeFloat)) { - biffMovef(TEN, NRRD, "%s: problem forming histogram of DWI %d", me, ni); + biffMove_va(TEN, NRRD, + "%s: problem forming histogram of DWI %d", me, ni); airMopError(mop); return 1; } if (!ni) { @@ -236,8 +237,9 @@ E = nrrdArithBinaryOp(nhist, nrrdBinaryOpAdd, nhist, ntmp); } if (E) { - biffMovef(TEN, NRRD, "%s: problem updating histogram sum on DWI %d", - me, ni); + biffMove_va(TEN, NRRD, + "%s: problem updating histogram sum on DWI %d", + me, ni); airMopError(mop); return 1; } } @@ -251,10 +253,10 @@ } */ if (nrrdHistoThresholdOtsu(DWthrP, nhist, expo)) { - biffMovef(TEN, NRRD, "%s: problem finding DWI threshold", me); + biffMove_va(TEN, NRRD, "%s: problem finding DWI threshold", me); airMopError(mop); return 1; } - + airMopOkay(mop); return 0; } @@ -289,8 +291,8 @@ } if (nrrdMaybeAlloc_va(nthresh[ni], nrrdTypeUChar, 3, sx, sy, sz)) { - biffMovef(TEN, NRRD, "%s: trouble allocating threshold %u", - me, (unsigned int)ni); + biffMove_va(TEN, NRRD, "%s: trouble allocating threshold %u", + me, (unsigned int)ni); airMopError(mop); return 1; } thr = (unsigned char *)(nthresh[ni]->data); @@ -358,8 +360,8 @@ || nrrdCCMerge(ncc, ncc, nval, -1, big-1, 0, conny) || nrrdCCRevalue(nthr[ni], ncc, nval)) { if (big) { - biffMovef(TEN, NRRD, - "%s: trouble with 3-D processing nthr[%d]", me, ni); + biffMove_va(TEN, NRRD, + "%s: trouble with 3-D processing nthr[%d]", me, ni); return 1; } else { biffAddf(TEN, "%s: got size 0 for biggest bright CC of nthr[%d]", @@ -377,8 +379,8 @@ || nrrdCCRevalue(nslc, ncc, nval) || nrrdSplice(nthr[ni], nthr[ni], nslc, 2, z) ) { if (big) { - biffMovef(TEN, NRRD, "%s: trouble processing slice %d of nthr[%d]", - me, z, ni); + biffMove_va(TEN, NRRD, "%s: trouble processing slice %d of nthr[%d]", + me, z, ni); return 1; } else { /* biggest bright CC on this slice had size 0 @@ -431,8 +433,8 @@ } if (nrrdMaybeAlloc_va(nmom[ni], nrrdTypeDouble, 2, AIR_CAST(size_t, 5), sz)) { - biffMovef(TEN, NRRD, - "%s: couldn't allocate nmom[%u]", me, (unsigned int)ni); + biffMove_va(TEN, NRRD, + "%s: couldn't allocate nmom[%u]", me, (unsigned int)ni); return 1; } nrrdAxisInfoSet_va(nmom[ni], nrrdAxisInfoLabel, "mx,my,h,s,t", "z"); @@ -523,7 +525,7 @@ AIR_CAST(size_t, sz), AIR_CAST(size_t, ninLen), AIR_CAST(size_t, ninLen))) { - biffMovef(TEN, NRRD, "%s: couldn't allocate transform nrrd", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate transform nrrd", me); return 1; } nrrdAxisInfoSet_va(npxfr, nrrdAxisInfoLabel, @@ -574,7 +576,7 @@ if (nrrdMaybeAlloc_va(nmat[z], nrrdTypeDouble, 2, AIR_CAST(size_t, (1 == order ? 3 : 9)), AIR_CAST(size_t, npairs))) { - biffMovef(TEN, NRRD, "%s: couldn't allocate fitting matrices", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate fitting matrices", me); airMopError(mop); return 1; } airMopAdd(mop, ninv[z]=nrrdNew(), (airMopper)nrrdNuke, airMopAlways); @@ -587,7 +589,7 @@ || nrrdMaybeAlloc_va(nvec, nrrdTypeDouble, 2, AIR_CAST(size_t, 1), AIR_CAST(size_t, npairs))) { - biffMovef(TEN, NRRD, "%s: couldn't allocate HST nrrd", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate HST nrrd", me); airMopError(mop); return 1; } nrrdAxisInfoSet_va(nhst, nrrdAxisInfoLabel, @@ -644,7 +646,7 @@ } } else { if (ell_Nm_pseudo_inv(ninv[z], nmat[z])) { - biffMovef(TEN, ELL, "%s: trouble estimating model (slice %d)", me, z); + biffMove_va(TEN, ELL, "%s: trouble estimating model (slice %d)", me, z); airMopError(mop); return 1; } } @@ -668,9 +670,9 @@ } } if (ell_Nm_mul(nans, ninv[z], nvec)) { - biffMovef(TEN, ELL, - "%s: trouble estimating model (slice %d): Sx, Sy, Sz", - me, z); + biffMove_va(TEN, ELL, + "%s: trouble estimating model (slice %d): Sx, Sy, Sz", + me, z); airMopError(mop); return 1; } ans = (double *)(nans->data); @@ -727,9 +729,9 @@ } } if (ell_Nm_mul(nans, ninv[z], nvec)) { - biffMovef(TEN, ELL, - "%s: trouble estimating model (slice %d): Tx, Ty, Tz", - me, z); + biffMove_va(TEN, ELL, + "%s: trouble estimating model (slice %d): Tx, Ty, Tz", + me, z); airMopError(mop); return 1; } ans = (double *)(nans->data); @@ -776,7 +778,7 @@ || nrrdProject(ntB, ntA, 0, nrrdMeasureSum, nrrdTypeFloat) || nrrdProject(nl2, ntB, 0, nrrdMeasureSum, nrrdTypeFloat) || nrrdArithBinaryOp(ntA, nrrdBinaryOpDivide, nsd, nl2)) { - biffMovef(TEN, NRRD, "%s: trouble doing CC projections", me); + biffMove_va(TEN, NRRD, "%s: trouble doing CC projections", me); airMopError(mop); return 1; } if (verb) { @@ -784,7 +786,7 @@ } if (prog && _tenEpiRegSave("regtmp-messy.txt", ntA, NULL, 0, "segmentation uncertainty")) { - biffMovef(TEN, NRRD, "%s: EpiRegSave failed", me); + biffMove_va(TEN, NRRD, "%s: EpiRegSave failed", me); airMopError(mop); return 1; } /* now ntA stores the per-slice messiness */ @@ -999,7 +1001,7 @@ || nrrdMaybeAlloc_va(nidx, nrrdTypeInt, 2, AIR_CAST(size_t, 2*supp), AIR_CAST(size_t, sy))) { - biffMovef(TEN, NRRD, "%s: trouble allocating buffers", me); + biffMove_va(TEN, NRRD, "%s: trouble allocating buffers", me); airMopError(mop); return 1; } for (ni=0; ni<ninLen; ni++) { @@ -1010,7 +1012,7 @@ || ((!ni) && nrrdSlice(nslcB, ndone[ni], 2, 0)) /* only when 0==ni */ || nrrdAxesSwap(ntmp, nin[ni], 0, 1) || nrrdConvert(nfin, ntmp, nrrdTypeFloat)) { - biffMovef(TEN, NRRD, "%s: trouble prepping at ni=%d", me, ni); + biffMove_va(TEN, NRRD, "%s: trouble prepping at ni=%d", me, ni); airMopError(mop); return 1; } for (zi=0; zi<sz; zi++) { @@ -1020,7 +1022,7 @@ || _tenEpiRegSliceWarp(nslcB, nslcA, nwght, nidx, kern, kparm, hh, ss, tt, cx, cy) || nrrdSplice(ndone[ni], ndone[ni], nslcB, 2, zi)) { - biffMovef(TEN, NRRD, "%s: trouble on slice %d if ni=%d", me, zi, ni); + biffMove_va(TEN, NRRD, "%s: trouble on slice %d if ni=%d", me, zi, ni); /* because the _tenEpiReg calls above don't use biff */ airMopError(mop); return 1; } @@ -1077,10 +1079,10 @@ airMopAdd(mop, nhst = nrrdNew(), (airMopper)nrrdNuke, airMopAlways); airMopAdd(mop, ngrad = nrrdNew(), (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(ngrad, _ngrad, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: trouble converting gradients to doubles", me); + biffMove_va(TEN, NRRD, "%s: trouble converting gradients to doubles", me); airMopError(mop); return 1; } - + /* ------ blur */ if (_tenEpiRegBlur(nbuffA, nin, ninLen, bwX, bwY, verbose)) { biffAddf(TEN, "%s: trouble %s", me, (bwX || bwY) ? "blurring" : "copying"); @@ -1233,10 +1235,10 @@ airMopAdd(mop, ndwigrad, (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(ngrad, _ngrad, nrrdTypeDouble) || nrrdConvert(ndwigrad, _ngrad, nrrdTypeDouble)) { /* HACK applies */ - biffMovef(TEN, NRRD, "%s: trouble converting gradients to doubles", me); + biffMove_va(TEN, NRRD, "%s: trouble converting gradients to doubles", me); airMopError(mop); return 1; } - + nin = (Nrrd **)calloc(ninLen, sizeof(Nrrd*)); ndwi = (Nrrd **)calloc(ninLen, sizeof(Nrrd*)); nout = (Nrrd **)calloc(ninLen, sizeof(Nrrd*)); @@ -1265,8 +1267,8 @@ airMopAdd(mop, ndwiOut[dwiIdx], (airMopper)nrrdNuke, airMopAlways); if (nrrdSlice(ndwi[dwiIdx], _nin, dwiAx, AIR_CAST(unsigned int, ninIdx))) { - biffMovef(TEN, NRRD, "%s: trouble slicing at %d on axis %u", - me, ninIdx, dwiAx); + biffMove_va(TEN, NRRD, "%s: trouble slicing at %d on axis %u", + me, ninIdx, dwiAx); airMopError(mop); return 1; } /* NOTE: this works because dwiIdx <= ninIdx */ @@ -1308,8 +1310,8 @@ nout[ninIdx] = nrrdNew(); airMopAdd(mop, nout[ninIdx], (airMopper)nrrdNuke, airMopAlways); if (nrrdSlice(nout[ninIdx], _nin, dwiAx, ninIdx)) { - biffMovef(TEN, NRRD, "%s: trouble slicing at %d on axis %u", - me, dwiIdx, dwiAx); + biffMove_va(TEN, NRRD, "%s: trouble slicing at %d on axis %u", + me, dwiIdx, dwiAx); airMopError(mop); return 1; } /* @@ -1318,7 +1320,7 @@ } } if (nrrdJoin(_nout, (const Nrrd**)nout, ninLen, dwiAx, AIR_TRUE)) { - biffMovef(TEN, NRRD, "%s: trouble joining output", me); + biffMove_va(TEN, NRRD, "%s: trouble joining output", me); airMopError(mop); return 1; } nrrdAxisInfoCopy(_nout, _nin, NULL, NRRD_AXIS_INFO_NONE); @@ -1332,7 +1334,7 @@ /* note that we're ALWAYS copying the key/value pairs- its just too annoying to have to set nrrdStateKeyValuePairsPropagate in order for the DWI-specific key/value pairs to be set */ - biffMovef(TEN, NRRD, "%s:", me); + biffMove_va(TEN, NRRD, "%s:", me); airMopError(mop); return 1; } Modified: teem/trunk/src/ten/estimate.c =================================================================== --- teem/trunk/src/ten/estimate.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/estimate.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -639,7 +639,7 @@ if (!E) size[1] = tec->dwiNum; if (!E) E |= nrrdMaybeAlloc_nva(tec->nwght, nrrdTypeDouble, 2, size); if (E) { - biffMovef(TEN, NRRD, "%s: couldn't allocate dwi nrrds", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate dwi nrrds", me); return 1; } /* nrrdSave("0-nbmat.txt", tec->nbmat, NULL); */ @@ -738,9 +738,9 @@ if (!tec->simulate) { /* HEY: ignores weights! */ if (ell_Nm_pseudo_inv(tec->nemat, tec->nbmat)) { - biffMovef(TEN, ELL, "%s: trouble pseudo-inverting %ux%u B-matrix", me, - AIR_CAST(unsigned int, tec->nbmat->axis[1].size), - AIR_CAST(unsigned int, tec->nbmat->axis[0].size)); + biffMove_va(TEN, ELL, "%s: trouble pseudo-inverting %ux%u B-matrix", me, + AIR_CAST(unsigned int, tec->nbmat->axis[1].size), + AIR_CAST(unsigned int, tec->nbmat->axis[0].size)); return 1; } } @@ -1053,7 +1053,7 @@ } if (nrrdMaybeAlloc_va(ndwi, outType, 4, AIR_CAST(size_t, tec->allNum), sizeX, sizeY, sizeZ)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate DWI output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate DWI output", me); airMopError(mop); return 1; } NN = sizeX * sizeY * sizeZ; @@ -1093,7 +1093,7 @@ ndwi->axis[0].kind = nrrdKindList; if (nrrdBasicInfoCopy(ndwi, nten, NRRD_BASIC_INFO_ALL ^ NRRD_BASIC_INFO_SPACE)) { - biffMovef(TEN, NRRD, "%s:", me); + biffMove_va(TEN, NRRD, "%s:", me); airMopError(mop); return 1; } if (keyValueSet) { @@ -1221,10 +1221,10 @@ wght[dwiIdx + tec->dwiNum*dwiIdx] = dwi*dwi/sum; } if (ell_Nm_wght_pseudo_inv(tec->nemat, tec->nbmat, tec->nwght)) { - biffMovef(TEN, ELL, "%s(1): trouble wght-pseudo-inverting %ux%u B-matrix", - me, - AIR_CAST(unsigned int, tec->nbmat->axis[1].size), - AIR_CAST(unsigned int, tec->nbmat->axis[0].size)); + biffMove_va(TEN, ELL, + "%s(1): trouble wght-pseudo-inverting %ux%u B-matrix", me, + AIR_CAST(unsigned int, tec->nbmat->axis[1].size), + AIR_CAST(unsigned int, tec->nbmat->axis[0].size)); return 1; } /* @@ -1266,9 +1266,9 @@ nrrdSave("nbmat.txt", tec->nbmat, NULL); nrrdSave("nwght.txt", tec->nwght, NULL); */ - biffMovef(TEN, ELL, "%s(2): trouble w/ %ux%u B-matrix (iter %u)", me, - AIR_CAST(unsigned int, tec->nbmat->axis[1].size), - AIR_CAST(unsigned int, tec->nbmat->axis[0].size), iter); + biffMove_va(TEN, ELL, "%s(2): trouble w/ %ux%u B-matrix (iter %u)", me, + AIR_CAST(unsigned int, tec->nbmat->axis[1].size), + AIR_CAST(unsigned int, tec->nbmat->axis[0].size), iter); return 1; } _tenEstimate1Tensor_LLS(tec); @@ -1856,7 +1856,7 @@ return 1; } if (nrrdCheck(ndwi)) { - biffMovef(TEN, NRRD, "%s: DWI volume not valid", me); + biffMove_va(TEN, NRRD, "%s: DWI volume not valid", me); return 1; } if (!( 4 == ndwi->dim && 7 <= ndwi->axis[0].size )) { @@ -1914,14 +1914,14 @@ if (nrrdMaybeAlloc_va(nten, outType, 4, sizeTen, sizeX, sizeY, sizeZ)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate tensor output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate tensor output", me); airMopError(mop); return 1; } if (nB0P) { *nB0P = nrrdNew(); if (nrrdMaybeAlloc_va(*nB0P, outType, 3, sizeX, sizeY, sizeZ)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate B0 output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate B0 output", me); airMopError(mop); return 1; } airMopAdd(mop, *nB0P, (airMopper)nrrdNuke, airMopOnError); @@ -1942,7 +1942,7 @@ | (nrrdStateKeyValuePairsPropagate ? 0 : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { - biffMovef(TEN, NRRD, "%s: couldn't creatting fitting error output", me); + biffMove_va(TEN, NRRD, "%s: couldn't creatting fitting error output", me); airMopError(mop); return 1; } ELL_3V_SET(axmap, 1, 2, 3); Modified: teem/trunk/src/ten/fiber.c =================================================================== --- teem/trunk/src/ten/fiber.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/fiber.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -739,7 +739,7 @@ AIR_CAST(size_t, 3), AIR_CAST(size_t, (fptsArr[0]->len + fptsArr[1]->len - 1)))) { - biffMovef(TEN, NRRD, "%s: couldn't allocate fiber nrrd", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate fiber nrrd", me); airMopError(mop); return 1; } fiber = (double*)(nfiber->data); @@ -976,7 +976,7 @@ nseed = nrrdNew(); airMopAdd(mop, nseed, AIR_CAST(airMopper, nrrdNuke), airMopAlways); if (nrrdConvert(nseed, _nseed, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: couldn't convert seed list", me); + biffMove_va(TEN, NRRD, "%s: couldn't convert seed list", me); return 1; } seedData = AIR_CAST(const double *, nseed->data); Modified: teem/trunk/src/ten/fiberMethods.c =================================================================== --- teem/trunk/src/ten/fiberMethods.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/fiberMethods.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -127,15 +127,15 @@ if ( !(tfx->gtx = gageContextNew()) || !(tfx->pvl = gagePerVolumeNew(tfx->gtx, vol, kind)) || (gagePerVolumeAttach(tfx->gtx, tfx->pvl)) ) { - biffMovef(TEN, GAGE, "%s: gage trouble", me); + biffMove_va(TEN, GAGE, "%s: gage trouble", me); free(tfx); return NULL; } - + tfx->nin = vol; tfx->ksp = nrrdKernelSpecNew(); if (nrrdKernelSpecParse(tfx->ksp, tenDefFiberKernel)) { - biffMovef(TEN, NRRD, "%s: couldn't parse tenDefFiberKernel \"%s\"", - me, tenDefFiberKernel); + biffMove_va(TEN, NRRD, "%s: couldn't parse tenDefFiberKernel \"%s\"", + me, tenDefFiberKernel); return NULL; } if (tenFiberKernelSet(tfx, tfx->ksp->kernel, tfx->ksp->parm)) { @@ -702,10 +702,10 @@ nrrdKernelSpecSet(tfx->ksp, kern, parm); if (gageKernelSet(tfx->gtx, gageKernel00, tfx->ksp->kernel, tfx->ksp->parm)) { - biffMovef(TEN, GAGE, "%s: problem setting kernel", me); + biffMove_va(TEN, GAGE, "%s: problem setting kernel", me); return 1; } - + return 0; } @@ -784,7 +784,7 @@ } if (gageQuerySet(tfx->gtx, tfx->pvl, tfx->query) || gageUpdate(tfx->gtx)) { - biffMovef(TEN, GAGE, "%s: trouble with gage", me); + biffMove_va(TEN, GAGE, "%s: trouble with gage", me); return 1; } if (tfx->useDwi) { Modified: teem/trunk/src/ten/glyph.c =================================================================== --- teem/trunk/src/ten/glyph.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/glyph.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -235,7 +235,7 @@ } if (!npos) { if (gageShapeSet(shape, nten, tenGageKind->baseDim)) { - biffMovef(TEN, GAGE, "%s: trouble", me); + biffMove_va(TEN, GAGE, "%s: trouble", me); airMopError(mop); return 1; } } Modified: teem/trunk/src/ten/grads.c =================================================================== --- teem/trunk/src/ten/grads.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/grads.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -67,7 +67,7 @@ static const char me[]="tenGradientCheck"; if (nrrdCheck(ngrad)) { - biffMovef(TEN, NRRD, "%s: basic validity check failed", me); + biffMove_va(TEN, NRRD, "%s: basic validity check failed", me); return 1; } if (!( 3 == ngrad->axis[0].size && 2 == ngrad->dim )) { @@ -109,7 +109,7 @@ if (nrrdMaybeAlloc_va(ngrad, nrrdTypeDouble, 2, AIR_CAST(size_t, 3), AIR_CAST(size_t, num))) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); return 1; } airSrandMT(seed); @@ -154,7 +154,7 @@ unsigned int gi, num; if (nrrdConvert(nout, nin, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: trouble converting input to double", me); + biffMove_va(TEN, NRRD, "%s: trouble converting input to double", me); return 1; } if (tenGradientCheck(nout, nrrdTypeDouble, 3)) { @@ -387,10 +387,10 @@ return 1; } if (nrrdConvert(nout, nin, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: can't initialize output with input", me); + biffMove_va(TEN, NRRD, "%s: can't initialize output with input", me); return 1; } - + rstate = airRandMTStateNew(tgparm->seed); lastLen = 1.0; do { @@ -452,10 +452,10 @@ airMopAdd(mop, npos[1], (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(npos[0], nin, nrrdTypeDouble) || nrrdConvert(npos[1], nin, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: trouble allocating temp buffers", me); + biffMove_va(TEN, NRRD, "%s: trouble allocating temp buffers", me); airMopError(mop); return 1; } - + pos = (double*)(npos[0]->data); for (ii=0; ii<num; ii++) { ELL_3V_NORM(pos, pos, len); @@ -596,7 +596,7 @@ } else { fprintf(stderr, "%s: .......................... (no balancing)\n", me); if (nrrdConvert(nout, npos[oldIdx], nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: couldn't set output", me); + biffMove_va(TEN, NRRD, "%s: couldn't set output", me); airMopError(mop); return 1; } } Modified: teem/trunk/src/ten/miscTen.c =================================================================== --- teem/trunk/src/ten/miscTen.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/miscTen.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -55,7 +55,7 @@ if (nrrdMaybeAlloc_nva(nout, (nrrdTypeDefault == rgbp->typeOut ? nin->type : rgbp->typeOut), nin->dim, size)) { - biffMovef(TEN, NRRD, "%s: couldn't alloc output", me); + biffMove_va(TEN, NRRD, "%s: couldn't alloc output", me); return 1; } odataUC = AIR_CAST(unsigned char *, nout->data); @@ -99,7 +99,7 @@ } } if (nrrdAxisInfoCopy(nout, nin, NULL, (NRRD_AXIS_INFO_SIZE_BIT))) { - biffMovef(TEN, NRRD, "%s: couldn't copy axis info", me); + biffMove_va(TEN, NRRD, "%s: couldn't copy axis info", me); return 1; } nout->axis[0].kind = nrrdKind3Color; @@ -181,7 +181,7 @@ sz = nin->axis[3].size; if (nrrdMaybeAlloc_va(nout, nrrdTypeShort, 3, sx, sy, sz)) { - biffMovef(TEN, NRRD, "%s: can't allocate output", me); + biffMove_va(TEN, NRRD, "%s: can't allocate output", me); return 1; } N = sx*sy*sz; @@ -200,7 +200,7 @@ ELL_3V_SET(map, 1, 2, 3); if (nrrdAxisInfoCopy(nout, nin, map, (NRRD_AXIS_INFO_SIZE_BIT | NRRD_AXIS_INFO_KIND_BIT) )) { - biffMovef(TEN, NRRD, "%s: trouble", me); + biffMove_va(TEN, NRRD, "%s: trouble", me); return 1; } if (nrrdBasicInfoCopy(nout, nin, @@ -217,7 +217,7 @@ static const char me[]="tenBMatrixCheck"; if (nrrdCheck(nbmat)) { - biffMovef(TEN, NRRD, "%s: basic validity check failed", me); + biffMove_va(TEN, NRRD, "%s: basic validity check failed", me); return 1; } if (!( 6 == nbmat->axis[0].size && 2 == nbmat->dim )) { @@ -292,7 +292,7 @@ nrrdKernelBCCubicD, dparm, &bins, NULL) || nrrdSimpleResample(nhistDD, ntmpB, nrrdKernelBCCubicDD, dparm, &bins, NULL)) { - biffMovef(TEN, NRRD, "%s: trouble processing histogram", me); + biffMove_va(TEN, NRRD, "%s: trouble processing histogram", me); airMopError(mop); return 1; } if (save) { Modified: teem/trunk/src/ten/mod.c =================================================================== --- teem/trunk/src/ten/mod.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/mod.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -68,7 +68,7 @@ } if (nout != nin) { if (nrrdCopy(nout, nin)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); return 1; } } Modified: teem/trunk/src/ten/path.c =================================================================== --- teem/trunk/src/ten/path.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/path.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -673,7 +673,7 @@ AIR_CAST(size_t, 7), AIR_CAST(size_t, 6), AIR_CAST(size_t, 2*NN + 1))) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); airMopError(mop); return 1; } geod = AIR_CAST(double *, ngeod->data); @@ -707,7 +707,7 @@ if (!E) E |= nrrdResampleRenormalizeSet(rsmc, AIR_TRUE); if (!E) E |= nrrdResampleExecute(rsmc, ntt); if (E) { - biffMovef(TEN, NRRD, "%s: problem upsampling course solution", me); + biffMove_va(TEN, NRRD, "%s: problem upsampling course solution", me); airMopError(mop); return 1; } *numIter += subIter; @@ -806,7 +806,7 @@ if (nrrdMaybeAlloc_va(nout, nrrdTypeDouble, 2, AIR_CAST(size_t, 7), AIR_CAST(size_t, num))) { - biffMovef(TEN, NRRD, "%s: trouble allocating output", me); + biffMove_va(TEN, NRRD, "%s: trouble allocating output", me); airMopError(mop); return 1; } out = AIR_CAST(double *, nout->data); @@ -978,7 +978,7 @@ return 1; } if (!nrrdSameSize(nin[0], nin[ninIdx], AIR_TRUE)) { - biffMovef(TEN, NRRD, "%s: nin[0] doesn't match nin[%u]", me, ninIdx); + biffMove_va(TEN, NRRD, "%s: nin[0] doesn't match nin[%u]", me, ninIdx); return 1; } if (nin[0]->type != nin[ninIdx]->type) { @@ -991,7 +991,7 @@ mop = airMopNew(); if (nrrdCopy(nout, nin[0])) { - biffMovef(TEN, NRRD, "%s: couldn't initialize output", me); + biffMove_va(TEN, NRRD, "%s: couldn't initialize output", me); airMopError(mop); return 1; } if (_tip) { Modified: teem/trunk/src/ten/qglox.c =================================================================== --- teem/trunk/src/ten/qglox.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/qglox.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -528,7 +528,7 @@ /* compute iterated weighted mean, stored in qOut */ if (ell_q_avgN_d(qOut, &qiter, tip->qIn, tip->qBuff, wght, NN, tip->convEps, tip->maxIter)) { - biffMovef(TEN, ELL, "%s: problem doing quaternion mean", me); + biffMove_va(TEN, ELL, "%s: problem doing quaternion mean", me); return 1; } /* Modified: teem/trunk/src/ten/tenDwiGage.c =================================================================== --- teem/trunk/src/ten/tenDwiGage.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/tenDwiGage.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -748,7 +748,7 @@ int E; if (tenDwiGageKindCheck(kind)) { - biffMovef(GAGE, TEN, "%s: kindData not ready for use", me); + biffMove_va(GAGE, TEN, "%s: kindData not ready for use", me); return NULL; } kindData = AIR_CAST(tenDwiGageKindData *, kind->data); @@ -782,7 +782,7 @@ kindData->thresh, kindData->soft); if (!E) E |= tenEstimateUpdate(tec); if (E) { - biffMovef(GAGE, TEN, "%s: trouble setting %u estimation", me, num); + biffMove_va(GAGE, TEN, "%s: trouble setting %u estimation", me, num); return NULL; } } @@ -1092,7 +1092,7 @@ kindData = AIR_CAST(tenDwiGageKindData *, dwiKind->data); if (nrrdConvert(kindData->ngrad, ngrad, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: trouble converting", me); + biffMove_va(TEN, NRRD, "%s: trouble converting", me); return 1; } dwiKind->valLen = kindData->ngrad->axis[1].size; Modified: teem/trunk/src/ten/tenModel.c =================================================================== --- teem/trunk/src/ten/tenModel.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/tenModel.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -188,8 +188,8 @@ ntmp = nrrdNew(); airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(ntmp, _nparm, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: couldn't convert parm to %s", me, - airEnumStr(nrrdType, nrrdTypeDouble)); + biffMove_va(TEN, NRRD, "%s: couldn't convert parm to %s", me, + airEnumStr(nrrdType, nrrdTypeDouble)); airMopError(mop); return 1; } ndparm = ntmp; @@ -208,7 +208,7 @@ max[ax] = ndparm->axis[ax].size-1; } if (nrrdPad_nva(ntmp, ndparm, min, max, nrrdBoundaryBleed, 0.0)) { - biffMovef(TEN, NRRD, "%s: couldn't pad", me); + biffMove_va(TEN, NRRD, "%s: couldn't pad", me); airMopError(mop); return 1; } ndpparm = ntmp; @@ -223,8 +223,8 @@ ntmp = nrrdNew(); airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(ntmp, _nB0, nrrdTypeDouble)) { - biffMovef(TEN, NRRD, "%s: couldn't convert B0 to %s", me, - airEnumStr(nrrdType, nrrdTypeDouble)); + biffMove_va(TEN, NRRD, "%s: couldn't convert B0 to %s", me, + airEnumStr(nrrdType, nrrdTypeDouble)); airMopError(mop); return 1; } nB0 = ntmp; @@ -234,7 +234,7 @@ ntmp = nrrdNew(); airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); if (nrrdSplice(ntmp, ndpparm, nB0, 0, 0)) { - biffMovef(TEN, NRRD, "%s: couldn't splice in B0", me); + biffMove_va(TEN, NRRD, "%s: couldn't splice in B0", me); airMopError(mop); return 1; } nparm = ntmp; @@ -250,7 +250,7 @@ : AIR_CAST(int, ii)); } if (nrrdMaybeAlloc_nva(ndwi, typeOut, nparm->dim, szOut)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); airMopError(mop); return 1; } if (!(ddwi = AIR_CAST(double *, calloc(espec->imgNum, sizeof(double))))) { @@ -291,10 +291,10 @@ | (nrrdStateKeyValuePairsPropagate ? 0 : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { - biffMovef(TEN, NRRD, "%s: couldn't copy axis or basic info", me); + biffMove_va(TEN, NRRD, "%s: couldn't copy axis or basic info", me); airMopError(mop); return 1; } - + airMopOkay(mop); return 0; } @@ -413,7 +413,7 @@ : AIR_CAST(int, ii)); } if (nrrdMaybeAlloc_nva(nparm, typeOut, ndwi->dim, szOut)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); airMopError(mop); return 1; } ddwi = AIR_CAST(double *, calloc(espec->imgNum, sizeof(double))); @@ -470,7 +470,7 @@ | (nrrdStateKeyValuePairsPropagate ? 0 : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { - biffMovef(TEN, NRRD, "%s: couldn't copy axis or basic info", me); + biffMove_va(TEN, NRRD, "%s: couldn't copy axis or basic info", me); airMopError(mop); return 1; } lablen = (strlen(tenModelPrefixStr) @@ -565,10 +565,10 @@ : AIR_CAST(int, ii)); } if (nrrdMaybeAlloc_nva(nparmDst, nparmSrc->type, nparmSrc->dim, szOut)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); airMopError(mop); return 1; } - + NN = nrrdElementNumber(nparmSrc)/nparmSrc->axis[0].size; tsize = nrrdTypeSize[nparmSrc->type]; parmSrc = AIR_CAST(char *, nparmSrc->data); @@ -607,7 +607,7 @@ | (nrrdStateKeyValuePairsPropagate ? 0 : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { - biffMovef(TEN, NRRD, "%s: couldn't copy axis or basic info", me); + biffMove_va(TEN, NRRD, "%s: couldn't copy axis or basic info", me); airMopError(mop); return 1; } /* HEY: COPY AND PASTE! from above. perhaps make helper functions? */ Modified: teem/trunk/src/ten/tendEstim.c =================================================================== --- teem/trunk/src/ten/tendEstim.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/tendEstim.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -99,7 +99,8 @@ ndwi[dwiIdx] = nrrdNew(); airMopAdd(mop, ndwi[dwiIdx], (airMopper)nrrdNuke, airMopAlways); if (nrrdSlice(ndwi[dwiIdx], nin4d, dwiAx, slIdx)) { - biffMovef(TEN, NRRD, "%s: trouble slicing DWI at index %u", me, slIdx); + biffMove_va(TEN, NRRD, + "%s: trouble slicing DWI at index %u", me, slIdx); airMopError(mop); return 1; } } Modified: teem/trunk/src/ten/tendSatin.c =================================================================== --- teem/trunk/src/ten/tendSatin.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/tendSatin.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -135,10 +135,10 @@ AIR_CAST(size_t, 3), size[0], size[1], size[2]) || nrrdMaybeAlloc_va(nevec=nrrdNew(), nrrdTypeFloat, 4, AIR_CAST(size_t, 9), size[0], size[1], size[2])) { - biffMovef(TEN, NRRD, "%s: trouble allocating temp nrrds", me); + biffMove_va(TEN, NRRD, "%s: trouble allocating temp nrrds", me); return 1; } - + conf = (float *)nconf->data; eval = (float *)neval->data; evec = (float *)nevec->data; Modified: teem/trunk/src/ten/tensor.c =================================================================== --- teem/trunk/src/ten/tensor.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/tensor.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -173,7 +173,7 @@ N = sx*sy*sz; if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 4, AIR_CAST(size_t, 9), sx, sy, sz)) { - biffMovef(TEN, NRRD, "%s: trouble", me); + biffMove_va(TEN, NRRD, "%s: trouble", me); return 1; } for (I=0; I<=N-1; I++) { @@ -188,7 +188,7 @@ } if (nrrdAxisInfoCopy(nout, nin, NULL, NRRD_AXIS_INFO_SIZE_BIT)) { - biffMovef(TEN, NRRD, "%s: trouble", me); + biffMove_va(TEN, NRRD, "%s: trouble", me); return 1; } /* by call above we just copied axis-0 kind, which might be wrong; @@ -250,7 +250,7 @@ } if (nrrdMaybeAlloc_va(tseven, nrrdTypeFloat, 4, AIR_CAST(size_t, 7), sx, sy, sz)) { - biffMovef(TEN, NRRD, "%s: trouble allocating output", me); + biffMove_va(TEN, NRRD, "%s: trouble allocating output", me); return 1; } seven = (float *)tseven->data; @@ -265,7 +265,7 @@ } if (nrrdAxisInfoCopy(tseven, tnine, NULL, NRRD_AXIS_INFO_SIZE_BIT)) { - biffMovef(TEN, NRRD, "%s: trouble", me); + biffMove_va(TEN, NRRD, "%s: trouble", me); return 1; } /* by call above we just copied axis-0 kind, which might be wrong; @@ -471,7 +471,7 @@ return 1; } if (nrrdCheck(nconf) || nrrdCheck(neval) || nrrdCheck(nevec)) { - biffMovef(TEN, NRRD, "%s: didn't get three valid nrrds", me); + biffMove_va(TEN, NRRD, "%s: didn't get three valid nrrds", me); return 1; } if (!( 3 == nconf->dim && nrrdTypeFloat == nconf->type )) { @@ -525,7 +525,7 @@ /* finally */ if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 4, AIR_CAST(size_t, 7), sx, sy, sz)) { - biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); + biffMove_va(TEN, NRRD, "%s: couldn't allocate output", me); return 1; } N = sx*sy*sz; @@ -542,7 +542,7 @@ } ELL_4V_SET(map, -1, 0, 1, 2); if (nrrdAxisInfoCopy(nout, nconf, map, NRRD_AXIS_INFO_SIZE_BIT)) { - biffMovef(TEN, NRRD, "%s: trouble", me); + biffMove_va(TEN, NRRD, "%s: trouble", me); return 1; } nout->axis[0].label = (char *)airFree(nout->axis[0].label); @@ -558,10 +558,10 @@ | (nrrdStateKeyValuePairsPropagate ? 0 : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { - biffMovef(TEN, NRRD, "%s:", me); + biffMove_va(TEN, NRRD, "%s:", me); return 1; } - + return 0; } @@ -607,7 +607,7 @@ if (3 == dim) { if (nrrdSlice(nslice, nten, axis+1, pos) || nrrdAxesInsert(nout, nslice, axis+1)) { - biffMovef(TEN, NRRD, "%s: trouble making slice", me); + biffMove_va(TEN, NRRD, "%s: trouble making slice", me); airMopError(mop); return 1; } } else { @@ -636,7 +636,7 @@ || nrrdSlice(ncoeff[2], nslice, 0, ci[2]) || nrrdSlice(ncoeff[3], nslice, 0, ci[3]) || nrrdJoin(nout, (const Nrrd **)ncoeff, 4, 0, AIR_TRUE)) { - biffMovef(TEN, NRRD, "%s: trouble collecting coefficients", me); + biffMove_va(TEN, NRRD, "%s: trouble collecting coefficients", me); airMopError(mop); return 1; } } Modified: teem/trunk/src/ten/test/csim.c =================================================================== --- teem/trunk/src/ten/test/csim.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/test/csim.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -28,7 +28,7 @@ Nrrd *ntbuff, tenEstimateContext *tec, double *dwibuff, double sigma, double bvalue, double B0, unsigned int NN, int randrot, double _tenOrig[7]) { - char me[]="csimDo", err[BIFF_STRLEN]; + char me[]="csimDo"; double *tbuff; unsigned int II, taa, tbb, cc; @@ -37,9 +37,8 @@ && 2 == ntbuff->dim && 7 == ntbuff->axis[0].size && NN == ntbuff->axis[1].size)) { - sprintf(err, "%s: ntbuff not allocated for 2-by-%u array of %s", me, - NN, airEnumStr(nrrdType, nrrdTypeDouble)); - biffAdd(TEN, err); return 1; + biffAddf(TEN, "%s: ntbuff not allocated for 2-by-%u array of %s", me, + NN, airEnumStr(nrrdType, nrrdTypeDouble)); return 1; } /* find all tensors from simulated DWIs */ @@ -77,8 +76,7 @@ if (tenEstimate1TensorSimulateSingle_d(tec, dwibuff, sigma, bvalue, B0, tenOrig) || tenEstimate1TensorSingle_d(tec, tbuff, dwibuff)) { - sprintf(err, "%s: trouble on exp %u/%u", me, II, NN); - biffAdd(TEN, err); return 1; + biffAddf(TEN, "%s: trouble on exp %u/%u", me, II, NN); return 1; } if (randrot) { TEN_T2M(matA, tbuff); Modified: teem/trunk/src/ten/triple.c =================================================================== --- teem/trunk/src/ten/triple.c 2009-11-13 22:42:10 UTC (rev 4369) +++ teem/trunk/src/ten/triple.c 2009-11-13 22:48:33 UTC (rev 4370) @@ -446,10 +446,10 @@ nrrdAxisInfoGet_nva(nten, nrrdAxisInfoSize, size); size[0] = 3; if (nrrdMaybeAlloc_nva(nout, nten->type, nten->dim, size)) { - biffMovef(TEN, NRRD, "%s: couldn't alloc output", me); + biffMove_va(TEN, NRRD, "%s: couldn't alloc output", me); return 1; } - + NN = nrrdElementNumber(nten)/7; lup = nrrdDLookup[nten->type]; ins = nrrdDInsert[nten->type]; @@ -465,7 +465,7 @@ } } if (nrrdAxisInfoCopy(nout, nten, NULL, (NRRD_AXIS_INFO_SIZE_BIT))) { - biffMovef(TEN, NRRD, "%s: couldn't copy axis info", me); + biffMove_va(TEN, NRRD, "%s: couldn't copy axis info", me); return 1; } nout->axis[0].kind = nrrdKindUnknown; @@ -507,7 +507,7 @@ } if (nrrdCopy(nout, nin)) { - biffMovef(TEN, NRRD, "%s: couldn't initialize output", me); + biffMove_va(TEN, NRRD, "%s: couldn't initialize output", me); return 1; } lup = nrrdDLookup[nin->type]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-11-18 21:18:43
|
Revision: 4399 http://teem.svn.sourceforge.net/teem/?rev=4399&view=rev Author: kindlmann Date: 2009-11-18 21:18:36 +0000 (Wed, 18 Nov 2009) Log Message: ----------- added tenEigenvalueMultiply tend evalmult Modified Paths: -------------- teem/trunk/src/ten/GNUmakefile teem/trunk/src/ten/mod.c teem/trunk/src/ten/sources.cmake teem/trunk/src/ten/ten.h Modified: teem/trunk/src/ten/GNUmakefile =================================================================== --- teem/trunk/src/ten/GNUmakefile 2009-11-18 18:02:00 UTC (rev 4398) +++ teem/trunk/src/ten/GNUmakefile 2009-11-18 21:18:36 UTC (rev 4399) @@ -61,7 +61,8 @@ tendFiber.o tendEpireg.o tendBmat.o tendEstim.o tendSim.o \ tendMsim.o tendMfit.o tendMconv.o \ tendSlice.o tendEllipse.o tendEvecrgb.o tendNorm.o tendAnscale.o \ - tendEvalpow.o tendEvalclamp.o tendEvaladd.o tendHelix.o tendBfit.o \ + tendEvalpow.o tendEvalclamp.o tendEvaladd.o tendEvalmult.o \ + tendHelix.o tendBfit.o \ tendUnmf.o tendLog.o tendExp.o $(L).TESTS = test/roistat test/tg test/tt test/tem test/rotedge \ test/tsoid test/odf-hist test/to test/tensorDotDat \ Modified: teem/trunk/src/ten/mod.c =================================================================== --- teem/trunk/src/ten/mod.c 2009-11-18 18:02:00 UTC (rev 4398) +++ teem/trunk/src/ten/mod.c 2009-11-18 21:18:36 UTC (rev 4399) @@ -41,6 +41,7 @@ funcEigenvalueClamp, funcEigenvaluePower, funcEigenvalueAdd, + funcEigenvalueMultiply, funcLog, funcExp, funcLast @@ -190,6 +191,19 @@ tout += 7; } break; + case funcEigenvalueMultiply: + for (II=0; II<=NN-1; II++) { + /* HEY: this doesn't require eigensolve */ + tenEigensolve_f(eval, evec, tin); + ELL_3V_SET_TT(eval, float, + eval[0]*parm->val, + eval[1]*parm->val, + eval[2]*parm->val); + tenMakeSingle_f(tout, tin[0], eval, evec); + tin += 7; + tout += 7; + } + break; case funcLog: for (II=0; II<=NN-1; II++) { tenEigensolve_f(eval, evec, tin); @@ -327,6 +341,24 @@ } /* +******** tenEigenvalueMultiply +** +** multiplies eigenvalues by something +*/ +int +tenEigenvalueMultiply(Nrrd *nout, const Nrrd *nin, double val) { + static const char me[]="tenEigenvalueMultiply"; + funcParm parm; + + parm.val = val; + if (theFunc(nout, nin, funcEigenvalueMultiply, &parm)) { + biffAddf(TEN, "%s: trouble", me); + return 1; + } + return 0; +} + +/* ******** tenLog ** ** takes the logarithm (by taking the log of the eigenvalues) Modified: teem/trunk/src/ten/sources.cmake =================================================================== --- teem/trunk/src/ten/sources.cmake 2009-11-18 18:02:00 UTC (rev 4398) +++ teem/trunk/src/ten/sources.cmake 2009-11-18 21:18:36 UTC (rev 4399) @@ -36,6 +36,7 @@ tendEstim.c tendEval.c tendEvaladd.c + tendEvalmult.c tendEvalclamp.c tendEvalpow.c tendEvec.c Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-11-18 18:02:00 UTC (rev 4398) +++ teem/trunk/src/ten/ten.h 2009-11-18 21:18:36 UTC (rev 4399) @@ -1635,6 +1635,7 @@ TEN_EXPORT int tenEigenvalueClamp(Nrrd *nout, const Nrrd *nin, double min, double max); TEN_EXPORT int tenEigenvalueAdd(Nrrd *nout, const Nrrd *nin, double val); +TEN_EXPORT int tenEigenvalueMultiply(Nrrd *nout, const Nrrd *nin, double val); TEN_EXPORT int tenLog(Nrrd *nout, const Nrrd *nin); TEN_EXPORT int tenExp(Nrrd *nout, const Nrrd *nin); @@ -1705,6 +1706,7 @@ F(evalpow) \ F(evalclamp) \ F(evaladd) \ +F(evalmult) \ F(log) \ F(exp) \ F(evec) \ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <kin...@us...> - 2009-12-12 11:23:44
|
Revision: 4453 http://teem.svn.sourceforge.net/teem/?rev=4453&view=rev Author: kindlmann Date: 2009-12-12 11:23:36 +0000 (Sat, 12 Dec 2009) Log Message: ----------- API NEW: added tenRotateSingle_f for rotating a single tensor Modified Paths: -------------- teem/trunk/src/ten/ten.h teem/trunk/src/ten/tensor.c Modified: teem/trunk/src/ten/ten.h =================================================================== --- teem/trunk/src/ten/ten.h 2009-12-12 11:22:19 UTC (rev 4452) +++ teem/trunk/src/ten/ten.h 2009-12-12 11:23:36 UTC (rev 4453) @@ -1296,6 +1296,8 @@ /* tensor.c */ TEN_EXPORT int tenVerbose; +TEN_EXPORT void tenRotateSingle_f(float tenOut[7], + const float rot[9], const float tenIn[7]); TEN_EXPORT int tenTensorCheck(const Nrrd *nin, int wantType, int want4D, int useBiff); TEN_EXPORT int tenMeasurementFrameReduce(Nrrd *nout, const Nrrd *nin); Modified: teem/trunk/src/ten/tensor.c =================================================================== --- teem/trunk/src/ten/tensor.c 2009-12-12 11:22:19 UTC (rev 4452) +++ teem/trunk/src/ten/tensor.c 2009-12-12 11:23:36 UTC (rev 4453) @@ -26,6 +26,19 @@ int tenVerbose = 0; +void +tenRotateSingle_f(float tenOut[7], const float rot[9], const float tenIn[7]) { + float rotT[9], matIn[9], tmp[9], matOut[9]; + + ELL_3M_TRANSPOSE(rotT, rot); + TEN_T2M(matIn, tenIn); + ELL_3M_MUL(tmp, matIn, rotT); + ELL_3M_MUL(matOut, rot, tmp); + TEN_M2T(tenOut, matOut); + tenOut[0] = tenIn[0]; + return; +} + /* ******** tenTensorCheck() ** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |