/*! A function to call SUMA_qhull_wrap or SUMA_qdelaunay_wrap */ SUMA_SurfaceObject *SUMA_ConvexHullSurface( SUMA_GENERIC_PROG_OPTIONS_STRUCT * Opt) { static char FuncName[]={"SUMA_ConvexHullSurface"}; SUMA_SurfaceObject *SO=NULL; float *xyz=NULL, *xyzp=NULL, *txyz=NULL; int npt, *ijk=NULL, nf=0, cnt, i, j, k, nxx, nyy, nzz,N_txyz=-1; FILE *fid=NULL; THD_fvec3 fv, iv; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; npt = 0; N_txyz=-1; if (Opt->UseThisBrain) { MRI_IMAGE *im = NULL; float *far=NULL; int nx2, i3; /* load the 1D file */ im = mri_read_1D (Opt->UseThisBrain); if (!im) { SUMA_S_Err("Failed to read file"); SUMA_RETURN(NULL); } far = MRI_FLOAT_PTR(im); if (im->nx == 0) { SUMA_S_Errv("Empty file %s.\n", Opt->UseThisBrain); SUMA_RETURN(NULL); } if (im->ny != 3) { SUMA_S_Errv("Found %d columns in %s. Expecting 3\n", im->ny, Opt->UseThisBrain); SUMA_RETURN(NULL); } /* copy the columns */ N_txyz = im->nx; txyz = (float *)SUMA_malloc(im->nx*im->ny*sizeof(float)); if (!txyz) { SUMA_S_Crit("Failed to allocate."); SUMA_RETURN(NULL); } nx2 = 2*im->nx; for (i=0; i<N_txyz; ++i) { i3 = 3*i; txyz[i3 ] = far[i]; txyz[i3+1] = far[i+im->nx]; txyz[i3+2] = far[i+nx2]; } /* done, clean up and out you go */ if (im) mri_free(im); im = NULL; } if (Opt->in_vol) { cnt = 0; npt = 0; nxx = (DSET_NX(Opt->in_vol)); nyy = (DSET_NY(Opt->in_vol)); nzz = (DSET_NZ(Opt->in_vol)); if (Opt->debug) fprintf(SUMA_STDERR,"%s:\nRunning qhull...\n", FuncName); xyz = (float *)SUMA_malloc(3*nxx*nyy*nzz*sizeof(float)); if (!xyz) { SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NULL); } for( k = 0 ; k < nzz ; k++ ) { for( j = 0 ; j < nyy ; j++ ) { for( i = 0 ; i < nxx ; i++ ) { if (Opt->mcdatav[cnt] == 1) { fv.xyz[0] = DSET_XORG(Opt->in_vol) + i * DSET_DX(Opt->in_vol); fv.xyz[1] = DSET_YORG(Opt->in_vol) + j * DSET_DY(Opt->in_vol); fv.xyz[2] = DSET_ZORG(Opt->in_vol) + k * DSET_DZ(Opt->in_vol); /* change mm to RAI coords */ iv = SUMA_THD_3dmm_to_dicomm( Opt->in_vol->daxes->xxorient, Opt->in_vol->daxes->yyorient, Opt->in_vol->daxes->zzorient, fv ); xyz[3*npt] = iv.xyz[0]; xyz[3*npt+1] = iv.xyz[1]; xyz[3*npt+2] = iv.xyz[2]; npt++; } ++cnt; } } } } else if (Opt->XYZ) { xyz = (float *)SUMA_malloc(3*Opt->N_XYZ*sizeof(float)); if (!xyz) { SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NULL); } for( k = 0 ; k < 3*Opt->N_XYZ ; k++ ) { xyz[k] = Opt->XYZ[k]; npt = Opt->N_XYZ; } } else { SUMA_S_Err("No input"); goto CLEANUP; } if (Opt->corder) { SUMA_PC_XYZ_PROJ *pcp=NULL; if (Opt->geom==1) { SUMA_S_Warn("PCA projection makes no sense for usual convex hull"); } if (!(pcp = SUMA_Project_Coords_PCA (xyz, npt, npt/2, NULL, E3_PLN_PRJ, ROT_2_Z,0))) { SUMA_S_Err("Failed to project"); goto CLEANUP; } xyzp = pcp->xyzp; pcp->xyzp = NULL; pcp = SUMA_Free_PC_XYZ_Proj(pcp); } else { xyzp = xyz; } if (N_txyz >= 0 && N_txyz != npt) { SUMA_S_Errv("Mismatch between number of coordinates for convex hull\n" "and number of coordinates to adopt in the end.\n" " %d, versus %d in -these_coords\n", npt, N_txyz); goto CLEANUP; } if (Opt->geom == 1) { /* convex hull */ if (! (nf = SUMA_qhull_wrap(npt, xyzp, &ijk, 1, Opt->s)) ) { fprintf(SUMA_STDERR,"%s:\nFailed in SUMA_qhull_wrap\n", FuncName); goto CLEANUP; } /* Other than unif==0 make no sense here, but leave it to the user */ switch (Opt->unif) { case 0: /* coordinates as passed to qhull, could be projected ones*/ SO = SUMA_Patch2Surf(xyzp, npt, ijk, nf, 3); break; case 1: /* Original corrdinates passed to qhull (pre-projections, if any) */ SO = SUMA_Patch2Surf(xyz, npt, ijk, nf, 3); break; case 2: /* special coordinates passed by user, never passed in any form to qhull */ SUMA_S_Warn("Makes no sense to mess with coords for convex hull..."); SO = SUMA_Patch2Surf(txyz, npt, ijk, nf, 3); break; default: SUMA_S_Err("pit of despair"); goto CLEANUP; } if (Opt->debug) fprintf(SUMA_STDERR,"%s:\n%d triangles.\n", FuncName, nf); } else if (Opt->geom == 2) { /* triangulation */ if (! (nf = SUMA_qdelaunay_wrap(npt, xyzp, &ijk, 1, Opt->s)) ) { fprintf(SUMA_STDERR,"%s:\nFailed in SUMA_qdelaunay_wrap\n", FuncName); goto CLEANUP; } switch (Opt->unif) { case 0: /* coordinates as passed to qdelaunay, could be projected ones*/ if (xyz == xyzp) xyz=NULL; /* xyzp will be set to null in next call, so xyz is treated the same here */ SO = SUMA_NewSO(&xyzp, npt, &ijk, nf, NULL); SUMA_LHv("xyzp %p, ijk %p\n", txyz, ijk); break; case 1: /* Original corrdinates passed to qdelaunay (pre-projections, if any) */ SO = SUMA_NewSO(&xyz, npt, &ijk, nf, NULL); SUMA_LHv("xyz %p, ijk %p\n", txyz, ijk); break; case 2: /* special coordinates passed by user, never passed in any form to qdelaunay */ SO = SUMA_NewSO(&txyz, npt, &ijk, nf, NULL); SUMA_LHv("txyz %p, ijk %p\n", txyz, ijk); break; default: SUMA_S_Err("pit of despair, again"); goto CLEANUP; } } else { SUMA_S_Errv("Opt->geom = %d not valid\n", Opt->geom); goto CLEANUP; } CLEANUP: if (ijk) SUMA_free(ijk); ijk=NULL; if(txyz) SUMA_free(txyz); txyz=NULL; if (xyzp != xyz && xyzp != NULL) SUMA_free(xyzp); xyzp = NULL; if (xyz) SUMA_free(xyz); xyz = NULL; SUMA_RETURN(SO); }
int main(int argc, char **argv) { static char FuncName[]={"3dGenFeatureDist"}; SEG_OPTS *Opt=NULL; char *atr=NULL, sbuf[512], *methods=NULL; int cc, /* class counter */ kk, /* key counter */ aa, /* feature counter */ nn, /* sub-brick index */ vv, /* voxel index */ ss, /* subjects counter */ iii, /* dummy counter */ nbins, /* number of bins */ *ifeat=NULL, key, **N_alloc_FCset=NULL, /* Number of values allocated for each vector in FCset */ **N_FCset=NULL, /* Number of filled values for each vector in FCset */ N_ffalloc=0, N_ff, isneg=0, missfeatwarn=-1 /* Missing feature warning for some subject */; float fsf=0.0, fsb=0.0, ***FCset=NULL, /* Table holding samples for each feature/class combo */ hrange[2]={-3.0, 3.0}, bwidth1=0.05, bwidth=0.0, *ff=NULL; short *sf=NULL, *sb=NULL; byte **masks=NULL; SUMA_HIST ***hh=NULL, **hf=NULL; double ff_m, ff_s; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); Opt = GenFeatureDist_Default(argv, argc); Opt = GenFeatureDist_ParseInput (Opt, argv, argc); Opt->hist = tross_commandline( FuncName , argc , argv ) ; if (!GenFeatureDist_CheckOpts(Opt)) { ERROR_exit("Failed on option check"); } /* labeltable? */ if (Opt->labeltable_name) { Dtable *vl_dtable=NULL; char *labeltable_str=NULL; /* read the table */ if (!(labeltable_str = AFNI_suck_file( Opt->labeltable_name))) { ERROR_exit("Failed to read %s", Opt->labeltable_name); } if (!(vl_dtable = Dtable_from_nimlstring(labeltable_str))) { ERROR_exit("Could not parse labeltable"); } /* make sure all classes are in the labeltable */ for (cc=0; cc<Opt->clss->num; ++cc) { if ((key = SUMA_KeyofLabel_Dtable(vl_dtable, Opt->clss->str[cc]))<0){ ERROR_exit("Key not found in %s for %s ", Opt->labeltable_name, Opt->clss->str[cc]); } if (Opt->keys) { if (Opt->keys[cc]!=key) { ERROR_exit("Key mismatch %d %d", Opt->keys[cc], key); } } } if (!Opt->keys) { /* get them from table */ Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int)); for (cc=0; cc<Opt->clss->num; ++cc) { if ((key = SUMA_KeyofLabel_Dtable(vl_dtable, Opt->clss->str[cc]))<0){ ERROR_exit("(should noy happen) Key not found in %s for %s ", Opt->labeltable_name, Opt->clss->str[cc]); } Opt->keys[cc] = key; } } destroy_Dtable(vl_dtable); vl_dtable=NULL; } if (!Opt->keys) { /* add default keys */ SUMA_S_Note("Keys not available, assuming defaults"); Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int)); for (cc=0; cc<Opt->clss->num; ++cc) { Opt->keys[cc] = cc+1; } } /* Show the match between keys and classes */ SUMA_ShowClssKeys(Opt->clss->str, Opt->clss->num, Opt->keys); /* For each feature, each class, collect the values */ SUMA_S_Notev("Collecting data from %d subjects\n", Opt->sig_names->num); missfeatwarn = -1; for (ss=0; ss<Opt->sig_names->num; ++ss) { /* for each subject */ /* load the input data */ if (!(Opt->sig = Seg_load_dset( Opt->sig_names->str[ss] ))) { exit(1); } if (Opt->debug > 1) { SUMA_S_Notev("Have %d sub-bricks in signatures of dude %d\n", DSET_NVALS(Opt->sig), ss); } if (ss == 0) { /* some setup based on initial grid */ if (!Opt->feats) { /* create features from signature */ char *allfeats=NULL; for (nn=0; nn<DSET_NVALS(Opt->sig); ++nn) { allfeats = SUMA_append_replace_string(allfeats, DSET_BRICK_LABEL(Opt->sig,nn),";", 1); } Opt->feats = NI_strict_decode_string_list(allfeats,";, "); SUMA_free(allfeats); allfeats=NULL; } SUMA_S_Notev("Have to work with %d classes, %d features\n", Opt->clss->num, Opt->feats->num); SUMA_S_Note("Initializing storage"); /* Receptacles for all observations for each feature and class combination */ FCset = (float ***)SUMA_calloc(Opt->feats->num, sizeof(float **)); N_FCset = (int **)SUMA_calloc(Opt->feats->num, sizeof(int *)); N_alloc_FCset = (int **)SUMA_calloc(Opt->feats->num, sizeof(int *)); ifeat = (int *)SUMA_calloc(Opt->feats->num, sizeof(int)); for (aa=0; aa<Opt->feats->num; ++aa) { FCset[aa] = (float **)calloc(Opt->clss->num, sizeof(float *)); N_FCset[aa] = (int *)SUMA_calloc(Opt->clss->num, sizeof(int)); N_alloc_FCset[aa] = (int *)SUMA_calloc(Opt->clss->num, sizeof(int)); } masks = (byte **)SUMA_calloc(Opt->sig_names->num, sizeof (byte *)); /* Fix VoxDbg */ if (Opt->VoxDbg >= 0) { Vox1D2Vox3D(Opt->VoxDbg, DSET_NX(Opt->sig), DSET_NX(Opt->sig)*DSET_NY(Opt->sig), Opt->VoxDbg3); } else if (Opt->VoxDbg3[0]>=0) { Opt->VoxDbg = Opt->VoxDbg3[0] + Opt->VoxDbg3[1]*DSET_NX(Opt->sig) + Opt->VoxDbg3[2]*DSET_NX(Opt->sig)*DSET_NY(Opt->sig); } } /* allocate for mask which will be non-zero whenever a voxel is in at least 1 mask. It will have the 1st assignment */ masks[ss] = (byte *)SUMA_calloc(DSET_NVOX(Opt->sig), sizeof(byte)); /* create mapping between feature names and sub-briks */ for (aa=0; aa<Opt->feats->num; ++aa) { ifeat[aa] = 0; while (ifeat[aa] < DSET_NVALS(Opt->sig) && strcmp(DSET_BRICK_LABEL(Opt->sig,ifeat[aa]), Opt->feats->str[aa])) ++ifeat[aa]; if (ifeat[aa] >= DSET_NVALS(Opt->sig)) ifeat[aa]=-1; if (Opt->debug > 1) { SUMA_S_Notev("Have feature %s in sub-brick %d\n", Opt->feats->str[aa], ifeat[aa]); } } SUMA_S_Notev("Loading sample classes for subject #%d\n", ss); if (!(Opt->samp = Seg_load_dset( Opt->samp_names->str[ss] ))) { exit(1); } if (THD_dataset_mismatch(Opt->samp, Opt->sig)) { SUMA_S_Err( "Grid mismatch between -samp [%dx%dx%d] and \n" " -sig [%dx%dx%d] volumes for pair #%d\n", DSET_NX(Opt->samp), DSET_NY(Opt->samp), DSET_NZ(Opt->samp), DSET_NX(Opt->sig), DSET_NY(Opt->sig), DSET_NZ(Opt->sig), ss); exit(1); } if (Opt->debug > 1) { SUMA_S_Notev("Have %d sub-bricks in samples of dude %d\n", DSET_NVALS(Opt->samp), ss); } /* Now collect features for each class */ SUMA_S_Note("Collecting features for each class"); for (cc=0; cc<Opt->clss->num; ++cc) { if (Opt->debug > 1) { SUMA_S_Notev("Working class %s\n", Opt->clss->str[cc]); } key = Opt->keys[cc]; for (nn=0; nn<DSET_NVALS(Opt->samp); ++nn) { if (Opt->debug > 2) { SUMA_S_Notev("Looking for key %d for class %s in sb %d\n", key, Opt->clss->str[cc], nn); } sb = (short *)DSET_ARRAY(Opt->samp,nn); fsb = DSET_BRICK_FACTOR(Opt->samp,nn); if (fsb == 0.0) fsb = 1.0; if (fsb != 1.0) { SUMA_S_Err("Non-integral dset, possibly."); exit(1); } for (vv=0; vv<DSET_NVOX(Opt->samp); ++vv) { if (sb[vv] == key) { for (aa=0; aa<Opt->feats->num; ++aa) { if (ifeat[aa]>-1) { if (N_alloc_FCset[aa][cc] <= N_FCset[aa][cc]) { N_alloc_FCset[aa][cc] += 10000; FCset[aa][cc] = (float*)SUMA_realloc(FCset[aa][cc], N_alloc_FCset[aa][cc]*sizeof(float)); } sf = (short *)DSET_ARRAY(Opt->sig, ifeat[aa]); fsf = DSET_BRICK_FACTOR(Opt->sig,ifeat[aa]); if (fsf == 0.0) fsf = 1.0; FCset[aa][cc][N_FCset[aa][cc]] = sf[vv]*fsf; ++N_FCset[aa][cc]; if (!masks[ss][vv]) { masks[ss][vv] = (short)key; /* fcfs */ /* in case we exceed short range */ if (masks[ss][vv]) masks[ss][vv] = 1; } } else { if (missfeatwarn != ss) { SUMA_S_Warnv("Feature %s not found in subject %d\n", Opt->feats->str[aa], ss); missfeatwarn = ss; } } } } } } } DSET_delete(Opt->sig); Opt->sig=NULL; DSET_delete(Opt->samp); Opt->samp=NULL; } /* loop across all subjects */ /* compute histograms of features across all classes and save them */ hf = (SUMA_HIST **)SUMA_calloc(Opt->feats->num, sizeof(SUMA_HIST *)); SUMA_S_Note("Computing histograms of features across all classes"); ff = NULL; N_ffalloc = 0; for (aa=0; aa<Opt->feats->num; ++aa) { N_ff=0; for (cc=0; cc<Opt->clss->num; ++cc) { N_ff += N_FCset[aa][cc]; /* more than I need because same voxel can belong to multiple classes, but just to be safe */ } if (N_ffalloc < N_ff) { N_ffalloc = N_ff; if (ff) SUMA_free(ff); ff=NULL; if (!(ff = (float*)SUMA_calloc(N_ff, sizeof(float)))) { SUMA_S_Crit("Failed to allocate"); exit(1); } } N_ff=0; isneg = 0; ff_m=0.0; for (ss=0; ss<Opt->sig_names->num; ++ss) { /* Once again, unfortunately */ /* load the input data */ if (!(Opt->sig = Seg_load_dset( Opt->sig_names->str[ss] ))) { exit(1); } if (Opt->debug > 1) { SUMA_S_Notev("Have %d sub-bricks in signatures of dude %d\n", DSET_NVALS(Opt->sig), ss); } if (ifeat[aa]>-1) { sb = (short *)DSET_ARRAY(Opt->sig,ifeat[aa]); fsb = DSET_BRICK_FACTOR(Opt->sig,ifeat[aa]); if (fsb == 0.0) fsb = 1.0; for (vv=0; vv<DSET_NVOX(Opt->sig); ++vv) { if (masks[ss][vv]) { ff[N_ff] = sb[vv]*fsb; if (ff[N_ff] < 0) ++isneg; ff_m += ff[N_ff]; ++N_ff; } } } DSET_delete(Opt->sig); Opt->sig=NULL; } ff_m /= N_ff; ff_s=0.0; for (iii=0; iii<N_ff; ++iii) { ff_s += SUMA_POW2(ff[iii]-ff_m); } ff_s = sqrt(ff_s/N_ff); sprintf(sbuf, "h(%s)",Opt->feats->str[aa]); /* Check if you have user specified binning specs */ bwidth = -1; nbins = -1; for (iii=0; iii<Opt->N_hspec; ++iii) { if (!strcmp(Opt->feats->str[aa], Opt->hspec[iii]->label)) { hrange[0] = Opt->hspec[iii]->min; hrange[1] = Opt->hspec[iii]->max; nbins = Opt->hspec[iii]->K; bwidth = 0; methods = "hands off sir"; break; } } if (bwidth < 0) { int nmatch = -1; /* Check the wildcard option */ for (iii=0; iii<Opt->N_hspec; ++iii) { if ((nmatch = SUMA_is_wild_hspec_label(Opt->hspec[iii]->label))>=0) { if (!nmatch || !strncmp(Opt->feats->str[aa], Opt->hspec[iii]->label, nmatch)) { SUMA_S_Note("Feature %s matched with hspec %s\n", Opt->feats->str[aa], Opt->hspec[iii]->label); hrange[0] = Opt->hspec[iii]->min; hrange[1] = Opt->hspec[iii]->max; nbins = Opt->hspec[iii]->K; bwidth = 0; methods = "hands woff sir"; break; } } } } if (bwidth < 0) { /* no user specs found */ nbins = 0; methods = "Range|OsciBinWidth"; if ((float)isneg/(float)N_ff*100.0 > 1.0) { hrange[0] = ff_m-3*ff_s; hrange[1] = ff_m+3*ff_s; bwidth = bwidth1*ff_s; } else if (ff_m-3*ff_s > 0) { hrange[0] = ff_m-3*ff_s; hrange[1] = ff_m+3*ff_s; bwidth = bwidth1*ff_s; } else { hrange[0] = 0; hrange[1] = 6.0*ff_s/2.0; bwidth = bwidth1*ff_s/2.0; } } SUMA_S_Notev("Feature %s: mean %f, std %f\n" "Hist params: [%f %f], binwidth %f\n", Opt->feats->str[aa], ff_m, ff_s, hrange[0], hrange[1], bwidth); if (!(hf[aa] = SUMA_hist_opt(ff, N_ff, nbins, bwidth, hrange, sbuf, 1, 0.1, methods))) { SUMA_S_Errv("Failed to generate histogram for %s. \n" "This will cause trouble at classification.\n", Opt->feats->str[aa]); } else { if ((float)hf[aa]->N_ignored/(float)hf[aa]->n > 0.05) { SUMA_S_Warnv("For histogram %s, %.2f%% of the samples were\n" "ignored for being outside the range [%f %f]\n", Opt->feats->str[aa], 100*(float)hf[aa]->N_ignored/(float)hf[aa]->n, hf[aa]->min, hf[aa]->max); } if (Opt->debug > 1) SUMA_Show_hist(hf[aa], 1, NULL); /* save the histogram */ if (!SUMA_write_hist(hf[aa], SUMA_hist_fname(Opt->proot, Opt->feats->str[aa], NULL, 0))) { SUMA_S_Errv("Failed to write histog to %s\n", sbuf); } } } if (ff) SUMA_free(ff); ff = NULL; /* Compute histograms of features per class && save them*/ hh = (SUMA_HIST ***)SUMA_calloc(Opt->feats->num, sizeof(SUMA_HIST **)); for (aa=0; aa<Opt->feats->num; ++aa) { hh[aa] = (SUMA_HIST **)SUMA_calloc(Opt->clss->num, sizeof(SUMA_HIST *)); } SUMA_S_Note("Computing histograms of features per class"); for (cc=0; cc<Opt->clss->num; ++cc) { if (N_FCset[0][cc] < 10) { SUMA_S_Errv("Requested class %s (%d) has just %d samples.\n" "Not enough to grease your pan.\n", Opt->clss->str[cc], Opt->keys[cc], N_FCset[0][cc]); exit(1); } for (aa=0; aa<Opt->feats->num; ++aa) { sprintf(sbuf, "h(%s|%s)",Opt->feats->str[aa], Opt->clss->str[cc]); hrange[0] = hf[aa]->min; hrange[1] = hf[aa]->max; /* Do not optimize hist range and binwidth anymore, but allow smoothing. This is needed when a particular class has very few samples */ if (!(hh[aa][cc] = SUMA_hist_opt(FCset[aa][cc], N_FCset[aa][cc], hf[aa]->K, hf[aa]->W, hrange, sbuf, 1, 0.1, "OsciSmooth"))) { SUMA_S_Errv("Failed to generate histogram for %s|%s. \n" "This will cause trouble at classification.\n", Opt->feats->str[aa], Opt->clss->str[cc]) } else { if (Opt->debug > 1) SUMA_Show_hist(hh[aa][cc], 1, NULL); /* save the histogram */ if (!SUMA_write_hist(hh[aa][cc], SUMA_hist_fname(Opt->proot, Opt->feats->str[aa], Opt->clss->str[cc], 0))) { SUMA_S_Errv("Failed to write histog to %s\n", sbuf); } } } } SUMA_S_Note("Computing Correlation matrices"); /* L2 normalize all of FCset */ for (cc=0; cc<Opt->clss->num; ++cc) { for (aa=0; aa<Opt->feats->num; ++aa) { THD_normalize(N_FCset[aa][cc], FCset[aa][cc]); } } { NI_element **CC=NULL; float *fm=NULL, *fn=NULL; NI_element *nel = NULL; int suc; /* Compute the correlation matrices for each class */ CC = (NI_element **) SUMA_calloc(Opt->clss->num, sizeof(NI_element *)); for(cc=0; cc<Opt->clss->num; ++cc) { sprintf(sbuf, "CorrMat(%s)", Opt->clss->str[cc]); CC[cc] = NI_new_data_element(sbuf, Opt->feats->num); NI_set_attribute(CC[cc],"Measure","correlation"); atr = SUMA_NI_str_ar_2_comp_str(Opt->feats, " ; "); NI_set_attribute(CC[cc],"ColumnLabels", atr);SUMA_free(atr); atr = NULL; atr = SUMA_HistString (FuncName, argc, argv, NULL); NI_set_attribute(CC[cc],"CommandLine", atr);SUMA_free(atr); atr = NULL; for (aa=0; aa<Opt->feats->num; ++aa) { NI_add_column_stride ( CC[cc], NI_FLOAT, NULL, 1 ); } for (aa=0; aa<Opt->feats->num; ++aa) { fm = (float*)CC[cc]->vec[aa]; for (iii=0; iii<aa; ++iii) fm[iii] = 0.0; /* will fill later */ fm[aa]=1.0; for (iii=aa+1; iii<Opt->feats->num; ++iii) { if (N_FCset[aa][cc]!=N_FCset[iii][cc]) { SUMA_S_Errv("Sanity check failed, %d != %d\n", N_FCset[aa][cc], N_FCset[iii][cc]); } SUMA_DOTP_VEC(FCset[aa][cc], FCset[iii][cc], fm[iii], N_FCset[aa][cc], float, float); } } /* Now fill the remainder */ for (aa=0; aa<Opt->feats->num; ++aa) { fm = (float*)CC[cc]->vec[aa]; for (iii=0; iii<aa; ++iii) { fn = (float*)CC[cc]->vec[iii]; fm[iii] = fn[aa]; } } snprintf(sbuf, 510, "file:%s.niml.cormat", SUMA_corrmat_fname(Opt->proot, Opt->clss->str[cc], 0)); NEL_WRITE_TXH(CC[cc], sbuf, suc); } } /* free everything */ if (FCset) { for (aa=0; aa<Opt->feats->num; ++aa) { for (cc=0; cc<Opt->clss->num; ++cc) { if (FCset[aa][cc]) SUMA_free(FCset[aa][cc]); } SUMA_free(FCset[aa]); } SUMA_free(FCset); FCset=NULL; } if (N_FCset) { for (aa=0; aa<Opt->feats->num; ++aa) { SUMA_free(N_FCset[aa]); } SUMA_free(N_FCset); N_FCset=NULL; } if (N_alloc_FCset) { for (aa=0; aa<Opt->feats->num; ++aa) { SUMA_free(N_alloc_FCset[aa]); } SUMA_free(N_alloc_FCset); N_alloc_FCset=NULL; } if (ifeat) SUMA_free(ifeat); ifeat=NULL; if (hh) { for (aa=0; aa<Opt->feats->num; ++aa) { for (cc=0; cc<Opt->clss->num; ++cc) { if (hh[aa][cc]) hh[aa][cc] = SUMA_Free_hist(hh[aa][cc]); } SUMA_free(hh[aa]); } SUMA_free(hh); hh=NULL; } if (hf) { for (aa=0; aa<Opt->feats->num; ++aa) { if (hf[aa]) hf[aa] = SUMA_Free_hist(hf[aa]); } SUMA_free(hf); hf=NULL; } if (masks) { for (ss=0; ss<Opt->sig_names->num; ++ss) { if (masks[ss]) SUMA_free(masks[ss]); } masks[ss]=NULL; } SUMA_S_Notev("\n" "Consider running this script to examine the distributions:\n" " @ExamineGenFeatDists -fdir %s -odir %s\n", Opt->proot, Opt->proot); /* all done, free */ Opt = free_SegOpts(Opt); PRINT_COMPILE_DATE ; exit(0); }
int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"ConvexHull"}; int i, i3, nspec = 0; void *SO_name=NULL; SUMA_SurfaceObject *SO = NULL; SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt; char stmp[200]; SUMA_Boolean exists = NOPE; SUMA_Boolean LocalHead = NOPE; SUMA_GENERIC_ARGV_PARSE *ps=NULL; SUMA_STANDALONE_INIT; SUMA_mainENTRY; /* Allocate space for DO structure */ SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); ps = SUMA_Parse_IO_Args(argc, argv, "-o;-i;-sv;"); if (argc < 2) { usage_SUMA_ConvexHull(ps); exit (1); } Opt = SUMA_ConvexHull_ParseInput (argv, argc, ps); SO_name = SUMA_Prefix2SurfaceName(Opt->out_prefix, NULL, NULL, Opt->SurfFileType, &exists); if (exists && !THD_ok_overwrite()) { SUMA_S_Err("Output file(s) %s* on disk.\nWill not overwrite.\n", Opt->out_prefix); exit(1); } if (Opt->obj_type < 0) { if (Opt->in_name) { if (Opt->debug) { SUMA_S_Note("Creating mask..."); } if (!SUMA_Get_isosurface_datasets (Opt)) { SUMA_SL_Err("Failed to get data."); exit(1); } if (Opt->debug > 1) { if (Opt->debug == 2) { FILE *fout=fopen("inmaskvec.1D","w"); SUMA_S_Note("Writing masked values...\n"); if (!fout) { SUMA_SL_Err("Failed to write maskvec"); exit(1); } fprintf(fout, "#Col. 0 Voxel Index\n" "#Col. 1 Is a mask (all values here should be 1)\n" ); for (i=0; i<Opt->nvox; ++i) { if (Opt->mcdatav[i]) { fprintf(fout,"%d %.2f\n", i, Opt->mcdatav[i]); } } fclose(fout); fout = NULL; } else { FILE *fout=fopen("maskvec.1D","w"); SUMA_S_Note("Writing all mask values...\n"); if (!fout) { SUMA_S_Err("Failed to write maskvec"); exit(1); } fprintf(fout, "#Col. 0 Voxel Index\n" "#Col. 1 Is in mask ?\n" ); for (i=0; i<Opt->nvox; ++i) { fprintf(fout,"%d %.2f\n", i, Opt->mcdatav[i]); } fclose(fout); fout = NULL; } } } else if (Opt->in_1D) { MRI_IMAGE *im = NULL; float *far=NULL; int nx2; /* load the 1D file */ im = mri_read_1D (Opt->in_1D); if (!im) { SUMA_S_Err("Failed to read file"); exit(1); } far = MRI_FLOAT_PTR(im); if (im->nx == 0) { fprintf(SUMA_STDERR,"Error %s:\n Empty file %s.\n", FuncName, Opt->in_1D); exit(1); } if (im->ny != 3) { fprintf(SUMA_STDERR,"Error %s:\n Found %d columns in %s. Expecting 3\n", FuncName, im->ny, Opt->in_1D); exit(1); } /* copy the columns */ Opt->N_XYZ = im->nx; Opt->XYZ = (float *)SUMA_malloc(im->nx*im->ny*sizeof(float)); if (!Opt->XYZ) { SUMA_S_Crit("Failed to allocate."); exit(1); } nx2 = 2*im->nx; for (i=0;i<Opt->N_XYZ; ++i) { i3 = 3*i; Opt->XYZ[i3 ] = far[i]; Opt->XYZ[i3+1] = far[i+im->nx]; Opt->XYZ[i3+2] = far[i+nx2]; } /* done, clean up and out you go */ if (im) mri_free(im); im = NULL; } else if (ps->i_N_surfnames) { SUMA_SurfSpecFile *Spec=NULL; SUMA_SurfaceObject *SO=NULL; if (ps->i_N_surfnames > 1) { SUMA_S_Err("Only 1 input surface allowed!"); exit(1); } Spec = SUMA_IO_args_2_spec(ps, &nspec); if (!Spec) { SUMA_S_Err("Failed to create spec!"); exit(1); } if (nspec != 1) { SUMA_S_Warn("Expected one spec and nothing else"); } /* load the surface object */ SO = SUMA_Load_Spec_Surf(Spec, 0, ps->sv[0], 0); if (!SO) { SUMA_S_Err("Failed to read surface."); exit(1); } /* transfer coords */ if(SO->NodeDim != 3) { SUMA_S_Err("bad node coords."); exit(1); } Opt->N_XYZ = SO->N_Node; Opt->XYZ = (float *)SUMA_malloc(SO->N_Node * SO->NodeDim * sizeof(float)); if (!Opt->XYZ) { SUMA_S_Crit("Failed to allocate."); exit(1); } for (i=0;i<SO->NodeDim*SO->N_Node; ++i) Opt->XYZ[i] = SO->NodeList[i]; if (nspec) { int k=0; for (k=0; k<nspec; ++k) { if (!SUMA_FreeSpecFields(&(Spec[k]))) { SUMA_S_Err("Failed to free spec fields"); } } SUMA_free(Spec); Spec = NULL; nspec = 0; } if (SO) SUMA_Free_Surface_Object(SO); SO = NULL; } else { SUMA_S_Err("No input!"); exit(1); } } else { SUMA_S_Err("Bad input!"); exit(1); } /* Now call Marching Cube functions */ if (!(SO = SUMA_ConvexHullSurface(Opt))) { SUMA_S_Err("Failed to create surface.\n"); exit(1); } /* write the surface to disk */ if (!SUMA_Save_Surface_Object (SO_name, SO, Opt->SurfFileType, Opt->SurfFileFormat, NULL)) { fprintf (SUMA_STDERR, "Error %s: Failed to write surface object.\n", FuncName); exit (1); } if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL; if (Opt->fvec) SUMA_free(Opt->fvec); Opt->fvec = NULL; if (Opt->mcdatav) {SUMA_free(Opt->mcdatav); Opt->mcdatav = NULL;} if (Opt->in_vol) { DSET_delete( Opt->in_vol); Opt->in_vol = NULL;} if (Opt->out_prefix) SUMA_free(Opt->out_prefix); Opt->out_prefix = NULL; if (Opt->XYZ) SUMA_free(Opt->XYZ); Opt->XYZ = NULL; if (Opt) SUMA_free(Opt); if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) { SUMA_SL_Err("DO Cleanup Failed!"); } if (SO_name) SUMA_free(SO_name); SO_name = NULL; if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1); exit(0); }