From cba2a09b42c867ccef2de3cbdd9c26d0af625fef Mon Sep 17 00:00:00 2001
From: Stephen Smith <steve@fmrib.ox.ac.uk>
Date: Sat, 4 Jun 2005 06:27:54 +0000
Subject: [PATCH] *** empty log message ***

---
 avwmaths.c | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 348 insertions(+), 20 deletions(-)

diff --git a/avwmaths.c b/avwmaths.c
index 0fa4034..f3f36dd 100644
--- a/avwmaths.c
+++ b/avwmaths.c
@@ -113,7 +113,7 @@ double tmpd;
     if (isupper((int)argv[i][1]))
       /* {{{ group operations (dimensionality reduction) */
 
-#define CI FDT tmpval, *tmpdata=malloc(sizeof(FDT)*MAX(MAX(im.x,im.y),MAX(im.z,im.t))); double sum=0,sumsquares=0,min=im.dtmax,max=im.dtmin; int nmax=0, n
+#define CI FDT tmpval, *tmpdata=malloc(sizeof(FDT)*MAX(MAX(im.x,im.y),MAX(im.z,im.t))); double sum=0,sumsquares=0,min=im.dtmax,max=im.dtmin; int nmax=0, n=0
 
 #define CU {        if (argv[i][1] == 'T')  n=t;                                                                            \
                else if (argv[i][1] == 'Z')  n=z;                                                                            \
@@ -364,8 +364,7 @@ double tmpd;
 
 {
   for(j=0;j<size;j++)
-    if (in[0][j]<0)
-      in[0][j]=-in[0][j];
+    in[0][j]=ABS(in[0][j]);
 }
 
 /* }}} */
@@ -601,7 +600,27 @@ double tmpd;
 
 /* }}} */
     else if (!strncmp(argv[i], "-nms", 4))
