/* ** read a 2nd level design file */ VImage VRead2ndLevel(FILE *fp) { VImage dest = NULL; int i, j, nrows, ncols; float val; char buf[LEN], token[32]; nrows = ncols = 0; while(!feof(fp)) { memset(buf, 0, LEN); if(!fgets(buf, LEN, fp)) break; if(strlen(buf) < 1) continue; if(buf[0] == '%') continue; j = 0; while(VStringToken(buf, token, j, 30)) { if(!sscanf(token, "%f", &val)) VError("illegal input string: %s", token); j++; } if(ncols == 0) ncols = j; if(j < 1) continue; else if(ncols != j) VError(" inconsistent number of columns in row %d", nrows + 1); nrows++; } rewind(fp); dest = VCreateImage(1, nrows, ncols, VFloatRepn); VFillImage(dest, VAllBands, 0); VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, "X"); VSetAttr(VImageAttrList(dest), "name", NULL, VStringRepn, "X"); VSetAttr(VImageAttrList(dest), "ntimesteps", NULL, VLongRepn, (VLong)VImageNRows(dest)); VSetAttr(VImageAttrList(dest), "nsessions", NULL, VShortRepn, (VShort)1); VSetAttr(VImageAttrList(dest), "designtype", NULL, VShortRepn, (VShort)2); i = 0; while(!feof(fp)) { memset(buf, 0, LEN); if(!fgets(buf, LEN, fp)) break; if(strlen(buf) < 1) continue; if(buf[0] == '%') continue; j = 0; while(VStringToken(buf, token, j, 30)) { sscanf(token, "%f", &val); VPixel(dest, 0, i, j, VFloat) = val; j++; } if(j < 1) continue; i++; } return dest; }
VBoolean VSetBandInterp (VImage image, VBandInterp frame_interp, int nframes, VBandInterp viewpoint_interp, int nviewpoints, VBandInterp color_interp, int ncolors, VBandInterp component_interp, int ncomponents) { VBoolean result = TRUE; VString str; if (VImageNBands (image) != nframes * nviewpoints * ncolors * ncomponents) { VWarning ("VSetBandInterp: No. bands (%d) conflicts with no. " "of frames, etc. (%d %d %d %d)", VImageNBands (image), nframes, nviewpoints, ncolors, ncomponents); result = FALSE; } if (frame_interp == VBandInterpNone) result &= VExtractAttr (VImageAttrList (image), VFrameInterpAttr, NULL, VStringRepn, & str, FALSE); else VSetAttr (VImageAttrList (image), VFrameInterpAttr, VBandInterpDict, VLongRepn, (VLong) frame_interp); VImageNFrames (image) = nframes; if (viewpoint_interp == VBandInterpNone) result &= VExtractAttr (VImageAttrList (image), VViewpointInterpAttr, NULL, VStringRepn, & str, FALSE); else VSetAttr (VImageAttrList (image), VViewpointInterpAttr, VBandInterpDict, VLongRepn, (VLong) viewpoint_interp); VImageNViewpoints (image) = nviewpoints; if (color_interp == VBandInterpNone) result &= VExtractAttr (VImageAttrList (image), VColorInterpAttr, NULL, VStringRepn, & str, FALSE); else VSetAttr (VImageAttrList (image), VColorInterpAttr, VBandInterpDict, VLongRepn, (VLong) color_interp); VImageNColors (image) = ncolors; if (component_interp == VBandInterpNone) result &= VExtractAttr (VImageAttrList (image), VComponentInterpAttr, NULL, VStringRepn, & str, FALSE); else VSetAttr (VImageAttrList (image), VComponentInterpAttr, VBandInterpDict, VLongRepn, (VLong) component_interp); VImageNComponents (image) = ncomponents; return result; }
/* ** concordance mapping */ VImage VCCM2(float *A1,float *A2,VImage map,int type) { VImage dest=NULL; size_t b,r,c,i,j,k,kk,nvoxels; int nslices=0,nrows=0,ncols=0; double *arr1=NULL,*arr2=NULL,u; nslices = VPixel(map,0,3,0,VShort); nrows = VPixel(map,0,3,1,VShort); ncols = VPixel(map,0,3,2,VShort); nvoxels = VImageNColumns(map); dest = VCreateImage(nslices,nrows,ncols,VFloatRepn); VFillImage(dest,VAllBands,0); VCopyImageAttrs (map, dest); VSetAttr(VImageAttrList(dest),"modality",NULL,VStringRepn,"conimg"); arr1 = (double *) VCalloc(nvoxels,sizeof(double)); arr2 = (double *) VCalloc(nvoxels,sizeof(double)); fprintf(stderr," concordance mapping...\n"); for (i=0; i<nvoxels; i++) { if (i%50 == 0) fprintf(stderr," %6d of %d\r",i,nvoxels); b = (int)VPixel(map,0,0,i,VShort); r = (int)VPixel(map,0,1,i,VShort); c = (int)VPixel(map,0,2,i,VShort); for (j=0; j<nvoxels; j++) arr1[j] = arr2[j] = 0; kk = 0; for (j=0; j<i; j++) { k=j+i*(i+1)/2; arr1[kk] = (double)A1[k]; arr2[kk] = (double)A2[k]; kk++; } for (j=i+1; j<nvoxels; j++) { k=i+j*(j+1)/2; arr1[kk] = (double)A1[k]; arr2[kk] = (double)A2[k]; kk++; } u = 0; switch (type) { case 0: u = kendall(arr1,arr2,nvoxels); break; case 1: u = CCC(arr1,arr2,nvoxels); break; default: VError("illegal type"); } VPixel(dest,b,r,c,VFloat) = (VFloat)u; } fprintf(stderr,"\n"); 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; }
VImage WriteOutput(VImage src,VImage map,int nslices,int nrows, int ncols, float *ev, int n) { VImage dest=NULL; int i,b,r,c; dest = VCreateImage(nslices,nrows,ncols,VFloatRepn); VFillImage(dest,VAllBands,0); VCopyImageAttrs (src, dest); VSetAttr(VImageAttrList(dest),"modality",NULL,VStringRepn,"conimg"); 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); if (b < 0 || r < 0 || c < 0) VError(" WriteOutput: illegal address %d %d %d",b,r,c); VPixel(dest,b,r,c,VFloat) = ev[i]; } return dest; }
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; }
/* ** slicetime correction for non-constant TR */ void VSlicetime_NC(VAttrList list, VShort minval, VFloat tdel, VBoolean slicetime_correction, float *onset_array, VString filename) { FILE *fp = NULL; VImage src; VAttrListPosn posn; VString buf, str; int b, r, c, i, j, nt = 0, mt = 0, val, del = 0; double xmin, xmax, sum, nx, estim_tr = 0; double *xx = NULL, *yy = NULL, xi, yi, slicetime = 0, u = 0; gsl_interp_accel *acc = NULL; gsl_spline *spline = NULL; xmin = (VShort) VRepnMinValue(VShortRepn); xmax = (VShort) VRepnMaxValue(VShortRepn); buf = VMalloc(LEN); /* ** read scan times from file, non-constant TR */ if(strlen(filename) > 2) { fp = fopen(filename, "r"); if(!fp) VError(" error opening file %s", filename); 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; i++; } rewind(fp); nt = i; fprintf(stderr, " num timesteps: %d\n", nt); xx = (double *) VCalloc(nt, sizeof(double)); yy = (double *) VCalloc(nt, sizeof(double)); i = 0; sum = 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(sscanf(buf, "%lf", &u) != 1) VError(" line %d: illegal input format", i + 1); xx[i] = u * 1000.0; /* convert to millisec */ if(i > 1) sum += xx[i] - xx[i - 1]; i++; } fclose(fp); estim_tr = sum / (double)(nt - 2); fprintf(stderr, " average scan interval = %.3f sec\n", estim_tr / 1000.0); } /* ** process data */ b = -1; for(VFirstAttr(list, & posn); VAttrExists(& posn); VNextAttr(& posn)) { if(VGetAttrRepn(& posn) != VImageRepn) continue; VGetAttrValue(& posn, NULL, VImageRepn, & src); if(VPixelRepn(src) != VShortRepn) continue; VSetAttr(VImageAttrList(src), "repetition_time", NULL, VLongRepn, (VLong)estim_tr); VExtractAttr(VImageAttrList(src), "MPIL_vista_0", NULL, VStringRepn, &str, FALSE); b++; if(VImageNRows(src) < 2) continue; /* ** get header info */ if(VGetAttr(VImageAttrList(src), "slice_time", NULL, VDoubleRepn, (VPointer) & slicetime) != VAttrFound && slicetime_correction && onset_array == NULL) VError(" 'slice_time' info missing"); if(onset_array != NULL) slicetime = onset_array[b]; if(nt != VImageNBands(src)) VError(" inconsistent number of time steps, %d %d", nt, VImageNBands(src)); if(acc == NULL && slicetime_correction) { acc = gsl_interp_accel_alloc(); spline = gsl_spline_alloc(gsl_interp_akima, nt); for(i = 0; i < 5; i++) { if(xx[i] / 1000.0 > tdel) break; } del = i; fprintf(stderr, " The first %.2f secs (%d timesteps) will be replaced.\n", tdel, del); } /* ** loop through all voxels in current slice */ if(slicetime_correction) fprintf(stderr, " slice: %3d, %10.3f ms\r", b, slicetime); for(r = 0; r < VImageNRows(src); r++) { for(c = 0; c < VImageNColumns(src); c++) { if(VPixel(src, 0, r, c, VShort) < minval) continue; /* replace first few time steps by average */ if(del > 0) { mt = del + 10; if(mt > nt) mt = nt; sum = nx = 0; for(i = del; i < mt; i++) { sum += VPixel(src, i, r, c, VShort); nx++; } if(nx < 1) continue; val = sum / nx; for(i = 0; i < del; i++) { VPixel(src, i, r, c, VShort) = val; } } if(!slicetime_correction) continue; /* correct for slicetime offsets using cubic spline interpolation */ for(i = 0; i < nt; i++) { yy[i] = VPixel(src, i, r, c, VShort); } gsl_spline_init(spline, xx, yy, nt); for(i = 1; i < nt; i++) { xi = xx[i] - slicetime; yi = gsl_spline_eval(spline, xi, acc); val = (int)(yi + 0.49); if(val > xmax) val = xmax; if(val < xmin) val = xmin; VPixel(src, i, r, c, VShort) = val; } } } } fprintf(stderr, "\n"); }
VImage PairedTest(VImage *src1, VImage *src2, VImage dest, int n, VShort type) { int i, j, k, b, r, c, nslices, nrows, ncols; float ave1, ave2, var1, var2, nx, u; float sum, smooth = 0; float t, z, df, sd, cov, *data1 = NULL, *data2 = NULL; float tiny = 1.0e-10; nslices = VImageNBands(src1[0]); nrows = VImageNRows(src1[0]); ncols = VImageNColumns(src1[0]); gsl_set_error_handler_off(); dest = VCopyImage(src1[0], NULL, VAllBands); VFillImage(dest, VAllBands, 0); VSetAttr(VImageAttrList(dest), "num_images", NULL, VShortRepn, (VShort)n); VSetAttr(VImageAttrList(dest), "patient", NULL, VStringRepn, "paired_ttest"); if(type == 0) VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, "tmap"); else VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, "zmap"); VSetAttr(VImageAttrList(dest), "df", NULL, VShortRepn, (VShort)(n - 1)); /* get smoothness estimates */ sum = nx = 0; for(i = 0; i < n; i++) { if(VGetAttr(VImageAttrList(src1[i]), "smoothness", NULL, VFloatRepn, &smooth) == VAttrFound) { sum += smooth; nx++; } } for(i = 0; i < n; i++) { if(VGetAttr(VImageAttrList(src2[i]), "smoothness", NULL, VFloatRepn, &smooth) == VAttrFound) { sum += smooth; nx++; } } if(nx > 1) { VSetAttr(VImageAttrList(dest), "smoothness", NULL, VFloatRepn, sum / nx); } data1 = (float *) VMalloc(n * sizeof(float)); data2 = (float *) VMalloc(n * sizeof(float)); df = n - 1; nx = (float)n; for(b = 0; b < nslices; b++) { for(r = 0; r < nrows; r++) { for(c = 0; c < ncols; c++) { k = 0; for(i = 0; i < n; i++) { data1[i] = VPixel(src1[i], b, r, c, VFloat); data2[i] = VPixel(src2[i], b, r, c, VFloat); if(ABS(data1[i]) > tiny && ABS(data2[i]) > tiny) k++; } if(k < n - 3) continue; avevar(data1, n, &ave1, &var1); avevar(data2, n, &ave2, &var2); if(var1 < tiny || var2 < tiny) continue; z = t = 0; cov = 0; for(j = 0; j < n; j++) cov += (data1[j] - ave1) * (data2[j] - ave2); cov /= df; u = (var1 + var2 - 2.0 * cov); if(u < tiny) continue; sd = sqrt(u / nx); if(sd < tiny) continue; t = (ave1 - ave2) / sd; if(isnan(t) || isinf(t)) continue; switch(type) { case 0: VPixel(dest, b, r, c, VFloat) = t; break; case 1: /* z = t2z_approx(t,df); */ z = t2z((double)t, (double)df); if(t < 0) z = -z; VPixel(dest, b, r, c, VFloat) = z; break; default: VError(" illegal type"); } } } } return dest; }
/* ** 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; }
int main(int argc, char *argv[]) { static VLong objnr = -1; static VString name = ""; static VString value = ""; static VOptionDescRec options[] = { { "obj", VLongRepn, 1, (VPointer) &objnr, VOptionalOpt, NULL, "object number, all objects (-1)" }, { "name", VStringRepn, 1, (VPointer) &name, VRequiredOpt, NULL, "attribute name" }, { "value", VStringRepn, 1, (VPointer) &value, VRequiredOpt, NULL, "attribute value" } }; FILE *in_file, *out_file; VAttrList list, olist; VAttrListPosn posn; VImage isrc; VGraph gsrc; Volumes vsrc; VString buf; int nobj; char prg_name[100]; char ver[100]; getLipsiaVersion(ver, sizeof(ver)); sprintf(prg_name, "vattredit V%s", ver); fprintf(stderr, "%s\n", prg_name); /* Parse command line arguments and identify files: */ VParseFilterCmd(VNumber(options), options, argc, argv, &in_file, & out_file); /* Read source image(s): */ if(!(list = VReadFile(in_file, NULL))) exit(1); /* Process each image: */ nobj = 0; for(VFirstAttr(list, & posn); VAttrExists(& posn); VNextAttr(& posn)) { olist = NULL; if(nobj == objnr || objnr < 0) { if(VGetAttrRepn(& posn) == VImageRepn) { VGetAttrValue(& posn, NULL, VImageRepn, & isrc); olist = VImageAttrList(isrc); } else if(VGetAttrRepn(& posn) == VGraphRepn) { VGetAttrValue(& posn, NULL, VGraphRepn, & gsrc); olist = VGraphAttrList(gsrc); } else if(VGetAttrRepn(& posn) == VolumesRepn) { VGetAttrValue(& posn, NULL, VolumesRepn, & vsrc); olist = VolumesAttrList(vsrc); } if(olist != NULL) { if(VGetAttr(olist, name, NULL, VStringRepn, &buf) == VAttrFound) fprintf(stderr, " object %3d, old value: %s\n", nobj, buf); VSetAttr(olist, name, NULL, VStringRepn, value); fprintf(stderr, " object %3d, new value: %s\n", nobj, value); } } nobj++; } /* Make History */ VHistory(VNumber(options), options, prg_name, &list, &list); /* Write out the results: */ if(! VWriteFile(out_file, list)) exit(1); fprintf(stderr, "%s: done.\n", argv[0]); return 0; }
VImage PairedWilcoxTest(VImage *src1, VImage *src2, VImage dest, int n) { int i, m, k, b, r, c, nslices, nrows, ncols; int sumpos, sumneg, w; double wx, u, v, z, p, tiny = 1.0e-10; double *ptr1, *ptr2; float *table = NULL; gsl_vector *vec1 = NULL, *vec2 = NULL; gsl_permutation *perm = NULL, *rank = NULL; extern void gsl_sort_vector_index(gsl_permutation *, gsl_vector *); nslices = VImageNBands(src1[0]); nrows = VImageNRows(src1[0]); ncols = VImageNColumns(src1[0]); dest = VCopyImage(src1[0], NULL, VAllBands); VFillImage(dest, VAllBands, 0); VSetAttr(VImageAttrList(dest), "num_images", NULL, VShortRepn, (VShort)n); VSetAttr(VImageAttrList(dest), "patient", NULL, VStringRepn, "paired_wilcoxtest"); VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, "zmap"); m = 0; for(i = 1; i <= n; i++) m += i; if(n > 18) { table = getTable(n); for(i = 0; i < m; i++) { p = table[i]; p *= 0.5; if(p < tiny) p = tiny; z = p2z(p); if(z < 0) z = 0; table[i] = z; } } else { table = (float *) VMalloc(sizeof(float) * m); for(i = 0; i < m; i++) { for(i = 0; i < m; i++) { wx = i; p = LevelOfSignificanceWXMPSR(wx, (long int)n); p *= 0.5; z = p2z(p); table[i] = z; } } } vec1 = gsl_vector_calloc(n); vec2 = gsl_vector_calloc(n); perm = gsl_permutation_alloc(n); rank = gsl_permutation_alloc(n); for(b = 0; b < nslices; b++) { for(r = 0; r < nrows; r++) { for(c = 0; c < ncols; c++) { k = 0; ptr1 = vec1->data; ptr2 = vec2->data; for(i = 0; i < n; i++) { u = VPixel(src1[i], b, r, c, VFloat); v = VPixel(src2[i], b, r, c, VFloat); if(ABS(u) > tiny && ABS(v) > tiny) k++; *ptr1++ = ABS(u - v); *ptr2++ = u - v; } if(k < n / 2) continue; gsl_sort_vector_index(perm, vec1); gsl_permutation_inverse(rank, perm); sumpos = sumneg = 0; ptr2 = vec2->data; for(i = 0; i < n; i++) { u = *ptr2++; if(u > 0) sumpos += rank->data[i]; else if(u < 0) sumneg += rank->data[i]; } w = sumpos; if(sumpos > sumneg) w = sumneg; if(w >= m) z = 0; else z = table[w]; if(sumneg > sumpos) z = -z; VPixel(dest, b, r, c, VFloat) = z; } } } return dest; }
VImage VDoTrans(VImage src, VImage dest, VImage transform, VFloat resolution, VLong type) { VImage src1 = NULL, dest_cor = NULL, dest_sag = NULL, trans = NULL; int i, nbands1 = 0, nrows1 = 0, ncols1 = 0; int xdim, ydim, zdim; int orient = AXIAL; float b0, r0, c0; float scaleb, scaler, scalec; float scale[3], shift[3]; VString str, str1, str2, str3, str4, str5, str6; VShort buf; VDouble u; float transResX = 1.0, transResY = 1.0, transResZ = 1.0; VString _transResString; if(VGetAttr(VImageAttrList(transform), "voxel", NULL, VStringRepn, (VPointer) &_transResString) == VAttrFound) { sscanf(_transResString, "%f %f %f", &transResX, &transResY, &transResZ); } /* ** get matrix size */ xdim = 160; ydim = 200; zdim = 160; if(VGetAttr(VImageAttrList(transform), "zdim", NULL, VShortRepn, (VPointer) & buf) == VAttrFound) { zdim = buf; } if(VGetAttr(VImageAttrList(transform), "ydim", NULL, VShortRepn, (VPointer) & buf) == VAttrFound) { ydim = buf; } if(VGetAttr(VImageAttrList(transform), "xdim", NULL, VShortRepn, (VPointer) & buf) == VAttrFound) { xdim = buf; } /* ** get slice orientation */ if(VGetAttr(VImageAttrList(src), "orientation", NULL, VStringRepn, (VPointer) & str) != VAttrFound) VError(" attribute 'orientation' missing in input file."); if(strcmp(str, "coronal") == 0) { orient = CORONAL; nbands1 = ydim; nrows1 = zdim; ncols1 = xdim; } else if(strcmp(str, "axial") == 0) { orient = AXIAL; nbands1 = zdim; nrows1 = ydim; ncols1 = xdim; } else if(strcmp(str, "sagittal") == 0) { orient = SAGITTAL; nbands1 = zdim; nrows1 = xdim; ncols1 = ydim; } else VError("orientation must be axial or coronal"); nbands1 /= (resolution / transResX); nrows1 /= (resolution / transResY); ncols1 /= (resolution / transResZ); /* ** scale to size */ if(VGetAttr(VImageAttrList(src), "voxel", NULL, VStringRepn, (VPointer) & str) != VAttrFound) VError(" attribute 'voxel' missing in input file."); sscanf(str, "%f %f %f", &scalec, &scaler, &scaleb); scaleb /= (resolution / transResX); scaler /= (resolution / transResY); scalec /= (resolution / transResZ); scale[0] = scaleb; scale[1] = scaler; scale[2] = scalec; shift[0] = 0; shift[1] = (float)nrows1 * 0.5 - scaler * (float)VImageNRows(src) * 0.5; shift[2] = (float)ncols1 * 0.5 - scalec * (float)VImageNColumns(src) * 0.5; src1 = VShuffleSlices(src, NULL); switch(type) { case 0: src = VTriLinearScale3d(src1, NULL, nbands1, nrows1, ncols1, shift, scale); break; case 1: src = VNNScale3d(src1, NULL, nbands1, nrows1, ncols1, shift, scale); break; default: VError(" illegal resampling type"); } /* ** resample image */ trans = VCopyImage(transform, NULL, VAllBands); for(i = 0; i < 3; i++) { u = VPixel(trans, 0, i, 0, VDouble); u /= resolution; VPixel(trans, 0, i, 0, VDouble) = u; } b0 = (float)nbands1 * 0.5; r0 = (float)nrows1 * 0.5; c0 = (float)ncols1 * 0.5; switch(type) { case 0: dest = VTriLinearSample3d(src, dest, trans, b0, r0, c0, nbands1, nrows1, ncols1); break; case 1: dest = VNNSample3d(src, dest, trans, b0, r0, c0, nbands1, nrows1, ncols1); break; } /* ** update header */ float _cax, _cay, _caz, _cpx, _cpy, _cpz; float _fixpointx, _fixpointy, _fixpointz; str1 = str2 = str3 = str4 = NULL; str1 = (VString) VMalloc(80); sprintf(str1, "%.2f %.2f %.2f", resolution, resolution, resolution); if(VGetAttr(VImageAttrList(trans), "ca", NULL, VStringRepn, (VPointer) & str2) != VAttrFound) { str2 = NULL; } else { sscanf(str2, "%f %f %f", &_cax, &_cay, &_caz); _cax /= (resolution / transResX); _cay /= (resolution / transResY); _caz /= (resolution / transResZ); sprintf(str2, "%.2f %.2f %.2f", _cax, _cay, _caz); } if(VGetAttr(VImageAttrList(trans), "cp", NULL, VStringRepn, (VPointer) & str3) != VAttrFound) { str3 = NULL; } else { sscanf(str3, "%f %f %f", &_cpx, &_cpy, &_cpz); _cpx /= (resolution / transResX); _cpy /= (resolution / transResY); _cpz /= (resolution / transResZ); sprintf(str3, "%.2f %.2f %.2f", _cpx, _cpy, _cpz); } if(VGetAttr(VImageAttrList(trans), "extent", NULL, VStringRepn, (VPointer) & str4) != VAttrFound) str4 = NULL; if(VGetAttr(VImageAttrList(trans), "fixpoint", NULL, VStringRepn, (VPointer) & str5) != VAttrFound) { str5 = NULL; } else { sscanf(str5, "%f %f %f", &_fixpointx, &_fixpointy, &_fixpointz); _fixpointx /= (resolution / transResX); _fixpointy /= (resolution / transResY); _fixpointz /= (resolution / transResZ); sprintf(str5, "%.2f %.2f %.2f", _fixpointx, _fixpointy, _fixpointz); } if(VGetAttr(VImageAttrList(trans), "talairach", NULL, VStringRepn, (VPointer) & str6) != VAttrFound) { str6 = NULL; } if(orient == CORONAL) { dest_cor = VAxial2Coronal(dest, NULL); VDestroyImage(dest); VCopyImageAttrs(src, dest_cor); VSetAttr(VImageAttrList(dest_cor), "voxel", NULL, VStringRepn, str1); if(str2) VSetAttr(VImageAttrList(dest_cor), "ca", NULL, VStringRepn, str2); if(str3) VSetAttr(VImageAttrList(dest_cor), "cp", NULL, VStringRepn, str3); if(str4) VSetAttr(VImageAttrList(dest_cor), "extent", NULL, VStringRepn, str4); if(str5) VSetAttr(VImageAttrList(dest_cor), "fixpoint", NULL, VStringRepn, str5); if(str6) VSetAttr(VImageAttrList(dest_cor), "talairach", NULL, VStringRepn, str6); return dest_cor; } else if(orient == SAGITTAL) { dest_sag = VAxial2Sagittal(dest, NULL); VDestroyImage(dest); VCopyImageAttrs(src, dest_sag); VSetAttr(VImageAttrList(dest_sag), "voxel", NULL, VStringRepn, str1); if(str2) VSetAttr(VImageAttrList(dest_sag), "ca", NULL, VStringRepn, str2); if(str3) VSetAttr(VImageAttrList(dest_sag), "cp", NULL, VStringRepn, str3); if(str4) VSetAttr(VImageAttrList(dest_sag), "extent", NULL, VStringRepn, str4); if(str5) VSetAttr(VImageAttrList(dest_sag), "fixpoint", NULL, VStringRepn, str5); if(str6) VSetAttr(VImageAttrList(dest_sag), "talairach", NULL, VStringRepn, str6); return dest_sag; } else { VCopyImageAttrs(src, dest); VSetAttr(VImageAttrList(dest), "voxel", NULL, VStringRepn, str1); if(str2) VSetAttr(VImageAttrList(dest), "ca", NULL, VStringRepn, str2); if(str3) VSetAttr(VImageAttrList(dest), "cp", NULL, VStringRepn, str3); if(str4) VSetAttr(VImageAttrList(dest), "extent", NULL, VStringRepn, str4); if(str5) VSetAttr(VImageAttrList(dest), "fixpoint", NULL, VStringRepn, str5); if(str6) VSetAttr(VImageAttrList(dest), "talairach", NULL, VStringRepn, str6); return dest; } }
VAttrList VGetContrast(VAttrList list, gsl_vector_float *con, VShort type) { VAttrList out_list; int nbands = 0, nrows = 0, ncols = 0, band, row, col; VImage src = NULL, dest = NULL, std_image = NULL; VImage beta_images[MBETA], res_image = NULL, bcov_image = NULL; VString buf = NULL; VAttrListPosn posn; VString str; int i, nbeta; float t = 0, s = 0, tsigma = 0, z = 0, zmax = 0, zmin = 0; float sigma, var, sum, df; float *ptr1, *ptr2; char *constring = NULL; gsl_vector_float *beta = NULL, *tmp = NULL; gsl_matrix_float *bcov = NULL; i = 0; for(VFirstAttr(list, & posn); VAttrExists(& posn); VNextAttr(& posn)) { if(VGetAttrRepn(& posn) != VImageRepn) continue; VGetAttrValue(& posn, NULL, VImageRepn, & src); if(VPixelRepn(src) != VFloatRepn) continue; VGetAttr(VImageAttrList(src), "modality", NULL, VStringRepn, &str); if(strcmp(str, "BETA") == 0) { beta_images[i++] = VCopyImage(src, NULL, VAllBands); } else if(strcmp(str, "RES/trRV") == 0) { res_image = VCopyImage(src, NULL, VAllBands); } else if(strcmp(str, "BCOV") == 0) { bcov_image = VCopyImage(src, NULL, VAllBands); } } nbeta = VImageNRows(bcov_image); nbands = VImageNBands(beta_images[0]); nrows = VImageNRows(beta_images[0]); ncols = VImageNColumns(beta_images[0]); if(VGetAttr(VImageAttrList(beta_images[0]), "df", NULL, VFloatRepn, &df) != VAttrFound) VError(" attribute 'df' not found"); if(nbeta > MBETA) { fprintf(stderr, " number of betas: %d, maximum number of betas: %d\n", nbeta, MBETA); VError(" maximum number of betas is exceeded"); } /* ** read contrast vector */ if(nbeta != con->size) VError("contrast vector has bad length (%d), correct length is %d", con->size, nbeta); fprintf(stderr, " contrast vector:\n"); char str1[10]; constring = (char *)VMalloc(sizeof(char) * 10 * nbeta); constring[0] = '\0'; for(i = 0; i < nbeta; i++) { fprintf(stderr, " %.2f", fvget(con, i)); sprintf(str1, "%1.2f ", fvget(con, i)); strcat((char *)constring, (const char *)str1); } fprintf(stderr, "\n"); /* get variance estimation */ bcov = gsl_matrix_float_alloc(nbeta, nbeta); ptr1 = VImageData(bcov_image); ptr2 = bcov->data; for(i = 0; i < nbeta * nbeta; i++) *ptr2++ = *ptr1++; gsl_matrix_float_transpose(bcov); tmp = fmat_x_vector(bcov, con, tmp); var = fskalarproduct(tmp, con); sigma = sqrt(var); /* ** create output data structs */ out_list = VCreateAttrList(); dest = VCreateImage(nbands, nrows, ncols, VFloatRepn); VFillImage(dest, VAllBands, 0); VCopyImageAttrs(beta_images[0], dest); switch(type) { case 0: /* conimg */ buf = VNewString("conimg"); break; case 1: /* t-image */ buf = VNewString("tmap"); break; case 2: /* zmap */ buf = VNewString("zmap"); break; default: VError(" illegal type"); } fprintf(stderr, " output type: %s\n", buf); VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, buf); VSetAttr(VImageAttrList(dest), "name", NULL, VStringRepn, buf); VSetAttr(VImageAttrList(dest), "contrast", NULL, VStringRepn, constring); VAppendAttr(out_list, "image", NULL, VImageRepn, dest); if(type == 0) { std_image = VCreateImage(nbands, nrows, ncols, VFloatRepn); VFillImage(std_image, VAllBands, 0); VCopyImageAttrs(beta_images[0], std_image); VSetAttr(VImageAttrList(std_image), "modality", NULL, VStringRepn, "std_dev"); VSetAttr(VImageAttrList(std_image), "name", NULL, VStringRepn, "std_dev"); VAppendAttr(out_list, "image", NULL, VImageRepn, std_image); } /* ** loop thru image */ zmax = zmin = 0; beta = gsl_vector_float_alloc(nbeta); for(band = 0; band < nbands; band++) { for(row = 0; row < nrows; row++) { for(col = 0; col < ncols; col++) { t = z = sum = 0; ptr1 = beta->data; for(i = 0; i < nbeta; i++) { *ptr1++ = VPixel(beta_images[i], band, row, col, VFloat); } sum = fskalarproduct(beta, con); if(ABS(sum) < 1.0e-10) continue; s = VPixel(res_image, band, row, col, VFloat); tsigma = sqrt(s) * sigma; if(tsigma > 0.00001) t = sum / tsigma; else t = 0; if(isnan(t) || isinf(t)) t = 0; switch(type) { case 0: /* conimg */ z = sum; break; case 1: /* t-image */ z = t; break; case 2: /* zmap */ z = t2z_approx(t, df); if(z > 30) z = 30; if(sum < 0) z = -z; break; default: ; } if(isnan(z) || isinf(z)) z = 0; if(z > zmax) zmax = z; if(z < zmin) zmin = z; VPixel(dest, band, row, col, VFloat) = z; if(type == 0) VPixel(std_image, band, row, col, VFloat) = tsigma; } } } fprintf(stderr, " min= %.3f, max= %.3f\n", zmin, zmax); return out_list; }
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; }
VImage VCovariates(VString cfile, VFloat tr, VBoolean normalize) { VImage dest = NULL; FILE *fp = NULL; char buf[LEN], token[80]; int i, j, nt, m, ncols, nrows; float x; double u, sum1, sum2, nx, mean, sigma, tiny = 1.0e-4; fp = fopen(cfile, "r"); if(fp == NULL) VError(" err opening file %s", cfile); nrows = ncols = 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) < 3) continue; 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); j++; } if(j > ncols) ncols = j; nrows++; } fprintf(stderr, "# num rows: %d, num cols: %d\n", nrows, ncols); dest = VCreateImage(1, nrows, ncols + 1, VFloatRepn); VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, "X"); VSetAttr(VImageAttrList(dest), "name", NULL, VStringRepn, "X"); VSetAttr(VImageAttrList(dest), "repetition_time", NULL, VLongRepn, (VLong)(tr * 1000.0)); VSetAttr(VImageAttrList(dest), "ntimesteps", NULL, VLongRepn, (VLong)nrows); VSetAttr(VImageAttrList(dest), "derivatives", NULL, VShortRepn, (VFloat) 0); VSetAttr(VImageAttrList(dest), "delay", NULL, VFloatRepn, (VFloat) 0); VSetAttr(VImageAttrList(dest), "undershoot", NULL, VFloatRepn, (VFloat) 0); VSetAttr(VImageAttrList(dest), "understrength", NULL, VFloatRepn, (VFloat) 0); VSetAttr(VImageAttrList(dest), "nsessions", NULL, VShortRepn, (VShort)1); VSetAttr(VImageAttrList(dest), "designtype", NULL, VShortRepn, (VShort)1); VFillImage(dest, VAllBands, 0); for(j = 0; j < nrows; j++) VPixel(dest, 0, j, ncols, VFloat) = 1; rewind(fp); 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) < 3) 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(dest, 0, i, j, VFloat) = x; j++; } if(j < 1) continue; if(i >= nrows) continue; i++; } fclose(fp); if(i != nrows) VError(" file: inconsistent number of rows: %d %d", i, nrows); if(!normalize) return dest; nt = VImageNRows(dest); m = VImageNColumns(dest); for(i = 0; i < m; i++) { sum1 = sum2 = nx = 0; for(j = 0; j < nt; j++) { u = VPixel(dest, 0, j, i, VFloat); sum1 += u; sum2 += u * u; nx++; } mean = sum1 / nx; sigma = sqrt((sum2 - nx * mean * mean) / (nx - 1.0)); if(sigma < tiny) continue; for(j = 0; j < nt; j++) { u = VPixel(dest, 0, j, i, VFloat); u = (u - mean) / sigma; VPixel(dest, 0, j, i, VFloat) = u; } } return dest; }
VAttrList VBayes(VImage cbeta_images[], VImage sd_images[], int nimages, VBoolean level, VBoolean zscore) { VAttrList out_list = NULL; VImage dest = NULL, sigma_image = NULL; int i, j, k, npixels; VFloat *dest_pp, *beta_pp[N], *sd_pp[N], *sigma_pp = NULL; VFloat pmin, pmax; double mean = 0, sigma = 0; float rx, wsum, msum, w0, wx, s, msumold; float result = 0; float gmean[N], gvar[N]; float tiny = 1.0e-12; /* ** create output image */ dest = VCopyImage(cbeta_images[0], NULL, VAllBands); if(!dest) return NULL; VFillImage(dest, VAllBands, 0); VSetAttr(VImageAttrList(dest), "num_images", NULL, VShortRepn, (VShort)nimages); VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, "bayes_map"); VSetAttr(VImageAttrList(dest), "name", NULL, VStringRepn, "bayes"); if(level == TRUE) { VSetAttr(VImageAttrList(dest), "modality", NULL, VStringRepn, "mean"); VSetAttr(VImageAttrList(dest), "name", NULL, VStringRepn, "mean"); sigma_image = VCopyImage(dest, NULL, VAllBands); if(!sigma_image) return NULL; VFillImage(sigma_image, VAllBands, 0); VSetAttr(VImageAttrList(sigma_image), "num_images", NULL, VShortRepn, (VShort)nimages); VSetAttr(VImageAttrList(sigma_image), "modality", NULL, VStringRepn, "std_dev"); VSetAttr(VImageAttrList(sigma_image), "name", NULL, VStringRepn, "std_dev"); } /* ** for each voxel */ pmax = VRepnMinValue(VFloatRepn); pmin = VRepnMaxValue(VFloatRepn); npixels = VImageNPixels(cbeta_images[0]); for(i = 0; i < nimages; i++) { beta_pp[i] = (VFloat *) VImageData(cbeta_images[i]); sd_pp[i] = (VFloat *) VImageData(sd_images[i]); } dest_pp = (VFloat *) VImageData(dest); if(level == TRUE) sigma_pp = (VFloat *) VImageData(sigma_image); for(j = 0; j < npixels; j++) { if(j % 10000 == 0) fprintf(stderr, "...%.2f%%\r", (float)100 * j / (float)npixels); result = mean = sigma = 0; /* ** read data from input images */ for(k = 0; k < nimages; k++) { gmean[k] = *beta_pp[k]++; /* mean c*beta */ rx = *sd_pp[k]++; /* standard deviation of c*beta*/ gvar[k] = rx * rx; /* variation of c*beta*/ } /* see Box,Tiao, pp.17-18 calculate probability distribution */ wsum = 0; msum = 0; w0 = 0; for(k = 0; k < nimages; k++) { /* for each image */ s = gvar[k]; if(s < tiny) goto next; s = sqrt((double)s); if(s < tiny) goto next; wx = 1.0 / (s * s); wsum = w0 + wx; msumold = msum; msum = (w0 * msum + wx * gmean[k]) / wsum; w0 = wsum; sigma = 1.0 / sqrt(wsum); } if(wsum < tiny) goto next; /* resulting mean and std dev */ mean = msum; sigma = 1.0 / sqrt(wsum); if(level == TRUE) { result = mean; goto next; } /* calculate probability under distribution */ result = CumulativeNormal(mean, sigma); /* output */ if(zscore) { /* CHECK HERE IF "1.0-" is correct */ result = (float)p2z((double)(1.0 - result)); if(mean < 0) result = -result; if(result > 20) result = 20; if(result < -20) result = -20; } else { result *= 100.0; if(result > 100) result = 100; if(mean < 0) result = -result; } if(result < pmin) pmin = result; if(result > pmax) pmax = result; next: *dest_pp++ = result; if(level) *sigma_pp++ = sigma; } out_list = VCreateAttrList(); fprintf(stderr, "...100.00%%\n"); if(level == FALSE) { fprintf(stderr, "\n min: %.3f, max: %.3f\n", pmin, pmax); VAppendAttr(out_list, "zmap", NULL, VImageRepn, dest); return out_list; } else { VAppendAttr(out_list, "mean", NULL, VImageRepn, dest); VAppendAttr(out_list, "std_dev", NULL, VImageRepn, sigma_image); return out_list; } return NULL; }