bytevec * THD_create_mask_from_string( char *str ) /* Jul 2010 */ { bytevec *bvec=NULL ; int nstr ; char *buf=NULL ; ENTRY("THD_create_mask") ; if( str == NULL || *str == '\0' ) RETURN(NULL) ; nstr = strlen(str) ; bvec = (bytevec *)malloc(sizeof(bytevec)) ; /* try to read it as a dataset */ if( nstr < THD_MAX_NAME ){ THD_3dim_dataset *dset = THD_open_one_dataset(str) ; if( dset != NULL ){ bvec->nar = DSET_NVOX(dset) ; bvec->ar = THD_makemask( dset , 0 , 1.0f,0.0f ) ; DSET_delete(dset) ; if( bvec->ar == NULL ){ ERROR_message("Can't make mask from dataset '%s'",str) ; free(bvec) ; bvec = NULL ; } RETURN(bvec) ; } } /* if str is a filename, read that file; otherwise, use the string itself to find the mask */ if( THD_is_file(str) ){ buf = AFNI_suck_file(str) ; if( buf != NULL ) nstr = strlen(buf) ; } else { buf = str ; } /* try to read buf as a Base64 mask string */ if( strrchr(buf,'=') != NULL ){ int nvox ; bvec->ar = mask_from_b64string( buf , &nvox ) ; if( bvec->ar != NULL ){ bvec->nar = nvox ; } else { ERROR_message("Can't make mask from string '%.16s' %s",buf,(nstr<=16)?" ":"...") ; free(bvec) ; bvec = NULL ; } } else { ERROR_message("Don't understand mask string '%.16s'",buf,(nstr<=16)?" ":"...") ; free(bvec) ; bvec = NULL ; } if( buf != str && buf != NULL ) free(buf) ; RETURN(bvec) ; }
THD_3dim_dataset * THD_open_tcat( char *dlist ) { THD_3dim_dataset *dset_out , **dset_in ; int ndset_in , dd , nerr , new_nvals, sb=0 ; NI_str_array *sar ; double angle=0.0; char *dp, *dlocal = dlist; /* local dlist, in case it is altered */ ENTRY("THD_open_tcat") ; if( dlocal == NULL || *dlocal == '\0' ) RETURN(NULL) ; /* allow file list to be read from a file 23 Jul 2012 [rickr] */ if( ! strncmp(dlocal, "filelist:", 9) ) { dlocal = AFNI_suck_file(dlocal+9) ; if ( ! dlocal ) { ERROR_message("THD_open_tcat: failed to open '%s' as filelist", dlocal+9); RETURN(NULL) ; } /* make it look more like expected */ for( dd=0, dp=dlocal; dd < strlen(dlocal); dd++, dp++ ) if( *dp == '\n' || *dp == '\r' ) *dp = ' '; } if( strchr(dlocal,' ') == NULL ){ dset_out = THD_open_dataset(dlocal) ; RETURN(dset_out) ; } sar = NI_decode_string_list( dlocal , "~" ) ; if( sar == NULL ) RETURN(NULL) ; ndset_in = sar->num ; dset_in = (THD_3dim_dataset **)malloc(sizeof(THD_3dim_dataset *)*sar->num) ; for( nerr=dd=0 ; dd < ndset_in ; dd++ ){ dset_in[dd] = THD_open_dataset( sar->str[dd] ) ; if( dset_in[dd] == NULL ){ fprintf(stderr,"** THD_open_tcat: can't open dataset %s\n",sar->str[dd]) ; nerr++ ; } } if( nerr > 0 ){ for( dd=0 ; dd < ndset_in ; dd++ ) if( dset_in[dd] != NULL ) DSET_delete(dset_in[dd]) ; free((void *)dset_in) ; NI_delete_str_array(sar) ; RETURN(NULL) ; } if( ndset_in == 1 ){ dset_out = dset_in[0] ; free((void *)dset_in) ; NI_delete_str_array(sar) ; RETURN(dset_out) ; } (void)THD_check_for_duplicates( sar->num , sar->str , 1 ) ; /* 31 May 2007 */ for( nerr=0,dd=1 ; dd < ndset_in ; dd++ ){ if( DSET_NX(dset_in[0]) != DSET_NX(dset_in[dd]) || DSET_NY(dset_in[0]) != DSET_NY(dset_in[dd]) || DSET_NZ(dset_in[0]) != DSET_NZ(dset_in[dd]) ){ ERROR_message( "THD_open_tcat: %s [%dx%dx%d] doesn't match %s [%dx%dx%d]\n", sar->str[0] ,DSET_NX(dset_in[0]) , DSET_NY(dset_in[0]) ,DSET_NZ(dset_in[0]) , sar->str[dd],DSET_NX(dset_in[dd]), DSET_NY(dset_in[dd]),DSET_NZ(dset_in[dd]) ) ; nerr++ ; } else { if( !EQUIV_DATAXES(dset_in[dd]->daxes,dset_in[0]->daxes) ){ WARNING_message( "THD_open_tcat: %s grid mismatch with %s\n", sar->str[0] , sar->str[dd] ) ; /* don't increment nerr! */ } angle = dset_obliquity_angle_diff(dset_in[dd], dset_in[0], -1.0); if (angle > 0.0) { WARNING_message( "dataset %s has an obliquity difference of %f degress with %s\n", dset_in[dd] , angle, dset_in[0] ); } } } if( nerr > 0 ){ for( dd=0 ; dd < ndset_in ; dd++ ) if( dset_in[dd] != NULL ) DSET_delete(dset_in[dd]) ; free((void *)dset_in) ; NI_delete_str_array(sar) ; RETURN(NULL) ; } /*-- Check for type problems ZSS: Aug 27 2012 --*/ for (nerr=0,dd=0; dd < ndset_in ; dd++) { for (sb=0; sb < DSET_NVALS(dset_in[dd]); ++sb) { if ( DSET_BRICK_TYPE(dset_in[0],0) != DSET_BRICK_TYPE(dset_in[dd],sb) ) { ++nerr; } } } if (nerr > 0) { /* don't die, just complain */ WARNING_message( "Command-line catenated dataset has %d sub-bricks that differ \n" " in data type from the first sub-brick of the first set.\n" " Mme Irma sees potential for grief if you go down that path. \n" " Use 3dinfo -datum on each input to understand why this is happening.\n" " You can use 3dcalc's -datum option to rewrite the dataset with \n" " all sub-bricks set to the same type then start over.\n\n", nerr); nerr=0; } /*-- OK, start making new dataset --*/ new_nvals = 0 ; for( dd=0 ; dd < ndset_in ; dd++ ) new_nvals += DSET_NVALS(dset_in[dd]) ; for( dd=0 ; dd < ndset_in ; dd++ ) if( DSET_TIMESTEP(dset_in[dd]) > 0.0 ) break ; /* 1st 3D+time */ if( dd == ndset_in ) dd = 0 ; dset_out = EDIT_empty_copy( dset_in[dd] ) ; /* since this is basically an input dataset, set the storage_mode * to match 27 Jul 2010 [rickr] */ if( DSET_ONDISK(dset_out) && IS_VALID_NON_AFNI_DSET(dset_in[dd]) ) THD_set_storage_mode(dset_out, dset_in[dd]->dblk->diskptr->storage_mode); EDIT_dset_items( dset_out , ADN_prefix , "tcat" , ADN_func_type , ISANAT(dset_in[dd]) ? ANAT_EPI_TYPE : FUNC_FIM_TYPE , ADN_ntt , new_nvals , ADN_nvals , new_nvals , ADN_none ) ; DSET_mallocize( dset_out ) ; /* check if we have a valid time axis; if not, make one up */ if( DSET_TIMESTEP(dset_out) <= 0.0f ){ float TR=1.0f , torg=0.0f , tdur=0.0f ; int tunits=UNITS_SEC_TYPE ; EDIT_dset_items( dset_out , ADN_tunits , tunits , ADN_ttdel , TR , ADN_ttorg , torg , ADN_ttdur , tdur , ADN_none ) ; } dset_out->tcat_list = strdup( dlocal ) ; dset_out->tcat_num = ndset_in ; dset_out->tcat_len = (int *)malloc(sizeof(int)*ndset_in) ; for( dd=0 ; dd < ndset_in ; dd++ ){ dset_out->tcat_len[dd] = DSET_NVALS(dset_in[dd]) ; DSET_delete(dset_in[dd]) ; } free((void *)dset_in) ; NI_delete_str_array(sar) ; #if 0 fprintf(stderr,"THD_open_tcat('%s'):",dset_out->tcat_list); for(dd=0;dd<ndset_in;dd++)fprintf(stderr," %d",dset_out->tcat_len[dd]); fprintf(stderr,"\n"); #endif RETURN(dset_out) ; }
int AFNI_process_environ( char *fname ) { int nbuf , nused , ii ; char *fbuf , *fptr ; char str[NSBUF] , left[NSBUF] , middle[NSBUF] , right[NSBUF], fname_str[NSBUF] = {"not_set"}; int nenv=0 , senv=0 ; static int first=1 ; /* 13 Mar 2008 */ ENTRY("AFNI_process_environ") ; bloced = 1 ; if( fname != NULL ){ strcpy(str,fname) ; } else { char *home ; if( afni_env_done ) RETURN(nenv) ; home = getenv("HOME") ; if( home != NULL ){ strcpy(str,home) ; strcat(str,"/.afnirc") ; } else { strcpy(str,".afnirc") ; } if( !THD_is_file(str) ){ /* 19 Sep 2007 */ if( home != NULL ){ strcpy(str,home) ; strcat(str,"/AFNI.afnirc") ; } else { strcpy(str,"AFNI.afnirc") ; } } afni_env_done = 1 ; } strcpy(fname_str,str) ; /* ZSS: Nov. 25 08 */ fbuf = AFNI_suck_file( str ) ; if( fbuf == NULL ){ bloced=0; if(fname==NULL)afni_env_done=0; RETURN(nenv); } nbuf = strlen(fbuf) ; if( nbuf == 0 ){ bloced=0; if(fname==NULL)afni_env_done=0; RETURN(nenv); } fptr = fbuf ; nused = 0 ; /** scan for section strings, which start with "***" **/ str[0] = '\0' ; /* initialize string */ while( nused < nbuf ){ /**----------------------------------------**/ /**-- skip ahead to next section keyword --**/ SkipSection: while( ! ISTARRED(str) ){ GETSTR; } /*- 04 Jun 1999 -*/ if( strcmp(str,"***END") == 0 ) break ; /* exit main loop */ if( strcmp(str,"***ENVIRONMENT") != 0 ){ GETSTR ; goto SkipSection ; } /**---------------------------------------**/ /**-- ENVIRONMENT section [04 Jun 1999] --**/ if( strcmp(str,"***ENVIRONMENT") == 0 ){ /* loop: find environment eqns */ char *enveqn , *eee; int nl , nr , allow_reset ; senv = 1 ; eee = getenv("AFNI_ENVIRON_RESET") ; allow_reset = YESSISH(eee) ; while(1){ /* loop, looking for 'name = value' */ GETEQN ; if( !THD_filename_pure(left) ) continue ; nl = strlen(left) ; nr = strlen(right) ; enveqn = (char *) malloc(nl+nr+4) ; strcpy(enveqn,left) ; strcat(enveqn,"=") ; strcat(enveqn,right) ; if( !(eee = getenv(left)) || allow_reset ){ /* ZSS Nov 25 2008 */ putenv(enveqn) ; } else if( !AFNI_noenv("AFNI_ENVIRON_WARNINGS") && strcmp(right, eee)){ INFO_message( "Environment variable %s already set to '%s'. " "Value of '%s' from %s is ignored. \n" "To kill such warnings Set AFNI_ENVIRON_WARNINGS to NO", left, eee, right, fname_str); } nenv++ ; } continue ; /* to end of outer while */ } /* end of ENVIRONMENT */ } /* end of while loop */ Done: if( fname == NULL && first ){ if( senv == 0 ) WARNING_message("didn't find '***ENVIRONMENT' line in ~/.afnirc") ; else if( nenv == 0 ) WARNING_message("didn't find any environment equations in ~/.afnirc") ; } first = 0 ; free(fbuf) ; bloced = 0 ; RETURN(nenv) ; }
int main(int argc, char **argv) { static char FuncName[]={"3dSeg"}; SEG_OPTS *Opt=NULL; char *atr=NULL; float *mixfrac= NULL; int i=0; double ff; SUMA_SEND_2AFNI SS2A; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); Opt = Seg_Default(argv, argc); Opt = Seg_ParseInput (Opt,argv, argc); Opt->hist = tross_commandline( FuncName , argc , argv ) ; /* load the input data */ if (!(Opt->aset = Seg_load_dset( Opt->aset_name ))) { SUMA_RETURN(1); } if (!Seg_CheckOpts(Opt)) { SUMA_S_Err("Failed on option check"); SUMA_RETURN(1); } /* Load mask dataset */ if (Opt->mset_name) { if (!strncasecmp(Opt->mset_name,"auto", 4)) { byte *mm=NULL; int j; short *sb=NULL; if (!(mm = THD_automask(Opt->aset))) { SUMA_RETURN(1); } NEW_SHORTY(Opt->aset, DSET_NVALS(Opt->aset), "automask.cp", Opt->mset); sb = (short *)DSET_ARRAY(Opt->mset,0); for (j=0; j<DSET_NVOX(Opt->mset); ++j) { sb[j] = (short)mm[j]; } free(mm); mm=NULL; } else if (!(Opt->mset = Seg_load_dset( Opt->mset_name ))) { SUMA_RETURN(1); } } /* reference classes */ if (Opt->gold_name) { if (!(Opt->gold = Seg_load_dset( Opt->gold_name ))) { SUMA_RETURN(1); } } if (Opt->gold_bias_name) { if (!(Opt->gold_bias = Seg_load_dset( Opt->gold_bias_name ))) { SUMA_RETURN(1); } } if (!Opt->clss) { SUMA_S_Err("Need -classes option"); SUMA_RETURN(1); } /* Talk ? */ if (Opt->ps->cs->talk_suma) { Opt->ps->cs->istream = SUMA_BRAINWRAP_LINE; Opt->ps->cs->afni_istream = SUMA_AFNI_STREAM_INDEX2; if (!SUMA_SendToAfni (Opt->ps->cs, NULL, 0)) { SUMA_SL_Err("Failed to initialize SUMA_SendToAfni"); Opt->ps->cs->afni_Send = NOPE; Opt->ps->cs->Send = NOPE; } else { /* send in_vol to afni */ SUMA_SL_Note("Sending anat volume to AFNI"); SS2A.dset = Opt->aset; SS2A.at_sb=-1; if (!SUMA_SendToAfni(Opt->ps->cs, &SS2A, 1)) { SUMA_SL_Err("Failed to send volume to AFNI"); Opt->ps->cs->afni_Send = NOPE; } } } /* classified set ? */ if (Opt->this_cset_name) { /* user supplied initializer */ if (!(Opt->cset = Seg_load_dset( Opt->this_cset_name ))) { SUMA_RETURN(1); } } /* labeltable? */ if (Opt->labeltable_name) { Dtable *vl_dtable=NULL; char *labeltable_str=NULL; int kk=0; /* 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"); } CLASS_KEYS_FROM_LT(vl_dtable); destroy_Dtable(vl_dtable); vl_dtable=NULL; } if (!Opt->keys) { Dtable *vl_dtable=NULL; if (Opt->cset && (vl_dtable = DSET_Label_Dtable(Opt->cset))) { if (Opt->debug) SUMA_S_Note("Getting keys from -cset dataset"); /* try getting keys from cset */ CLASS_KEYS_FROM_LT(vl_dtable); /* Do not delete vl_dtable, it is the same pointer in Opt->cset */ } else { /* add default keys */ if (Opt->debug) SUMA_S_Note("Keys not available, assuming defaults"); Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int)); for (i=0; i<Opt->clss->num; ++i) { Opt->keys[i] = i+1; } } } /* Make sure you have no negative values and requesting bias field correction. The implementation uses log() for this so the negative values would be ill advised */ { float amin, amax; THD_subbrick_minmax(Opt->aset, 0, 1,&amin, &amax); if (amin < 0 && Opt->bias_param > 0) { SUMA_S_Err("Cannot use field bias correction on volumes with negative\n" "values. Either turn off bias field estimation with -bias_fwhm 0.0\n" "or shift the values of the input by something like:\n" " 3dcalc -a %s -expr 'a+bool(a)*%d' -prefix SHIFTED\n" "and rerun the segmentation on SHIFTED. Note the suggested shift\n" "leaves zero values unchanged.", DSET_HEADNAME(Opt->aset), (int)ceil(-amin+1.0)); exit(1); } } /* Show the match between keys and classes */ if (Opt->debug > 1) { SUMA_S_Note("Class-->key map"); SUMA_ShowClssKeys(Opt->clss->str, Opt->clss->num, Opt->keys); } if (Opt->clss->num < 2) { if (Opt->debug <= 1) { SUMA_S_Note("Class-->key map"); SUMA_ShowClssKeys(Opt->clss->str, Opt->clss->num, Opt->keys); } SUMA_S_Err("Less than 2 classes? I am out of here"); SUMA_RETURN(0); } /* Mask setup */ if (Opt->debug > 1) { SUMA_S_Note("MaskSetup"); } Opt->cmask = MaskSetup(Opt, Opt->aset, 1, &(Opt->mset), &(Opt->cmask), Opt->dimcmask, Opt->mask_bot, Opt->mask_top, &(Opt->cmask_count)); if (Opt->VoxDbg >= 0) { SUMA_S_Note("DBG setup"); fprintf(Opt->VoxDbgOut, "Command:"); for (i=0; i<argc; ++i) { fprintf(Opt->VoxDbgOut, "%s ", argv[i]); } fprintf(Opt->VoxDbgOut, "\nDebug info for voxel %d\n", Opt->VoxDbg); } Opt->cs = SUMA_New_Class_Stat(Opt->clss->str, Opt->clss->num, Opt->keys, 3, NULL); /* Load prob. of class given features */ if (Opt->priCgAname && strcmp(Opt->priCgAname, "INIT_MIXFRAC")) { if (!(Opt->priCgA = Seg_load_dset(Opt->priCgAname))) { SUMA_S_Errv("Failed to read priCgA %s\n", Opt->priCgAname); SUMA_RETURN(1); } if (GRID_MISMATCH(Opt->priCgA, Opt->aset)) { SUMA_S_Err("All input data must have same grid (-priCgA != -aset)"); SUMA_RETURN(1); } /* Make sure dset is properly formatted */ if (!SUMA_ShortizeProbDset(&Opt->priCgA, Opt->cs, Opt->cmask, Opt->cmask_count, Opt, &Opt->priCgA)) { SUMA_S_Errv("Failed to shortize priCgA %s\n", Opt->priCgAname); SUMA_RETURN(1); } /* set the floor of the input dset */ if (0) { SUMA_S_Note("Setting probability floor, USEFULNESS NOT TESTED..."); if (!set_p_floor(Opt->priCgA, 0.1, Opt->cmask)) { SUMA_S_Errv("Failed to set p floor for priCgA %s\n", Opt->priCgAname); SUMA_RETURN(1); } } } else { /* uniform probability */ } /* Load prob. of class given location */ if (Opt->priCgLname && strcmp(Opt->priCgLname, "INIT_MIXFRAC")) { if (!(Opt->priCgL = Seg_load_dset(Opt->priCgLname))) { SUMA_S_Errv("Failed to read priCgL %s\n", Opt->priCgLname); SUMA_RETURN(1); } if (GRID_MISMATCH(Opt->priCgL, Opt->aset)) { SUMA_S_Err("All input data must have same grid (-priCgL != -aset)"); SUMA_RETURN(1); } /* Make sure dset is properly formatted */ if (!SUMA_ShortizeProbDset(&Opt->priCgL, Opt->cs, Opt->cmask, Opt->cmask_count, Opt, &Opt->priCgL)) { SUMA_S_Errv("Failed to shortize priCgL %s\n", Opt->priCgLname); SUMA_RETURN(1); } } else { /* uniform probability */ } /* check on weights of priors */ if (Opt->wA >= 0.0 && Opt->wL < 0.0) { Opt->wL = 1.0 - Opt->wA; } else if (Opt->wL >= 0.0 && Opt->wA < 0.0) { Opt->wA = 1.0 - Opt->wL; } else if (Opt->wA < 0.0 && Opt->wL < 0.0) { /* defaults */ Opt->wA = 0.5; Opt->wL = 0.5; } ff = Opt->wA+Opt->wL; Opt->wA = Opt->wA/ff; Opt->wL = Opt->wL/ff; if (!Opt->cset) { if (!SUMA_SegInitCset(Opt->aset, &Opt->cset, Opt->cmask, Opt->cmask_count, Opt->mixopt, Opt->cs, Opt)) { SUMA_S_Err("Failed to get initializer"); SUMA_RETURN(1); } } if (Opt->debug > 1) { SUMA_Seg_Write_Dset(Opt->proot, "classes_init", Opt->cset, -1, Opt->hist); } /* Now add the 'OTHER' class if needed */ if (Opt->Other) { if (!SUMA_AddOther( Opt->clss, &Opt->keys, Opt->cmask, Opt->cmask_count, Opt->cset, Opt->pstCgALL, Opt->priCgA, Opt->priCgL, Opt->cs)) { SUMA_S_Err("Failed to add other"); SUMA_RETURN(0); } } /* store mixfrac in class stats */ for (i=0;i<Opt->cs->N_label; ++i) { if ((ff = SUMA_mixopt_2_mixfrac(Opt->mixopt, Opt->cs->label[i], Opt->cs->keys[i], Opt->cs->N_label, Opt->cmask, Opt->cset))<0.0) { SUMA_S_Errv("Can't get mixfrac for %s\n", Opt->mixopt); SUMA_RETURN(1); } SUMA_set_Stat(Opt->cs, Opt->cs->label[i], "init.mix", ff); SUMA_set_Stat(Opt->cs, Opt->cs->label[i], "mix", ff); } /* Now call the workhorse */ if (!SUMA_SegEngine(Opt)) { SUMA_S_Err("Failed in SUMA_SegEngine"); exit(1); } /* write output */ if (Opt->Bset && !Opt->this_fset_name) { tross_Append_History(Opt->Bset, Opt->hist); SUMA_Seg_Write_Dset(Opt->proot, "BiasField", /* DSET_PREFIX(Opt->Bset) */ Opt->Bset, -1, Opt->hist); } if (Opt->xset && !Opt->this_xset_name) { AFNI_FEED(Opt->ps->cs, "BiasCorrect", -1, Opt->xset); SUMA_Seg_Write_Dset(Opt->proot, "AnatUB", /* DSET_PREFIX(Opt->xset)*/ Opt->xset, -1, Opt->hist); } if (Opt->cset) { SUMA_Seg_Write_Dset(Opt->proot, "Classes", /* Opt->crefix */ Opt->cset, -1, Opt->hist); AFNI_FEED(Opt->ps->cs, "FinalClasses", -1, Opt->cset); } if (Opt->pstCgALL) { SUMA_Seg_Write_Dset(Opt->proot, "Posterior", /* Opt->prefix */ Opt->pstCgALL, -1, Opt->hist); AFNI_FEED(Opt->ps->cs, "pstCgALL-final", -1, Opt->pstCgALL); } if (Opt->aset) { SUMA_Seg_Write_Dset(Opt->proot, "Anat", Opt->aset, -1, Opt->hist); } if (Opt->debug) SUMA_S_Note("Writing Unmodulated output"); if (!(SUMA_pst_C_giv_ALL(Opt->xset, Opt->cmask, Opt->cmask_count, Opt->cs, NULL, NULL, Opt->B, Opt->T, 0, &Opt->pstCgALL))) { SUMA_S_Err("Failed in SUMA_pst_C_giv_ALL unmodulated"); SUMA_RETURN(1); } SUMA_Seg_Write_Dset(Opt->proot, "Unmodulated.p", Opt->pstCgALL, -1, Opt->hist); if (!(SUMA_assign_classes( Opt->pstCgALL, Opt->cs, Opt->cmask, &Opt->cset))) { SUMA_S_Err("Failed in assign_classes"); SUMA_RETURN(1); } SUMA_Seg_Write_Dset(Opt->proot, "Unmodulated.c", Opt->cset, -1, Opt->hist); /* all done, free */ Opt = free_SegOpts(Opt); PRINT_COMPILE_DATE ; SUMA_RETURN(0); }
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 GenFeatureDist_CheckOpts(SEG_OPTS *Opt) { static char FuncName[]={"GenFeatureDist_CheckOpts"}; int i=0, kk=0, nmatch; SUMA_ENTRY; if (!Opt->clss) { SUMA_S_Err("Need -classes option"); SUMA_RETURN(1); } if (!Opt->sig_names) { SUMA_S_Err("Need -sig option"); SUMA_RETURN(1); } if (!Opt->samp_names) { SUMA_S_Err("Need -samp option"); SUMA_RETURN(1); } if (Opt->samp_names->num != Opt->sig_names->num) { SUMA_S_Errv("Need as many -samp options (%d) as -sig options (%d)\n", Opt->samp_names->num, Opt->sig_names->num); SUMA_RETURN(1); } /* 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 (i=0; i<Opt->clss->num; ++i) { if ((kk = SUMA_KeyofLabel_Dtable(vl_dtable, Opt->clss->str[i]))<0){ ERROR_exit("Key not found in %s for %s ", Opt->labeltable_name, Opt->clss->str[i]); } if (Opt->keys) { if (Opt->keys[i]!=kk) { ERROR_exit("Key mismatch %d %d", Opt->keys[i], kk); } } } if (!Opt->keys) { /* get them from table */ Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int)); for (i=0; i<Opt->clss->num; ++i) { if ((kk = SUMA_KeyofLabel_Dtable(vl_dtable, Opt->clss->str[i]))<0){ ERROR_exit("(should noy happen) Key not found in %s for %s ", Opt->labeltable_name, Opt->clss->str[i]); } Opt->keys[i] = kk; } } destroy_Dtable(vl_dtable); vl_dtable=NULL; } /* Make sure any histogram specs are for a class in use */ for (kk=0; kk<Opt->N_hspec; ++kk) { if ( (nmatch = SUMA_is_wild_hspec_label(Opt->hspec[kk]->label)) >= 0) { if (!nmatch) break; for (i=0; i<Opt->feats->num; ++i) { if (!strncmp(Opt->feats->str[i], Opt->hspec[kk]->label, nmatch)) break; } } else { for (i=0; i<Opt->feats->num; ++i) { if (!strcmp(Opt->feats->str[i], Opt->hspec[kk]->label)) break; } } if (i==Opt->feats->num) { SUMA_S_Warn("Feature %s in -hspec not found under -features and will have no impact on the output\n", Opt->hspec[kk]->label); } } if (!Opt->keys) { /* add default keys */ if (Opt->debug) SUMA_S_Note("Keys not available, assuming defaults"); Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int)); for (i=0; i<Opt->clss->num; ++i) { Opt->keys[i] = i+1; } } /* Show the match between keys and classes */ if (Opt->debug > 1) { SUMA_S_Note("Class-->key map"); SUMA_ShowClssKeys(Opt->clss->str, Opt->clss->num, Opt->keys); } if( ! THD_is_directory(Opt->proot) ){ if( mkdir( Opt->proot , THD_MKDIR_MODE ) != 0 ){ SUMA_S_Errv("Failed to create %s\n", Opt->proot); SUMA_RETURN(0); } } SUMA_RETURN(1); }