Esempio n. 1
0
int main (int argc,char *argv[])
{
    static char FuncName[]= {"SUMA_inflate_compare"};
    SUMA_SurfSpecFile Spec;
    char *specfilename = NULL;
    int kar, id;
    SUMA_Boolean brk;
    SUMA_Boolean SurfIn = NOPE;

    SUMA_SurfaceObject *Surf1 = NULL, *Surf2=NULL;
    char *Surf1_FileName = NULL;
    char *Surf2_FileName = NULL;
    char *Vol1Parent_FileName=NULL;
    char *Vol2Parent_FileName=NULL;

    /* for SureFit surface */
    SUMA_SFname *Surf1_SFName = NULL, *Surf2_SFName = NULL;

    /* other variables */
    int i;
    int num_nodes1;
    int num_nodes2;
    float P0[3];
    float delta_t;
    float P1[3];
    float N0[3];
    float maxdistance, mindistance;
    float *distance;
    float Points[2][3]= { {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}, p1[3]= {0.0, 0.0, 0.0}, p2[3]= {0.0, 0.0, 0.0};
    SUMA_COLOR_MAP *MyColMap;
    SUMA_SCALE_TO_MAP_OPT *MyOpt;
    SUMA_COLOR_SCALED_VECT * MySV;
    SUMA_MT_INTERSECT_TRIANGLE *triangle;
    SUMA_SURF_NORM SN1;
    SUMA_SURF_NORM SN2;
    SUMA_SurfaceObject *SO1, *SO2;
    struct timeval tt;
    FILE *colorfile;
    FILE *distancefile;
    char colorfilename[1000];
    char distancefilename[1000];
    char *tag1 = NULL;
    char *tag2 = NULL;
    char *state1 = NULL;
    char *state2 = NULL;
    char *hemi = NULL;
    float B_dim[3];
    SUMA_ISINBOX isin;
    SUMA_PATCH *Patch=NULL;
    SUMA_Boolean TryFull = NOPE, FullOnly;
    SUMA_MEMBER_FACE_SETS *Memb = NULL;
    int *FaceSet_tmp;
    int N_FaceSet_tmp;
    char *fout = NULL;
    int inflation = 10; /* inflation in mm */

    /* allocate space for CommonFields structure */
    SUMAg_CF = SUMA_Create_CommonFields ();
    if (SUMAg_CF == NULL) {
        fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
        exit(1);
    }

    if (argc < 5) {
        cmp_surf_usage();
        exit (1);
    }

    /* read in the surfaces */
    kar = 1;
    brk = NOPE;
    SurfIn = NOPE;
    FullOnly = YUP;
    while (kar < argc) {
        /* loop accross command line options */
        if ((strcmp(argv[kar], "-h") == 0) || (strcmp(argv[kar], "-help") == 0)) {
            cmp_surf_usage ();
            exit (1);
        }
        if (!brk && (strcmp(argv[kar], "-hemi")) == 0) {
            kar ++;
            if (kar >= argc) {
                fprintf (SUMA_STDERR, "need argument after -hemi");
                exit (1);
            }
            hemi = argv[kar];
            brk = YUP;
        }
        if (!brk && (strcmp(argv[kar], "-prefix")) == 0) {
            kar ++;
            if (kar >= argc) {
                fprintf (SUMA_STDERR, "need argument after -prefix");
                exit (1);
            }
            fout = argv[kar];
            brk = YUP;
        }
        if (!brk && (strcmp(argv[kar], "-spec")) == 0) {
            kar ++;
            if (kar >= argc) {
                fprintf (SUMA_STDERR, "need argument after -spec ");
                exit (1);
            }
            specfilename = argv[kar];
            brk = YUP;
        }
        if (!brk && (strcmp(argv[kar], "-box")) == 0) {
            kar ++;
            if (kar+2 >= argc) {
                fprintf (SUMA_STDERR, "need 3 arguments after -box");
                exit (1);
            }
            B_dim[0] = atof(argv[kar]);
            kar ++;
            B_dim[1] = atof(argv[kar]);
            kar ++;
            B_dim[2] = atof(argv[kar]);

            FullOnly = NOPE;
            brk = YUP;
        }
        if (!brk) {
            fprintf (SUMA_STDERR,"Error %s: Option %s not understood. Try -help for usage\n", FuncName, argv[kar]);
            exit (1);
        }
        else {
            brk = NOPE;
            kar ++;
        }
    }/* loop across command line options */


    if (specfilename == NULL) {
        fprintf (SUMA_STDERR,"Error %s: No spec filename specified.\n", FuncName);
        exit(1);
    }
    if (!SUMA_AllocSpecFields(&Spec)) {
        SUMA_S_Err("Failed to allocate spec fields");
        exit(1);
    }
    if (!SUMA_Read_SpecFile (specfilename, &Spec)) {
        fprintf(SUMA_STDERR,"Error %s: Error in SUMA_Read_SpecFile\n", FuncName);
        exit(1);
    }

    /**** loading the first surface *****/
    if (SUMA_iswordin(Spec.SurfaceType[0], "FreeSurfer") == 1) {
        Surf1_FileName = Spec.SurfaceFile[0];
        Surf1 = SUMA_Load_Surface_Object(Surf1_FileName, SUMA_FREE_SURFER, SUMA_ASCII, Vol1Parent_FileName);
        tag1 =  "FS";
    }
    else if (SUMA_iswordin(Spec.SurfaceType[0], "SureFit") == 1) {
        Surf1_SFName = SUMA_malloc(sizeof(SUMA_SFname));
        strcpy(Surf1_SFName->name_coord,Spec.CoordFile[0]);
        strcpy(Surf1_SFName->name_topo, Spec.TopoFile[0]);
        strcpy(Surf1_SFName->name_param, Spec.SureFitVolParam[0]);
        Surf1 = SUMA_Load_Surface_Object(Surf1_SFName, SUMA_SUREFIT, SUMA_ASCII,Vol1Parent_FileName);
        tag1 =  "SF";
    }
    state1 = Spec.State[0];

    /**** loading the second surface *****/
    if (SUMA_iswordin(Spec.SurfaceType[0], "FreeSurfer") == 1) {
        Surf2_FileName = Spec.SurfaceFile[0];
        Surf2 = SUMA_Load_Surface_Object(Surf1_FileName, SUMA_FREE_SURFER, SUMA_ASCII, Vol1Parent_FileName);
        tag2 =  "FS";
    }
    else if (SUMA_iswordin(Spec.SurfaceType[0], "SureFit") == 1) {
        Surf2_SFName = SUMA_malloc(sizeof(SUMA_SFname));
        strcpy(Surf2_SFName->name_coord,Spec.CoordFile[0]);
        strcpy(Surf2_SFName->name_topo, Spec.TopoFile[0]);
        strcpy(Surf2_SFName->name_param, Spec.SureFitVolParam[0]);
        Surf2 = SUMA_Load_Surface_Object(Surf1_SFName, SUMA_SUREFIT, SUMA_ASCII,Vol1Parent_FileName);
        tag2 =  "SF";
    }
    state2 = Spec.State[0];

    if (fout == NULL) { /* form default name */
        sprintf(distancefilename, "dist_%s_%s_%s_%dmm.txt",hemi,tag1,state1,inflation);
        sprintf(colorfilename, "dist_%s_%s_%s_%dmm.col",hemi,tag1,state1,inflation);
    }
    else {
        sprintf (colorfilename, "%s.col", fout);
        sprintf (distancefilename, "%s.txt", fout);
    }

    if (SUMA_filexists(colorfilename) || SUMA_filexists(distancefilename)) {
        fprintf (SUMA_STDERR,"Error %s: One or both of output files %s, %s exists.\nWill not overwrite.\n", \
                 FuncName, distancefilename, colorfilename);
        exit(1);
    }

    /***********************************************************************************************/

    SO1 = Surf1;
    SO2 = Surf2;

    /*SUMA_Print_Surface_Object ( SO1, NULL);
    SUMA_Print_Surface_Object ( SO2, NULL);*/

    num_nodes1 = SO1->N_Node;
    num_nodes2 = SO2->N_Node;

    fprintf(SUMA_STDERR, "Number of nodes in surface 1: %d \n", num_nodes1);
    fprintf(SUMA_STDERR, "Number of nodes in surface 2: %d \n", num_nodes2);
    SN1 = SUMA_SurfNorm(SO1->NodeList,  SO1->N_Node, SO1->FaceSetList, SO1->N_FaceSet);

    /* Take each node in the SO1-> Nodelist and its corresponding SN1->NodeNormList.  This is the normalized normal vector to the node on the first surface.
       So each node is P0.  P1 is computed as some point along the normal vector to that node.  Lets say P1 is P0 + 10 mm along the normal.

     Write out P1 as a surface */
    /* for each node on the first surface do the following */
    SUMA_etime (&tt, 0);
    for (i = 0; i < num_nodes1; i++) {
        id = SO1->NodeDim * i;
        P0[0] = SO1->NodeList[id];
        P0[1] = SO1->NodeList[id+1];
        P0[2] = SO1->NodeList[id+2];
        N0[0] = SN1.NodeNormList[id];
        N0[1] = SN1.NodeNormList[id+1];
        N0[2] = SN1.NodeNormList[id+2];
        SUMA_POINT_AT_DISTANCE(N0, P0, 10, Points);
        P1[0] = Points[0][0];
        P1[1] = Points[0][1];
        P1[2] = Points[0][2];
        //    fprintf(SUMA_STDERR,"P0 values: %f\t%f\t%f, P1 values: %f\t%f\t%f\n", P0[0],P0[1],P0[2],P1[0],P1[1],P1[2]);

        /* Saving the new surfaces */
        SO2->NodeList[id] = P1[0];
        SO2->NodeList[id+1] = P1[1];
        SO2->NodeList[id+2] = P1[2];
    }

    /* Now use SO1 and SO2 as the two surfaces and compute the distance */

    SN1 = SUMA_SurfNorm(SO1->NodeList,  SO1->N_Node, SO1->FaceSetList, SO1->N_FaceSet);
    SN2 = SUMA_SurfNorm(SO2->NodeList,  SO2->N_Node, SO2->FaceSetList, SO2->N_FaceSet);
    if (!FullOnly) {
        /* get the Node member structure */
        fprintf(SUMA_STDOUT, "%s: Computing MemberFaceSets... \n", FuncName);
        Memb = SUMA_MemberFaceSets (SO2->N_Node, SO2->FaceSetList, SO2->N_FaceSet, 3, SO2->idcode_str);
        if (Memb->NodeMemberOfFaceSet == NULL) {
            fprintf(SUMA_STDERR, "Error %s: Failed in SUMA_MemberFaceSets. \n", FuncName);
            exit(1);
        }
    }

    /* Take each node in the SO1-> Nodelist and its corresponding SN1->NodeNormList.  This is the normalized normal vector to the node on the first surface.
       So each node is P0.  P1 is computed as some point along the normal vector to that node.  Lets say P1 is P0 + 10 mm along the normal.  */

    /* for each node on the first surface do the following */

    SUMA_etime (&tt, 0);
    distance = SUMA_malloc(num_nodes1*sizeof(float));
    for (i = 0; i < num_nodes1; i++) {
        //for (i = 0; i < 10; i++) {
        id = SO1->NodeDim * i;
        P0[0] = SO1->NodeList[id];
        P0[1] = SO1->NodeList[id+1];
        P0[2] = SO1->NodeList[id+2];
        N0[0] = SN1.NodeNormList[id];
        N0[1] = SN1.NodeNormList[id+1];
        N0[2] = SN1.NodeNormList[id+2];
        SUMA_POINT_AT_DISTANCE(N0, P0, 1000, Points);
        P1[0] = Points[0][0];
        P1[1] = Points[0][1];
        P1[2] = Points[0][2];
        if (!FullOnly) {
            /* trying to speed up intersection computations
                             by restricting it to nodes within a box */
            TryFull = NOPE;
            /* search for nodes on surface 2 within xx mm of P0 */
            isin = SUMA_isinbox (SO2->NodeList, SO2->N_Node, P0, B_dim, 0);
            if (isin.nIsIn) {
                /* find the patch of surface 2 that is formed by those intersection nodes */
                Patch = SUMA_getPatch ( isin.IsIn, isin.nIsIn,
                                        SO2->N_Node, SO2->FaceSetList, SO2->N_FaceSet,
                                        Memb, 1, 0, 1);
                if (Patch == NULL) {
                    fprintf(SUMA_STDERR,
                            "Error %s: Null returned from SUMA_getPatch.\n", FuncName);
                    exit (1);
                }

                /* Perform the intersection based on that patch using Shruti's version */
                FaceSet_tmp = Patch->FaceSetList;
                N_FaceSet_tmp = Patch->N_FaceSet;
            } else {
                fprintf (SUMA_STDOUT,
                         "%s: No nodes in box about node %d. \n"
                         "Trying for full surface intersection.\n", FuncName, i);
                TryFull = YUP; /* flag to send it to full intersection */
            }
        }

        if (FullOnly || TryFull) {
            Patch = NULL;
            FaceSet_tmp = SO2->FaceSetList;
            N_FaceSet_tmp = SO2->N_FaceSet;
        }

        /*now try with the segment from Points[0] to Points[1] returned above. */
        p1[0] = Points[0][0];
        p1[1] = Points[0][1];
        p1[2] = Points[0][2];
        p2[0] = Points[1][0];
        p2[1] = Points[1][1];
        p2[2] = Points[1][2];
        triangle = SUMA_MT_intersect_triangle(p1,p2, SO2->NodeList, SO2->N_Node, SO2->FaceSetList, SO2->N_FaceSet, NULL, 0);
        //SUMA_Show_MT_intersect_triangle(triangle, NULL);
        if (triangle->N_hits ==0) {
            distance[i] = -1;
            // fprintf(SUMA_STDERR, "Could not find hit for node %d in either direction.\n", i);
        }
        else {
            distance[i] = sqrtf( pow(triangle->P[0]-P0[0],2)+
                                 pow(triangle->P[1]-P0[1],2)+
                                 pow(triangle->P[2]-P0[2],2)   );
            /* fprintf(SUMA_STDERR, "distance is : %f\n", distance[i]); */

        }

        SUMA_Free_MT_intersect_triangle(triangle);
        if (Patch) SUMA_freePatch(Patch);

        /* calculating the time elapsed and remaining */
        if (!(i%100)) {
            delta_t = SUMA_etime(&tt, 1);
            fprintf (SUMA_STDERR,
                     " [%d]/[%d] %.2f/100%% completed. "
                     "Dt = %.2f min done of %.2f min total\r" ,
                     i, num_nodes1, (float)i / num_nodes1 * 100,
                     delta_t/60, delta_t/i * num_nodes1/60);
        }

    }

    /* write out the distance file */
    if((distancefile = fopen(distancefilename, "w"))==NULL) {
        fprintf(SUMA_STDERR, "Could not open file distance.txt.\n");
        exit(1);
    }
    else {
        for (i=0; i < num_nodes1; ++i) {
            fprintf (distancefile,"%d\t%f\n", i, distance[i]);
        }
        fclose (distancefile);
    }

    /* output this distance as a color file */
    MyColMap = SUMA_FindNamedColMap("byr64");
    MyOpt = SUMA_ScaleToMapOptInit();
    MySV = SUMA_Create_ColorScaledVect(num_nodes1, 0);
    mindistance = minimum(num_nodes1, distance);
    maxdistance = maximum(num_nodes1, distance);
    SUMA_ScaleToMap(distance,num_nodes1,mindistance, maxdistance,
                    MyColMap,MyOpt,MySV);


    /* write out the distance color file */
    if((colorfile = fopen(colorfilename, "w"))==NULL) {
        fprintf(SUMA_STDERR, "Could not open file distance.col.\n");
        exit(1);
    }
    else {
        for (i=0; i < num_nodes1; ++i) {
            fprintf (colorfile,
                     "%d\t%f\t%f\t%f\n",
                     i, MySV->cV[3*i  ], MySV->cV[3*i+1], MySV->cV[3*i+2]);
        }
        fclose (colorfile);
    }

    if (!SUMA_FreeSpecFields(&Spec)) {
        SUMA_S_Err("Failed to free spec fields");
    }
    if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);

    return 1;
}
Esempio n. 2
0
SUMA_DSET *calcWithOffsets(SUMA_SurfaceObject *SO, SUMA_KUBATEST_OPTIONS* Opt)
{
   static char FuncName[]={"calcWithOffsets"};
   /* initialize OffS */
   SUMA_GET_OFFSET_STRUCT *OffS = SUMA_Initialize_getoffsets (SO->N_Node);
   struct timeval start_time, start_time_all;
   float etime_GetOffset, etime_GetOffset_all;
   float *gD=NULL, *pD=NULL, *rD=NULL;
   int *Pr=NULL, *Nd=NULL, *Lj=NULL;
   float pathD = 0;/*shortest distance along surface to node ii*/
   float geomD = 0;/*geometric distance to node ii*/
   float ratio = 1;
   int i = 0,  j = 0, ii = 0, lj =0;
   float x1, x2 , y1, y2, z1, z2, dx, dy, dz, d1, d2, r;
   FILE* outFile = NULL, *segDO=NULL;
   SUMA_DSET *dset=NULL;
   SUMA_Boolean LocalHead = NOPE;
   
   SUMA_ENTRY;

   if (Opt->outfile) {
      if (!(outFile = fopen(Opt->outfile, "w"))) {
         SUMA_S_Errv("Failed to open %s for writing.\n",
                  Opt->outfile);
         SUMA_RETURN(NULL);
      }
      fprintf(outFile,  
         "#Col. 0 Node index\n"
         "#Col. 1 Node for which the ratio in 4 is the largest. "
         " (Companion of Node in Col.0)\n"
         "#Col. 2 distance in 3D\n"
         "#Col. 3 shortest surface path\n"
         "#Col. 4 Ratio of path/distance\n"
         "#Col. 5 Neighborhood layer of node in Col.1, "
         " i.e. Neighborhood layer of the companion of node in Col.0");
      if (Opt->histnote) {
         fprintf(outFile,  "#History:%s\n", Opt->histnote);
      }
   }
   
   if (Opt->segdo) {
      if (!(segDO = fopen(Opt->segdo, "w"))) {
         SUMA_S_Errv("Failed to open %s for writing.\n",
                  Opt->segdo);
         SUMA_RETURN(NULL);
      }
      fprintf(segDO,
         "#node-based_segments\n");
      if (Opt->histnote) {
         fprintf(segDO,  "#History:%s\n", Opt->histnote);
      }
   } 
    
   Nd=(int *)SUMA_calloc(SO->N_Node, sizeof(int));   
   Pr=(int *)SUMA_calloc(SO->N_Node, sizeof(int));   
   Lj=(int *)SUMA_calloc(SO->N_Node, sizeof(int));   
   gD=(float *)SUMA_calloc(SO->N_Node, sizeof(float));   
   pD=(float *)SUMA_calloc(SO->N_Node, sizeof(float));   
   rD=(float *)SUMA_calloc(SO->N_Node, sizeof(float)); 
   if (!Pr || !gD || !pD || !rD) {
      SUMA_S_Err("Failed to allocate");
      SUMA_RETURN(NOPE);
   }  
   
   SUMA_etime(&start_time_all,0);
   for (i=0; i < SO->N_Node; ++i)
   {
      pathD = 0;/*shortest distance along surface to node ii*/
      geomD = 0;/*geometric distance to node ii*/
      ratio = 1;
      j = 0;
      ii = 0;
      lj = -1;
      /* show me the offset from node 0 */
      SUMA_LHv("Calculating offsets from node %d\n", i);
      if (i == 0) {
         SUMA_etime(&start_time,0);
      }
      SUMA_getoffsets2 (i, SO, Opt->plimit, OffS, NULL, 0);
      if (i == 99) {
         etime_GetOffset = SUMA_etime(&start_time,1);
         SUMA_LHv("Search to %f mm took %f seconds for %d nodes.\n"
                  "Projected completion time: %f minutes\n",
                  Opt->plimit, etime_GetOffset, i+1,
                  etime_GetOffset * SO->N_Node / 60.0 / (i+1));
      }
      /*find smallest ratio*/
      for (j=0; j < OffS->N_Nodes; j++)
      {
         if( i!=j && OffS->LayerVect[j] >= 0)
         {
            x1 = SO->NodeList[i*3+0];
            x2 = SO->NodeList[j*3+0];
            y1 = SO->NodeList[i*3+1];
            y2 = SO->NodeList[j*3+1];
            z1 = SO->NodeList[i*3+2];
            z2 = SO->NodeList[j*3+2];
            dx = x1 - x2;
            dy = y1 - y2;
            dz = z1 - z2;
            d1 = OffS->OffVect[j];
            d2 = sqrt(dx*dx + dy*dy + dz*dz);
            r = d1 / d2;
            if ( d2 < Opt->dlimit && d1 < Opt->plimit && r > ratio )
            {
               if (r > 1000) {
                  SUMA_S_Notev("Extreme Ratio:\n"
                        "node=%d (%f %f %f), paired with node %d (%f %f %f)\n"
                        " geo_dist=%f Euc_dist=%f r=%f layer=%d\n", 
                     i, x1, y1, z1,
                     j, x2, y2, z2,
                     d1, d2, r, OffS->LayerVect[j]);
               }
               ratio = r;
               ii = j;
               lj = OffS->LayerVect[j];
               pathD = d1;
               geomD = d2;
            }
         }
      }
      Nd[i] = i;
      Pr[i] = ii;
      Lj[i] = lj;
      gD[i] = geomD;
      pD[i] = pathD;
      rD[i] = ratio;
      if (outFile)
         fprintf(outFile, "%i\t%i\t%f\t%f\t%f\t%d\n", 
                     i, ii, geomD, pathD, ratio, lj);
      if (segDO) {
         float r,g,b,a;
         SUMA_RAND_COL(i?-1:0,r,g,b,a);
         fprintf(segDO, "%i\t%i\t%f %f %f %f\n", i, ii, r,g,b,1.0);
      }
      
      if (LocalHead) 
         fprintf(SUMA_STDERR,"%s: Recycling OffS\n", FuncName);
      SUMA_Recycle_getoffsets (OffS);
      if (LocalHead)
         fprintf(SUMA_STDERR,"%s: Done.\n", FuncName);
   }
   
   if (outFile) fclose(outFile);
   if (segDO) fclose(segDO);
   
   dset = SUMA_CreateDsetPointer(Opt->prefix, SUMA_NODE_BUCKET,
                                 NULL, SO->idcode_str,
                                 SO->N_Node);
   if (!SUMA_AddDsetNelCol(dset, "node index", SUMA_NODE_INDEX, Nd, NULL, 1)) {
      SUMA_S_Err("Failed to add new data");
      SUMA_FreeDset(dset); SUMA_RETURN(NULL);
   } 
   if (!SUMA_AddDsetNelCol(dset, "PairingNode", SUMA_NODE_INT, Pr, NULL, 1)) {
      SUMA_S_Err("Failed to add new data");
      SUMA_FreeDset(dset); SUMA_RETURN(NULL);
   } 
   if (!SUMA_AddDsetNelCol(dset, "LayerOfPairNode", SUMA_NODE_INT, Lj, NULL, 1)){
      SUMA_S_Err("Failed to add new data");
      SUMA_FreeDset(dset); SUMA_RETURN(NULL);
   } 
   if (!SUMA_AddDsetNelCol(dset, "Eucl.Dist", SUMA_NODE_FLOAT, gD, NULL, 1)) {
      SUMA_S_Err("Failed to add new data");
      SUMA_FreeDset(dset); SUMA_RETURN(NULL);
   } 
   if (!SUMA_AddDsetNelCol(dset, "Geo.Dist",SUMA_NODE_FLOAT,  pD, NULL, 1)) {
      SUMA_S_Err("Failed to add new data");
      SUMA_FreeDset(dset); SUMA_RETURN(NULL);
   } 
   if (!SUMA_AddDsetNelCol(dset, "G/E.Dist",SUMA_NODE_FLOAT,  rD, NULL, 1)) {
      SUMA_S_Err("Failed to add new data");
      SUMA_FreeDset(dset); SUMA_RETURN(NULL);
   } 
   
   etime_GetOffset_all = SUMA_etime(&start_time_all,1);
   SUMA_S_Notev("Done.\nSearch to %f mm took %f minutes for %d nodes.\n" ,
                 Opt->plimit, etime_GetOffset_all / 60.0 , SO->N_Node);
   SUMA_Free_getoffsets(OffS);
   SUMA_free(Nd); Nd = NULL;
   SUMA_free(Pr); Pr = NULL;
   SUMA_free(Lj); Lj = NULL;
   SUMA_free(gD); gD = NULL;
   SUMA_free(pD); pD = NULL;
   SUMA_free(rD); rD = NULL;
   SUMA_RETURN(dset);
}