/* $Id: shoot_diffeo3d.c 6137 2014-08-19 12:43:11Z john $ */ /* (c) John Ashburner (2011) */ #include #include #include #include "shoot_optim3d.h" #include "shoot_expm3.h" #include "shoot_boundary.h" extern double log(double x); extern double exp(double x); #define LOG(x) (((x)>0) ? log(x+0.001): -6.9078) /* * Lie Bracket * C = [A,B] */ void bracket(mwSize dm[], float *A, float *B, float *C) { float *Ax, *Ay, *Az; float *Bx, *By, *Bz; float *Cx, *Cy, *Cz; mwSize i, j, k, mm = dm[0]*dm[1]*dm[2]; Ax = A; Ay = A + mm; Az = A + mm*2; Bx = B; By = B + mm; Bz = B + mm*2; Cx = C; Cy = C + mm; Cz = C + mm*2; for(k=0; k=0 && s1) { j13 = (y1[i+kp]-y1[i+km])/dm[2]; j13 = 0.5*(j13 - floor(j13+0.5))*dm[2]; j23 = (y2[i+kp]-y2[i+km])/dm[2]; j23 = 0.5*(j23 - floor(j23+0.5))*dm[2]; j33 = (y3[i+kp]-y3[i+km])/dm[2]; j33 = 0.5*(j33 - floor(j33+0.5))*dm[2]; } else { j13 = 0.0; j23 = 0.0; j33 = 1.0; } if (!code) { dp[i] = j11*(j22*j33-j23*j32)+j21*(j13*j32-j12*j33)+j31*(j12*j23-j13*j22); } else { dp[i ] = j11; dp[i+mm ] = j21; dp[i+mm*2] = j31; dp[i+mm*3] = j12; dp[i+mm*4] = j22; dp[i+mm*5] = j32; dp[i+mm*6] = j13; dp[i+mm*7] = j23; dp[i+mm*8] = j33; } } } } } static void def2jac_neuman(mwSize dm[], float *Y, float *J, mwSignedIndex s, int code) { mwSignedIndex k, k0, k2, mm; if (s>=0 && s=0 && x=0 && y=0 && z=-1) && (x=-1) && (y=-1) && (z=0) { tmpz = dm[1]*iz; if (iy>=0) { tmpy = dm[0]*(iy + tmpz); if (ix>=0) { o[nn] = ix+tmpy; w[nn] = dx2*dy2*dz2; nn++; } if (ix1=0) { o[nn] = ix+tmpy; w[nn] = dx2*dy1*dz2; nn++; } if (ix1=0) { tmpy = dm[0]*(iy + tmpz); if (ix>=0) { o[nn] = ix +tmpy; w[nn] = dx2*dy2*dz1; nn++; } if (ix1=0) { o[nn] = ix +tmpy; w[nn] = dx2*dy1*dz1; nn++; } if (ix11) { j13 = (px[i2p]-px[i2m])/dm[2]; j13 = 0.5*(j13 - floor(j13+0.5))*dm[2]; j23 = (py[i2p]-py[i2m])/dm[2]; j23 = 0.5*(j23 - floor(j23+0.5))*dm[2]; j33 = (pz[i2p]-pz[i2m])/dm[2]; j33 = 0.5*(j33 - floor(j33+0.5))*dm[2]; } else { j13 = 0.0; j23 = 0.0; j33 = 1.0; } } else { /* Neumann boundary - only discontinuities at edges */ if ((i0==0) || (i0==dm[0]-1)) { j11 = 1.0; j21 = 0.0; j31 = 0.0; } else { j11 = (px[1]-px[-1])*0.5; j21 = (py[1]-py[-1])*0.5; j31 = (pz[1]-pz[-1])*0.5; } if ((i1==0) || (i1==dm[1]-1)) { j12 = 0.0; j22 = 1.0; j32 = 0.0; } else { j12 = (px[dm[0]]-px[-dm[0]])*0.5; j22 = (py[dm[0]]-py[-dm[0]])*0.5; j32 = (pz[dm[0]]-pz[-dm[0]])*0.5; } if ((i2==0) || (i2==dm[2]-1)) { j13 = 0.0; j23 = 0.0; j33 = 1.0; } else { mwSignedIndex op = dm[0]*dm[1]; j13 = (px[op]-px[-op])*0.5; j23 = (py[op]-py[-op])*0.5; j33 = (pz[op]-pz[-op])*0.5; } } } ij11 = j22*j33-j23*j32; ij12 = j13*j32-j12*j33; ij13 = j12*j23-j13*j22; dj = j11*ij11 + j21*ij12 + j31*ij13; /* dj = (dj*0.99+0.01); */ dj = 1.0/dj; ij11*= dj; ij12*= dj; ij13*= dj; ij21 = (j23*j31-j21*j33)*dj; ij22 = (j11*j33-j13*j31)*dj; ij23 = (j13*j21-j11*j23)*dj; ij31 = (j21*j32-j22*j31)*dj; ij32 = (j12*j31-j11*j32)*dj; ij33 = (j11*j22-j12*j21)*dj; f1 = pf[i]; f2 = pf[i+my]; f3 = pf[i+my*2]; rf[0] = ij11*f1 + ij21*f2 + ij31*f3; rf[1] = ij12*f1 + ij22*f2 + ij32*f3; rf[2] = ij13*f1 + ij23*f2 + ij33*f3; ix = (mwSignedIndex)floor(x); dx1=x-ix; dx2=1.0-dx1; iy = (mwSignedIndex)floor(y); dy1=y-iy; dy2=1.0-dy1; iz = (mwSignedIndex)floor(z); dz1=z-iz; dz2=1.0-dz1; /* Weights for trilinear interpolation */ w000 = dx2*dy2*dz2; w100 = dx1*dy2*dz2; w010 = dx2*dy1*dz2; w110 = dx1*dy1*dz2; w001 = dx2*dy2*dz1; w101 = dx1*dy2*dz1; w011 = dx2*dy1*dz1; w111 = dx1*dy1*dz1; ix = bound(ix, dmo[0]); iy = bound(iy, dmo[1]); iz = bound(iz, dmo[2]); ix1 = bound(ix+1, dmo[0]); iy1 = bound(iy+1, dmo[1]); iz1 = bound(iz+1, dmo[2]); /* Neighbouring voxels used for trilinear interpolation */ tmpz = dmo[1]*iz; tmpy = dmo[0]*(iy + tmpz); o000 = ix +tmpy; o100 = ix1+tmpy; tmpy = dmo[0]*(iy1 + tmpz); o010 = ix +tmpy; o110 = ix1+tmpy; tmpz = dmo[1]*iz1; tmpy = dmo[0]*(iy + tmpz); o001 = ix +tmpy; o101 = ix1+tmpy; tmpy = dmo[0]*(iy1 + tmpz); o011 = ix +tmpy; o111 = ix1+tmpy; for (j=0; j<3; j++) { /* Increment the images themselves */ float *pj = po+mo*j; float f = rf[j]; pj[o000] += f*w000; pj[o100] += f*w100; pj[o010] += f*w010; pj[o110] += f*w110; pj[o001] += f*w001; pj[o101] += f*w101; pj[o011] += f*w011; pj[o111] += f*w111; } } } } } } /* * t0 = Id + v0*sc */ void smalldef(mwSize dm[], double sc, float v0[], float t0[]) { mwSize j0, j1, j2; mwSize m = dm[0]*dm[1]*dm[2]; float *v1 = v0+m, *v2 = v1+m; float *t1 = t0+m, *t2 = t1+m; for(j2=0; j2 0) { om1 = o; op1 = bound(j0+1,dm[0])+dm[0]*(j1+dm[1]*j2); } else { om1 = bound(j0-1,dm[0])+dm[0]*(j1+dm[1]*j2); op1 = o; } */ om1 = bound(j0-1,dm[0])+dm[0]*(j1+dm[1]*j2); op1 = bound(j0+1,dm[0])+dm[0]*(j1+dm[1]*j2); J0[o ] = (v0[op1]-v0[om1])*sc2 + 1.0; J0[o+ m] = (v1[op1]-v1[om1])*sc2; J0[o+2*m] = (v2[op1]-v2[om1])*sc2; /* if (v1[o] > 0) { om1 = o; op1 = j0+dm[0]*(j1p1+dm[1]*j2); } else { om1 = j0+dm[0]*(j1m1+dm[1]*j2); op1 = o; } */ om1 = j0+dm[0]*(j1m1+dm[1]*j2); op1 = j0+dm[0]*(j1p1+dm[1]*j2); J0[o+3*m] = (v0[op1]-v0[om1])*sc2; J0[o+4*m] = (v1[op1]-v1[om1])*sc2 + 1.0; J0[o+5*m] = (v2[op1]-v2[om1])*sc2; /* if (v2[o] > 0) { om1 = o; op1 = j0+dm[0]*(j1+dm[1]*j2p1); } { om1 = j0+dm[0]*(j1+dm[1]*j2m1); op1 = o; } */ om1 = j0+dm[0]*(j1+dm[1]*j2m1); op1 = j0+dm[0]*(j1+dm[1]*j2p1); J0[o+6*m] = (v0[op1]-v0[om1])*sc2; J0[o+7*m] = (v1[op1]-v1[om1])*sc2; J0[o+8*m] = (v2[op1]-v2[om1])*sc2 + 1.0; } } } } /* * t0 = Id + v0*sc * J0 = Id + expm(D v0) */ void smalldef_jac1(mwSize dm[], double sc, float v0[], float t0[], float J0[]) { mwSize j0, j1, j2; mwSize m = dm[0]*dm[1]*dm[2]; double sc2 = sc/2.0; float *v1 = v0+m, *v2 = v1+m; float A[9], E[9]; for(j2=0; j2maxdiv) maxdiv = div; } } } mnmx[0] = 0.5*mindiv; mnmx[1] = 0.5*maxdiv; } /* * Jacobian determinant field */ void determinant(mwSize dm[], float J0[], float d[]) { mwSize m = dm[0]*dm[1]*dm[2]; mwSize j; double j00, j01, j02, j10, j11, j12, j20, j21, j22; for(j=0; j