int main(int argc, char *argv[]) { char **av, *in_vol, *out_vol; int ac, nargs; MRI *mri_in, *mri_out, *mri_tmp ; LTA *lta = 0; MATRIX *i_to_r_src = 0; /* src geometry of the input LTA */ MATRIX *V_to_V = 0; /* Final voxel-to-voxel transform */ MATRIX *r_to_i_dst = 0; /* dst geometry of the input LTA */ MATRIX *m_tmp = 0; MATRIX *i_to_r_reg = 0; /* i_to_r of the volume after registration */ MATRIX *r_to_i_out = 0; /* r_to_i of the final output volume */ VOL_GEOM vgm_in; int x, y, z; double maxV, minV, value; // MATRIX *i_to_r, *r_to_i; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_transform_to_COR.c,v 1.8 2011/03/02 00:04:55 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) usage_exit (0); argc -= nargs; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 3) usage_exit(0) ; in_vol = argv[1] ; out_vol = argv[2] ; printf("reading volume from %s...\n", in_vol) ; mri_in = MRIread(in_vol) ; if (!mri_in) ErrorExit(ERROR_NOFILE, "%s: could not read MRI volume %s", Progname, in_vol) ; /* Convert mri_in to float type */ /* double would be more accurate */ if (mri_in->type != MRI_FLOAT) { printf("Input volume type is %d\n", mri_in->type); printf("Change input volume to float type for convenience and accuracy"); mri_tmp = MRIchangeType(mri_in, MRI_FLOAT, 0, 1.0, 1); MRIfree(&mri_in); mri_in = mri_tmp; //swap } /* Get input volume geometry, which is needed to compute i_to_r * and r_to_i of input volume. Note that i_to_r and r_to_i assumed * a certain prespecified c_r, c_a, c_s */ getVolGeom(mri_in, &vgm_in); maxV = -10000.0; minV = 10000.0; for (z=0; z < mri_in->depth; z++) for (y=0; y< mri_in->height; y++) for (x=0; x < mri_in->width; x++) { if (MRIFvox(mri_in, x, y, z) > maxV ) maxV = MRIFvox(mri_in, x, y,z) ; if (MRIFvox(mri_in, x, y, z) < minV ) minV = MRIFvox(mri_in, x, y,z) ; } printf("Input volume has max = %g, min =%g\n", maxV, minV); printf("Scale input volume by %g \n", scale); maxV = -10000.0; minV = 10000.0; for (z=0; z < mri_in->depth; z++) for (y=0; y< mri_in->height; y++) for (x=0; x < mri_in->width; x++) { MRIFvox(mri_in, x, y, z) *= scale; if (MRIFvox(mri_in, x, y, z) > maxV ) maxV = MRIFvox(mri_in, x, y,z) ; if (MRIFvox(mri_in, x, y, z) < minV ) minV = MRIFvox(mri_in, x, y,z) ; } printf("Input volume after scaling has max = %g, min =%g\n", maxV, minV); /* Try to compute the Voxel_to_Voxel transform from the input volume * and the registration target/reference volume! * If no registration is involved, vox_to_vox is simply identity */ /* Things become more complicated when allowing inverse transform */ if (transform_flag) { int transform_type; printf("INFO: Applying transformation from file %s...\n", transform_fname); transform_type = TransformFileNameType(transform_fname); /* Read in LTA transform file name */ if (transform_type == MNI_TRANSFORM_TYPE || transform_type == TRANSFORM_ARRAY_TYPE || transform_type == REGISTER_DAT || transform_type == FSLREG_TYPE ) { printf("Reading transform ...\n"); lta = LTAreadEx(transform_fname) ; if (!lta) ErrorExit(ERROR_NOFILE, "%s: could not read transform file %s", Progname, transform_fname) ; if (transform_type == FSLREG_TYPE) { if (lta_src == 0 || lta_dst == 0) { fprintf(stderr, "ERROR: fslmat does not have information on the src and dst volumes\n"); fprintf(stderr, "ERROR: you must give options '-src' and '-dst' to specify the src and dst volume infos for the registration\n"); } LTAmodifySrcDstGeom(lta, lta_src, lta_dst); // add src and dst information //The following is necessary to interpret FSLMAT correctly!!! LTAchangeType(lta, LINEAR_VOX_TO_VOX); } if (lta->xforms[0].src.valid == 0) { if (lta_src == 0) { fprintf(stderr, "The transform does not have the valid src volume info.\n"); fprintf(stderr, "Either you give src volume info by option -src or\n"); fprintf(stderr, "make the transform to have the valid src info.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, lta_src, NULL); // add src information } } if (lta->xforms[0].dst.valid == 0) { if (lta_dst == 0) { fprintf(stderr, "The transform does not have the valid dst volume info.\n"); fprintf(stderr, "Either you give src volume info by option -dst or\n"); fprintf(stderr, "make the transform to have the valid dst info.\n"); fprintf(stderr, "If the dst was average_305, then you can set\n"); fprintf(stderr, "environmental variable USE_AVERAGE305 true\n"); fprintf(stderr, "instead.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, NULL, lta_dst); // add dst information } } // The following procedure aims to apply an LTA computed from COR format to a volume in non-COR format, or vice versa, as long as they share the same RAS // first change to LINEAR RAS_TO_RAS using old info if (lta->type != LINEAR_RAS_TO_RAS) { LTAchangeType(lta, LINEAR_RAS_TO_RAS); } // now possiblly reset the src and dst if (lta_src != NULL) { //always trust the user LTAmodifySrcDstGeom(lta, lta_src, NULL); } if (lta_dst != NULL) { //always trust the user LTAmodifySrcDstGeom(lta, NULL, lta_dst); } if (lta->type == LINEAR_RAS_TO_RAS) { /* Convert it to VOX_TO_VOX */ /* VOXELsrc_to_VOXELdst = R2Vdst*R2Rlta*V2Rsrc */ /* Note whether the input should be identical to src or dst here depends * on whether the LTA here is the direct or inverse transform */ i_to_r_src = vg_i_to_r(<a->xforms[0].src); r_to_i_dst = vg_r_to_i(<a->xforms[0].dst); if (!r_to_i_dst || !i_to_r_src) ErrorExit(ERROR_BADFILE, "%s: failed to extract volume geometries from input LTA file",Progname); m_tmp = MatrixMultiply(lta->xforms[0].m_L, i_to_r_src, NULL); V_to_V = MatrixMultiply(r_to_i_dst, m_tmp, NULL); MatrixFree(&m_tmp); MatrixFree(&i_to_r_src); MatrixFree(&r_to_i_dst); } } else { fprintf(stderr, "unknown transform type in file %s\n", transform_fname); exit(1); } if (invert_flag) { /* Geometry of input volume should match that of the dst of the LTA */ if (MYvg_isEqual(<a->xforms[0].dst, &vgm_in) == 0) { ErrorExit(ERROR_BADFILE, "%s: dst volume of lta doesn't match that of input volume",Progname); } i_to_r_reg = vg_i_to_r(<a->xforms[0].src); if (!i_to_r_reg) ErrorExit(ERROR_BADFILE, "%s: failed to extract i_to_r of registered volume from LTA",Progname); m_tmp = MatrixInverse(V_to_V, NULL); if (!m_tmp) ErrorExit(ERROR_BADPARM, "%s: transform is singular!", Progname); MatrixFree(&V_to_V); V_to_V = m_tmp; } else { /* Geometry of input volume should match that of the src of the LTA */ if (MYvg_isEqual(<a->xforms[0].src, &vgm_in) == 0) { ErrorExit(ERROR_BADFILE, "%s: src volume of lta doesn't match that of input volume",Progname); } i_to_r_reg = vg_i_to_r(<a->xforms[0].dst); if (!i_to_r_reg) ErrorExit(ERROR_BADFILE, "%s: failed to extract i_to_r of registered volume from LTA",Progname); } } else { /* No registration transform need be applied */ V_to_V = MatrixIdentity(4, NULL); i_to_r_reg = extract_i_to_r(mri_in); if (!i_to_r_reg) ErrorExit(ERROR_BADFILE, "%s: failed to extract i_to_r from input volume",Progname); } /* Now need to find the vox-to-vox transformation between registered volume * (or input volume itself if no registration involved) and the output * volume, either in COR format or as the out-like volume */ /* Given a volume with a certain i_to_r, we need to compute the necessary * vox-to-voxel transform to change its i_to_r to like another volume. * The vox-to-vox is equal to R2V(r_to_i)_likevol*i_to_r_current_vol. */ if (out_like_fname) { mri_tmp = MRIread(out_like_fname) ; if (!mri_tmp) ErrorExit(ERROR_NOFILE, "%s: could not read template volume from %s",out_like_fname) ; /* out_type = mri_tmp->type; */ /* specify the out-type to float initially so as not to lose accuracy * during reslicing, will change type to correct type later. */ mri_out = MRIalloc(mri_tmp->width, mri_tmp->height, mri_tmp->depth, MRI_FLOAT) ; MRIcopyHeader(mri_tmp, mri_out) ; MRIfree(&mri_tmp); } else /* assume output is in COR format */ { mri_out = MRIalloc(256, 256, 256, MRI_FLOAT) ; /* out_type = MRI_UCHAR; */ /* Who says MRIlinearTransformInterp will change the header?? * I don't think so! */ //E/ set xyzc_ras to coronal ones.. - these'll get zorched //by MRIlinearTransformInterp() - copy again later - is there //any use in having them here now? yes, so we can pass mri_out //to the ras2vox fns. mri_out->imnr0 = 1; /* what's this? */ mri_out->imnr1 = 256; /* what's this? */ mri_out->thick = 1.0; mri_out->ps = 1.0; /* what's this? */ mri_out->xsize = mri_out->ysize = mri_out->zsize = 1.0; mri_out->xstart = mri_out->ystart = mri_out->zstart = -128.0; mri_out->xend = mri_out->yend = mri_out->zend = 128.0; mri_out->x_r =-1; mri_out->y_r = 0; mri_out->z_r = 0; mri_out->x_a = 0; mri_out->y_a = 0; mri_out->z_a = 1; mri_out->x_s = 0; mri_out->y_s =-1; mri_out->z_s = 0; /* In this case, the RAS itself is not fully determined, i.e., c_ras. * It's quite arbitrary, different values just change the final * sitting of the volume inside the RAS system. */ /* NO! The C_RAS has to be set correctly, depending which target * volume the previous Vox_to_Vox transformation assumes! * When a registration is involved, the target volume is either * the src of LTA (direct) or the dst (inverse transform). When * just change format, the target volume is the input itself!! */ if (transform_flag) { if (invert_flag) { mri_out->c_r = lta->xforms[0].src.c_r; mri_out->c_a = lta->xforms[0].src.c_a; mri_out->c_s = lta->xforms[0].src.c_s; } else { mri_out->c_r = lta->xforms[0].dst.c_r; mri_out->c_a = lta->xforms[0].dst.c_a; mri_out->c_s = lta->xforms[0].dst.c_s; } } else { mri_out->c_r = mri_in->c_r; mri_out->c_a = mri_in->c_a; mri_out->c_s = mri_in->c_s; } mri_out->ras_good_flag=1; /* What does this flag mean ? */ /* since output is just transformed input */ MRIcopyPulseParameters(mri_in, mri_out) ; } /* Compute the final input-to-output VOX_to_VOX transformation matrix */ r_to_i_out = extract_r_to_i(mri_out); m_tmp = MatrixMultiply(r_to_i_out, i_to_r_reg, NULL); V_to_V = MatrixMultiply(m_tmp, V_to_V, V_to_V); MatrixFree(&m_tmp); printf("InterpMethod = %d\n", InterpMethod); /* Modify the MyMRIlinearTr... if I want to implement my cubic-B-spline * interpolation method. Otherwise, unnecessary */ /* mri_out = MyMRIlinearTransformInterp(mri_in, mri_out, V_to_V, InterpMethod); */ if (InterpMethod == SAMPLE_BSPLINE) mri_out = MRIlinearTransformInterpBSpline(mri_in, mri_out, V_to_V, SplineDegree); else mri_out = MRIlinearTransformInterp(mri_in, mri_out, V_to_V, InterpMethod); maxV = -10000.0; minV = 10000.0; for (z=0; z < mri_out->depth; z++) for (y=0; y< mri_out->height; y++) for (x=0; x < mri_out->width; x++) { if (MRIFvox(mri_out, x, y, z) > maxV ) maxV = MRIFvox(mri_out, x, y,z) ; if (MRIFvox(mri_out, x, y, z) < minV ) minV = MRIFvox(mri_out, x, y,z) ; } if (autoscale) { noscale = 1; /* compute histogram of output volume */ HISTOGRAM *h, *hsmooth ; float fmin, fmax, val, peak, smooth_peak; int i, nbins, bin; fmin = minV; fmax = maxV; if (fmin < 0) fmin = 0; nbins = 256 ; h = HISTOalloc(nbins) ; hsmooth = HISTOcopy(h, NULL) ; HISTOclear(h, h) ; h->bin_size = (fmax-fmin)/255.0 ; for (i = 0 ; i < nbins ; i++) h->bins[i] = (i+1)*h->bin_size ; for (z=0; z < mri_out->depth; z++) for (y=0; y< mri_out->height; y++) for (x=0; x < mri_out->width; x++) { val = MRIFvox(mri_out, x, y, z); if (val <= 0) continue; bin = nint((val - fmin)/h->bin_size); if (bin >= h->nbins) bin = h->nbins-1; else if (bin < 0) bin = 0; h->counts[bin] += 1.0; } HISTOfillHoles(h) ; HISTOsmooth(h, hsmooth, 5) ; peak = hsmooth->bins[HISTOfindHighestPeakInRegion(h, 1, h->nbins)] ; // smooth_peak = // hsmooth->bins[HISTOfindHighestPeakInRegion(hsmooth, 1, hsmooth->nbins)] ; smooth_peak = hsmooth->bins[HISTOfindLastPeak(hsmooth, 5, 0.8)] ; /* bin = nint((smooth_peak - fmin)/hsmooth->bin_size) ; printf("Highest peak has count = %d\n", (int)hsmooth->counts[bin]); bin = nint((420 - fmin)/hsmooth->bin_size) ; printf("bin at 420 has count = %d\n", (int)hsmooth->counts[bin]); */ scale = 110.0/smooth_peak; printf("peak of output volume is %g, smooth-peak is %g, multiply by %g to scale it to 110\n", peak, smooth_peak, scale); for (z=0; z < mri_out->depth; z++) for (y=0; y< mri_out->height; y++) for (x=0; x < mri_out->width; x++) { val = MRIFvox(mri_out, x, y, z); MRIFvox(mri_out, x, y, z) = val*scale; } } printf("Output volume (before type-conversion) has max = %g, min =%g\n", maxV, minV); /* Finally change type to desired */ if (mri_out->type != out_type) { printf("Change output volume to type %d\n", out_type); /* I need to modify the MIRchangeType function to make sure * it does roundoff instead of simple truncation! */ /* Note if the last flag is set to 1, then it won't do scaling and small float numbers will become zero after convert to BYTE */ if (out_type == 0 && noscale == 1) { //convert data to UCHAR mri_tmp = MRIalloc(mri_out->width, mri_out->height, mri_out->depth, out_type) ; MRIcopyHeader(mri_out, mri_tmp); for (z=0; z < mri_out->depth; z++) for (y=0; y< mri_out->height; y++) for (x=0; x < mri_out->width; x++) { value = floor(MRIgetVoxVal(mri_out, x, y, z, 0) + 0.5); if (value < 0 ) value = 0; if (value > 255) value = 255; MRIvox(mri_tmp,x,y,z) = (unsigned char)value; } } else mri_tmp = MRIchangeType(mri_out, out_type, thred_low, thred_high, noscale); MRIfree(&mri_out); mri_out = mri_tmp; //swap } MRIwrite(mri_out, out_vol) ; MRIfree(&mri_in); MRIfree(&mri_out); if (lta_src) MRIfree(<a_src); if (lta_dst) MRIfree(<a_dst); MatrixFree(&V_to_V); if (!r_to_i_out) MatrixFree(&r_to_i_out); if (!i_to_r_reg) MatrixFree(&i_to_r_reg); return(0) ; /* for ansi */ }
int main(int argc, char *argv[]) { char **av, *avg_surf_name, *canon_surf_name, fname[STRLEN], *mdir, ico_fname[STRLEN], *hemi, *out_sname ; int ac, nargs, i, vno, n ; VERTEX *v ; MRI_SURFACE *mris_ico ; MRI_SP *mrisp_total ; LTA *lta ; VOL_GEOM vg; float average_surface_area = 0.0 ; MATRIX *XFM=NULL; GCA_MORPH *gcam=NULL; memset((void *) &vg, 0, sizeof (VOL_GEOM)); /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mris_make_average_surface.c,v 1.29 2011/03/02 00:04:33 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; mdir = getenv("FREESURFER_HOME") ; if (!mdir) ErrorExit(ERROR_BADPARM, "%s: no FREESURFER_HOME in environment.\n",Progname); ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (sdir == NULL) { sdir = getenv("SUBJECTS_DIR"); if (!sdir) ErrorExit(ERROR_BADPARM, "%s: no SUBJECTS_DIR in environment.\n",Progname); } if (sdirout == NULL) sdirout = sdir; if (argc < 6) usage_exit() ; hemi = argv[1] ; avg_surf_name = argv[2] ; canon_surf_name = argv[3] ; out_sname = argv[4] ; printf("---------------------------------------------------\n"); printf("hemi = %s\n",hemi); printf("avg_surf_name = %s\n",avg_surf_name); printf("canon_surf_name = %s\n",canon_surf_name); printf("out_sname = %s\n",out_sname); printf("xform = %s\n",xform_name); printf("---------------------------------------------------\n"); printf("\n\n"); fflush(stdout); #define SCALE 1 mrisp_total = MRISPalloc(SCALE, 3) ; for (n = 0, i = 5 ; i < argc ; i++) { MRI *mri; MRI_SURFACE *mris; MRI_SP *mrisp; printf("\n---------------------------------------------------\n"); printf("#@# processing subject %d/%d %s...\n", i-4,argc-5,argv[i]) ; fflush(stdout); // read sphere.reg sprintf(fname, "%s/%s/surf/%s.%s", sdir, argv[i], hemi, canon_surf_name) ; printf(" Reading %s\n",fname); fflush(stdout); mris = MRISread(fname) ; if (!mris) { ErrorExit(ERROR_NOFILE, "%s: could not read surface file %s", Progname, fname) ; exit(1); } // get "pial" surface vertex into ->origx, origy, origz if (MRISreadOriginalProperties(mris, orig_name) != NO_ERROR) ErrorExit(ERROR_BADFILE,"%s: could not read orig file for %s.\n", Progname, argv[1]); // read transform if (0) { sprintf(fname, "%s/%s/mri/transforms/%s", sdir, argv[i], xform_name) ; lta = LTAreadEx(fname) ; if (!lta) ErrorExit(ERROR_BADPARM, "%s: could not read transform from %s", Progname, fname) ; } // read T1 volume sprintf(fname, "%s/%s/mri/T1.mgz", sdir, argv[i]) ; if (fio_FileExistsReadable(fname)) mri = MRIreadHeader(fname,MRI_MGH_FILE); else { sprintf(fname, "%s/%s/mri/T1", sdir, argv[i]) ; mri = MRIreadHeader(fname, MRI_UCHAR); // MRI_CORONAL_SLICE_DIRECTORY) ; } printf(" Read %s\n",fname); fflush(stdout); if (!mri) ErrorExit(ERROR_BADPARM, "%s: could not read reference MRI volume from %s", Progname, fname) ; // save current vertex position into ->cx MRISsaveVertexPositions(mris, CANONICAL_VERTICES) ; // get the vertex position from ->origx, ... // (get the "pial" vertex position) MRISrestoreVertexPositions(mris, ORIGINAL_VERTICES) ; MRIScomputeMetricProperties(mris) ; printf(" Surface area: %2.1f cm^2\n", mris->total_area/100) ; fflush(stdout); average_surface_area += mris->total_area ; // this means that we transform "pial" surface if (xform_name) { if (!strcmp(xform_name,"talairach.xfm")) { printf(" Applying linear transform\n"); fflush(stdout); XFM = DevolveXFMWithSubjectsDir(argv[i], NULL, "talairach.xfm", sdir); if (XFM == NULL) exit(1); MRISmatrixMultiply(mris, XFM); MatrixFree(&XFM); } else if (!strcmp(xform_name,"talairach.m3z")) { printf(" Applying GCA Morph\n"); fflush(stdout); sprintf(fname, "%s/%s/mri/transforms/talairach.m3z", sdir, argv[i]) ; gcam = GCAMreadAndInvert(fname); if (gcam == NULL) exit(1); GCAMmorphSurf(mris, gcam); GCAMfree(&gcam); } else { printf("ERROR: don't know what to do with %s\n",xform_name); exit(1); } } // save transformed position in ->orig // (store "pial" vertices position in orig) MRIScomputeMetricProperties(mris) ; MRISsaveVertexPositions(mris, ORIGINAL_VERTICES) ; // get the vertex position from ->cx // (note that this is not transformed) sphere.reg vertices MRISrestoreVertexPositions(mris, CANONICAL_VERTICES) ; // mris contains sphere.reg in vertex and pial vertices in orig // map to a theta-phi space and accumulate values mrisp = MRIScoordsToParameterization(mris, NULL, SCALE, ORIGINAL_VERTICES) ; MRISPaccumulate(mrisp, mrisp_total, 0) ; MRISPaccumulate(mrisp, mrisp_total, 1) ; MRISPaccumulate(mrisp, mrisp_total, 2) ; MRISPfree(&mrisp) ; MRISfree(&mris) ; MRIfree(&mri) ; //LTAfree(<a) ; fflush(stdout); n++ ; } printf("Finished loading all data\n"); average_surface_area /= (float)n ; printf("Avg surf area = %g cm\n",average_surface_area/100.0); fflush(stdout); // mrisp_total lost info on the modified surface sprintf(ico_fname, "%s/lib/bem/ic%d.tri", mdir, ico_no) ; printf("Reading icosahedron from %s...\n", ico_fname) ; mris_ico = ICOread(ico_fname) ; if (!mris_ico) ErrorExit(ERROR_NOFILE, "%s: could not read icosahedron file %s\n", Progname,ico_fname) ; MRISscaleBrain(mris_ico, mris_ico, DEFAULT_RADIUS/MRISaverageRadius(mris_ico)) ; // save current ico position to ->cx, cy, cz MRISsaveVertexPositions(mris_ico, CANONICAL_VERTICES) ; // using mrisp_total to calculate position into ->origx, origy, origz // (orig is the "pial" vertices) MRIScoordsFromParameterization(mrisp_total, mris_ico, ORIGINAL_VERTICES) ; // copy geometry info memcpy((void *) &mris_ico->vg, (void *) &vg, sizeof (VOL_GEOM)); if (Gdiag_no >= 0 && Gdiag_no < mris_ico->nvertices) { int n ; VERTEX *vn ; v = &mris_ico->vertices[Gdiag_no] ; printf( "v %d: x = (%2.2f, %2.2f, %2.2f)\n", Gdiag_no, v->origx, v->origy, v->origz) ; for (n = 0 ; n < v->vnum ; n++) { vn = &mris_ico->vertices[v->v[n]] ; printf( "v %d: x = (%2.2f, %2.2f, %2.2f)\n", v->v[n], vn->origx, vn->origy, vn->origz) ; } } // write *h.sphere.reg sprintf(fname, "%s/%s/surf/%s.%s", sdirout, out_sname, hemi, canon_surf_name) ; if (Gdiag & DIAG_SHOW) printf("writing average canonical surface to %s\n", fname); MRISwrite(mris_ico, fname) ; // get "pial vertices" from orig MRISrestoreVertexPositions(mris_ico, ORIG_VERTICES); for (vno = 0 ; vno < mris_ico->nvertices ; vno++) { v = &mris_ico->vertices[vno] ; // n = number of subjects v->x /= (float)n ; v->y /= (float)n ; v->z /= (float)n ; } if (normalize_area) { MRIScomputeMetricProperties(mris_ico) ; printf("setting group surface area to be %2.1f cm^2 (scale=%2.2f)\n", average_surface_area/100.0, sqrt(average_surface_area/mris_ico->total_area)) ; #if 0 MRISscaleBrain(mris_ico, mris_ico, sqrt(average_surface_area/mris_ico->total_area)) ; #else mris_ico->group_avg_surface_area = average_surface_area ; #endif MRIScomputeMetricProperties(mris_ico) ; } sprintf(fname, "%s/%s/surf/%s.%s", sdirout,out_sname, hemi, avg_surf_name) ; printf("writing average %s surface to %s\n", avg_surf_name, fname); MRISwrite(mris_ico, fname) ; if (0) { char path[STRLEN] ; LTA *lta ; FileNamePath(fname, path) ; lta = LTAalloc(1, NULL) ; // write to a different location sprintf(fname, "%s/../mri/transforms/%s", path,xform_name) ; LTAwriteEx(lta, fname) ; LTAfree(<a) ; } MRISfree(&mris_ico) ; MRISPfree(&mrisp_total) ; printf("mris_make_average_surface done\n"); exit(0) ; return(0) ; /* for ansi */ }
int main(int argc, char *argv[]) { char **av, *cp ; int ac, nargs, i, dof, no_transform, which, sno = 0, nsubjects = 0 ; MRI *mri=0, *mri_mean = NULL, *mri_std=0, *mri_T1=0,*mri_binary=0,*mri_dof=NULL, *mri_priors = NULL ; char *subject_name, *out_fname, fname[STRLEN] ; /* LTA *lta;*/ MRI *mri_tmp=0 ; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_make_template.c,v 1.26 2011/03/02 00:04:22 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; Progname = argv[0] ; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (!strlen(subjects_dir)) { cp = getenv("SUBJECTS_DIR") ; if (!cp) ErrorExit(ERROR_BADPARM,"%s: SUBJECTS_DIR not defined in environment.\n", Progname) ; strcpy(subjects_dir, cp) ; } if (argc < 3) usage_exit(1) ; out_fname = argv[argc-1] ; no_transform = first_transform ; if (binary_name) /* generate binarized volume with priors and */ { /* separate means and variances */ for (which = BUILD_PRIORS ; which <= OFF_STATS ; which++) { /* for each subject specified on cmd line */ for (dof = 0, i = 1 ; i < argc-1 ; i++) { if (*argv[i] == '-') /* don't do transform for next subject */ { no_transform = 1 ; continue ; } dof++ ; subject_name = argv[i] ; if (which != BUILD_PRIORS) { sprintf(fname, "%s/%s/mri/%s", subjects_dir, subject_name, T1_name); fprintf(stderr, "%d of %d: reading %s...\n", i, argc-2, fname) ; mri_T1 = MRIread(fname) ; if (!mri_T1) ErrorExit(ERROR_NOFILE,"%s: could not open volume %s", Progname,fname); } sprintf(fname, "%s/%s/mri/%s",subjects_dir,subject_name,binary_name); fprintf(stderr, "%d of %d: reading %s...\n", i, argc-2, fname) ; mri_binary = MRIread(fname) ; if (!mri_binary) ErrorExit(ERROR_NOFILE,"%s: could not open volume %s", Progname,fname); /* only count voxels which are mostly labeled */ MRIbinarize(mri_binary, mri_binary, WM_MIN_VAL, 0, 100) ; if (transform_fname && no_transform-- <= 0) { sprintf(fname, "%s/%s/mri/transforms/%s", subjects_dir, subject_name, transform_fname) ; fprintf(stderr, "reading transform %s...\n", fname) ; //////////////////////////////////////////////////////// #if 1 { TRANSFORM *transform ; transform = TransformRead(fname) ; if (transform == NULL) ErrorExit(ERROR_NOFILE, "%s: could not open transform file %s\n",Progname, fname) ; mri_tmp = TransformApply(transform, mri_T1, NULL) ; TransformFree(&transform) ; } #else lta = LTAreadEx(fname); if (lta == NULL) ErrorExit(ERROR_NOFILE, "%s: could not open transform file %s\n", Progname, fname) ; /* LTAtransform() runs either MRIapplyRASlinearTransform() for RAS2RAS or MRIlinearTransform() for Vox2Vox. */ /* MRIlinearTransform() calls MRIlinearTransformInterp() */ mri_tmp = LTAtransform(mri_T1, NULL, lta); MRIfree(&mri_T1) ; mri_T1 = mri_tmp ; LTAfree(<a); lta = NULL; #endif if (DIAG_VERBOSE_ON) fprintf(stderr, "transform application complete.\n") ; } if (which == BUILD_PRIORS) { mri_priors = MRIupdatePriors(mri_binary, mri_priors) ; } else { if (!mri_mean) { mri_dof = MRIalloc(mri_T1->width, mri_T1->height, mri_T1->depth, MRI_UCHAR) ; mri_mean = MRIalloc(mri_T1->width, mri_T1->height,mri_T1->depth,MRI_FLOAT); mri_std = MRIalloc(mri_T1->width,mri_T1->height,mri_T1->depth,MRI_FLOAT); if (!mri_mean || !mri_std) ErrorExit(ERROR_NOMEMORY, "%s: could not allocate templates.\n", Progname) ; } if (DIAG_VERBOSE_ON) fprintf(stderr, "updating mean and variance estimates...\n") ; if (which == ON_STATS) { MRIaccumulateMaskedMeansAndVariances(mri_T1, mri_binary, mri_dof, 90, 100, mri_mean, mri_std) ; fprintf(stderr, "T1 = %d, binary = %d, mean = %2.1f\n", (int)MRIgetVoxVal(mri_T1, 141,100,127,0), MRIvox(mri_binary, 141,100,127), MRIFvox(mri_mean, 141,100,127)) ; } else /* computing means and vars for off */ MRIaccumulateMaskedMeansAndVariances(mri_T1, mri_binary, mri_dof, 0, WM_MIN_VAL-1, mri_mean, mri_std) ; MRIfree(&mri_T1) ; } MRIfree(&mri_binary) ; } if (which == BUILD_PRIORS) { mri = MRIcomputePriors(mri_priors, dof, NULL) ; MRIfree(&mri_priors) ; fprintf(stderr, "writing priors to %s...\n", out_fname) ; } else { MRIcomputeMaskedMeansAndStds(mri_mean, mri_std, mri_dof) ; mri_mean->dof = dof ; fprintf(stderr, "writing T1 means with %d dof to %s...\n", mri_mean->dof, out_fname) ; if (!which) MRIwrite(mri_mean, out_fname) ; else MRIappend(mri_mean, out_fname) ; MRIfree(&mri_mean) ; fprintf(stderr, "writing T1 variances to %s...\n", out_fname); if (dof <= 1) MRIreplaceValues(mri_std, mri_std, 0, 1) ; mri = mri_std ; } if (!which) MRIwrite(mri, out_fname) ; else MRIappend(mri, out_fname) ; MRIfree(&mri) ; } } else { /* for each subject specified on cmd line */ if (xform_mean_fname) { m_xform_mean = MatrixAlloc(4,4,MATRIX_REAL) ; /* m_xform_covariance = MatrixAlloc(12,12,MATRIX_REAL) ;*/ } dof = 0; for (i = 1 ; i < argc-1 ; i++) { if (*argv[i] == '-') { /* don't do transform for next subject */ no_transform = 1 ; continue ; } dof++ ; subject_name = argv[i] ; sprintf(fname, "%s/%s/mri/%s", subjects_dir, subject_name, T1_name); fprintf(stderr, "%d of %d: reading %s...\n", i, argc-2, fname) ; mri_T1 = MRIread(fname) ; if (!mri_T1) ErrorExit(ERROR_NOFILE,"%s: could not open volume %s",Progname,fname); check_mri(mri_T1) ; if (binarize) MRIbinarize(mri_T1, mri_T1, binarize, 0, 1) ; if (erode) { int i ; printf("eroding input %d times\n", erode) ; for (i = 0 ; i < erode ; i++) MRIerode(mri_T1, mri_T1) ; } if (open) { int i ; printf("opening input %d times\n", open) ; for (i = 0 ; i < open ; i++) MRIerode(mri_T1, mri_T1) ; for (i = 0 ; i < open ; i++) MRIdilate(mri_T1, mri_T1) ; } check_mri(mri_T1) ; if (transform_fname) { sprintf(fname, "%s/%s/mri/transforms/%s", subjects_dir, subject_name, transform_fname) ; fprintf(stderr, "reading transform %s...\n", fname) ; //////////////////////////////////////////////////////// #if 1 { TRANSFORM *transform ; transform = TransformRead(fname) ; if (transform == NULL) ErrorExit(ERROR_NOFILE, "%s: could not open transform file %s\n",Progname, fname) ; mri_tmp = TransformApply(transform, mri_T1, NULL) ; if (DIAG_VERBOSE_ON) MRIwrite(mri_tmp, "t1.mgz") ; TransformFree(&transform) ; } #else lta = LTAreadEx(fname); if (lta == NULL) ErrorExit(ERROR_NOFILE, "%s: could not open transform file %s\n", Progname, fname) ; printf("transform matrix -----------------------\n"); MatrixPrint(stdout,lta->xforms[0].m_L); /* LTAtransform() runs either MRIapplyRASlinearTransform() for RAS2RAS or MRIlinearTransform() for Vox2Vox. */ /* MRIlinearTransform() calls MRIlinearTransformInterp() */ mri_tmp = LTAtransform(mri_T1, NULL, lta); printf("----- -----------------------\n"); LTAfree(<a); #endif MRIfree(&mri_T1); mri_T1 = mri_tmp ; // reassign pointers if (DIAG_VERBOSE_ON) fprintf(stderr, "transform application complete.\n") ; } if (!mri_mean) { mri_mean = MRIalloc(mri_T1->width, mri_T1->height, mri_T1->depth, MRI_FLOAT) ; mri_std = MRIalloc(mri_T1->width, mri_T1->height, mri_T1->depth, MRI_FLOAT) ; if (!mri_mean || !mri_std) ErrorExit(ERROR_NOMEMORY, "%s: could not allocate templates.\n", Progname) ; // if(transform_fname == NULL){ if (DIAG_VERBOSE_ON) printf("Copying geometry\n"); MRIcopyHeader(mri_T1,mri_mean); MRIcopyHeader(mri_T1,mri_std); // } } check_mri(mri_mean) ; if (!stats_only) { if (DIAG_VERBOSE_ON) fprintf(stderr, "updating mean and variance estimates...\n") ; MRIaccumulateMeansAndVariances(mri_T1, mri_mean, mri_std) ; } check_mri(mri_mean) ; if (DIAG_VERBOSE_ON) MRIwrite(mri_mean, "t2.mgz") ; MRIfree(&mri_T1) ; no_transform = 0; } /* end loop over subjects */ if (xform_mean_fname) { FILE *fp ; VECTOR *v = NULL, *vT = NULL ; MATRIX *m_vvT = NULL ; int rows, cols ; nsubjects = sno ; fp = fopen(xform_covariance_fname, "w") ; if (!fp) ErrorExit(ERROR_NOFILE, "%s: could not open covariance file %s", Progname, xform_covariance_fname) ; fprintf(fp, "nsubjects=%d\n", nsubjects) ; MatrixScalarMul(m_xform_mean, 1.0/(double)nsubjects, m_xform_mean) ; printf("means:\n") ; MatrixPrint(stdout, m_xform_mean) ; MatrixAsciiWrite(xform_mean_fname, m_xform_mean) ; /* subtract the mean from each transform */ rows = m_xform_mean->rows ; cols = m_xform_mean->cols ; for (sno = 0 ; sno < nsubjects ; sno++) { MatrixSubtract(m_xforms[sno], m_xform_mean, m_xforms[sno]) ; v = MatrixReshape(m_xforms[sno], v, rows*cols, 1) ; vT = MatrixTranspose(v, vT) ; m_vvT = MatrixMultiply(v, vT, m_vvT) ; if (!m_xform_covariance) m_xform_covariance = MatrixAlloc(m_vvT->rows, m_vvT->cols,MATRIX_REAL) ; MatrixAdd(m_vvT, m_xform_covariance, m_xform_covariance) ; MatrixAsciiWriteInto(fp, m_xforms[sno]) ; } MatrixScalarMul(m_xform_covariance, 1.0/(double)nsubjects, m_xform_covariance) ; printf("covariance:\n") ; MatrixPrint(stdout, m_xform_covariance) ; MatrixAsciiWriteInto(fp, m_xform_covariance) ; fclose(fp) ; if (stats_only) exit(0) ; } MRIcomputeMeansAndStds(mri_mean, mri_std, dof) ; check_mri(mri_mean) ; check_mri(mri_std) ; mri_mean->dof = dof ; if (smooth) { MRI *mri_kernel, *mri_smooth ; printf("applying smoothing kernel\n") ; mri_kernel = MRIgaussian1d(smooth, 100) ; mri_smooth = MRIconvolveGaussian(mri_mean, NULL, mri_kernel) ; MRIfree(&mri_kernel) ; MRIfree(&mri_mean) ; mri_mean = mri_smooth ; } fprintf(stderr, "\nwriting T1 means with %d dof to %s...\n", mri_mean->dof, out_fname) ; MRIwrite(mri_mean, out_fname) ; MRIfree(&mri_mean) ; if (dof <= 1) /* can't calculate variances - set them to reasonable val */ { // src dst MRIreplaceValues(mri_std, mri_std, 0, 1) ; } if (!novar) { // mri_std contains the variance here (does it?? I don't think so -- BRF) if (!var_fname) { fprintf(stderr, "\nwriting T1 standard deviations to %s...\n", out_fname); MRIappend(mri_std, out_fname) ; } else { fprintf(stderr, "\nwriting T1 standard deviations to %s...\n", var_fname); MRIwrite(mri_std, var_fname) ; } } MRIfree(&mri_std) ; if (mri) MRIfree(&mri); } /* end if binarize */ return(0) ; }
int main(int argc, char *argv[]) { char **av; MRI *mri_T1, *mri_tmp, *mri_ctrl, *mri_in, *mri_out; MRI *mri_snr, *mri_bias; MRI *mri_mask1 = NULL; MRI *mri_mask2 = NULL; int ac, nargs; int width, height, depth, x, y, z; int mask1_set = 0; int mask2_set = 0; int i, j, k, cx, cy, cz, count; LTA *lta = 0; int transform_type; double mean, std, value, src, bias, norm; // HISTOGRAM *h; // float bin_size; // int nbins, bin_no; double mean1, std1, mean2, std2, count1, count2, slope, offset; VOL_GEOM vgtmp; LT *lt = NULL; MATRIX *m_tmp = NULL; Progname = argv[0]; nargs = handle_version_option (argc, argv, "$Id: mri_normalize_tp2.c,v 1.8 2011/03/02 00:04:23 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc != 3) usage(1); if (tp1_ctrl_fname == NULL || tp1_T1_fname == NULL) { printf("Use options to specify ctrl volume and T1 volume for tp1\n"); usage(1); } mri_in = MRIread(argv[1]) ; if (!mri_in) ErrorExit(ERROR_BADPARM, "%s: could not read input volume %s", Progname, argv[1]) ; mri_T1 = MRIread(tp1_T1_fname) ; if (!mri_T1) ErrorExit(ERROR_BADPARM, "%s: could not read T1 volume for tp1 %s", Progname, tp1_T1_fname) ; mri_ctrl = MRIread(tp1_ctrl_fname) ; if (!mri_ctrl) ErrorExit(ERROR_BADPARM, "%s: could not read control points volume for tp1 %s", Progname, tp1_ctrl_fname) ; if ((mri_in->width != mri_T1->width) || (mri_in->height != mri_T1->height) || (mri_in->depth != mri_T1->depth) || (mri_in->width != mri_ctrl->width) || (mri_in->height != mri_ctrl->height) || (mri_in->depth != mri_ctrl->depth) ) ErrorExit (ERROR_BADPARM, "%s: three input volumes have different sizes \n", Progname); if (mask1_fname) { mri_mask1 = MRIread(mask1_fname) ; if (!mri_mask1) ErrorExit(ERROR_BADPARM, "%s, could not read mask volume for tp1 %s", Progname, mask1_fname); mask1_set = 1; if ((mri_mask1->width != mri_in->width) || (mri_mask1->height != mri_in->height) || (mri_mask1->depth != mri_in->depth)) ErrorExit (ERROR_BADPARM, "%s: mask volumes have different sizes than other volumes \n", Progname); } if (mask2_fname) { mri_mask2 = MRIread(mask2_fname) ; if (!mri_mask2) ErrorExit (ERROR_BADPARM, "%s, could not read mask volume for tp2 %s", Progname, mask2_fname); mask2_set = 1; if ((mri_mask2->width != mri_T1->width) || (mri_mask2->height != mri_T1->height) || (mri_mask2->depth != mri_T1->depth) ) ErrorExit (ERROR_BADPARM, "%s: mask volumes have different sizes than other volumes \n", Progname); } width = mri_in->width ; height = mri_in->height ; depth = mri_in->depth ; //nbins = 200; //h = HISTOalloc(nbins); mri_out = MRIclone(mri_in, NULL) ; /* Read LTA transform and apply it to mri_ctrl */ if (xform_fname != NULL) { // read transform transform_type = TransformFileNameType(xform_fname); if (transform_type == MNI_TRANSFORM_TYPE || transform_type == TRANSFORM_ARRAY_TYPE || transform_type == REGISTER_DAT || transform_type == FSLREG_TYPE ) { printf("Reading transform ...\n"); lta = LTAreadEx(xform_fname) ; if (!lta) ErrorExit(ERROR_NOFILE, "%s: could not read transform file %s", Progname, xform_fname) ; if (transform_type == FSLREG_TYPE) { if (lta_src == 0 || lta_dst == 0) { fprintf (stderr, "ERROR: fslmat does not have information " "on the src and dst volumes\n"); fprintf (stderr, "ERROR: you must give options '-lta_src' and " "'-lta_dst' to specify the src and dst volume infos\n"); } LTAmodifySrcDstGeom (lta, lta_src, lta_dst); // add src and dst information LTAchangeType(lta, LINEAR_VOX_TO_VOX); //this is necessary } if (lta->xforms[0].src.valid == 0) { if (lta_src == 0) { fprintf (stderr, "The transform does not have the valid src volume info.\n"); fprintf (stderr, "Either you give src volume info by option -lta_src or\n"); fprintf(stderr, "make the transform to have the valid src info.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, lta_src, NULL); // add src information // getVolGeom(lta_src, <->src); } } if (lta->xforms[0].dst.valid == 0) { if (lta_dst == 0) { fprintf (stderr, "The transform does not have the valid dst volume info.\n"); fprintf (stderr, "Either you give src volume info by option -lta_dst or\n"); fprintf (stderr, "make the transform to have the valid dst info.\n"); fprintf (stderr, "If the dst was average_305, then you can set\n"); fprintf (stderr, "environmental variable USE_AVERAGE305 true\n"); fprintf (stderr, "without giving the dst volume for RAS-to-RAS transform.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, NULL, lta_dst); // add dst information } } } else { ErrorExit (ERROR_BADPARM, "transform is not of MNI, nor Register.dat, nor FSLMAT type"); } if (invert) { m_tmp = lta->xforms[0].m_L ; lta->xforms[0].m_L = MatrixInverse(lta->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a->xforms[0]; if (lt->dst.valid == 0 || lt->src.valid == 0) { fprintf (stderr, "WARNING:***********************************************\n"); fprintf (stderr, "WARNING: dst volume infor is invalid. " "Most likely produce wrong inverse.\n"); fprintf (stderr, "WARNING:***********************************************\n"); } copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); } // LTAchangeType(lta, LINEAR_VOX_TO_VOX); /* apply lta to the ctrl volume */ mri_tmp = MRIalloc(mri_ctrl->width, mri_ctrl->height, mri_ctrl->depth, mri_ctrl->type) ; MRIcopyHeader(mri_in, mri_tmp) ; // this function doesn't do NEAREST at all!! // I found the bug, in LTAtransformInterp() mri_tmp = LTAtransformInterp(mri_ctrl, mri_tmp, lta, SAMPLE_NEAREST); MRIfree(&mri_ctrl); mri_ctrl = mri_tmp; if (mask1_fname != NULL && mask2_fname == NULL) { printf("map mask for tp1 to get mask for tp2 ...\n"); mri_mask2 = MRIalloc(mri_in->width, mri_in->height, mri_in->depth, mri_mask1->type) ; MRIcopyHeader(mri_in, mri_mask2) ; mri_mask2 = LTAtransformInterp(mri_mask1, mri_mask2, lta, SAMPLE_NEAREST); mask2_set = 1; if (debug_flag) MRIwrite(mri_mask2, "mri_mask2.mgz"); } else if (mask2_fname != NULL && mask1_fname == NULL) { printf("map mask for tp2 to get mask for tp1 ...\n"); //need to invert lta first m_tmp = lta->xforms[0].m_L ; lta->xforms[0].m_L = MatrixInverse(lta->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a->xforms[0]; copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); mri_mask1 = MRIalloc(mri_T1->width, mri_T1->height, mri_T1->depth, mri_mask2->type) ; MRIcopyHeader(mri_T1, mri_mask1) ; mri_mask1 = LTAtransformInterp(mri_mask2, mri_mask1, lta, SAMPLE_NEAREST); mask1_set = 1; if (debug_flag) MRIwrite(mri_mask1, "mri_mask1.mgz"); } if (lta_src) MRIfree(<a_src); if (lta_dst) MRIfree(<a_dst); if (lta) LTAfree(<a); } /* if (xform_fname != NULL) */ if (debug_flag) { // MRIwrite(mri_snr, "snr.mgz"); MRIwrite(mri_ctrl, "ctrl.mgz"); } if (mask1_set == 0) { //create mask1 mri_mask1 = MRIalloc(mri_T1->width, mri_T1->height, mri_T1->depth, MRI_UCHAR) ; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_T1, x, y, z, 0) < noise_threshold) { MRIvox(mri_mask1,x,y,z) = 0; } else MRIvox(mri_mask1,x,y,z) = 1; } } if (mask2_set == 0) { //create mask2 mri_mask2 = MRIalloc(mri_in->width, mri_in->height, mri_in->depth, MRI_UCHAR) ; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_in, x, y, z, 0) < noise_threshold) { MRIvox(mri_mask2,x,y,z) = 0; } else MRIvox(mri_mask2,x,y,z) = 1; } } #if 0 /* compute the mean and std of T1 volume */ /* Using only high SNR points */ mri_snr = MRIalloc(mri_T1->width, mri_T1->height, mri_T1->depth, MRI_FLOAT) ; MRIcopyHeader(mri_T1, mri_snr) ; h->bin_size = bin_size = 0.5; for (bin_no = 0; bin_no < nbins; bin_no++) h->bins[bin_no] = (bin_no)*bin_size; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_T1, x, y, z, 0) < noise_threshold) { MRIFvox(mri_snr,x,y,z) = 0; continue; } mean = 0; std = 0; count = 0; for (i=-1; i<=1; i++) for (j=-1; j<=1; j++) for (k=-1;k<=1;k++) { cx = x+i; cy = y+j, cz = z+k; if (cx < 0 || cx >= width || cy < 0 || cy >= height || cz < 0 || cz >= depth) continue; count++; value = MRIgetVoxVal(mri_T1, cx, cy, cz, 0); mean += value; std += value*value; } mean /= (count + 1e-30); std /= (count + 1e-30); std = std - mean *mean; if (std <= 0) std = 0; value = mean/sqrt(std); MRIFvox(mri_snr,x,y,z) = value; bin_no = nint((float)value/(float)bin_size); if (bin_no >= nbins) bin_no = nbins - 1; h->counts[bin_no]++; } for (num = 0.0f, b = h->nbins - 1; b >= 1; b --) { num += h->counts[b]; if (num > 20000) /* this may make me only use WM points, is it good to use only WM to compute scale of intensity?? */ break; } printf("using SNR threshold %2.3f at bin %d\n", h->bins[b], b); mean1 = 0; std1 = 0; count1 = 0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_T1, x, y, z, 0) < noise_threshold) { continue; } value = MRIFvox(mri_snr,x,y,z); if (value < h->bins[b]) continue; value = MRIgetVoxVal(mri_T1, x, y, z, 0); count1++; mean1 += value; std1 += value*value; } MRIfree(&mri_snr); #else printf("compute mean and std of tp1 volume within masked area...\n"); mean1 = 0; std1 = 0; count1 = 0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_mask1, x, y, z, 0) <= 1e-30) { continue; } value = MRIgetVoxVal(mri_T1, x, y, z, 0); count1++; mean1 += value; std1 += value*value; } #endif mean1 /= (count1 + 1e-30); std1 /= (count1 + 1e-30); std1 = std1 - mean1*mean1; if (std1 <= 0) printf("warning: negative std for T1 volume. \n"); else printf("mean and variance for tp1 volume are %g and %g\n", mean1, std1); printf("now compute SNR and stats for input volume ... \n"); mri_snr = MRIalloc(mri_in->width, mri_in->height, mri_in->depth, MRI_FLOAT) ; MRIcopyHeader(mri_in, mri_snr) ; //HISTOclear(h,h); //h->bin_size = bin_size = 0.5; //for (bin_no = 0; bin_no < nbins; bin_no++) // h->bins[bin_no] = (bin_no)*bin_size; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_in, x, y, z, 0) < noise_threshold) { MRIFvox(mri_snr,x,y,z) = 0; continue; } mean = 0; std = 0; count = 0; for (i=-1; i<=1; i++) for (j=-1; j<=1; j++) for (k=-1;k<=1;k++) { cx = x+i; cy = y+j, cz = z+k; if (cx < 0 || cx >= width || cy < 0 || cy >= height || cz < 0 || cz >= depth) continue; count++; value = MRIgetVoxVal(mri_in, cx, cy, cz, 0); mean += value; std += value*value; } mean /= (count + 1e-30); std /= (count + 1e-30); std = std - mean *mean; if (std <= 0) std = 0; value = mean/sqrt(std); MRIFvox(mri_snr,x,y,z) = value; //bin_no = nint((float)value/(float)bin_size); //if (bin_no >= nbins) bin_no = nbins - 1; //h->counts[bin_no]++; } #if 0 for (num = 0.0f, b = h->nbins - 1; b >= 1; b --) { num += h->counts[b]; if (num > 20000) /* this may make me only use WM points, is it good to use only WM to compute scale of intensity?? */ break; } printf("using SNR threshold %2.3f at bin %d\n", h->bins[b], b); mean2 = 0; std2 = 0; count2 = 0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_in, x, y, z, 0) < noise_threshold) { continue; } value = MRIFvox(mri_snr,x,y,z); if (value >= h->bins[b]) { count2++; mean2 += value; std2 += value*value; } } #else printf("compute mean and std of tp2 volume within masked area\n"); /* somehow mri_watershed seems to leave some unzero voxels around image border, so I will skip image boundaries no, that's not a problem of most recent mri_watershed; something wrong previously */ mean2 = 0; std2 = 0; count2 = 0; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_mask2, x, y, z, 0) <= 1e-30) { continue; } value = MRIgetVoxVal(mri_in, x, y, z, 0); count2++; mean2 += value; std2 += value*value; } #endif mean2 /= (count2 + 1e-30); std2 /= (count2 + 1e-30); std2 = std2 - mean2*mean2; if (std2 <= 0) printf("warning: negative std for input volume. \n"); else printf("mean and variance for input tp2 volume are %g and %g\n", mean2, std2); //compute intensity scale slope = sqrt(std1/std2); offset = mean1 - slope*mean2; printf("scale input volume by %g x + %g\n", slope, offset); // first change mri_in to FLOAT type mri_tmp = MRIchangeType(mri_in, MRI_FLOAT, 0, 1.0, 1); MRIfree(&mri_in); mri_in = mri_tmp; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { value = MRIFvox(mri_in, x, y, z); MRIFvox(mri_in, x, y, z) = value*slope + offset; } // printf("compute SNR map of tp2 volume\n"); //already done above // mri_snr = MRIalloc(mri_ctrl->width, // mri_ctrl->height, mri_ctrl->depth, MRI_FLOAT) ; for (z=0; z < depth; z++) for (y=0; y< height; y++) for (x=0; x < width; x++) { if (MRIgetVoxVal(mri_in, x, y, z, 0) < noise_threshold) { // MRIFvox(mri_snr,x,y,z) = 0; continue; } value = MRIFvox(mri_snr,x,y,z); if (value < 20) MRIvox(mri_ctrl, x, y, z) = 0; else if (MRIvox(mri_ctrl, x, y, z) > 0) { MRIvox(mri_ctrl, x, y, z) = 1; } } if (debug_flag) { MRIwrite(mri_snr, "snr.mgz"); // MRIwrite(mri_ctrl, "ctrl.mgz"); } // SNR >= 20 seems a good threshold // Now use ctrl points to normalize tp2 printf("normalize tp2...\n"); mri_bias = MRIbuildBiasImage(mri_in, mri_ctrl, NULL, bias_sigma) ; for (z = 0 ; z < depth ; z++) { for (y = 0 ; y < height ; y++) { for (x = 0 ; x < width ; x++) { src = MRIgetVoxVal(mri_in, x, y, z, 0) ; bias = MRIgetVoxVal(mri_bias, x, y, z, 0) ; if (!bias) /* should never happen */ norm = (float)src ; else norm = (float)src * 110.0 / (float)bias ; if (norm > 255.0f && mri_out->type == MRI_UCHAR) norm = 255.0f ; else if (norm < 0.0f && mri_out->type == MRI_UCHAR) norm = 0.0f ; MRIsetVoxVal(mri_out, x, y, z, 0, norm) ; } } } printf("writing normalized volume to %s...\n", argv[2]) ; MRIwrite(mri_out, argv[2]); MRIfree(&mri_in); MRIfree(&mri_bias); MRIfree(&mri_out); MRIfree(&mri_T1); MRIfree(&mri_ctrl); MRIfree(&mri_snr); //HISTOfree(&h); exit(0); } /* end main() */
int main(int argc, char *argv[]) { char **av; MRI *mri_src, *mri_mask, *mri_dst ; int nargs, ac, nmask; int x, y, z; float value; MRI_REGION *region; LTA *lta = 0; int transform_type; MRI *mri_tmp; nargs = handle_version_option ( argc, argv, "$Id: mri_mask.c,v 1.18 2012/12/07 22:45:50 greve Exp $", "$Name: $" ); if (nargs && argc - nargs == 1) { exit (0); } argc -= nargs ; Progname = argv[0]; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc != 4) { printf("Incorrect number of arguments, argc = %d\n", argc); usage(1); } mri_src = MRIread(argv[1]) ; if (!mri_src) ErrorExit(ERROR_BADPARM, "%s: could not read source volume %s", Progname, argv[1]) ; mri_mask = MRIread(argv[2]) ; if (!mri_mask) ErrorExit(ERROR_BADPARM, "%s: could not read mask volume %s", Progname, argv[2]) ; if(mri_src->width != mri_mask->width) { printf("ERROR: dimension mismatch between source and mask\n"); exit(1); } printf("DoAbs = %d\n",DoAbs); /* Read LTA transform and apply it to mri_mask */ if (xform_fname != NULL) { printf("Apply the given LTA xfrom to the mask volume\n"); // read transform transform_type = TransformFileNameType(xform_fname); if (transform_type == MNI_TRANSFORM_TYPE || transform_type == TRANSFORM_ARRAY_TYPE || transform_type == REGISTER_DAT || transform_type == FSLREG_TYPE ) { printf("Reading transform ...\n"); lta = LTAreadEx(xform_fname) ; if (!lta) ErrorExit(ERROR_NOFILE, "%s: could not read transform file %s", Progname, xform_fname) ; if (transform_type == FSLREG_TYPE) { if (lta_src == 0 || lta_dst == 0) { fprintf(stderr, "ERROR: fslmat does not have information on " "the src and dst volumes\n"); fprintf(stderr, "ERROR: you must give options '-lta_src' " "and '-lta_dst' to specify the src and dst volume infos\n"); } LTAmodifySrcDstGeom(lta, lta_src, lta_dst); // add src and dst information LTAchangeType(lta, LINEAR_VOX_TO_VOX); } if (lta->xforms[0].src.valid == 0) { if (lta_src == 0) { fprintf(stderr, "The transform does not have the valid src volume info.\n"); fprintf(stderr, "Either you give src volume info by option -lta_src or\n"); fprintf(stderr, "make the transform to have the valid src info.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, lta_src, NULL); // add src information // getVolGeom(lta_src, <->src); } } if (lta->xforms[0].dst.valid == 0) { if (lta_dst == 0) { fprintf(stderr, "The transform does not have the valid dst volume info.\n"); fprintf(stderr, "Either you give src volume info by option -lta_dst or\n"); fprintf(stderr, "make the transform to have the valid dst info.\n"); fprintf(stderr, "If the dst was average_305, then you can set\n"); fprintf(stderr, "environmental variable USE_AVERAGE305 true\n"); fprintf(stderr, "without giving the dst volume for RAS-to-RAS transform.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, NULL, lta_dst); // add dst information } } } else { ErrorExit(ERROR_BADPARM, "transform is not of MNI, nor Register.dat, nor FSLMAT type"); } if (invert) { VOL_GEOM vgtmp; LT *lt; MATRIX *m_tmp = lta->xforms[0].m_L ; lta->xforms[0].m_L = MatrixInverse(lta->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a->xforms[0]; if (lt->dst.valid == 0 || lt->src.valid == 0) { fprintf(stderr, "WARNING:**************************************" "*************************\n"); fprintf(stderr, "WARNING:dst volume information is invalid. " "Most likely produced wrong inverse.\n"); fprintf(stderr, "WARNING:**************************************" "*************************\n"); } copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); } // LTAchangeType(lta, LINEAR_VOX_TO_VOX); mri_tmp = MRIalloc(mri_src->width, mri_src->height, mri_src->depth, mri_mask->type) ; MRIcopyHeader(mri_src, mri_tmp) ; mri_tmp = LTAtransformInterp(mri_mask, mri_tmp, lta, InterpMethod); // mri_tmp = //MRIlinearTransformInterp // ( // mri_mask, mri_tmp, lta->xforms[0].m_L, InterpMethod // ); MRIfree(&mri_mask); mri_mask = mri_tmp; if (lta_src) { MRIfree(<a_src); } if (lta_dst) { MRIfree(<a_dst); } if (lta) { LTAfree(<a); } } /* if (xform_fname != NULL) */ // Threshold mask nmask = 0; for (z = 0 ; z <mri_mask->depth ; z++) { for (y = 0 ; y < mri_mask->height ; y++) { for (x = 0 ; x < mri_mask->width ; x++) { value = MRIgetVoxVal(mri_mask, x, y, z, 0); if(DoAbs) { value = fabs(value); } if(value <= threshold) { MRIsetVoxVal(mri_mask,x,y,z,0,0); } else { nmask ++; } } } } printf("Found %d voxels in mask (pct=%6.2f)\n",nmask, 100.0*nmask/(mri_mask->width*mri_mask->height*mri_mask->depth)); if(DoBB){ printf("Computing bounding box, npad = %d\n",nPadBB); region = REGIONgetBoundingBox(mri_mask,nPadBB); REGIONprint(stdout, region); mri_tmp = MRIextractRegion(mri_mask, NULL, region); if(mri_tmp == NULL) exit(1); MRIfree(&mri_mask); mri_mask = mri_tmp; mri_tmp = MRIextractRegion(mri_src, NULL, region); if(mri_tmp == NULL) exit(1); MRIfree(&mri_src); mri_src = mri_tmp; } int mask=0; float out_val=0; if (do_transfer) { mask = (int)transfer_val; out_val = transfer_val; } mri_dst = MRImask(mri_src, mri_mask, NULL, mask, out_val) ; if (!mri_dst) { ErrorExit(Gerror, "%s: stripping failed", Progname) ; } if (keep_mask_deletion_edits) { mri_dst = MRImask(mri_dst, mri_mask, NULL, 1, 1) ; // keep voxels = 1 if (!mri_dst) ErrorExit(Gerror, "%s: stripping failed on keep_mask_deletion_edits", Progname) ; } printf("Writing masked volume to %s...", argv[3]) ; MRIwrite(mri_dst, argv[3]); printf("done.\n") ; MRIfree(&mri_src); MRIfree(&mri_mask); MRIfree(&mri_dst); exit(0); } /* end main() */