//////////////////////////////////////////////////////////////////////// // FUNCTION: WinInvertPixel // // DESCRIPTION: This routine draw a pixel in the draw window using // the current foreground color. // // PARAMETERS: (Coord) x - pointer to the x coordinate of a pixel // (Coord) y - pointer to the y coordinate of a pixel // // RETURNED: Returns nothing. // // REVISION HISTORY: // Name Date Description // ---- ---- ----------- // Jerry 5/29/01 Initial Revision //////////////////////////////////////////////////////////////////////// void WinInvertPixel (Coord x, Coord y) { if ( VGetPixel (x, y) == 1 ) { // FOREGROUNDCOLOR VDrawPixel (x, y, BACKGROUNDCOLOR); } else if ( VGetPixel (x, y) == 0 ) { // BACKGROUNDCOLOR VDrawPixel (x, y, FOREGROUNDCOLOR); } }
/*! \fn VImage VMedianImage2d (VImage src, VImage dest, int dim, VBoolean ignore) \param src input image \param dest output image \param dim kernel size \param ignore whether to ignore zero voxels */ VImage VMedianImage2d (VImage src, VImage dest, int dim, VBoolean ignore) { int nbands,nrows,ncols; int i,len,b,r,c,rr,cc,d=0; gsl_vector *vec=NULL; double u,tiny=1.0e-10; if (dim%2 == 0) VError("VMedianImage2d: dim (%d) must be odd",dim); nrows = VImageNRows (src); ncols = VImageNColumns (src); nbands = VImageNBands (src); d = dim/2; len = dim * dim; vec = gsl_vector_calloc(len); dest = VCopyImage(src,dest,VAllBands); for (b=0; b<nbands; b++) { for (r=d; r<nrows-d; r++) { for (c=d; c<ncols-d; c++) { gsl_vector_set_zero(vec); u = VGetPixel(src,b,r,c); if ( !ignore || ABS(u) > tiny) { i = 0; for (rr=r-d; rr<=r+d; rr++) { for (cc=c-d; cc<=c+d; cc++) { u = VGetPixel(src,b,rr,cc); if (ABS(u) > 0) { gsl_vector_set(vec,i,u); i++; } } } gsl_sort_vector(vec); u = gsl_stats_median_from_sorted_data(vec->data,vec->stride,i); VSetPixel(dest,b,r,c,u); } } } } return dest; }
VImage ConcatDesigns(VImage *design, int nimages) { VImage dest = NULL; VString buf = NULL; VDouble x; int i, r, c, row, col; int nrows, ncols; nrows = ncols = 0; for(i = 0; i < nimages; i++) { ncols += VImageNColumns(design[i]); nrows += VImageNRows(design[i]); } dest = VCreateImage(1, nrows, ncols, VFloatRepn); VFillImage(dest, VAllBands, 0); VCopyImageAttrs(design[0], dest); VSetAttr(VImageAttrList(dest), "nsessions", NULL, VShortRepn, (VShort)nimages); buf = (VString) VMalloc(80); buf[0] = '\0'; for(i = 0; i < nimages; i++) sprintf(buf, "%s %d", buf, (int)VImageNRows(design[i])); VSetAttr(VImageAttrList(dest), "session_lengths", NULL, VStringRepn, buf); buf[0] = '\0'; for(i = 0; i < nimages; i++) sprintf(buf, "%s %d", buf, (int)VImageNColumns(design[i])); VSetAttr(VImageAttrList(dest), "session_covariates", NULL, VStringRepn, buf); row = col = 0; for(i = 0; i < nimages; i++) { for(r = 0; r < VImageNRows(design[i]); r++) { for(c = 0; c < VImageNColumns(design[i]); c++) { x = VGetPixel(design[i], 0, r, c); if(row + r >= VImageNRows(dest)) VError(" row: %d\n", row + r); if(col + c >= VImageNColumns(dest)) VError(" column: %d\n", col + c); VSetPixel(dest, 0, row + r, col + c, x); } } row += VImageNRows(design[i]); col += VImageNColumns(design[i]); } return dest; }
/* * Flip3dImage * */ VImage Flip3dImage(VImage src, VImage dest, VBand band, VBoolean x_axis, VBoolean y_axis, VBoolean z_axis) { int nx, ny, nz; int i, j, k; nx = VImageNColumns(src); ny = VImageNRows(src); nz = VImageNBands(src); /* Check the destination image. If it is NULL, then create one of the appropriate size and type. */ dest = VSelectDestImage("Flip3dImage", dest, nz, ny, nx, VPixelRepn(src)); if(! dest) return NULL; for(i = 0; i < nx; i++) for(j = 0; j < ny; j++) for(k = 0; k < nz; k++) { if(! x_axis && ! y_axis && ! z_axis) VSetPixel(dest, k, j, i, VGetPixel(src, k, j, i)); if(x_axis && ! y_axis && ! z_axis) VSetPixel(dest, k, j, i, VGetPixel(src, k, j, nx - i - 1)); if(! x_axis && y_axis && ! z_axis) VSetPixel(dest, k, j, i, VGetPixel(src, k, ny - j - 1, i)); if(! x_axis && ! y_axis && z_axis) VSetPixel(dest, k, j, i, VGetPixel(src, nz - k - 1, j, i)); if(x_axis && y_axis && ! z_axis) VSetPixel(dest, k, j, i, VGetPixel(src, k, ny - j - 1, nx - i - 1)); if(x_axis && ! y_axis && z_axis) VSetPixel(dest, k, j, i, VGetPixel(src, nz - k - 1, j, nx - i - 1)); if(! x_axis && y_axis && z_axis) VSetPixel(dest, k, j, i, VGetPixel(src, nz - k - 1, ny - j - 1, i)); if(x_axis && y_axis && z_axis) VSetPixel(dest, k, j, i, VGetPixel(src, nz - k - 1, ny - j - 1, nx - i - 1)); }; /* Let the destination inherit any attributes of the source image: */ VCopyImageAttrs(src, dest); return dest; };
/*! \fn void VDeriche2d(VImage src,VFloat alpha,VImage *gradr,VImage *gradc); \param src input image (ubyte repn) \param alpha parameter controlling edge strength \param *gradr output gradient in row direction (float repn) \param *gradc output gradient in column direction (float repn) */ void VDeriche2d (VImage src,VFloat alpha,VImage *gradr,VImage *gradc) { int b,r,c; int nbands,nrows,ncols,npixels,len; double s,a,a0,a1,a2,a3,b1,b2,exp_alpha; float *left,*right; nbands = VImageNBands (src); nrows = VImageNRows (src); ncols = VImageNColumns (src); npixels = nbands * nrows * ncols; len = (ncols > nrows) ? ncols : nrows; left = (float *) VMalloc(sizeof(float) * len); right = (float *) VMalloc(sizeof(float) * len); exp_alpha = exp((double) ( - alpha)); a = 1.0 * exp_alpha; b1 = -2.0 * exp_alpha; b2 = exp((double) (-2.0 * alpha)); s = ((1.0 - exp_alpha) * (1.0 - exp_alpha)) / (1.0 + 2.0 * alpha * exp_alpha - b2); a0 = s; a1 = s * (alpha - 1.0) * exp_alpha; a2 = a1 - s * b1; a3 = - s * b2; /* col-grad */ *gradc = VCreateImage(nbands,nrows,ncols,VFloatRepn); for (b=0; b<nbands; b++) { for (r=0; r<nrows; r++) { /* left-to-right */ left[0] = 0; left[1] = 0; for (c=2; c<ncols; c++) { left[c] = (VFloat) VGetPixel(src,b,r,c-1) - b1 * left[c-1] - b2 * left[c-2]; } /* right-to-left */ right[ncols-1] = 0; right[ncols-2] = 0; for (c=ncols-3; c>=0; c--) { right[c] = (VFloat) VGetPixel(src,b,r,c+1) - b1 * right[c+1] - b2 * right[c+2]; } /* combine */ for (c=0; c<ncols; c++) { VPixel(*gradc,b,r,c,VFloat) = a * (left[c] - right[c]); } } } /* row-smooth */ for (b=0; b<nbands; b++) { for (c=0; c<ncols; c++) { /* left-to-right */ left[0] = 0; left[1] = 0; for (r=2; r<nrows; r++) { left[r] = a0 * (VFloat) VPixel(*gradc,b,r,c,VFloat) + a1 * (VFloat) VPixel(*gradc,b,r-1,c,VFloat) - b1 * left[r-1] - b2 * left[r-2]; } /* right-to-left */ right[nrows-1] = 0; right[nrows-2] = 0; for (r=nrows-3; r>=0; r--) { right[r] = a2 * (VFloat) VPixel(*gradc,b,r+1,c,VFloat) + a3 * (VFloat) VPixel(*gradc,b,r+2,c,VFloat) - b1 * right[r+1] - b2 * right[r+2]; } /* combine */ for (r=0; r<nrows; r++) { VPixel(*gradc,b,r,c,VFloat) += left[r] + right[r]; } } } /* ** row-grad */ *gradr = VCreateImage(nbands,nrows,ncols,VFloatRepn); /* row-deriv */ for (b=0; b<nbands; b++) { for (c=0; c<ncols; c++) { /* left-to-right */ left[0] = 0; left[1] = 0; for (r=2; r<nrows; r++) { left[r] = (VFloat) VGetPixel(src,b,r-1,c) - b1 * left[r-1] - b2 * left[r-2]; } /* right-to-left */ right[ncols-1] = 0; right[ncols-2] = 0; for (r=nrows-3; r>=0; r--) { right[r] = (VFloat) VGetPixel(src,b,r+1,c) - b1 * right[r+1] - b2 * right[r+2]; } /* combine */ for (r=0; r<nrows; r++) { VPixel(*gradr,b,r,c,VFloat) = a * (left[r] - right[r]); } } } /* col-smooth */ for (b=0; b<nbands; b++) { for (r=0; r<nrows; r++) { /* left-to-right */ left[0] = 0; left[1] = 0; for (c=2; c<ncols; c++) { left[c] = a0 * (VFloat) VPixel(*gradr,b,r,c,VFloat) + a1 * (VFloat) VPixel(*gradr,b,r,c-1,VFloat) - b1 * left[c-1] - b2 * left[c-2]; } /* right-to-left */ right[ncols-1] = 0; right[ncols-2] = 0; for (c=ncols-3; c>=0; c--) { right[r] = a2 * (VFloat) VPixel(*gradr,b,r,c+1,VFloat) + a3 * (VFloat) VPixel(*gradr,b,r,c+2,VFloat) - b1 * right[c+1] - b2 * right[c+2]; } /* combine */ for (c=0; c<ncols; c++) { VPixel(*gradr,b,r,c,VFloat) += left[c] + right[c]; } } } VFree(left); VFree(right); }
VAttrList VNCM(VAttrList list,VImage mask,VShort minval,VShort first,VShort length,VFloat threshold) { VAttrList out_list=NULL; VAttrListPosn posn; VImage src[NSLICES],map=NULL; VImage dest=NULL; size_t b,r,c,i,j,i1,n,m,nt,last,ntimesteps,nrows,ncols,nslices; gsl_matrix_float *mat=NULL; float *A=NULL,*ev=NULL; /* ** get image dimensions */ i = ntimesteps = nrows = ncols = 0; for (VFirstAttr (list, & posn); VAttrExists (& posn); VNextAttr (& posn)) { if (VGetAttrRepn (& posn) != VImageRepn) continue; VGetAttrValue (& posn, NULL,VImageRepn, & src[i]); if (VPixelRepn(src[i]) != VShortRepn) continue; if (VImageNBands(src[i]) > ntimesteps) ntimesteps = VImageNBands(src[i]); if (VImageNRows(src[i]) > nrows) nrows = VImageNRows(src[i]); if (VImageNColumns(src[i]) > ncols) ncols = VImageNColumns(src[i]); i++; if (i >= NSLICES) VError(" too many slices"); } nslices = i; /* get time steps to include */ if (length < 1) length = ntimesteps-2; last = first + length -1; if (last >= ntimesteps) last = ntimesteps-1; if (first < 0) first = 1; nt = last - first + 1; i1 = first+1; if (nt < 2) VError(" not enough timesteps, nt= %d",nt); fprintf(stderr,"# ntimesteps: %d, first= %d, last= %d, nt= %d\n", (int)ntimesteps,(int)first,(int)last,(int)nt); /* count number of voxels */ n = 0; for (b=0; b<nslices; b++) { if (VImageNRows(src[b]) < 2) continue; for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { if (VPixel(src[b],i1,r,c,VShort) < minval) continue; if (VGetPixel(mask,b,r,c) < 0.5) continue; n++; } } } fprintf(stderr," nvoxels: %ld\n",(long)n); /* ** voxel addresses */ map = VCreateImage(1,5,n,VFloatRepn); if (map == NULL) VError(" error allocating addr map"); VFillImage(map,VAllBands,0); VPixel(map,0,3,0,VFloat) = nslices; VPixel(map,0,3,1,VFloat) = nrows; VPixel(map,0,3,2,VFloat) = ncols; i = 0; for (b=0; b<nslices; b++) { if (VImageNRows(src[b]) < 2) continue; for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { if (VPixel(src[b],i1,r,c,VShort) < minval) continue; if (VGetPixel(mask,b,r,c) < 0.5) continue; VPixel(map,0,0,i,VFloat) = b; VPixel(map,0,1,i,VFloat) = r; VPixel(map,0,2,i,VFloat) = c; i++; } } } /* ** avoid casting to float, copy data to matrix */ mat = gsl_matrix_float_calloc(n,nt); for (i=0; i<n; i++) { b = VPixel(map,0,0,i,VFloat); r = VPixel(map,0,1,i,VFloat); c = VPixel(map,0,2,i,VFloat); float *ptr = gsl_matrix_float_ptr(mat,i,0); int k; j = 0; for (k=first; k<=last; k++) { if (j >= mat->size2) VError(" j= %d %d",j,mat->size2); if (k >= VImageNBands(src[b])) VError(" k= %d %d",k, VImageNBands(src[b])); *ptr++ = (float) VPixel(src[b],k,r,c,VShort); j++; } } /* ** compute similarity matrix */ m = (n*(n+1))/2; fprintf(stderr," matrix computation, n= %ld...\n",(long)n); A = (float *) calloc(m,sizeof(float)); if (!A) VError(" err allocating correlation matrix"); memset(A,0,m*sizeof(float)); size_t progress=0; #pragma omp parallel for shared(progress) private(j) schedule(guided) firstprivate(mat,A) for (i=0; i<n; i++) { if (i%100 == 0) fprintf(stderr," %d00\r",(int)(++progress)); const float *arr1 = gsl_matrix_float_const_ptr(mat,i,0); for (j=0; j<i; j++) { const float *arr2 = gsl_matrix_float_const_ptr(mat,j,0); const double v = Correlation(arr1,arr2,nt); const size_t k=j+i*(i+1)/2; if (k >= m) VError(" illegal addr k= %d, m= %d",k,m); A[k] = (float)v; } } fprintf(stderr," matrix done.\n"); gsl_matrix_float_free(mat); /* ** eigenvector centrality */ ev = (float *) VCalloc(n,sizeof(float)); DegreeCentrality(A,ev,n,threshold); dest = WriteOutput(src[0],map,nslices,nrows,ncols,ev,n); VSetAttr(VImageAttrList(dest),"name",NULL,VStringRepn,"DegreeCM"); out_list = VCreateAttrList(); VAppendAttr(out_list,"image",NULL,VImageRepn,dest); return out_list; }
VImage SimilarityMatrix(VAttrList list, VImage mask, VShort minval, VShort fisher) { VAttrListPosn posn; VImage src[NSLICES], dest = NULL, map = NULL; int b, r, c, i, j, n, ntimesteps, nrows, ncols, nslices; double u, x, y, smin, smax, tiny = 1.0e-6; gsl_matrix_float *mat = NULL; /* ** get image dimensions */ i = ntimesteps = nrows = ncols = 0; for(VFirstAttr(list, & posn); VAttrExists(& posn); VNextAttr(& posn)) { if(VGetAttrRepn(& posn) != VImageRepn) continue; VGetAttrValue(& posn, NULL, VImageRepn, & src[i]); if(VPixelRepn(src[i]) != VShortRepn) continue; if(VImageNBands(src[i]) > ntimesteps) ntimesteps = VImageNBands(src[i]); if(VImageNRows(src[i]) > nrows) nrows = VImageNRows(src[i]); if(VImageNColumns(src[i]) > ncols) ncols = VImageNColumns(src[i]); i++; if(i >= NSLICES) VError(" too many slices"); } nslices = i; n = 0; for(b = 0; b < nslices; b++) { if(VImageNRows(src[b]) < 2) continue; for(r = 0; r < nrows; r++) { for(c = 0; c < ncols; c++) { if(VPixel(src[b], 0, r, c, VShort) < minval) continue; if(VGetPixel(mask, b, r, c) < 0.1) continue; n++; } } } fprintf(stderr, " n: %d\n", n); /* ** voxel addresses */ map = VCreateImage(1, 5, n, VFloatRepn); VFillImage(map, VAllBands, 0); VPixel(map, 0, 3, 0, VFloat) = nslices; VPixel(map, 0, 3, 1, VFloat) = nrows; VPixel(map, 0, 3, 2, VFloat) = ncols; i = 0; for(b = 0; b < nslices; b++) { if(VImageNRows(src[b]) < 2) continue; for(r = 0; r < nrows; r++) { for(c = 0; c < ncols; c++) { if(VPixel(src[b], 0, r, c, VShort) < minval) continue; if(VGetPixel(mask, b, r, c) < 0.1) continue; VPixel(map, 0, 0, i, VFloat) = b; VPixel(map, 0, 1, i, VFloat) = r; VPixel(map, 0, 2, i, VFloat) = c; i++; } } } /* ini output image */ if(n < 8000) dest = VCreateImage(1, n, n, VFloatRepn); else if(n >= 8000 && n < 10000) dest = VCreateImage(1, n, n, VShortRepn); else dest = VCreateImage(1, n, n, VSByteRepn); VFillImage(dest, VAllBands, 0); smin = VPixelMinValue(dest); smax = VPixelMaxValue(dest); /* ** avoid casting to float, copy data to matrix */ mat = gsl_matrix_float_calloc(n, ntimesteps); for(i = 0; i < n; i++) { b = VPixel(map, 0, 0, i, VFloat); r = VPixel(map, 0, 1, i, VFloat); c = VPixel(map, 0, 2, i, VFloat); float *ptr = gsl_matrix_float_ptr(mat, i, 0); int k; j = 0; for(k = 0; k < ntimesteps; k++) { if(j >= mat->size2) VError(" j= %d %d", j, mat->size2); if(k >= VImageNBands(src[b])) VError(" k= %d %d", k, VImageNBands(src[b])); *ptr++ = (float) VPixel(src[b], k, r, c, VShort); j++; } } /* ** main process loop */ for(i = 0; i < n; i++) { if(i % 50 == 0) fprintf(stderr, " i: %4d\r", i); const float *arr1 = gsl_matrix_float_const_ptr(mat, i, 0); for(j = 0; j <= i; j++) { const float *arr2 = gsl_matrix_float_const_ptr(mat, j, 0); u = Correlation(arr1, arr2, ntimesteps); /* Fisher r-to-z transform */ if(fisher) { x = 1 + u; y = 1 - u; if(x < tiny) x = tiny; if(y < tiny) y = tiny; u = 0.5 * log(x / y); } if(VPixelRepn(dest) != VFloatRepn) { u *= smax; if(u < smin) u = smin; if(u > smax) u = smax; } VSetPixel(dest, 0, i, j, u); VSetPixel(dest, 0, j, i, u); } } VCopyImageAttrs(src[0], dest); VSetAttr(VImageAttrList(dest), "similarity_metric", NULL, VStringRepn, "corr_pearson"); VSetAttr(VImageAttrList(dest), "name", NULL, VStringRepn, "similarity_matrix"); VSetAttr(VImageAttrList(dest), "map", NULL, VImageRepn, map); return dest; }
/*! \fn VImage VMedianImage3d (VImage src, VImage dest, int dim, VBoolean ignore) \param src input image \param dest output image \param dim kernel size (3,5,7...) \param ignore whether to ignore zero voxels */ VImage VMedianImage3d (VImage src, VImage dest, int dim, VBoolean ignore) { int nbands,nrows,ncols; int i,len,len2,b,r,c,bb,rr,cc,b0,b1,r0,r1,c0,c1,d=0; gsl_vector *vec=NULL; double u,tiny=1.0e-10; if (dim%2 == 0) VError("VMedianImage3d: dim (%d) must be odd",dim); nrows = VImageNRows (src); ncols = VImageNColumns (src); nbands = VImageNBands (src); if (nbands <= d) VError("VMedianImage3d: number of slices too small (%d)",nbands); d = dim/2; len = dim * dim * dim; len2 = 10; if (len < len2) len2 = len; vec = gsl_vector_calloc(len); dest = VCopyImage(src,dest,VAllBands); for (b=d; b<nbands-d; b++) { for (r=d; r<nrows-d; r++) { for (c=d; c<ncols-d; c++) { u = VGetPixel(src,b,r,c); if ( !ignore || ABS(u) > tiny) { i = 0; b0 = b-d; b1 = b+d; for (bb=b0; bb<=b1; bb++) { r0 = r-d; r1 = r+d; for (rr=r0; rr<=r1; rr++) { c0 = c-d; c1 = c+d; for (cc=c0; cc<=c1; cc++) { u = VGetPixel(src,bb,rr,cc); if (ABS(u) > tiny) { gsl_vector_set(vec,i,u); i++; } } } } if (i < len2) continue; gsl_sort_vector(vec); u = gsl_stats_median_from_sorted_data(vec->data,vec->stride,i); VSetPixel(dest,b,r,c,u); } } } } gsl_vector_free(vec); return dest; }
/*! \fn VImage VTriLinearSample3d (VImage src,VImage dest,VImage transform, float b0,float r0,float c0,int dst_nbands,int dst_nrows,int dst_ncolumns) \brief Resample a 3D image using trilinear interpolation. \param src input image (any repn) \param dest output image (any repn) \param transform 4x3 transformation image (float or double repn). The first column of <transform> contains the translation vector. The remaining three columns contains the 3x3 linear transformation matrix. \param b0 slice address that remains fixed \param r0 row address that remains fixed \param c0 column address that remains fixed \param dst_nbands number of output slices \param dst_nrows number of output rows \param dst_ncolumns number of output columns */ VImage VTriLinearSample3d(VImage src,VImage dest,VImage transform, float b0,float r0,float c0, int dst_nbands,int dst_nrows,int dst_ncolumns) { int src_nrows, src_ncols, src_nbands; VRepnKind repn; int b,r,c; int i,j,n; float bp,rp,cp,bx,rx,cx; float a[3][3],ainv[3][3],detA,signx; float shift[3]; float val; int sx, sy, sz; /* origin of subcube */ float px, py, pz; /* fractions of subcube */ float qx, qy, qz; /* fractions of subcube */ float value; /* value of voxel */ int lx, ly, lz; /* lengths */ int ox, oy, oz; /* offsets */ int x, y, z; /* indices */ if (VPixelRepn(transform) != VFloatRepn && VPixelRepn(transform) != VDoubleRepn) VError("transform image must be float or double repn"); /* Extract data from source image */ src_nrows = VImageNRows(src); src_ncols = VImageNColumns(src); src_nbands = VImageNBands(src); repn = VPixelRepn(src); /* get transformation matrix : */ for (i=0; i<3; i++) { for (j=0; j<3; j++) { a[i][j] = VGetPixel(transform,0,i,j+1); } } /* get its inverse : */ ainv[0][0] = a[1][1]*a[2][2] - a[1][2]*a[2][1]; ainv[1][0] = -a[1][0]*a[2][2] + a[1][2]*a[2][0]; ainv[2][0] = a[1][0]*a[2][1] - a[1][1]*a[2][0]; ainv[0][1] = -a[0][1]*a[2][2] + a[0][2]*a[2][1]; ainv[1][1] = a[0][0]*a[2][2] - a[0][2]*a[2][0]; ainv[2][1] = -a[0][0]*a[2][1] + a[0][1]*a[2][0]; ainv[0][2] = a[0][1]*a[1][2] - a[0][2]*a[1][1]; ainv[1][2] = -a[0][0]*a[1][2] + a[0][2]*a[1][0]; ainv[2][2] = a[0][0]*a[1][1] - a[0][1]*a[1][0]; /* determinant */ detA = a[0][0]*ainv[0][0] + a[0][1]*ainv[1][0] + a[0][2]*ainv[2][0]; if (detA == 0) VError(" VTriLinearSample3d: transformation matrix is singular"); for (i=0; i<3; i++) { for (j=0; j<3; j++) { ainv[i][j] /= detA; } } /* get translation vector */ shift[0] = VGetPixel(transform,0,0,0); shift[1] = VGetPixel(transform,0,1,0); shift[2] = VGetPixel(transform,0,2,0); #define GetValues(type) \ { \ type *src_pp; \ src_pp = (type *) VPixelPtr (src, sz, sy, sx); \ val += (float) pz * py * px * *src_pp; src_pp += ox; \ val += (float) pz * py * qx * *src_pp; src_pp += oy; \ val += (float) pz * qy * px * *src_pp; src_pp += ox; \ val += (float) pz * qy * qx * *src_pp; src_pp += oz; \ val += (float) qz * py * px * *src_pp; src_pp += ox; \ val += (float) qz * py * qx * *src_pp; src_pp += oy; \ val += (float) qz * qy * px * *src_pp; src_pp += ox; \ val += (float) qz * qy * qx * *src_pp; \ VPixel(dest,b,r,c,type) = val; \ } /* ** create output image */ dest = VSelectDestImage("VTriLinearSample3d",dest,dst_nbands,dst_nrows,dst_ncolumns,repn); if (! dest) return NULL; VFillImage(dest,VAllBands,0); /* Determines the value of each pixel in the destination image: */ for (b=0; b<dst_nbands; b++) { for (r=0; r<dst_nrows; r++) { for (c=0; c<dst_ncolumns; c++) { bx = (float) b - shift[0]; rx = (float) r - shift[1]; cx = (float) c - shift[2]; bp = ainv[0][0] * bx + ainv[0][1] * rx + ainv[0][2] * cx; rp = ainv[1][0] * bx + ainv[1][1] * rx + ainv[1][2] * cx; cp = ainv[2][0] * bx + ainv[2][1] * rx + ainv[2][2] * cx; bp += b0; rp += r0; cp += c0; if (bp < 0 || bp > src_nbands) continue; if (rp < 0 || rp > src_nrows) continue; if (cp < 0 || cp > src_ncols) continue; /* compute origin of subcube */ sx = (int) (cp); sy = (int) (rp); sz = (int) (bp); /* check subcube */ if ((sx < -1) || (sx > src_ncols - 1)) continue; if ((sy < -1) || (sy > src_nrows - 1)) continue; if ((sz < -1) || (sz > src_nbands - 1)) continue; /* compute fractions of subcube */ qx = cp - sx; px = 1 - qx; qy = rp - sy; py = 1 - qy; qz = bp - sz; pz = 1 - qz; /* compute lengths and offsets */ lx = 1; ly = src_ncols; lz = src_nrows * src_ncols; if (sx == -1) {sx = 0; lx = 0;}; if (sy == -1) {sy = 0; ly = 0;}; if (sz == -1) {sz = 0; lz = 0;}; if (sx == src_ncols - 1) lx = 0; if (sy == src_nrows - 1) ly = 0; if (sz == src_nbands - 1) lz = 0; ox = lx; oy = ox + ly - 2 * lx; oz = oy + lz - 2 * ly; val = 0; switch(repn) { case VShortRepn: GetValues(VShort); break; case VUByteRepn: GetValues(VUByte); break; case VFloatRepn: GetValues(VFloat); break; case VSByteRepn: GetValues(VSByte); break; default: VError(" illegal pixel repn"); } } } } VCopyImageAttrs (src, dest); return dest; }
int main(int argc, char *argv[]) { static VFloat reso = -1.0; static VLong itype = 0; static VBoolean flip = TRUE; static VBoolean reorder = TRUE; static VOptionDescRec options[] = { { "reso", VFloatRepn, 1, (VPointer) &reso, VOptionalOpt, NULL, "New voxel resolution in mm, def: -1 means min(1.0,\"best source resolution\")" }, { "flip", VBooleanRepn, 1, (VPointer) &flip, VOptionalOpt, NULL, "Whether to flip to natural convention" }, { "reorder", VBooleanRepn, 1, (VPointer) &reorder, VOptionalOpt, NULL, "Whether to reorder axial slices from axial source image" }, { "interpolation", VLongRepn, 1, & itype, VOptionalOpt, ITYPDict, "Type of interpolation (0: linear, 1: nearest neighbour, 2: cubic spline)" } }; FILE *in_file, *out_file; VAttrList list; VAttrListPosn posn; int nobjects = 0; VImage src = NULL, dest = NULL, result = NULL; int i, b, r, c, nbands, nrows, ncols; VString str, newstr, fixpointString, caString, cpString; float fix_c, fix_r, fix_b; float ca_c, ca_r, ca_b; float cp_c, cp_r, cp_b; float x, y, z, min; VDouble v, scale_band, scale_row, scale_col; float scale[3], shift[3]; /* print information */ char prg_name[100]; char ver[100]; getLipsiaVersion(ver, sizeof(ver)); sprintf(prg_name, "visotrop V%s", ver); fprintf(stderr, "%s\n", prg_name); fflush(stderr); /* Parse command line arguments: */ VParseFilterCmd(VNumber(options), options, argc, argv, & in_file, & out_file); /* Read source image(s): */ if(!(list = VReadFile(in_file, NULL))) exit(EXIT_FAILURE); /* Scale each object: */ for(VFirstAttr(list, & posn); VAttrExists(& posn); VNextAttr(& posn)) { switch(VGetAttrRepn(& posn)) { case VImageRepn: VGetAttrValue(& posn, NULL, VImageRepn, & src); if(VGetAttr(VImageAttrList(src), "voxel", NULL, VStringRepn, (VPointer) & str) == VAttrFound) { sscanf(str, "%f %f %f", &x, &y, &z); fprintf(stderr, " voxel: %f %f %f\n", x, y, z); min = x < y ? x : y; min = z < min ? z : min; /* if resolution is not set, use default value 1 or smaler value if the image resolution is better */ if(reso < 0.0) reso = min < 1.0 ? min : 1.0; if(reso <= 0.0) exit(EXIT_FAILURE); fprintf(stderr, " new resolution: %f \n", reso); scale_col = x / reso; scale_row = y / reso; scale_band = z / reso; nbands = VImageNBands(src) * scale_band; nrows = VImageNRows(src) * scale_row; ncols = VImageNColumns(src) * scale_col; if(VImageNBands(src) == nbands && VImageNRows(src) == nrows && VImageNColumns(src) == ncols) { itype = 0; } fprintf(stderr, " interpolation type: %s\n", ITYPDict[itype].keyword); fprintf(stderr, " old dim: %3d %3d %3d\n", VImageNBands(src), VImageNRows(src), VImageNColumns(src)); for(i = 0; i < 3; i++) shift[i] = scale[i] = 0; scale[0] = scale_band; scale[1] = scale_row; scale[2] = scale_col; switch(itype) { /* trilinear interpolation resampling */ case 0: dest = VTriLinearScale3d(src, NULL, (int)nbands, (int)nrows, (int)ncols, shift, scale); break; /* nearest neightbour resampling */ case 1: dest = VNNScale3d(src, NULL, (int)nbands, (int)nrows, (int)ncols, shift, scale); break; /* cubic spline */ case 2: dest = VCubicSplineScale3d(src, NULL, (int)nbands, (int)nrows, (int)ncols, shift, scale); break; case 3: /* no interpolation, just reshuffle */ dest = VCopyImage(src, NULL, VAllBands); break; default: VError(" unknown resampling type %d", itype); } if(! dest) exit(EXIT_FAILURE); /*aa 2003/09/11 added function not to rotate siemens data*/ if(! VGetAttr(VImageAttrList(src), "orientation", NULL, VStringRepn, (VPointer) & str) == VAttrFound) VError(" attribute 'orientation' missing"); if(strcmp(str, "axial") == 0) { fprintf(stderr, " new dim: %3d %3d %3d\n", nbands, nrows, ncols); result = VCreateImage(nbands, nrows, ncols, VPixelRepn(src)); VFillImage(result, VAllBands, 0); for(b = 0; b < nbands; b++) for(r = 0; r < nrows; r++) for(c = 0; c < ncols; c++) { v = VGetPixel(dest, b, r, c); if((flip == FALSE) && (reorder == FALSE)) VSetPixel(result, b, r, ncols - c - 1, v); else if((flip == TRUE) && (reorder == FALSE)) VSetPixel(result, b, r, c, v); else if((flip == FALSE) && (reorder == TRUE)) VSetPixel(result, nbands - b - 1, r, ncols - c - 1, v); else if((flip == TRUE) && (reorder == TRUE)) VSetPixel(result, nbands - b - 1, r, c, v); } } else if(strcmp(str, "sagittal") == 0) { /* re-arrange from sagittal to axial orientation */ fprintf(stderr, " new dim: %3d %3d %3d\n", nrows, ncols, nbands); result = VCreateImage(nrows, ncols, nbands, VPixelRepn(src)); VFillImage(result, VAllBands, 0); for(b = 0; b < nbands; b++) for(r = 0; r < nrows; r++) for(c = 0; c < ncols; c++) { v = VGetPixel(dest, b, r, c); if(flip == FALSE) VSetPixel(result, r, c, nbands - b - 1, v); else VSetPixel(result, r, c, b, v); } } else if(strcmp(str, "coronal") == 0) { /* re-arrange from coronal to axial orientation */ fprintf(stderr, " new dim: %3d %3d %3d\n", nrows, nbands, ncols); result = VCreateImage(nrows, nbands, ncols, VPixelRepn(src)); VFillImage(result, VAllBands, 0); for(b = 0; b < nbands; b++) for(r = 0; r < nrows; r++) for(c = 0; c < ncols; c++) { v = VGetPixel(dest, b, r, c); if(flip == FALSE) VSetPixel(result, r, b, ncols - c - 1, v); else VSetPixel(result, r, b, c, v); } } else { VError(" unknown resampling type %d", itype); exit(EXIT_FAILURE); } /* copy attributes from source image */ VCopyImageAttrs(src, result); // [TS] 08/03/27 // correct 'fixpoint', 'ca' and 'cp' if they exist in the source image // // NOTE: // this is only done when no flipping or reordering is requested :-( // (WARNING!!!!) '-flip true' actually means that no flipping is done (WHAAAAT ????) // and therefore we test for reorder = false and flip = true fixpointString = VMalloc(80); caString = VMalloc(80); cpString = VMalloc(80); VBoolean _issueWarning = FALSE; if(VGetAttr(VImageAttrList(src), "fixpoint", NULL, VStringRepn, (VPointer)&fixpointString) == VAttrFound) { if(reorder == FALSE && flip == TRUE) { sscanf(fixpointString, "%f %f %f", &fix_c, &fix_r, &fix_b); fix_c *= scale_col; fix_r *= scale_row; fix_b *= scale_band; sprintf((char *)fixpointString, "%f %f %f", fix_c, fix_r, fix_b); VSetAttr(VImageAttrList(result), "fixpoint", NULL, VStringRepn, fixpointString); } else { _issueWarning = TRUE; } } if(VGetAttr(VImageAttrList(src), "ca", NULL, VStringRepn, (VPointer)&caString) == VAttrFound) { if(reorder == FALSE && flip == TRUE) { sscanf(caString, "%f %f %f", &ca_c, &ca_r, &ca_b); ca_c *= scale_col; ca_r *= scale_row; ca_b *= scale_band; sprintf((char *)caString, "%f %f %f", ca_c, ca_r, ca_b); VSetAttr(VImageAttrList(result), "ca", NULL, VStringRepn, caString); } else { _issueWarning = TRUE; } } if(VGetAttr(VImageAttrList(src), "cp", NULL, VStringRepn, (VPointer)&cpString) == VAttrFound) { if(reorder == FALSE && flip == TRUE) { sscanf(cpString, "%f %f %f", &cp_c, &cp_r, &cp_b); cp_c *= scale_col; cp_r *= scale_row; cp_b *= scale_band; sprintf((char *)cpString, "%f %f %f", cp_c, cp_r, cp_b); VSetAttr(VImageAttrList(result), "cp", NULL, VStringRepn, cpString); } else { _issueWarning = TRUE; } } if(_issueWarning) { VWarning("Attributes 'fixpoint', 'ca' and 'cp' exist but were not corrected and are therefore likely to be wrong"); VWarning("This was caused by setting -flip to false or -reorder to true"); VWarning("Please correct the values manually using vattredit"); } /* set the attributes to the changed values */ newstr = VMalloc(80); sprintf((char *)newstr, "%f %f %f", reso, reso, reso); VSetAttr(VImageAttrList(result), "voxel", NULL, VStringRepn, newstr); VSetAttr(VImageAttrList(result), "orientation", NULL, VStringRepn, "axial"); if(flip) VSetAttr(VImageAttrList(result), "convention", NULL, VStringRepn, "natural"); else VSetAttr(VImageAttrList(result), "convention", NULL, VStringRepn, "radiologic"); } VSetAttrValue(& posn, NULL, VImageRepn, result); VDestroyImage(src); break; default: continue; } nobjects++; } /* Make History */ VHistory(VNumber(options), options, prg_name, &list, &list); /* Write the results to the output file: */ if(! VWriteFile(out_file, list)) exit(EXIT_FAILURE); fprintf(stderr, "%s: done.\n", argv[0]); return EXIT_SUCCESS; }
/* ** general linear regression */ VAttrList VRegression(ListInfo *linfo, int nlists, VShort minval, VImage design, VFloat sigma, VLong itr) { VAttrList out_list; VImageInfo *xinfo; int nbands = 0, nslices = 0, nrows = 0, ncols = 0, slice, row, col, nr, nc; VImage src[NSLICES], res_image = NULL; VImage beta_image[MBETA], BCOV = NULL, KX_image = NULL; VImage res_map[ETMP]; float smooth_fwhm = 0, vx = 0, vy = 0, vz = 0; VFloat *float_pp, df; VRepnKind repn; float d, err; int i, k, l, n, m = 0, nt, fd = 0, npix = 0; int i0 = 0, i1 = 0; double u, sig, trace = 0, trace2 = 0, var = 0, sum = 0, nx = 0, mean = 0, sum2; float *ptr1, *ptr2; double x; gsl_matrix_float *X = NULL, *XInv = NULL, *SX = NULL; gsl_vector_float *y, *z, *beta, *ys; gsl_vector *kernel; gsl_matrix_float *S = NULL, *Vc = NULL, *F = NULL, *P = NULL, *Q = NULL; gsl_matrix_float *R = NULL, *RV = NULL; VBoolean smooth = TRUE; /* no smoothness estimation */ gsl_set_error_handler_off(); /* ** read input data */ nslices = nbands = nrows = ncols = 0; for(k = 0; k < nlists; k++) { n = linfo[k].nslices; nr = linfo[k].nrows; nc = linfo[k].ncols; nt = linfo[k].ntimesteps; nbands += nt; if(nslices == 0) nslices = n; else if(nslices != n) VError(" inconsistent image dimensions, slices: %d %d", n, nslices); if(nrows == 0) nrows = nr; else if(nrows != nr) VError(" inconsistent image dimensions, rows: %d %d", nr, nrows); if(ncols == 0) ncols = nc; else if(ncols != nc) VError(" inconsistent image dimensions, cols: %d %d", nc, ncols); } fprintf(stderr, " num images: %d, image dimensions: %d x %d x %d\n", nlists, nslices, nrows, ncols); /* ** get design dimensions */ m = VImageNRows(design); /* number of timesteps */ n = VImageNColumns(design); /* number of covariates */ fprintf(stderr, " ntimesteps=%d, num covariates=%d\n", m, n); if(n >= MBETA) VError(" too many covariates (%d), max is %d", n, MBETA); if(m != nbands) VError(" design dimension inconsistency: %d %d", m, nbands); fprintf(stderr, " working...\n"); /* ** read design matrix */ X = gsl_matrix_float_alloc(m, n); for(k = 0; k < m; k++) { for(l = 0; l < n; l++) { x = VGetPixel(design, 0, k, l); fmset(X, k, l, (float)x); } } /* ** pre-coloring, set up K-matrix, S=K, V = K*K^T with K=S */ S = gsl_matrix_float_alloc(m, m); GaussMatrix((double)sigma, S); Vc = fmat_x_matT(S, S, NULL); /* ** compute pseudoinverse */ SX = fmat_x_mat(S, X, NULL); XInv = fmat_PseudoInv(SX, NULL); /* ** get variance estimate */ Q = fmat_x_mat(XInv, Vc, Q); F = fmat_x_matT(Q, XInv, F); BCOV = VCreateImage(1, n, n, VFloatRepn); float_pp = VImageData(BCOV); ptr1 = F->data; for(i = 0; i < n * n; i++) *float_pp++ = *ptr1++; gsl_matrix_float_free(Q); gsl_matrix_float_free(F); /* ** get effective degrees of freedom */ R = gsl_matrix_float_alloc(m, m); P = fmat_x_mat(SX, XInv, P); gsl_matrix_float_set_identity(R); gsl_matrix_float_sub(R, P); RV = fmat_x_mat(R, Vc, NULL); trace = 0; for(i = 0; i < m; i++) trace += fmget(RV, i, i); P = fmat_x_mat(RV, RV, P); trace2 = 0; for(i = 0; i < m; i++) trace2 += fmget(P, i, i); df = (trace * trace) / trace2; fprintf(stderr, " df= %.3f\n", df); /* ** create output images */ xinfo = linfo[0].info; out_list = VCreateAttrList(); res_image = VCreateImage(nslices, nrows, ncols, VFloatRepn); VFillImage(res_image, VAllBands, 0); VSetAttr(VImageAttrList(res_image), "name", NULL, VStringRepn, "RES/trRV"); VSetAttr(VImageAttrList(res_image), "modality", NULL, VStringRepn, "RES/trRV"); VSetAttr(VImageAttrList(res_image), "df", NULL, VFloatRepn, df); VSetAttr(VImageAttrList(res_image), "patient", NULL, VStringRepn, xinfo->patient); VSetAttr(VImageAttrList(res_image), "voxel", NULL, VStringRepn, xinfo->voxel); VSetAttr(VImageAttrList(res_image), "repetition_time", NULL, VLongRepn, itr); VSetAttr(VImageAttrList(res_image), "talairach", NULL, VStringRepn, xinfo->talairach); /* neu */ VSetAttr(VImageAttrList(res_image),"indexOrigin",NULL,VStringRepn,xinfo->indexOrigin); VSetAttr(VImageAttrList(res_image),"columnVec",NULL,VStringRepn,xinfo->columnVec); VSetAttr(VImageAttrList(res_image),"rowVec",NULL,VStringRepn,xinfo->rowVec); VSetAttr(VImageAttrList(res_image),"sliceVec",NULL,VStringRepn,xinfo->sliceVec); VSetAttr(VImageAttrList(res_image),"FOV",NULL,VStringRepn,xinfo->FOV); /*--------*/ if(xinfo->fixpoint[0] != 'N') VSetAttr(VImageAttrList(res_image), "fixpoint", NULL, VStringRepn, xinfo->fixpoint); if(xinfo->ca[0] != 'N') { VSetAttr(VImageAttrList(res_image), "ca", NULL, VStringRepn, xinfo->ca); VSetAttr(VImageAttrList(res_image), "cp", NULL, VStringRepn, xinfo->cp); VSetAttr(VImageAttrList(res_image), "extent", NULL, VStringRepn, xinfo->extent); } VAppendAttr(out_list, "image", NULL, VImageRepn, res_image); for(i = 0; i < n; i++) { beta_image[i] = VCreateImage(nslices, nrows, ncols, VFloatRepn); VFillImage(beta_image[i], VAllBands, 0); VSetAttr(VImageAttrList(beta_image[i]), "patient", NULL, VStringRepn, xinfo->patient); VSetAttr(VImageAttrList(beta_image[i]), "voxel", NULL, VStringRepn, xinfo->voxel); VSetAttr(VImageAttrList(beta_image[i]), "repetition_time", NULL, VLongRepn, itr); VSetAttr(VImageAttrList(beta_image[i]), "talairach", NULL, VStringRepn, xinfo->talairach); /* neu */ VSetAttr(VImageAttrList(beta_image[i]),"indexOrigin",NULL,VStringRepn,xinfo->indexOrigin); VSetAttr(VImageAttrList(beta_image[i]),"columnVec",NULL,VStringRepn,xinfo->columnVec); VSetAttr(VImageAttrList(beta_image[i]),"rowVec",NULL,VStringRepn,xinfo->rowVec); VSetAttr(VImageAttrList(beta_image[i]),"sliceVec",NULL,VStringRepn,xinfo->sliceVec); VSetAttr(VImageAttrList(beta_image[i]),"FOV",NULL,VStringRepn,xinfo->FOV); /*--------*/ if(xinfo->fixpoint[0] != 'N') VSetAttr(VImageAttrList(beta_image[i]), "fixpoint", NULL, VStringRepn, xinfo->fixpoint); if(xinfo->ca[0] != 'N') { VSetAttr(VImageAttrList(beta_image[i]), "ca", NULL, VStringRepn, xinfo->ca); VSetAttr(VImageAttrList(beta_image[i]), "cp", NULL, VStringRepn, xinfo->cp); VSetAttr(VImageAttrList(beta_image[i]), "extent", NULL, VStringRepn, xinfo->extent); } VSetAttr(VImageAttrList(beta_image[i]), "name", NULL, VStringRepn, "BETA"); VSetAttr(VImageAttrList(beta_image[i]), "modality", NULL, VStringRepn, "BETA"); VSetAttr(VImageAttrList(beta_image[i]), "beta", NULL, VShortRepn, i + 1); VSetAttr(VImageAttrList(beta_image[i]), "df", NULL, VFloatRepn, df); VAppendAttr(out_list, "image", NULL, VImageRepn, beta_image[i]); } VSetAttr(VImageAttrList(design), "name", NULL, VStringRepn, "X"); VSetAttr(VImageAttrList(design), "modality", NULL, VStringRepn, "X"); VAppendAttr(out_list, "image", NULL, VImageRepn, design); KX_image = Mat2Vista(SX); VSetAttr(VImageAttrList(KX_image), "name", NULL, VStringRepn, "KX"); VSetAttr(VImageAttrList(KX_image), "modality", NULL, VStringRepn, "KX"); VAppendAttr(out_list, "image", NULL, VImageRepn, KX_image); VSetAttr(VImageAttrList(BCOV), "name", NULL, VStringRepn, "BCOV"); VSetAttr(VImageAttrList(BCOV), "modality", NULL, VStringRepn, "BCOV"); VAppendAttr(out_list, "image", NULL, VImageRepn, BCOV); /* ** create temporary images for smoothness estimation */ /* smoothness estim only for 3D images, i.e. CA/CP known */ /* if(xinfo->ca[0] == 'N') smooth = FALSE;*/ if(smooth) { i0 = 20; i1 = i0 + 30; if(i1 > m) i1 = m; for(i = i0; i < i1; i++) { if(i - i0 >= ETMP) VError(" too many tmp images"); res_map[i - i0] = VCreateImage(nslices, nrows, ncols, VFloatRepn); VFillImage(res_map[i - i0], VAllBands, 0); } } /* ** process */ ys = gsl_vector_float_alloc(m); y = gsl_vector_float_alloc(m); z = gsl_vector_float_alloc(m); beta = gsl_vector_float_alloc(n); kernel = GaussKernel((double)sigma); for(k = 0; k < nlists; k++) { src[k] = VCreateImage(linfo[k].ntimesteps, nrows, ncols, linfo[k].repn); VFillImage(src[k], VAllBands, 0); } npix = 0; for(slice = 0; slice < nslices; slice++) { if(slice % 5 == 0) fprintf(stderr, " slice: %3d\r", slice); for(k = 0; k < nlists; k++) { if(linfo[k].zero[slice] == 0) goto next1; fd = open(linfo[k].filename, O_RDONLY); if(fd == -1) VError("could not open file %s", linfo[k].filename); nt = linfo[k].ntimesteps; if(! VReadBandDataFD(fd, &linfo[k].info[slice], 0, nt, &src[k])) VError(" error reading data"); close(fd); } repn = linfo[0].repn; for(row = 0; row < nrows; row++) { for(col = 0; col < ncols; col++) { for(k = 0; k < nlists; k++) if(VPixel(src[k], 0, row, col, VShort) < minval + 1) goto next; npix++; /* read time series data */ sum = sum2 = nx = 0; ptr1 = y->data; for(k = 0; k < nlists; k++) { nt = VImageNBands(src[k]); for(i = 0; i < nt; i++) { u = VPixel(src[k], i, row, col, VShort); (*ptr1++) = u; sum += u; sum2 += u * u; nx++; } } mean = sum / nx; sig = sqrt((double)((sum2 - nx * mean * mean) / (nx - 1.0))); if(sig < 0.001) continue; /* centering and scaling, Seber, p.330 */ ptr1 = y->data; for(i = 0; i < m; i++) { u = ((*ptr1) - mean) / sig; (*ptr1++) = u + 100.0; } /* S x y */ ys = VectorConvolve(y, ys, kernel); /* compute beta's */ fmat_x_vector(XInv, ys, beta); /* residuals */ fmat_x_vector(SX, beta, z); err = 0; ptr1 = ys->data; ptr2 = z->data; for(i = 0; i < m; i++) { d = ((*ptr1++) - (*ptr2++)); err += d * d; } /* sigma^2 */ var = err / trace; /* write residuals output */ VPixel(res_image, slice, row, col, VFloat) = (VFloat)var; /* save residuals of several timesteps for smoothness estimation */ if(smooth) { ptr1 = ys->data; ptr2 = z->data; err = 0; for(i = i0; i < i1; i++) { d = ((*ptr1++) - (*ptr2++)); err += d * d; VPixel(res_map[i - i0], slice, row, col, VFloat) = d; } if (err > 0) err = sqrt(err); for(i = i0; i < i1; i++) { d = VPixel(res_map[i - i0], slice, row, col, VFloat); if (err > 1.0e-6) d /= err; else d = 0; VPixel(res_map[i - i0], slice, row, col, VFloat) = d / err; } } /* write beta output */ ptr1 = beta->data; for(i = 0; i < n; i++) VPixel(beta_image[i], slice, row, col, VFloat) = (VFloat)(*ptr1++); next: ; } } next1: ; } /* ** Smoothness estimation based on residual images */ if(smooth) { smooth_fwhm = VSmoothnessEstim(res_map, i1 - i0); sscanf(xinfo->voxel, "%f %f %f", &vx, &vy, &vz); vx = (vx + vy + vz) / 3.0; /* voxels should be isotropic */ smooth_fwhm *= vx; fprintf(stderr, " smoothness: %f\n", smooth_fwhm); VSetAttr(VImageAttrList(res_image), "smoothness", NULL, VFloatRepn, smooth_fwhm); for(i = 0; i < n; i++) { VSetAttr(VImageAttrList(beta_image[i]), "smoothness", NULL, VFloatRepn, smooth_fwhm); } for(i = 0; i < i1 - i0; i++) VDestroyImage(res_map[i]); } ende: if(npix == 0) VError(" no voxels above threshold %d found", minval); return out_list; }
VImage GetMap(VAttrList list1,VAttrList list2,VImage mask,VShort minval) { VAttrListPosn posn; VImage src1[NSLICES],src2[NSLICES],map=NULL; size_t b,r,c,i,n; int nrows,ncols,nslices,nrows2,ncols2,nslices2; /* ** get image dimensions */ i = nrows = ncols = 0; for (VFirstAttr (list1, & posn); VAttrExists (& posn); VNextAttr (& posn)) { if (VGetAttrRepn (& posn) != VImageRepn) continue; VGetAttrValue (& posn, NULL,VImageRepn, & src1[i]); if (VPixelRepn(src1[i]) != VShortRepn) continue; if (VImageNRows(src1[i]) > nrows) nrows = VImageNRows(src1[i]); if (VImageNColumns(src1[i]) > ncols) ncols = VImageNColumns(src1[i]); i++; if (i >= NSLICES) VError(" too many slices"); } nslices = i; i = nrows2 = ncols2 = 0; for (VFirstAttr (list2, & posn); VAttrExists (& posn); VNextAttr (& posn)) { if (VGetAttrRepn (& posn) != VImageRepn) continue; VGetAttrValue (& posn, NULL,VImageRepn, & src2[i]); if (VPixelRepn(src2[i]) != VShortRepn) continue; if (VImageNRows(src2[i]) > nrows2) nrows2 = VImageNRows(src2[i]); if (VImageNColumns(src2[i]) > ncols2) ncols2 = VImageNColumns(src2[i]); i++; if (i >= NSLICES) VError(" too many slices"); } nslices2 = i; if (nslices2 != nslices) VError(" inconsistent number of slices: %d %d",nslices,nslices2); if (nrows2 != nrows) VError(" inconsistent number of rows: %d %d",nrows,nrows2); if (ncols2 != ncols) VError(" inconsistent number of cols: %d %d",ncols,ncols2); /* count number of voxels */ n = 0; for (b=0; b<nslices; b++) { if (VImageNRows(src1[b]) < 2) continue; if (VImageNRows(src2[b]) < 2) continue; for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { if (VPixel(src1[b],0,r,c,VShort) < minval) continue; if (VPixel(src2[b],0,r,c,VShort) < minval) continue; if (VGetPixel(mask,b,r,c) < 0.5) continue; n++; } } } fprintf(stderr," nvoxels: %ld\n",(long)n); /* ** voxel addresses */ map = VCreateImage(1,5,n,VShortRepn); if (map == NULL) VError(" error allocating addr map"); VFillImage(map,VAllBands,0); VCopyImageAttrs (src1[0],map); VPixel(map,0,3,0,VShort) = nslices; VPixel(map,0,3,1,VShort) = nrows; VPixel(map,0,3,2,VShort) = ncols; i = 0; for (b=0; b<nslices; b++) { if (VImageNRows(src1[b]) < 2) continue; if (VImageNRows(src2[b]) < 2) continue; for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { if (VPixel(src1[b],0,r,c,VShort) < minval) continue; if (VPixel(src2[b],0,r,c,VShort) < minval) continue; if (VGetPixel(mask,b,r,c) < 0.5) continue; VPixel(map,0,0,i,VShort) = b; VPixel(map,0,1,i,VShort) = r; VPixel(map,0,2,i,VShort) = c; i++; } } } return map; }
//////////////////////////////////////////////////////////////////////// // FUNCTION: WinGetPixel // // DESCRIPTION: This routine return the color value of a pixel in the // current draw window. // // PARAMETERS: (Coord) x - pointer to the x coordinate of a pixel // (Coord) y - pointer to the y coordinate of a pixel // // RETURNED: Returns the indexed color value of the pixel. // // REVISION HISTORY: // Name Date Description // ---- ---- ----------- // Jerry 5/29/01 Initial Revision //////////////////////////////////////////////////////////////////////// IndexedColorType WinGetPixel (Coord x, Coord y) { return VGetPixel (x, y); }
VImage VAddCovariates(VImage design, VString cfile) { VImage dest = NULL, tmp = NULL; FILE *fp = NULL; char buf[LEN], token[80]; int i, j, r, c, ncols, nrows, add_cols; double u; float x; add_cols = 0; nrows = VImageNRows(design); ncols = VImageNColumns(design); /* read first file */ fp = fopen(cfile, "r"); if(fp == NULL) VError(" err opening file %s", cfile); tmp = VCreateImage(1, nrows, NCOV, VFloatRepn); VFillImage(tmp, VAllBands, 0); i = 0; while(!feof(fp)) { for(j = 0; j < LEN; j++) buf[j] = '\0'; fgets(buf, LEN, fp); if(buf[0] == '#' || buf[0] == '%') continue; if(strlen(buf) < 2) continue; if(i > nrows) VError(" too many rows in file (%d), max is %d", i, nrows); j = 0; while(VStringToken(buf, token, j, 30)) { sscanf(token, "%f", &x); if(j >= NCOV) VError(" too many additional covariates (%d), max is %d", j, NCOV - 1); VPixel(tmp, 0, i, j, VFloat) = x; j++; } if(j < 1) continue; if(add_cols > 0 && j > add_cols) VError(" inconsistent number of columns (%d, %d), line %d", j, add_cols, i + 1); if(add_cols == 0 && j > add_cols) add_cols = j; if(i >= nrows) continue; i++; } fclose(fp); if(i != nrows) VError(" file: inconsistent number of rows: %d %d", i, nrows); /* ** create new design file */ dest = VCreateImage(1, nrows, ncols + add_cols, VPixelRepn(design)); VFillImage(dest, VAllBands, 1); VCopyImageAttrs(design, dest); for(r = 0; r < nrows; r++) { for(c = 0; c < ncols; c++) { u = VGetPixel(design, 0, r, c); VSetPixel(dest, 0, r, c, u); } } /* add covariates */ for(r = 0; r < nrows; r++) { for(c = 0; c < add_cols; c++) { u = VPixel(tmp, 0, r, c, VFloat); VSetPixel(dest, 0, r, c + ncols - 1, u); } } fprintf(stderr, " %d columns added to design file\n", add_cols); return dest; }
VImage VContrastAny(VImage src,VImage dest,VFloat low,VFloat high) { int nbands,nrows,ncols; double xmin,xmax,slope,sum,a; float *histo; int b,r,c,j,dim; VUByte *dest_pp; double smin,smax,u,v,tiny; nbands = VImageNBands(src); nrows = VImageNRows(src); ncols = VImageNColumns(src); dest = VSelectDestImage("VContrastAny",dest,nbands,nrows,ncols,VUByteRepn); if (! dest) VError(" err creating dest image"); VFillImage(dest,VAllBands,0); smin = VPixelMaxValue(src); smax = VPixelMinValue(src); for (b=0; b<nbands; b++) { for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { u = VGetPixel(src,b,r,c); if (u < smin) smin = u; if (u > smax) smax = u; } } } dim = 10000; if (VPixelRepn(src) == VUByteRepn) dim = 256; histo = (float *) VCalloc(dim,sizeof(float)); for (j=0; j<dim; j++) histo[j] = 0; tiny = 2.0/(double)dim; a = ((double) dim) / (smax - smin); for (b=0; b<nbands; b++) { for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { u = VGetPixel(src,b,r,c); if (ABS(u) < tiny) continue; j = (int) (a * (u - smin) + 0.5); if (j < 0) j = 0; if (j >= dim) j = dim-1; histo[j]++; } } } sum = 0; for (j=0; j<dim; j++) sum += histo[j]; for (j=0; j<dim; j++) histo[j] /= sum; xmin = 0; sum = 0; for (j=0; j<dim; j++) { sum += histo[j]; if (sum > low) break; } xmin = ((double)j)/a + smin; xmax = dim; sum = 0; for (j=dim; j>0; j--) { sum += histo[j]; if (sum > high) break; } xmax = ((double)j)/a + smin; slope = 255.0 / (xmax - xmin); dest_pp = (VUByte *) VImageData(dest); for (b=0; b<nbands; b++) { for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { u = VGetPixel(src,b,r,c); v = (int) (slope * (u - xmin) + 0.5); if (ABS(u) < tiny) v = 0; if (v < 0) v = 0; if (v > 255) v = 255; *dest_pp++ = (VUByte) v; } } } VCopyImageAttrs (src, dest); return dest; }
/*! \fn VImage VBiLinearScale2d (VImage src,VImage dest,int dest_nrows,int dest_ncols, VFloat yscale,VFloat xscale) \brief Scale all slices of a 3D image using a 2D slicewise bilinear interpolation. \param src input image (any repn) \param dest output image (any repn) \param dest_nrows number of rows in output image \param dest_ncols number of columns in output image \param shift[2] translation vector (row,column) \param scale[2] scaling vector (row,column) */ VImage VBiLinearScale2d (VImage src,VImage dest,int dest_nrows,int dest_ncols, VFloat shift[2], VFloat scale[2]) { int b,r,c; float rp=0,cp=0,x,y,yscale,xscale; int right,left,top,bottom; float p1,p2,p3,p4; float val; int nrows,ncols,nbands; VRepnKind repn; /* Extract data from source image */ nrows = VImageNRows(src); ncols = VImageNColumns(src); nbands = VImageNBands(src); repn = VPixelRepn(src); dest = VSelectDestImage("VBiLinearScale2d",dest,nbands,dest_nrows,dest_ncols,repn); if (! dest) return NULL; VFillImage(dest,VAllBands,0); #define Top(r) ( (int) (r) ) #define Bottom(r) ( (int) (r) + 1 ) #define Left(c) ( (int) (c) ) #define Right(c) ( (int) (c) + 1 ) yscale = 1.0 / scale[0]; xscale = 1.0 / scale[1]; for (b = 0; b < nbands; b++) { for (r = 0; r < dest_nrows; r++) { rp = yscale * ((float) r - shift[0]); if (rp < 0 || rp >= nrows) continue; for (c = 0; c < dest_ncols; c++) { cp = xscale * ((float) c - shift[1]); if (cp < 0 || cp >= ncols) continue; right = Right(cp); left = Left(cp); if (left < 0 || right >= ncols) continue; top = Top(rp); bottom = Bottom(rp); if (top < 0 || bottom >= nrows) continue; x = right - cp; y = bottom - rp; p1 = VGetPixel(src,b,top,left); p2 = VGetPixel(src,b,top,right); p3 = VGetPixel(src,b,bottom,left); p4 = VGetPixel(src,b,bottom,right); val = x * y * p1 + (1-x) * y * p2 + x * (1-y) * p3 + (1-x) * (1-y) * p4; if (repn == VUByteRepn) { val = (int)(val + 0.5); if (val < 0) val = 0; if (val > 255) val = 255; } VSetPixel(dest,b,r,c,(VDouble) val); } } } VCopyImageAttrs (src, dest); return dest; }
VImage VScaleIntensity(VImage src, double white, double black) /* scale any input image to VUByte, mapping white (black) percent of the voxel to white (black) */ { int x, y, z, nx, ny, nz, i, range, maxshort; unsigned int lb, ub, limit, sum, *histo; double m, b, max, min, mean, var, v; VImage dst; maxshort = (int)(VRepnMaxValue(VShortRepn)); histo = (unsigned int *)VCalloc(maxshort, sizeof(unsigned int)); nx = VImageNColumns(src); ny = VImageNRows(src); nz = VImageNBands(src); if (white < 0 || white > 100 || black < 0 || black > 100 || white+black >= 100) { fprintf(stderr, "VScaleIntensity: illegal percentage given.\n"); return 0; }; /* first pass: find maximum and minimum values */ VImageStats(src, VAllBands, &min, &max, &mean, &var); if (max == min) { fprintf(stderr, "VScaleIntensity: illegal data in image.\n"); return 0; }; b = min; m = (max-min) / (double)maxshort; /* second pass: build a histogram*/ for (z = 0; z < nz; z++) { for (y = 0; y < ny; y++) { for (x = 0; x < nx; x++) { v = VGetPixel(src, z, y, x); i = (int)((v-b)/m+0.5); histo[i]++; }; }; }; /* throw away pc percent of the voxel below lb and pc percent above ub */ limit = (black * nx * ny * nz) / 100; lb = 0; sum = 0; for (i = 0; i < maxshort; i++) { sum += histo[i]; if (sum >= limit) { lb = i; break; }; }; limit = (white * nx * ny * nz) / 100; ub = maxshort-1; sum = 0; for (i = maxshort-1; i >= 0; i--) { sum += histo[i]; if (sum >= limit) { ub = i; break; }; }; min = lb*m+b; max = ub*m+b; /* third pass: create and convert image */ dst = VCreateImage(nz, ny, nx, VUByteRepn); if (dst == 0) return 0; range = 256; m = range / (max - min); b = range - (m * max); for (z = 0; z < nz; z++) { for (y = 0; y < ny; y++) { for (x = 0; x < nx; x++) { v = VGetPixel(src, z, y, x); i = (int)(v * m + b + 0.5); if (i < 0) i = 0; else if (i >= range) i = range-1; VPixel(dst, z, y, x, VUByte) = i; }; }; }; VFree(histo); VCopyImageAttrs(src, dst); return dst; }
int main (int argc,char *argv[]) { static VString filename = ""; static VString filename1 = ""; static VString filename2 = ""; static VShort first = 2; static VShort length = 0; static VShort type = 0; static VShort minval = 0; static VShort nproc = 4; static VOptionDescRec options[] = { {"in1",VStringRepn,1,(VPointer) &filename1,VRequiredOpt,NULL,"first input file"}, {"in2",VStringRepn,1,(VPointer) &filename2,VRequiredOpt,NULL,"second input file"}, {"mask",VStringRepn,1,(VPointer) &filename,VRequiredOpt,NULL,"mask"}, {"type",VShortRepn,1,(VPointer) &type,VOptionalOpt,TYPDict,"type of concordance measure"}, {"minval",VShortRepn,1,(VPointer) &minval,VOptionalOpt,NULL,"signal threshold"}, {"first",VShortRepn,1,(VPointer) &first,VOptionalOpt,NULL,"first timestep to use"}, {"length",VShortRepn,1,(VPointer) &length,VOptionalOpt,NULL, "length of time series to use, '0' to use full length"}, {"j",VShortRepn,1,(VPointer) &nproc,VOptionalOpt,NULL,"number of processors to use, '0' to use all"} }; FILE *out_file,*fp; VAttrList list=NULL,list1=NULL,list2=NULL,out_list=NULL; VAttrListPosn posn; VImage mask=NULL,map=NULL,dest=NULL,disc=NULL; float *A1=NULL,*A2=NULL,u=0,tiny=1.0e-6; int b,r,c; char *prg = "vccm2"; VParseFilterCmd (VNumber (options),options,argc,argv,NULL,&out_file); if (type > 3) VError("illegal type"); /* ** read mask */ fp = VOpenInputFile (filename, TRUE); list = VReadFile (fp, NULL); if (! list) VError("Error reading mask file"); fclose(fp); for (VFirstAttr (list, & posn); VAttrExists (& posn); VNextAttr (& posn)) { if (VGetAttrRepn (& posn) != VImageRepn) continue; VGetAttrValue (& posn, NULL,VImageRepn, & mask); if (VPixelRepn(mask) == VFloatRepn || VPixelRepn(mask) == VDoubleRepn) { mask = NULL; continue; } } if (mask == NULL) VError(" no mask found"); /* read files */ fp = VOpenInputFile (filename1, TRUE); list1 = VReadFile (fp, NULL); if (! list1) VError("Error reading 1st input file"); fclose(fp); fp = VOpenInputFile (filename2, TRUE); list2 = VReadFile (fp, NULL); if (! list2) VError("Error reading 2nd input file"); fclose(fp); /* get voxel map */ map = GetMap(list1,list2,mask,minval); /* omp-stuff */ #ifdef _OPENMP int num_procs=omp_get_num_procs(); if (nproc > 0 && nproc < num_procs) num_procs = nproc; printf("using %d cores\n",(int)num_procs); omp_set_num_threads(num_procs); #endif /* _OPENMP */ /* compute corr matrices */ A1 = VCorrMatrix(list1,map,first,length); A2 = VCorrMatrix(list2,map,first,length); /* get concordance between two corr matrices */ dest = VCCM2(A1,A2,map,(int)type); /* invert to get discordant map */ disc = VCreateImageLike(dest); VFillImage(disc,VAllBands,0); if (type < 2) { for (b=0; b<VImageNBands(dest); b++) { for (r=0; r<VImageNRows(dest); r++) { for (c=0; c<VImageNColumns(dest); c++) { if (VGetPixel(mask,b,r,c) < 1) continue; u = VPixel(dest,b,r,c,VFloat); if (u < tiny) continue; VPixel(disc,b,r,c,VFloat) = 1-u; } } } } /* output */ out_list = VCreateAttrList(); VHistory(VNumber(options),options,prg,&list,&out_list); VAppendAttr(out_list,"concordant",NULL,VImageRepn,dest); if (type < 2) VAppendAttr(out_list,"discordant",NULL,VImageRepn,disc); if (! VWriteFile (out_file, out_list)) exit (1); fprintf (stderr, "%s: done.\n", argv[0]); return 0; }
/*! \fn VImage VAniso2d(VImage src,VImage dest,VShort numiter, VShort type,VFloat kappa,VFloat alpha); \param src input image \param dest output image \param numiter number of iterations \param type type of diffusion function (0 or 1) \param kappa parameter for diffusion function \param alpha parameter for diffusion function */ VImage VAniso2d(VImage src,VImage dest,VShort numiter, VShort type,VFloat kappa,VFloat alpha) { VImage tmp1=NULL,tmp2=NULL; int nbands,nrows,ncols; int b,r,c,iter; float delta; float dx,dy,dz,d,u,v; float ux1,ux2,uy1,uy2; float r1,r2,c1,c2; VDouble xmax,xmin; nbands = VImageNBands(src); nrows = VImageNRows(src); ncols = VImageNColumns(src); tmp1 = VCreateImage(1,nrows,ncols,VFloatRepn); tmp2 = VCreateImage(1,nrows,ncols,VFloatRepn); xmax = VPixelMaxValue (tmp1); xmin = VPixelMinValue (tmp1); dest = VCopyImage(src,dest,VAllBands); delta = 1.0 / 6.0; dz = 0; for (b=0; b<nbands; b++) { for (r=0; r<nrows; r++) { for (c=0; c<ncols; c++) { VPixel(tmp1,0,r,c,VFloat) = VGetPixel(src,b,r,c); } } for (iter=0; iter < numiter; iter++) { for (r=1; r<nrows-1; r++) { for (c=1; c<ncols-1; c++) { u = VPixel(tmp1,0,r,c,VFloat); c1 = VPixel(tmp1,0,r,c+1,VFloat); c2 = VPixel(tmp1,0,r,c-1,VFloat); r1 = VPixel(tmp1,0,r+1,c,VFloat); r2 = VPixel(tmp1,0,r-1,c,VFloat); /* col-dir */ dx = c1-u; dy = r1-r2; d = diffusion2d(dx,dy,type,kappa,alpha); ux1 = d*(c1 - u); dx = u-c2; d = diffusion2d(dx,dy,type,kappa,alpha); ux2 = d*(u - c2); /* row-dir */ dx = c1-c2; dy = r1-u; d = diffusion2d(dx,dy,type,kappa,alpha); uy1 = d*(r1 - u); dy = u-r2; d = diffusion2d(dx,dy,type,kappa,alpha); uy2 = d*(u - r2); /* sum */ v = u + delta*(ux1 - ux2 + uy1 - uy2); if (v > xmax) v = xmax; if (v < xmin) v = xmin; VPixel(tmp2,0,r,c,VFloat) = v; } } tmp1 = VCopyImagePixels(tmp2,tmp1,VAllBands); } /* ** output */ for (r=1; r<nrows-1; r++) { for (c=1; c<ncols-1; c++) { v = VPixel(tmp2,0,r,c,VFloat); if (v > VPixelMaxValue (dest)) v = VPixelMaxValue (dest); if (v < VPixelMinValue (dest)) v = VPixelMinValue (dest); VSetPixel(dest,b,r,c,(VDouble) v); } } } VDestroyImage(tmp1); VDestroyImage(tmp2); return dest; }