-      /* {{{ nms */
+      /* {{{ non-max-suppression */
+
+{
+  int maxsearch=0;
+  float origthresh, *tmpdata;
+  image_struct distancemap, thedata;
+	
+  if (!strncmp(argv[i], "-nmss", 5))
+    {
+      maxsearch=1;
+      i++;
+      origthresh=atof(argv[i]);
+      i++;
+      avw_read(argv[i],&distancemap);
+      i++;
+      avw_read(argv[i],&thedata);
+      
+      tmpdata=calloc(thedata.t*size,sizeof(float));
+    }
+
+  /* {{{ nms 3x3x3 CofG etc with flow smoothing */
 
 {
   int MAXZ=1;
@@ -610,35 +629,344 @@ double tmpd;
   if (im.z<3)
     MAXZ=0;
 
-  for(t=0;t<im.t;t++) for(z=MAXZ;z<im.z-MAXZ;z++) for(y=1;y<im.y-1;y++) for(x=1;x<im.x-1;x++)
+  for(t=0;t<im.t;t++) /* kill this - shouldn't do this over t */
+    {
+      /* {{{ setup temp images to store perp */
+
+      short *X=calloc(size,sizeof(short)),
+	*Y=calloc(size,sizeof(short)),
+	*Z=calloc(size,sizeof(short)),
+	*XX=calloc(size,sizeof(short)),
+	*YY=calloc(size,sizeof(short)),
+	*ZZ=calloc(size,sizeof(short));
+
+/* }}} */
+
+      /* {{{ estimate perp from CofG and curvature, and store this in X,Y,Z */
+
+      for(z=MAXZ;z<im.z-MAXZ;z++) for(y=1;y<im.y-1;y++) for(x=1;x<im.x-1;x++)
+	{
+	  FDT theval = in[0][t*xyzsize+z*xysize+y*im.x+x];
+
+	  if ( theval != 0 )
+	    {
+	      float CofGx=0, CofGy=0, CofGz=0, Sum=0, CofGl;
+	      int xx, yy, zz, xxx=0, yyy=0, zzz=0;
+
+	      for(zz=-MAXZ; zz<=MAXZ; zz++)
+		for(yy=-1; yy<=1; yy++)
+		  for(xx=-1; xx<=1; xx++)
+		    {
+		      float val = in[0][t*xyzsize+(z+zz)*xysize+(y+yy)*im.x+x+xx];
+		      Sum   += val;
+		      CofGx += xx * val;  CofGy += yy * val;  CofGz += zz * val;
+		    }	      
+	      
+	      CofGx /= Sum;  CofGy /= Sum;  CofGz /= Sum;
+	      CofGl = sqrt(CofGx*CofGx+CofGy*CofGy+CofGz*CofGz);
+	      
+	      if (CofGl > .1)  /* is CofG far enough away from centre voxel? */
+		{
+		  xxx = FTOI(CofGx/CofGl);
+		  yyy = FTOI(CofGy/CofGl);
+		  zzz = FTOI(CofGz/CofGl);
+		}
+	      else
+		/* {{{ find direction of max curvature */
+
+	{
+	  float maxcost=0, centreval=2.0 * (float)theval;
+
+	  for(zz=0; zz<=MAXZ; zz++) /* note - starts at zero as we're only searching half the voxels */
+	    for(yy=-1; yy<=1; yy++)
+	      for(xx=-1; xx<=1; xx++)
+		if ( (zz==1) || (yy==1) || ((yy==0)&&(xx==1)) ) /* only search half the voxels */
+		  {
+		    float weighting = pow( (float)(xx*xx+yy*yy+zz*zz) , -0.7 ); /* power is arbitrary: maybe test other functions here */
+		    float cost = weighting * ( centreval 
+					       - (float)in[0][t*xyzsize+(z+zz)*xysize+(y+yy)*im.x+x+xx]
+					       - (float)in[0][t*xyzsize+(z-zz)*xysize+(y-yy)*im.x+x-xx] );
+
+		    if (cost>maxcost)
+		      {
+			maxcost=cost;
+			xxx=xx;
+			yyy=yy;
+			zzz=zz;
+		      }
+		  }
+	}
+
+/* }}} */
+							   
+	      X[z*xysize+y*im.x+x]=xxx;
+	      Y[z*xysize+y*im.x+x]=yyy;
+	      Z[z*xysize+y*im.x+x]=zzz;
+	    }
+
+	}
+
+      /* {{{ COMMENT save perp image */
+
+#ifdef FoldingComment
+
+{
+  char tmpname[10000];
+  image_struct tmpim=im;
+
+  tmpim.i=calloc(size*3,sizeof(float));
+  sprintf(tmpname,"%s_flow",argv[argc-1]);
+
+  tmpim.dt=DT_FLOAT;
+  tmpim.t=3;
+
+  for(z=0;z<im.z;z++) for(y=0;y<im.y;y++) for(x=0;x<im.x;x++)
+    {
+      float tmpX=X[z*xysize+y*im.x+x],
+	tmpY=Y[z*xysize+y*im.x+x],
+	tmpZ=Z[z*xysize+y*im.x+x],
+	tmpf=sqrt(tmpX*tmpX+tmpY*tmpY+tmpZ*tmpZ);
+
+      if (tmpf>0)
+	{
+	  tmpim.i[          z*xysize+y*im.x+x]=tmpX/tmpf;
+	  tmpim.i[  xyzsize+z*xysize+y*im.x+x]=tmpY/tmpf;
+	  tmpim.i[2*xyzsize+z*xysize+y*im.x+x]=tmpZ/tmpf;
+	}
+    }
+
+  avw_write(tmpname,tmpim);
+  free(tmpim.i);
+}
+
+#endif
+
+/* }}} */
+
+/* }}} */
+      /* {{{ smooth X,Y,Z and store in XX,YY,ZZ */
+
+      for(z=MAXZ;z<im.z-MAXZ;z++) for(y=1;y<im.y-1;y++) for(x=1;x<im.x-1;x++)
+	{
+	  int xx, yy, zz, *localsum=calloc(27,sizeof(int)), localmax=0, xxx, yyy, zzz;
+
+	  for(zz=-MAXZ; zz<=MAXZ; zz++)
+	    for(yy=-1; yy<=1; yy++)
+	      for(xx=-1; xx<=1; xx++)
+		{
+		  xxx = X[(z+zz)*xysize+(y+yy)*im.x+x+xx];
+		  yyy = Y[(z+zz)*xysize+(y+yy)*im.x+x+xx];
+		  zzz = Z[(z+zz)*xysize+(y+yy)*im.x+x+xx];
+		  localsum[(1+zzz)*9+(1+yyy)*3+1+xxx]++;
+		  localsum[(1-zzz)*9+(1-yyy)*3+1-xxx]++;
+		}
+
+	  for(zz=-MAXZ; zz<=MAXZ; zz++)
+	    for(yy=-1; yy<=1; yy++)
+	      for(xx=-1; xx<=1; xx++)
+		{
+		  if (localsum[(1+zz)*9+(1+yy)*3+1+xx]>localmax)
+		    {
+		      localmax=localsum[(1+zz)*9+(1+yy)*3+1+xx];
+		      XX[z*xysize+y*im.x+x]=xx;
+		      YY[z*xysize+y*im.x+x]=yy;
+		      ZZ[z*xysize+y*im.x+x]=zz;
+		    }
+		}
+	}
+
+      /* {{{ COMMENT save perp image */
+
+#ifdef FoldingComment
+
+{
+  char tmpname[10000];
+  image_struct tmpim=im;
+
+  tmpim.i=calloc(size*3,sizeof(float));
+  sprintf(tmpname,"%s_flowsmooth",argv[argc-1]);
+
+  tmpim.dt=DT_FLOAT;
+  tmpim.t=3;
+
+  for(z=0;z<im.z;z++) for(y=0;y<im.y;y++) for(x=0;x<im.x;x++)
     {
-      double cost, mincost=1e10;
-      int xx, yy, zz, xxx=0, yyy=0, zzz=0;
+      float tmpX=XX[z*xysize+y*im.x+x],
+	tmpY=YY[z*xysize+y*im.x+x],
+	tmpZ=ZZ[z*xysize+y*im.x+x],
+	tmpf=sqrt(tmpX*tmpX+tmpY*tmpY+tmpZ*tmpZ);
+
+      if (tmpf>0)
+	{
+	  tmpim.i[          z*xysize+y*im.x+x]=tmpX/tmpf;
+	  tmpim.i[  xyzsize+z*xysize+y*im.x+x]=tmpY/tmpf;
+	  tmpim.i[2*xyzsize+z*xysize+y*im.x+x]=tmpZ/tmpf;
+	}
+    }
+
+  avw_write(tmpname,tmpim);
+  free(tmpim.i);
+}
+
+#endif
+
+/* }}} */
+
+/* }}} */
+      /* {{{ do non-max-suppression in the direction of perp */
+
+      for(z=MAXZ;z<im.z-MAXZ;z++) for(y=1;y<im.y-1;y++) for(x=1;x<im.x-1;x++)
+	{
+	  FDT theval = in[0][t*xyzsize+z*xysize+y*im.x+x];
+	  int xxx=XX[z*xysize+y*im.x+x];
+	  int yyy=YY[z*xysize+y*im.x+x];
+	  int zzz=ZZ[z*xysize+y*im.x+x];
+	  
+	  if ( ( (xxx!=0) || (yyy!=0) || (zzz!=0) ) &&
+	       ( theval >= in[0][t*xyzsize+(z+zzz)*xysize+(y+yyy)*im.x+x+xxx] ) &&
+	       ( theval >  in[0][t*xyzsize+(z-zzz)*xysize+(y-yyy)*im.x+x-xxx] ) &&
+	       ( theval >= in[0][t*xyzsize+(z+2*zzz)*xysize+(y+2*yyy)*im.x+x+2*xxx] ) &&
+	       ( theval >  in[0][t*xyzsize+(z-2*zzz)*xysize+(y-2*yyy)*im.x+x-2*xxx] ) )
+	    tmpim[t*xyzsize+z*xysize+y*im.x+x] = theval;
+	}
+
+/* }}} */
+
+      if (maxsearch==1)
+	/* {{{ do search in the direction of perp */
+
+#define SEARCHSIGMA 5 /* length in linear voxel dimensions */
+#define MAXSEARCHLENGTH (3*SEARCHSIGMA)
+
+{
+  int d, T, iters;
+
+  for(T=0;T<thedata.t;T++) for(z=MAXZ;z<im.z-MAXZ;z++) for(y=1;y<im.y-1;y++) for(x=1;x<im.x-1;x++)
+    if (tmpim[t*xyzsize+z*xysize+y*im.x+x] > origthresh)
+      {
+	int xxx=XX[z*xysize+y*im.x+x];
+	int yyy=YY[z*xysize+y*im.x+x];
+	int zzz=ZZ[z*xysize+y*im.x+x];
+	float maxval=thedata.i[T*xyzsize+z*xysize+y*im.x+x];
+	float maxval_weighted=maxval;
+	int maxvalX=x, maxvalY=y, maxvalZ=z;
+	float exponentfactor = -0.5 * (xxx*xxx+yyy*yyy+zzz*zzz) / (float)(SEARCHSIGMA*SEARCHSIGMA);
+
+	for(iters=0;iters<2;iters++)
+	  {
+	    float distance=0;
+
+	    for(d=1;d<MAXSEARCHLENGTH;d++)
+	      {
+		int D=d;
+		if (iters==1) D=-d;
+
+		if (distancemap.i[t*xyzsize+(z+zzz*D)*xysize+(y+yyy*D)*im.x+x+xxx*D]>=distance)
+		  {
+		    float distanceweight = exp(d * d * exponentfactor);
+		    distance=distancemap.i[t*xyzsize+(z+zzz*D)*xysize+(y+yyy*D)*im.x+x+xxx*D];
+		    if (distanceweight * thedata.i[T*xyzsize+(z+zzz*D)*xysize+(y+yyy*D)*im.x+x+xxx*D]>maxval_weighted)
+		      {
+			maxval=thedata.i[T*xyzsize+(z+zzz*D)*xysize+(y+yyy*D)*im.x+x+xxx*D];
+			maxval_weighted=maxval*distanceweight;
+			maxvalX=x+xxx*D;
+			maxvalY=y+yyy*D;
+			maxvalZ=z+zzz*D;
+		      }
+		  }
+		else
+		  d=MAXSEARCHLENGTH;
+	      }
+	  }
+	
+	tmpdata[T*xyzsize+z*xysize+y*im.x+x]=maxval; /* output maxsearch data */
 
-      for(zz=0; zz<=MAXZ; zz++)
-	for(yy=-1; yy<=1; yy++)
-	  for(xx=-1; xx<=1; xx++)
-	    if ( (zz==1) || (yy==1) || ((yy==0)&&(xx==1)) )
+	/*tmpdata[T*xyzsize+z*xysize+y*im.x+x]=maxvalX-x;*/ /* output X component of search vector */
+	/*tmpdata[T*xyzsize+z*xysize+y*im.x+x]=maxvalY-y;*/ /* output Y component of search vector */
+	/*tmpdata[T*xyzsize+z*xysize+y*im.x+x]=maxvalZ-z;*/ /* output Z component of search vector */
+      }
+
+  thedata.i=tmpdata;
+  avw_write(argv[argc-1],thedata);
+  
+  exit(0);
+}
+
+/* }}} */
+	/* {{{ COMMENT do search in the direction of perp */
+
+#ifdef FoldingComment
+
+/*#define MAXSEARCHLENGTH 20*/
+
+#define SEARCHSIGMA 5 /* length in linear voxel dimensions */
+#define MAXSEARCHLENGTH (3*SEARCHSIGMA)
+
+{
+  int d, T, iters;
+
+  for(T=0;T<thedata.t;T++) for(z=MAXZ;z<im.z-MAXZ;z++) for(y=1;y<im.y-1;y++) for(x=1;x<im.x-1;x++)
+    if (tmpim[t*xyzsize+z*xysize+y*im.x+x] > origthresh)
+      {
+	int xxx=XX[z*xysize+y*im.x+x];
+	int yyy=YY[z*xysize+y*im.x+x];
+	int zzz=ZZ[z*xysize+y*im.x+x];
+	float maxval=thedata.i[T*xyzsize+z*xysize+y*im.x+x];
+	int maxvalX=x, maxvalY=y, maxvalZ=z;
+
+	for(iters=0;iters<2;iters++)
+	  {
+	    float distance=0;
+
+	    for(d=1;d<MAXSEARCHLENGTH;d++)
 	      {
-		cost = in[0][t*xyzsize+(z+zz)*xysize+(y+yy)*im.x+x+xx] + in[0][t*xyzsize+(z-zz)*xysize+(y-yy)*im.x+x-xx];
-		if (cost<mincost)
+		int D=d;
+		if (iters==1) D=-d;
+
+		if (distancemap.i[t*xyzsize+(z+zzz*D)*xysize+(y+yyy*D)*im.x+x+xxx*D]>=distance)
 		  {
-		    mincost=cost;
-		    xxx=xx;
-		    yyy=yy;
-		    zzz=zz;
+		    distance=distancemap.i[t*xyzsize+(z+zzz*D)*xysize+(y+yyy*D)*im.x+x+xxx*D];
+		    if (thedata.i[T*xyzsize+(z+zzz*D)*xysize+(y+yyy*D)*im.x+x+xxx*D]>maxval)
+		      {
+			maxval=thedata.i[T*xyzsize+(z+zzz*D)*xysize+(y+yyy*D)*im.x+x+xxx*D];
+			maxvalX=x+xxx*D;
+			maxvalY=y+yyy*D;
+			maxvalZ=z+zzz*D;
+		      }
 		  }
+		else
+		  d=MAXSEARCHLENGTH;
 	      }
+	  }
+	
+	tmpdata[T*xyzsize+z*xysize+y*im.x+x]=maxval; /* output maxsearch data */
+
+	/*tmpdata[T*xyzsize+z*xysize+y*im.x+x]=maxvalX-x;*/ /* output X component of search vector */
+	/*tmpdata[T*xyzsize+z*xysize+y*im.x+x]=maxvalY-y;*/ /* output Y component of search vector */
+	/*tmpdata[T*xyzsize+z*xysize+y*im.x+x]=maxvalZ-z;*/ /* output Z component of search vector */
+	/*tmpdata[T*xyzsize+maxvalZ*xysize+maxvalY*im.x+maxvalX]++;*/ /* output number of times skel has looked in this original space voxel */
+      }
+
+  thedata.i=tmpdata;
+  avw_write(argv[argc-1],thedata);
+  
+  exit(0);
+}
 
-      if ( ( in[0][t*xyzsize+z*xysize+y*im.x+x] >= in[0][t*xyzsize+(z+zzz)*xysize+(y+yyy)*im.x+x+xxx] ) &&
-	   ( in[0][t*xyzsize+z*xysize+y*im.x+x] >  in[0][t*xyzsize+(z-zzz)*xysize+(y-yyy)*im.x+x-xxx] ) )
-	tmpim[t*xyzsize+z*xysize+y*im.x+x] = in[0][t*xyzsize+z*xysize+y*im.x+x];
+#endif
+
+/* }}} */
+
+      free(X); free(Y); free(Z); free(XX); free(YY); free(ZZ);
     }
 
   free(in[0]);
   in[0]=tmpim;
 }
 
+/* }}} */
+}
+
 /* }}} */
     else if (!strncmp(argv[i], "-nanm", 5))
       /* {{{ NaN mask */
-- 
GitLab