Example #1
0
MRI *
MRIcropVolumeToLabel(MRI *mri_src, 
                     MRI *mri_dst, 
                     LABEL *area, 
                     MRI_SURFACE *mris_white, 
                     MRI_SURFACE *mris_pial)
{
  MHT    *mht_white, *mht_pial ;
  int    x, y, z ;
  VERTEX *v_white, *v_pial ;
  Real   xs, ys, zs ;

  mht_white = MHTfillVertexTableRes(mris_white, NULL, CURRENT_VERTICES, 5.0) ;
  mht_pial = MHTfillVertexTableRes(mris_pial, NULL, CURRENT_VERTICES, 5.0) ;
  if (mri_dst == NULL)
    mri_dst = MRIclone(mri_src, NULL) ;

  MRISclearMarks(mris_white) ; MRISclearMarks(mris_pial) ;
  LabelMarkSurface(area, mris_white) ; LabelMarkSurface(area, mris_pial) ;
  for (x = 0 ; x < mri_src->width ; x++)
  {
    for (y = 0 ; y < mri_src->height ; y++)
    {
      for (z = 0 ; z < mri_src->depth ; z++)
      {
        if (x == Gx && y == Gy && z == Gz)
          DiagBreak() ;
              
        if (MRIgetVoxVal(mri_src, x, y, z, 0) > 0)
        {
          MRISsurfaceRASFromVoxel(mris_white, mri_dst, 
                                  x, y, z, 
                                  &xs, &ys, &zs) ;
          v_white = MHTfindClosestVertexInTable(mht_white, mris_white, 
                                                xs, ys, zs, 1) ;
          v_pial = MHTfindClosestVertexInTable(mht_pial, mris_pial, 
                                               xs, ys, zs, 1) ;
          if ((v_white && v_white->marked == 1) ||
              (v_pial && v_pial->marked == 1))
          {
            MRIsetVoxVal(mri_dst, x, y, z, 0, 255) ;
          }
          else
            MRIsetVoxVal(mri_dst, x, y, z, 0, 0) ;
        }
      }
    }
  }

  MHTfree(&mht_white) ; MHTfree(&mht_pial) ;
  return(mri_dst) ;
}
static int
initialize_cluster_centers_with_ico(MRI_SURFACE *mris, MRI *mri_profiles, CLUSTER *ct, MRI_SURFACE *mris_ico) {
  int             i, j, vno, nsamples, vnos[MAX_CLUSTERS], k ;
  double          r1, r2, res ;
  float           fmin ;
  MRIS_HASH_TABLE *mht ;
  VERTEX          *vico ;

  k = mris_ico->nvertices ;
  MRISstoreRipFlags(mris) ;
  MRISunrip(mris) ;
  r1 = MRISaverageRadius(mris) ;
  r2 = MRISaverageRadius(mris_ico) ;
  MRISscaleBrain(mris_ico,mris_ico, r1/r2);

  res = sqrt(mris->total_area/mris->nvertices) ;
  mht = MHTfillVertexTableRes(mris, NULL, CURRENT_VERTICES, 2*res) ;
  nsamples = mri_profiles->nframes ;
  for (i = 0 ; i < mris_ico->nvertices ; i++) {
    vico = &mris_ico->vertices[i] ;
    vno = MRISfindClosestVertex(mris, vico->x, vico->y, vico->z, &fmin) ;
    if (vno < 0)
      continue ;
    vnos[i] = vno ;
    for (j = 0 ; j < nsamples ; j++)
      VECTOR_ELT(ct[i].v_mean, j+1) = MRIgetVoxVal(mri_profiles, vno, 0, 0, j) ;
  }
  mris->ct = CTABalloc(k) ;
  for (i = 0 ; i < k ; i++) {
    mris->vertices[vnos[i]].curv = i ;
    ct[i].npoints++ ;
    ct[i].vno = vnos[i] ;
    CTABannotationAtIndex(mris->ct, i, &mris->vertices[vnos[i]].annotation) ;
  }
  MRISrestoreRipFlags(mris) ;
  return(NO_ERROR) ;
}
Example #3
0
/*--------------------------------------------------*/
int main(int argc, char **argv)
{
    int nargs, err, asegid, c, r, s, nctx, annot,vtxno,nripped;
    int annotid, IsCortex=0, IsWM=0, IsHypo=0, hemi=0, segval=0;
    int RibbonVal=0,nbrute=0;
    float dmin=0.0, lhRibbonVal=0, rhRibbonVal=0;

    /* rkt: check for and handle version tag */
    nargs = handle_version_option (argc, argv, vcid, "$Name: stable5 $");
    if (nargs && argc - nargs == 1)
    {
        exit (0);
    }
    argc -= nargs;

    Progname = argv[0] ;
    argc --;
    argv++;
    ErrorInit(NULL, NULL, NULL) ;
    DiagInit(NULL, NULL, NULL) ;

    if (argc == 0)
    {
        usage_exit();
    }

    SUBJECTS_DIR = getenv("SUBJECTS_DIR");
    if (SUBJECTS_DIR==NULL)
    {
        printf("ERROR: SUBJECTS_DIR not defined in environment\n");
        exit(1);
    }

    parse_commandline(argc, argv);
    check_options();
    dump_options(stdout);

    /* ------ Load subject's lh white surface ------ */
    sprintf(tmpstr,"%s/%s/surf/lh.white",SUBJECTS_DIR,subject);
    printf("\nReading lh white surface \n %s\n",tmpstr);
    lhwhite = MRISread(tmpstr);
    if (lhwhite == NULL)
    {
        fprintf(stderr,"ERROR: could not read %s\n",tmpstr);
        exit(1);
    }
    /* ------ Load subject's lh pial surface ------ */
    sprintf(tmpstr,"%s/%s/surf/lh.pial",SUBJECTS_DIR,subject);
    printf("\nReading lh pial surface \n %s\n",tmpstr);
    lhpial = MRISread(tmpstr);
    if (lhpial == NULL)
    {
        fprintf(stderr,"ERROR: could not read %s\n",tmpstr);
        exit(1);
    }
    if (lhwhite->nvertices != lhpial->nvertices)
    {
        printf("ERROR: lh white and pial have a different number of "
               "vertices (%d,%d)\n",
               lhwhite->nvertices,lhpial->nvertices);
        exit(1);
    }

    /* ------ Load lh annotation ------ */
    sprintf(annotfile,"%s/%s/label/lh.%s.annot",SUBJECTS_DIR,subject,annotname);
    printf("\nLoading lh annotations from %s\n",annotfile);
    err = MRISreadAnnotation(lhwhite, annotfile);
    if (err)
    {
        printf("ERROR: MRISreadAnnotation() failed %s\n",annotfile);
        exit(1);
    }

    /* ------ Load subject's rh white surface ------ */
    sprintf(tmpstr,"%s/%s/surf/rh.white",SUBJECTS_DIR,subject);
    printf("\nReading rh white surface \n %s\n",tmpstr);
    rhwhite = MRISread(tmpstr);
    if (rhwhite == NULL)
    {
        fprintf(stderr,"ERROR: could not read %s\n",tmpstr);
        exit(1);
    }
    /* ------ Load subject's rh pial surface ------ */
    sprintf(tmpstr,"%s/%s/surf/rh.pial",SUBJECTS_DIR,subject);
    printf("\nReading rh pial surface \n %s\n",tmpstr);
    rhpial = MRISread(tmpstr);
    if (rhpial == NULL)
    {
        fprintf(stderr,"ERROR: could not read %s\n",tmpstr);
        exit(1);
    }
    if (rhwhite->nvertices != rhpial->nvertices)
    {
        printf("ERROR: rh white and pial have a different "
               "number of vertices (%d,%d)\n",
               rhwhite->nvertices,rhpial->nvertices);
        exit(1);
    }

    /* ------ Load rh annotation ------ */
    sprintf(annotfile,"%s/%s/label/rh.%s.annot",SUBJECTS_DIR,subject,annotname);
    printf("\nLoading rh annotations from %s\n",annotfile);
    err = MRISreadAnnotation(rhwhite, annotfile);
    if (err)
    {
        printf("ERROR: MRISreadAnnotation() failed %s\n",annotfile);
        exit(1);
    }

    if (lhwhite->ct)
    {
        printf("Have color table for lh white annotation\n");
    }
    if (rhwhite->ct)
    {
        printf("Have color table for rh white annotation\n");
    }
    //print_annotation_table(stdout);

    if (UseRibbon)
    {
        sprintf(tmpstr,"%s/%s/mri/lh.ribbon.mgz",SUBJECTS_DIR,subject);
        printf("Loading lh ribbon mask from %s\n",tmpstr);
        lhRibbon = MRIread(tmpstr);
        if (lhRibbon == NULL)
        {
            printf("ERROR: loading %s\n",tmpstr);
            exit(1);
        }
        sprintf(tmpstr,"%s/%s/mri/rh.ribbon.mgz",SUBJECTS_DIR,subject);
        printf("Loading rh ribbon mask from %s\n",tmpstr);
        rhRibbon = MRIread(tmpstr);
        if (rhRibbon == NULL)
        {
            printf("ERROR: loading  %s\n",tmpstr);
            exit(1);
        }
    }

    if (UseNewRibbon)
    {
        sprintf(tmpstr,"%s/%s/mri/ribbon.mgz",SUBJECTS_DIR,subject);
        printf("Loading ribbon segmentation from %s\n",tmpstr);
        RibbonSeg = MRIread(tmpstr);
        if (RibbonSeg == NULL)
        {
            printf("ERROR: loading %s\n",tmpstr);
            exit(1);
        }
    }

    if (LabelHypoAsWM)
    {
        sprintf(tmpstr,"%s/%s/mri/filled.mgz",SUBJECTS_DIR,subject);
        printf("Loading filled from %s\n",tmpstr);
        filled = MRIread(tmpstr);
        if (filled == NULL)
        {
            printf("ERROR: loading filled %s\n",tmpstr);
            exit(1);
        }
    }

    // ------------ Rip -----------------------
    if (RipUnknown)
    {
        printf("Ripping vertices labeled as unkown\n");
        nripped = 0;
        for (vtxno = 0; vtxno < lhwhite->nvertices; vtxno++)
        {
            annot = lhwhite->vertices[vtxno].annotation;
            CTABfindAnnotation(lhwhite->ct, annot, &annotid);
            // Sometimes the annotation will be "none" indicated by
            // annotid = -1. We interpret this as "unknown".
            if (annotid == 0 || annotid == -1)
            {
                lhwhite->vertices[vtxno].ripflag = 1;
                lhpial->vertices[vtxno].ripflag = 1;
                nripped++;
            }
        }
        printf("Ripped %d vertices from left hemi\n",nripped);
        nripped = 0;
        for (vtxno = 0; vtxno < rhwhite->nvertices; vtxno++)
        {
            annot = rhwhite->vertices[vtxno].annotation;
            CTABfindAnnotation(rhwhite->ct, annot, &annotid);
            if (annotid == 0 || annotid == -1)
            {
                rhwhite->vertices[vtxno].ripflag = 1;
                rhpial->vertices[vtxno].ripflag = 1;
                nripped++;
            }
        }
        printf("Ripped %d vertices from right hemi\n",nripped);
    }


    printf("\n");
    printf("Building hash of lh white\n");
    lhwhite_hash = MHTfillVertexTableRes(lhwhite, NULL,CURRENT_VERTICES,hashres);
    printf("\n");
    printf("Building hash of lh pial\n");
    lhpial_hash = MHTfillVertexTableRes(lhpial, NULL,CURRENT_VERTICES,hashres);
    printf("\n");
    printf("Building hash of rh white\n");
    rhwhite_hash = MHTfillVertexTableRes(rhwhite, NULL,CURRENT_VERTICES,hashres);
    printf("\n");
    printf("Building hash of rh pial\n");
    rhpial_hash = MHTfillVertexTableRes(rhpial, NULL,CURRENT_VERTICES,hashres);

    /* ------ Load ASeg ------ */
    sprintf(tmpstr,"%s/%s/mri/aseg.mgz",SUBJECTS_DIR,subject);
    if (!fio_FileExistsReadable(tmpstr))
    {
        sprintf(tmpstr,"%s/%s/mri/aseg.mgh",SUBJECTS_DIR,subject);
        if (!fio_FileExistsReadable(tmpstr))
        {
            sprintf(tmpstr,"%s/%s/mri/aseg/COR-.info",SUBJECTS_DIR,subject);
            if (!fio_FileExistsReadable(tmpstr))
            {
                printf("ERROR: cannot find aseg\n");
                exit(1);
            }
            else
            {
                sprintf(tmpstr,"%s/%s/mri/aseg/",SUBJECTS_DIR,subject);
            }
        }
    }

    printf("\nLoading aseg from %s\n",tmpstr);
    ASeg = MRIread(tmpstr);
    if (ASeg == NULL)
    {
        printf("ERROR: loading aseg %s\n",tmpstr);
        exit(1);
    }
    mritmp = MRIchangeType(ASeg,MRI_INT,0,0,1);
    MRIfree(&ASeg);
    ASeg = mritmp;

    if (CtxSegFile)
    {
        printf("Loading Ctx Seg File %s\n",CtxSegFile);
        CtxSeg = MRIread(CtxSegFile);
        if (CtxSeg == NULL)
        {
            exit(1);
        }
    }

    AParc = MRIclone(ASeg,NULL);
    if (OutDistFile != NULL)
    {
        Dist = MRIclone(ASeg,NULL);
        mritmp = MRIchangeType(Dist,MRI_FLOAT,0,0,0);
        if (mritmp == NULL)
        {
            printf("ERROR: could change type\n");
            exit(1);
        }
        MRIfree(&Dist);
        Dist = mritmp;
    }

    Vox2RAS = MRIxfmCRS2XYZtkreg(ASeg);
    printf("ASeg Vox2RAS: -----------\n");
    MatrixPrint(stdout,Vox2RAS);
    printf("-------------------------\n");
    CRS = MatrixAlloc(4,1,MATRIX_REAL);
    CRS->rptr[4][1] = 1;
    RAS = MatrixAlloc(4,1,MATRIX_REAL);
    RAS->rptr[4][1] = 1;

    if (crsTest)
    {
        printf("Testing point %d %d %d\n",ctest,rtest,stest);
        err = FindClosestLRWPVertexNo(ctest,rtest,stest,
                                      &lhwvtx, &lhpvtx,
                                      &rhwvtx, &rhpvtx, Vox2RAS,
                                      lhwhite,  lhpial,
                                      rhwhite, rhpial,
                                      lhwhite_hash, lhpial_hash,
                                      rhwhite_hash, rhpial_hash);

        printf("Result: err = %d\n",err);
        exit(err);
    }

    printf("\nLabeling Slice\n");
    nctx = 0;
    annot = 0;
    annotid = 0;
    nbrute = 0;

    // Go through each voxel in the aseg
    for (c=0; c < ASeg->width; c++)
    {
        printf("%3d ",c);
        if (c%20 ==19)
        {
            printf("\n");
        }
        fflush(stdout);
        for (r=0; r < ASeg->height; r++)
        {
            for (s=0; s < ASeg->depth; s++)
            {

                asegid = MRIgetVoxVal(ASeg,c,r,s,0);
                if (asegid == 3 || asegid == 42)
                {
                    IsCortex = 1;
                }
                else
                {
                    IsCortex = 0;
                }
                if (asegid >= 77 && asegid <= 82)
                {
                    IsHypo = 1;
                }
                else
                {
                    IsHypo = 0;
                }
                if (asegid == 2 || asegid == 41)
                {
                    IsWM = 1;
                }
                else
                {
                    IsWM = 0;
                }
                if (IsHypo && LabelHypoAsWM && MRIgetVoxVal(filled,c,r,s,0))
                {
                    IsWM = 1;
                }

                // integrate surface information
                //
                // Only Do This for GM,WM or Unknown labels in the ASEG !!!
                //
                // priority is given to the ribbon computed from the surface
                // namely
                //  ribbon=GM => GM
                //  aseg=GM AND ribbon=WM => WM
                //  ribbon=UNKNOWN => UNKNOWN
                if (UseNewRibbon && ( IsCortex || IsWM || asegid==0 ) )
                {
                    RibbonVal = MRIgetVoxVal(RibbonSeg,c,r,s,0);
                    MRIsetVoxVal(ASeg,c,r,s,0, RibbonVal);
                    if (RibbonVal==2 || RibbonVal==41)
                    {
                        IsWM = 1;
                        IsCortex = 0;
                    }
                    else if (RibbonVal==3 || RibbonVal==42)
                    {
                        IsWM = 0;
                        IsCortex = 1;
                    }
                    if (RibbonVal==0)
                    {
                        IsWM = 0;
                        IsCortex = 0;
                    }
                }

                // If it's not labeled as cortex or wm in the aseg, skip
                if (!IsCortex && !IsWM)
                {
                    continue;
                }

                // If it's wm but not labeling wm, skip
                if (IsWM && !LabelWM)
                {
                    continue;
                }

                // Check whether this point is in the ribbon
                if (UseRibbon)
                {
                    lhRibbonVal = MRIgetVoxVal(lhRibbon,c,r,s,0);
                    rhRibbonVal = MRIgetVoxVal(rhRibbon,c,r,s,0);
                    if (IsCortex)
                    {
                        // ASeg says it's in cortex
                        if (lhRibbonVal < 0.5 && rhRibbonVal < 0.5)
                        {
                            // but it is not part of the ribbon,
                            // so set it to unknown (0) and go to the next voxel.
                            MRIsetVoxVal(ASeg,c,r,s,0,0);
                            continue;
                        }
                    }
                }

                // Convert the CRS to RAS
                CRS->rptr[1][1] = c;
                CRS->rptr[2][1] = r;
                CRS->rptr[3][1] = s;
                RAS = MatrixMultiply(Vox2RAS,CRS,RAS);
                vtx.x = RAS->rptr[1][1];
                vtx.y = RAS->rptr[2][1];
                vtx.z = RAS->rptr[3][1];

                // Get the index of the closest vertex in the
                // lh.white, lh.pial, rh.white, rh.pial
                if (UseHash)
                {
                    lhwvtx = MHTfindClosestVertexNo(lhwhite_hash,lhwhite,&vtx,&dlhw);
                    lhpvtx = MHTfindClosestVertexNo(lhpial_hash, lhpial, &vtx,&dlhp);
                    rhwvtx = MHTfindClosestVertexNo(rhwhite_hash,rhwhite,&vtx,&drhw);
                    rhpvtx = MHTfindClosestVertexNo(rhpial_hash, rhpial, &vtx,&drhp);
                    if (lhwvtx < 0 && lhpvtx < 0 && rhwvtx < 0 && rhpvtx < 0)
                    {
                        /*
                        printf("  Could not map to any surface with hash table:\n");
                        printf("  crs = %d %d %d, ras = %6.4f %6.4f %6.4f \n",
                        c,r,s,vtx.x,vtx.y,vtx.z);
                        printf("  Using brute force search %d ... \n",nbrute);
                        fflush(stdout);
                        */
                        lhwvtx = MRISfindClosestVertex(lhwhite,vtx.x,vtx.y,vtx.z,&dlhw);
                        lhpvtx = MRISfindClosestVertex(lhpial,vtx.x,vtx.y,vtx.z,&dlhp);
                        rhwvtx = MRISfindClosestVertex(rhwhite,vtx.x,vtx.y,vtx.z,&drhw);
                        rhpvtx = MRISfindClosestVertex(rhpial,vtx.x,vtx.y,vtx.z,&drhp);
                        nbrute ++;
                        //exit(1);
                    }
                }
                else
                {
                    lhwvtx = MRISfindClosestVertex(lhwhite,vtx.x,vtx.y,vtx.z,&dlhw);
                    lhpvtx = MRISfindClosestVertex(lhpial,vtx.x,vtx.y,vtx.z,&dlhp);
                    rhwvtx = MRISfindClosestVertex(rhwhite,vtx.x,vtx.y,vtx.z,&drhw);
                    rhpvtx = MRISfindClosestVertex(rhpial,vtx.x,vtx.y,vtx.z,&drhp);
                }

                if (lhwvtx < 0)
                {
                    dlhw = 1000000000000000.0;
                }
                if (lhpvtx < 0)
                {
                    dlhp = 1000000000000000.0;
                }
                if (rhwvtx < 0)
                {
                    drhw = 1000000000000000.0;
                }
                if (rhpvtx < 0)
                {
                    drhp = 1000000000000000.0;
                }

                if (dlhw <= dlhp && dlhw < drhw && dlhw < drhp && lhwvtx >= 0)
                {
                    annot = lhwhite->vertices[lhwvtx].annotation;
                    hemi = 1;
                    if (lhwhite->ct)
                    {
                        CTABfindAnnotation(lhwhite->ct, annot, &annotid);
                    }
                    else
                    {
                        annotid = annotation_to_index(annot);
                    }
                    dmin = dlhw;
                }
                if (dlhp < dlhw && dlhp < drhw && dlhp < drhp && lhpvtx >= 0)
                {
                    annot = lhwhite->vertices[lhpvtx].annotation;
                    hemi = 1;
                    if (lhwhite->ct)
                    {
                        CTABfindAnnotation(lhwhite->ct, annot, &annotid);
                    }
                    else
                    {
                        annotid = annotation_to_index(annot);
                    }
                    dmin = dlhp;
                }

                if (drhw < dlhp && drhw < dlhw && drhw <= drhp && rhwvtx >= 0)
                {
                    annot = rhwhite->vertices[rhwvtx].annotation;
                    hemi = 2;
                    if (rhwhite->ct)
                    {
                        CTABfindAnnotation(rhwhite->ct, annot, &annotid);
                    }
                    else
                    {
                        annotid = annotation_to_index(annot);
                    }
                    dmin = drhw;
                }
                if (drhp < dlhp && drhp < drhw && drhp < dlhw && rhpvtx >= 0)
                {
                    annot = rhwhite->vertices[rhpvtx].annotation;
                    hemi = 2;
                    if (rhwhite->ct)
                    {
                        CTABfindAnnotation(rhwhite->ct, annot, &annotid);
                    }
                    else
                    {
                        annotid = annotation_to_index(annot);
                    }
                    dmin = drhp;
                }

                // Sometimes the annotation will be "none" indicated by
                // annotid = -1. We interpret this as "unknown".
                if (annotid == -1)
                {
                    annotid = 0;
                }

                // why was this here in the first place?
                /*
                       if (annotid == 0 &&
                           lhwvtx >= 0 &&
                           lhpvtx >= 0 &&
                           rhwvtx >= 0 &&
                           rhpvtx >= 0) {
                         printf("%d %d %d %d\n",
                                lhwhite->vertices[lhwvtx].ripflag,
                                lhpial->vertices[lhpvtx].ripflag,
                                rhwhite->vertices[rhwvtx].ripflag,
                                rhpial->vertices[rhpvtx].ripflag);
                  } */

                if ( IsCortex && hemi == 1)
                {
                    segval = annotid+1000 + baseoffset;  //ctx-lh
                }
                if ( IsCortex && hemi == 2)
                {
                    segval = annotid+2000 + baseoffset;  //ctx-rh
                }
                if (!IsCortex && hemi == 1)
                {
                    segval = annotid+3000 + baseoffset;  // wm-lh
                }
                if (!IsCortex && hemi == 2)
                {
                    segval = annotid+4000 + baseoffset;  // wm-rh
                }

                if (!IsCortex && dmin > dmaxctx && hemi == 1)
                {
                    segval = 5001;
                }
                if (!IsCortex && dmin > dmaxctx && hemi == 2)
                {
                    segval = 5002;
                }

                // This is a hack for getting the right cortical seg with --rip-unknown
                // The aparc+aseg should be passed as CtxSeg.
                if (IsCortex && CtxSeg)
                {
                    segval = MRIgetVoxVal(CtxSeg,c,r,s,0);
                }

                MRIsetVoxVal(ASeg,c,r,s,0,segval);
                MRIsetVoxVal(AParc,c,r,s,0,annot);
                if (OutDistFile != NULL)
                {
                    MRIsetVoxVal(Dist,c,r,s,0,dmin);
                }

                if (debug || annotid == -1)
                {
                    // Gets here when there is no label at the found vertex.
                    // This is different than having a vertex labeled as "unknown"
                    if (!debug)
                    {
                        continue;
                    }
                    printf("\n");
                    printf("Found closest vertex, but it has no label.\n");
                    printf("aseg id = %d\n",asegid);
                    printf("crs = %d %d %d, ras = %6.4f %6.4f %6.4f \n",
                           c,r,s,vtx.x,vtx.y,vtx.z);
                    if (lhwvtx > 0) printf("lhw  %d  %7.5f     %6.4f  %6.4f  %6.4f\n",
                                               lhwvtx, dlhw,
                                               lhwhite->vertices[lhwvtx].x,
                                               lhwhite->vertices[lhwvtx].y,
                                               lhwhite->vertices[lhwvtx].z);
                    if (lhpvtx > 0) printf("lhp  %d  %7.5f     %6.4f  %6.4f  %6.4f\n",
                                               lhpvtx, dlhp,
                                               lhpial->vertices[lhpvtx].x,
                                               lhpial->vertices[lhpvtx].y,
                                               lhpial->vertices[lhpvtx].z);
                    if (rhwvtx > 0) printf("rhw  %d  %7.5f     %6.4f  %6.4f  %6.4f\n",
                                               rhwvtx, drhw,
                                               rhwhite->vertices[rhwvtx].x,
                                               rhwhite->vertices[rhwvtx].y,
                                               rhwhite->vertices[rhwvtx].z);
                    if (rhpvtx > 0) printf("rhp  %d  %7.5f     %6.4f  %6.4f  %6.4f\n",
                                               rhpvtx, drhp,
                                               rhpial->vertices[rhpvtx].x,
                                               rhpial->vertices[rhpvtx].y,
                                               rhpial->vertices[rhpvtx].z);
                    printf("annot = %d, annotid = %d\n",annot,annotid);
                    CTABprintASCII(lhwhite->ct,stdout);
                    continue;
                }

                nctx++;
            }
        }
    }
    printf("nctx = %d\n",nctx);
    printf("Used brute-force search on %d voxels\n",nbrute);

    if (FixParaHipWM)
    {
        /* This is a bit of a hack. There are some vertices that have been
           ripped because they are "unkown". When the above alorithm finds
           these, it searches for the closest known vertex. If this is
           less than dmax away, then the wm voxel gets labeled
           accordingly.  However, there are often some voxels near
           ventralDC that are just close enough in 3d space to parahip to
           get labeled even though they are very far away along the
           surface. These voxels end up forming an island. CCSegment()
           will eliminate any islands. Unforunately, CCSegment() uses
           6-neighbor (face) definition of connectedness, so some voxels
           may be eliminated.
         */
        printf("Fixing Parahip LH WM\n");
        CCSegment(ASeg, 3016, 5001); //3016 = lhphwm, 5001 = unsegmented WM left
        printf("Fixing Parahip RH WM\n");
        CCSegment(ASeg, 4016, 5002); //4016 = rhphwm, 5002 = unsegmented WM right
    }

    printf("Writing output aseg to %s\n",OutASegFile);
    MRIwrite(ASeg,OutASegFile);

    if (OutAParcFile != NULL)
    {
        printf("Writing output aparc to %s\n",OutAParcFile);
        MRIwrite(AParc,OutAParcFile);
    }
    if (OutDistFile != NULL)
    {
        printf("Writing output dist file to %s\n",OutDistFile);
        MRIwrite(Dist,OutDistFile);
    }


    return(0);
}
Example #4
0
int
MRIsampleParcellationToSurface(MRI_SURFACE *mris, MRI *mri_parc) {
  int             min_label, max_label, **label_histo, l, vno, nlabels, x, y, z, max_l ;
  float           fmin, fmax, max_count, d ;
  MRIS_HASH_TABLE *mht ;
  VERTEX          *v ;
  Real            xs, ys, zs, xv, yv, zv, val ;
  MRI             *mri_parc_unused ;

  mri_parc_unused = MRIcopy(mri_parc, NULL) ;
  MRIvalRange(mri_parc, &fmin, &fmax) ;
  min_label = (int)floor(fmin) ;
  max_label = (int)ceil(fmax) ;
  nlabels = max_label - min_label + 1 ;

  label_histo = (int **)calloc(mris->nvertices, sizeof(int *)) ;
  if (label_histo == NULL)
    ErrorExit(ERROR_NOMEMORY, "%s: could not create label frequency histo", Progname) ;
  for (vno = 0 ; vno < mris->nvertices ;  vno++) {
    label_histo[vno] = (int *)calloc(nlabels, sizeof(int)) ;
    if (label_histo[vno] == NULL)
      ErrorExit(ERROR_NOMEMORY, "%s: could not create label frequency histo[%d] with %d bins",
                Progname, vno, nlabels) ;
  }

  mht = MHTfillVertexTableRes(mris, NULL, CURRENT_VERTICES, 8.0) ;

  MRISclearMarks(mris) ;

  // build histograms at each vertex
  for (x = 0 ; x < mri_parc->width ; x++) {
    for (y = 0 ; y < mri_parc->height ; y++) {
      for (z = 0 ; z < mri_parc->depth ; z++) {
        if (x == Gx && y == Gy && z == Gz)
          DiagBreak() ;
        l = (int)MRIgetVoxVal(mri_parc, x, y, z, 0) ;
        if (l == 0)
          continue ;
        MRIvoxelToSurfaceRAS(mri_parc, x, y, z, &xs, &ys, &zs) ;
        v = MHTfindClosestVertexInTable(mht, mris, xs, ys, zs, 0) ;
        if (v == NULL)
          continue ;
        if (sqrt(SQR(v->x-xs) + SQR(v->y-ys) + SQR(v->z-zs)) > 3)
          continue ;
        MRIsetVoxVal(mri_parc_unused, x, y, z, 0, 0) ;
        vno = v-mris->vertices ;
        if (vno == Gdiag_no)
        {
          printf("v %d: sampling from (%d, %d, %d) - %d\n",
                 vno, x, y, z, l);
          DiagBreak() ;
        }
        label_histo[vno][l-min_label]++ ;
      }
    }
  }

  MRIwrite(mri_parc_unused, "pu.mgz") ;
  for (vno = 0 ; vno < mris->nvertices ;  vno++) {
    if (vno == Gdiag_no)
      DiagBreak() ;
    max_l = 0 ;
    max_count = 0 ;
    for (l = 0 ; l < nlabels ; l++) {
      if (label_histo[vno][l] > max_count) {
        max_count = label_histo[vno][l] ;
        max_l = l+min_label ;
      }
    }
    v = &mris->vertices[vno] ;
    v->val = v->annotation = max_l ;
    if (max_count > 0)
      v->marked = 1 ;
  }
  for (vno = 0 ; vno < mris->nvertices ;  vno++) {
    v = &mris->vertices[vno] ;
    if (vno == Gdiag_no)
      DiagBreak() ;
    if (v->marked)
      continue ;  // found something here

    for (d = 0 ; d <= 2 ; d += 0.25) {
      xs = v->x + d*v->nx;
      ys = v->y + d*v->ny;
      zs = v->z + d*v->nz;
      MRIsurfaceRASToVoxel(mri_parc, xs, ys, zs, &xv, &yv, &zv);
      MRIsampleVolumeType(mri_parc, xv, yv, zv, &val, SAMPLE_NEAREST) ;
      l = (int)nint(val) ;
      if (l > 0) {
        v->val = v->annotation = l ;
        break ;
      }
    }
  }

  MHTfree(&mht) ;
  for (vno = 0 ; vno < mris->nvertices ;  vno++)
    free(label_histo[vno]) ;
  free(label_histo) ;
  MRIfree(&mri_parc_unused) ;
  return(NO_ERROR) ;
}
Example #5
0
MRI*
MRIcomputeVolumeFractionFromSurface(MRI_SURFACE *mris, double acc, MRI *mri_src, MRI *mri_fractions)
{
  const int width = mri_src->width;
  const int height = mri_src->height;
  const int depth = mri_src->depth;
  int x,y,z, vno;
  double xs, ys, zs, dist; 
  MRIS_HASH_TABLE *mht;
  VERTEX *v; 
  
  /* preparing the output */
  printf("preparing the output\n");
  if (mri_fractions == NULL)
    {
      mri_fractions = MRIalloc(width,height,depth,MRI_FLOAT);
      MRIcopyHeader(mri_src, mri_fractions);
    }
  MRI *mri_shell, *mri_interior; 
  /* creating a shell from the surface */
  printf("computing the shell\n");
  mri_shell = MRIclone(mri_src, NULL);
  mri_shell = MRISshell(mri_src, mris, mri_shell, 1);
  /* creating an interior image from the surface */
  printf("computing an interior image\n");
  mri_interior = MRIclone(mri_src, NULL);
  MRIclear(mri_interior);
  mri_interior = MRISfillInterior(mris, 0.0, mri_interior);
  /* creating the hash table related to the surface vertices */
  printf("computing the hash table\n");
  mht = MHTfillVertexTableRes(mris, NULL, CURRENT_VERTICES, 10);
  /* looping over the nonzero elements of the shell */
  printf("computing the fractions\n");
  volFraction frac;
  octTreeVoxel V; 
  double vox[3], vsize[3];
  vsize[0] = mri_src->xsize; vsize[1] = mri_src->ysize; vsize[2] = mri_src->zsize; 
  for (x = 0; x < width; x++)
    {
      for (y = 0; y < height; y++)
	{
	  for (z = 0; z < depth; z++)
	    {	  
	      if (MRIgetVoxVal (mri_shell, x, y, z, 0) > 125.0)
		{	      
		  /* change of coordinates from image to surface domain */
		  MRIvoxelToSurfaceRAS(mri_shell, x, y, z, &xs, &ys, &zs);
		  /* find the closest vertex to the point */
		  MHTfindClosestVertexGeneric(mht, mris, xs, ys, zs, 10, 2, &v, &vno, &dist);	      
		  /* creating the oct tree voxel structure */
		  vox[0] = xs - vsize[0] / 2.0; 
		  vox[1] = ys - vsize[1] / 2.0; 
		  vox[2] = zs - vsize[2] / 2.0; 
		  V = octTreeVoxelCreate(vox,vsize);
		  /* compute the volume fraction of this voxel */	      
		  frac = MRIcomputeVoxelFractions( V, v, acc, 1, mris);
		  MRIsetVoxVal(mri_fractions,x,y,z,0,frac.frac);
		}
	      else if(MRIgetVoxVal(mri_interior,x,y,z,0) > 0.0)
		MRIsetVoxVal(mri_fractions,x,y,z,0,1.0);

	    }
	}

    }
  return mri_fractions;
}
static int
update_histograms(MRI_SURFACE *mris, MRI_SURFACE *mris_avg, float ***histograms, int nbins) {
  int    vno, vno2, vno_avg ;
  double volume_dist, surface_dist, circumference, angle ;
  VERTEX *v1, *v2 ;
  VECTOR *vec1, *vec2 ;
  MHT    *mht ;
  float  **histogram, min_dist ;

  mht = MHTfillVertexTableRes(mris_avg, NULL, CURRENT_VERTICES, 2.0) ;

  vec1 = VectorAlloc(3, MATRIX_REAL) ;
  vec2 = VectorAlloc(3, MATRIX_REAL) ;

  v1 = &mris->vertices[0] ;
  VECTOR_LOAD(vec1, v1->cx, v1->cy, v1->cz) ;  /* radius vector */
  circumference = M_PI * 2.0 * V3_LEN(vec1) ;
  MRISclearMarks(mris_avg) ;
#if 0
  for (vno = 0 ; vno < mris->nvertices ; vno++) {
    if ((vno % 1000) ==  0) {
      printf("\r%d of %d    ", vno, mris->nvertices) ;
      fflush(stdout) ;
    }
    v1 = &mris->vertices[vno] ;
    VECTOR_LOAD(vec1, v1->cx, v1->cy, v1->cz) ;  /* radius vector */
    vno_avg = MHTfindClosestVertexNo(mht, mris_avg, v1, &min_dist) ;  /* which histogram to increment */
    if (vno_avg < 0)
      continue ;
    if (vno_avg == Gdiag_no)
      DiagBreak() ;
    histogram = histograms[vno_avg] ;
    mris_avg->vertices[vno_avg].marked = 1 ;

    for (vno2 = 0 ; vno2 < mris->nvertices ; vno2++) {
      if (vno2 == vno)
        continue ;
      v2 = &mris->vertices[vno2] ;
      VECTOR_LOAD(vec2, v2->cx, v2->cy, v2->cz) ;  /* radius vector */
      volume_dist = sqrt(SQR(v1->origx-v2->origx)+SQR(v1->origy-v2->origy)+SQR(v1->origz-v2->origz)) ;
      if (nint(volume_dist) >= nbins || nint(volume_dist) < 0)
        continue ;
      angle = fabs(Vector3Angle(vec1, vec2)) ;
      surface_dist = circumference * angle / (2.0 * M_PI) ;
      if (surface_dist > nbins*MAX_SURFACE_SCALE)
        surface_dist = nbins*MAX_SURFACE_SCALE ;
      if (surface_dist < 1)
        surface_dist = 1 ;

      histogram[nint(volume_dist)][nint(surface_dist)]++ ;

      if (mht->buckets[0][0] != NULL)
        DiagBreak() ;
    }
  }
  MHTfree(&mht) ;
#endif

  /* map back ones that were missed */
  /* printf("\nfilling holes in mapping\n") ;*/
  mht = MHTfillVertexTableRes(mris, NULL, CURRENT_VERTICES, 2.0) ;
  for (vno_avg = 0 ; vno_avg < mris_avg->nvertices ; vno_avg++) {
    if (mris_avg->vertices[vno_avg].marked > 0)
      continue ;

    if ((vno_avg % 1000) ==  0) {
      printf("\r%d of %d    ", vno_avg, mris_avg->nvertices) ;
      fflush(stdout) ;
    }

    vno = MHTfindClosestVertexNo(mht, mris, &mris_avg->vertices[vno_avg], &min_dist) ;
    if (vno < 0)
      continue ;
    v1 = &mris->vertices[vno] ;
    VECTOR_LOAD(vec1, v1->cx, v1->cy, v1->cz) ;  /* radius vector */
    if (vno_avg < 0)
      continue ;
    if (vno_avg == Gdiag_no)
      DiagBreak() ;
    histogram = histograms[vno_avg] ;
    mris_avg->vertices[vno_avg].marked = 1 ;

    for (vno2 = 0 ; vno2 < mris->nvertices ; vno2++) {
      if (vno2 == vno)
        continue ;
      v2 = &mris->vertices[vno2] ;
      VECTOR_LOAD(vec2, v2->cx, v2->cy, v2->cz) ;  /* radius vector */
      volume_dist = sqrt(SQR(v1->origx-v2->origx)+SQR(v1->origy-v2->origy)+SQR(v1->origz-v2->origz)) ;
      if (nint(volume_dist) >= nbins || nint(volume_dist) < 0)
        continue ;
      angle = fabs(Vector3Angle(vec1, vec2)) ;
      surface_dist = circumference * angle / (2.0 * M_PI) ;
      if (surface_dist > nbins*MAX_SURFACE_SCALE)
        surface_dist = nbins*MAX_SURFACE_SCALE ;
      if (surface_dist < 1)
        surface_dist = 1 ;

      histogram[nint(volume_dist)][nint(surface_dist)]++ ;
    }
  }

  MHTfree(&mht) ;
  printf("\n") ;

  VectorFree(&vec1) ;
  VectorFree(&vec2) ;
  return(NO_ERROR) ;
}
Example #7
0
/*--------------------------------------------------*/
int main(int argc, char **argv) {
  int nargs, err, asegid, c, r, s, annot, hemioffset;
  int annotid;
  struct utsname uts;
  char *cmdline, cwd[2000];

  /* rkt: check for and handle version tag */
  nargs = handle_version_option (argc, argv, vcid, "$Name: stable5 $");
  if (nargs && argc - nargs == 1) exit (0);
  argc -= nargs;
  cmdline = argv2cmdline(argc,argv);
  uname(&uts);
  getcwd(cwd,2000);

  Progname = argv[0] ;
  argc --;
  argv++;
  ErrorInit(NULL, NULL, NULL) ;
  DiagInit(NULL, NULL, NULL) ;

  if (argc == 0) usage_exit();

  parse_commandline(argc, argv);
  check_options();
  dump_options(stdout);

  printf("\n");
  printf("%s\n",vcid);
  printf("cwd %s\n",cwd);
  printf("cmdline %s\n",cmdline);
  printf("sysname  %s\n",uts.sysname);
  printf("hostname %s\n",uts.nodename);
  printf("machine  %s\n",uts.machine);

  SUBJECTS_DIR = getenv("SUBJECTS_DIR");
  if (SUBJECTS_DIR==NULL) {
    printf("ERROR: SUBJECTS_DIR not defined in environment\n");
    exit(1);
  }
  printf("SUBJECTS_DIR %s\n",SUBJECTS_DIR);
  printf("subject %s\n",subject);
  printf("\n");
  fflush(stdout);

  /* ------ Load subject's lh white surface ------ */
  sprintf(tmpstr,"%s/%s/surf/lh.white",SUBJECTS_DIR,subject);
  printf("Reading lh white surface \n %s\n",tmpstr);
  lhwhite = MRISread(tmpstr);
  if (lhwhite == NULL) {
    fprintf(stderr,"ERROR: could not read %s\n",tmpstr);
    exit(1);
  }

  printf("Building hash of lh white\n");
  lhwhite_hash = MHTfillVertexTableRes(lhwhite, NULL,CURRENT_VERTICES,16);

  /* ------ Load lh annotation ------ */
  sprintf(annotfile,"%s/%s/label/lh.aparc.annot",SUBJECTS_DIR,subject);
  printf("Loading lh annotations from %s\n",annotfile);
  err = MRISreadAnnotation(lhwhite, annotfile);
  if (err) {
    printf("ERROR: MRISreadAnnotation() failed %s\n",annotfile);
    exit(1);
  }

  /* ------ Load subject's rh surface ------ */
  sprintf(tmpstr,"%s/%s/surf/rh.white",SUBJECTS_DIR,subject);
  printf("Reading rh white surface \n %s\n",tmpstr);
  rhwhite = MRISread(tmpstr);
  if (rhwhite == NULL) {
    fprintf(stderr,"ERROR: could not read %s\n",tmpstr);
    exit(1);
  }
  if (debug) printf("Building hash of rh white\n");
  rhwhite_hash = MHTfillVertexTableRes(rhwhite, NULL,CURRENT_VERTICES,16);

  /* ------ Load rh annotation ------ */
  sprintf(annotfile,"%s/%s/label/rh.aparc.annot",SUBJECTS_DIR,subject);
  printf("Loading rh annotations from %s\n",annotfile);
  err = MRISreadAnnotation(rhwhite, annotfile);
  if (err) {
    printf("ERROR: MRISreadAnnotation() failed %s\n",annotfile);
    exit(1);
  }

  if (debug && lhwhite->ct) printf("Have color table for annotation\n");
  if (debug) print_annotation_table(stdout);

  /* ------ Load ASeg ------ */
  sprintf(tmpstr,"%s/%s/mri/aseg.mgz",SUBJECTS_DIR,subject);
  if (!fio_FileExistsReadable(tmpstr)) {
    sprintf(tmpstr,"%s/%s/mri/aseg.mgh",SUBJECTS_DIR,subject);
    if (!fio_FileExistsReadable(tmpstr)) {
      sprintf(tmpstr,"%s/%s/mri/aseg/COR-.info",SUBJECTS_DIR,subject);
      if (!fio_FileExistsReadable(tmpstr)) {
        printf("ERROR: cannot find aseg\n");
        exit(1);
      } else
        sprintf(tmpstr,"%s/%s/mri/aseg/",SUBJECTS_DIR,subject);
    }
  }

  printf("Loading aseg from %s\n",tmpstr);
  ASeg = MRIread(tmpstr);
  if (ASeg == NULL) {
    printf("ERROR: loading aseg %s\n",tmpstr);
    exit(1);
  }
  mritmp = MRIchangeType(ASeg,MRI_INT,0,0,0);
  MRIfree(&ASeg);
  ASeg = mritmp;
  WMSeg = MRIclone(ASeg,NULL);

  Vox2RAS = MRIxfmCRS2XYZtkreg(ASeg);
  if (debug) {
    printf("ASeg Vox2RAS: -----------\n");
    MatrixPrint(stdout,Vox2RAS);
    printf("-------------------------\n");
  }
  CRS = MatrixAlloc(4,1,MATRIX_REAL);
  CRS->rptr[4][1] = 1;
  RAS = MatrixAlloc(4,1,MATRIX_REAL);
  RAS->rptr[4][1] = 1;

  // Go through each voxel in the aseg
  printf("\n");
  printf("Labeling WM\n");
  for (c=0; c < ASeg->width; c++) {
    if (debug) printf("%3d ",c);
    if (debug && c%20 ==19) printf("\n");
    for (r=0; r < ASeg->height; r++) {
      for (s=0; s < ASeg->depth; s++) {

        // If it's not labeled as white matter in the aseg, set
        // seg value to that from the aseg and skip the rest
        asegid = MRIgetVoxVal(ASeg,c,r,s,0);
        if (asegid != 2 && asegid != 41) {
          MRIsetVoxVal(WMSeg,c,r,s,0,asegid);
          continue;
        }

        // Convert the CRS to RAS
        CRS->rptr[1][1] = c;
        CRS->rptr[2][1] = r;
        CRS->rptr[3][1] = s;
        RAS = MatrixMultiply(Vox2RAS,CRS,RAS);
        vtx.x = RAS->rptr[1][1];
        vtx.y = RAS->rptr[2][1];
        vtx.z = RAS->rptr[3][1];

        // Get the index of the closest vertex in the
        // lh.white, rh.white
        lhwvtx = MHTfindClosestVertexNo(lhwhite_hash,lhwhite,&vtx,&dlhw);
        rhwvtx = MHTfindClosestVertexNo(rhwhite_hash,rhwhite,&vtx,&drhw);

        if ( (lhwvtx < 0) && (rhwvtx < 0) ) {
          printf("ERROR: could not map to any surface.\n");
          printf("crs = %d %d %d, ras = %6.4f %6.4f %6.4f \n",
                 c,r,s,vtx.x,vtx.y,vtx.z);
          exit(1);
        }

        if (lhwvtx < 0) dlhw = 1000000000000000.0;
        if (rhwvtx < 0) drhw = 1000000000000000.0;

        if (dlhw < drhw) {
          // Left hemi is closer than the right
          annot = lhwhite->vertices[lhwvtx].annotation;
          hemioffset = 1000;
          if (lhwhite->ct)
            CTABfindAnnotation(lhwhite->ct, annot, &annotid);
          else
            annotid = annotation_to_index(annot);
        } else {
          // Right hemi is closer than the left
          annot = rhwhite->vertices[rhwvtx].annotation;
          hemioffset = 2000;
          if (rhwhite->ct)
            CTABfindAnnotation(lhwhite->ct, annot, &annotid);
          else
            annotid = annotation_to_index(annot);
        }

        MRIsetVoxVal(WMSeg,c,r,s,0,annotid+hemioffset);
      }
    }
  }

  printf("\nWriting output wmseg to %s\n",WMSegFile);
  MRIwrite(WMSeg,WMSegFile);

  printf("mri_aparc2wmseg done\n");
  return(0);
}
static int
relabel_hypointensities(MRI *mri, MRI_SURFACE *mris, int right)
{
  int   x, y, z, label, changed ;
  MRIS_HASH_TABLE *mht ;
  VERTEX           *v ;
  float            dx, dy, dz, dot, dist ;
  Real             xw, yw, zw ;
  MRI              *mri_dist ;

  mri_dist = MRIcloneDifferentType(mri, MRI_FLOAT) ;
  MRIScomputeDistanceToSurface(mris, mri_dist, mri_dist->xsize) ;

  mht = MHTfillVertexTableRes(mris,NULL, CURRENT_VERTICES, 8.0f) ;
  for (changed = x = 0 ; x < mri->width ; x++) {
    for (y = 0 ; y < mri->height ; y++) {
      for (z = 0 ; z < mri->depth ; z++) {
        if (x == Gx && y == Gy && z == Gz) {
          DiagBreak() ;
        }
        label = MRIgetVoxVal(mri, x, y, z, 0) ;
        if (label == Left_WM_hypointensities) {
          MRIsetVoxVal(mri, x, y, z,0, WM_hypointensities) ;
        } else if (label == Right_WM_hypointensities) {
          MRIsetVoxVal(mri, x, y, z, 0,  WM_hypointensities) ;
        }
        if ((!right && (label != Left_Cerebral_Cortex)) ||
            (right && (label != Right_Cerebral_Cortex))) {
          continue ;
        }

        // MRIvoxelToWorld(mri, x, y, z, &xw, &yw, &zw) ;
        MRIvoxelToSurfaceRAS(mri, x, y, z, &xw, &yw, &zw);
        v = MHTfindClosestVertexInTable(mht, mris, xw, yw, zw, 0) ;
        if (v == NULL)  /* no vertices within range -
                           assume it is hypointensity */
        {
          dot = -1 ;
          dist = MRIgetVoxVal(mri_dist, x, y, z, 0) ;
          if (dist > 0) {
            dot = 1 ;
          }
        } else {
          dx = xw - v->x ;
          dy = yw - v->y ;
          dz = zw - v->z ;
          dot = v->nx*dx + v->ny*dy + v->nz*dz ;
          dist = sqrt(dx*dx+dy*dy+dz*dz) ;
        }
        if (dot < 0 && dist > 1) {
          changed++ ;
          MRIsetVoxVal(mri, x, y, z, 0, WM_hypointensities) ;
        }
      }
    }
  }

  printf("%d voxels changed to hypointensity...\n", changed) ;
  MHTfree(&mht) ;
  MRIfree(&mri_dist) ;
  return(NO_ERROR) ;
}