int Seg_ClssAndKeys_from_dset(THD_3dim_dataset *dset, NI_str_array **nstrp, int **keysp) { ATR_string *atr=NULL; NI_str_array *nstr=NULL; int *keys=NULL; NI_stream ns ; NI_element *nel ; int nn , ii ; Dtable *dt ; char **la , **lb ; if (!(atr = THD_find_string_atr( dset->dblk , "VALUE_LABEL_DTABLE" ))) return(0); if (!(nel = (NI_element *)NI_read_element_fromstring(atr->ch))) { return (0); } /* see if element is OK for this purpose */ if( NI_element_type(nel) != NI_ELEMENT_TYPE ){ NI_free_element(nel) ; return (0) ; } if( nel->vec_len < 1 || /* empty element? */ nel->vec_filled < 1 || /* no data was filled in? */ nel->vec_num < 2 || /* less than 4 columns? */ nel->vec_typ[0] != NI_STRING || /* must be String, String */ nel->vec_typ[1] != NI_STRING ){ NI_free_element(nel) ; return (0) ; } la = (char **) nel->vec[0] ; /* first column of String */ lb = (char **) nel->vec[1] ; /* second column of String */ nn = nel->vec_filled ; ii = rint(sqrt(2*nn+1.0l)) ; if( ii < 7 ) ii = 7 ; else if( ii%2 == 0 ) ii++ ; /* make array, insert strings */ nstr = SUMA_NI_string_vec_to_str_array(lb, nn); /* get keys */ keys = (int *)calloc(nn, sizeof(int)); for( ii=0 ; ii < nn ; ii++ ) keys[ii] = strtol(la[ii], NULL, 10); NI_free_element(nel) ; if (nstrp) {*nstrp = nstr; nstr=NULL;} else { nstr = SUMA_free_NI_str_array(nstr); } if (keysp) { *keysp = keys; keys=NULL; } else { free(keys); keys=NULL; } return (1) ; }
char * Dtable_to_nimlstring( Dtable *dt , char *name ) { int nn , ii ; char **la , **lb , *stout ; NI_element *nel ; NI_stream ns ; nn = listize_Dtable( dt , &la , &lb ) ; if( nn == 0 || la == NULL || lb == NULL ) return (char *)NULL ; if( name == NULL || *name == '\0' ) name = "Dtable" ; nel = NI_new_data_element( name , nn ) ; NI_add_column( nel , NI_STRING , la ) ; NI_add_column( nel , NI_STRING , lb ) ; free(la) ; free(lb) ; ns = NI_stream_open( "str:" , "w" ) ; (void) NI_write_element( ns , nel , NI_TEXT_MODE ) ; NI_free_element( nel ) ; stout = strdup( NI_stream_getbuf(ns) ) ; NI_stream_close( ns ) ; nn = strlen(stout) ; for( ii=nn-1 ; ii > 0 && isspace(stout[ii]) ; ii-- ) ; /* trailing blanks */ stout[ii+1] = '\0' ; return stout ; }
Dtable * Dtable_from_nimlstring( char *nstr ) { NI_stream ns ; NI_element *nel ; int nn , ii ; Dtable *dt ; char **la , **lb ; if (!nstr) return NULL; if (!(nel = (NI_element *)NI_read_element_fromstring(nstr))) { return NULL; } /* see if element is OK for this purpose */ if( NI_element_type(nel) != NI_ELEMENT_TYPE ){ NI_free_element(nel) ; return NULL ; } if( nel->vec_len < 1 || /* empty element? */ nel->vec_filled < 1 || /* no data was filled in? */ nel->vec_num < 2 || /* less than 4 columns? */ nel->vec_typ[0] != NI_STRING || /* must be String, String */ nel->vec_typ[1] != NI_STRING ){ NI_free_element(nel) ; return NULL ; } la = (char **) nel->vec[0] ; /* first column of String */ lb = (char **) nel->vec[1] ; /* second column of String */ nn = nel->vec_filled ; ii = rint(sqrt(2*nn+1.0l)) ; if( ii < 7 ) ii = 7 ; else if( ii%2 == 0 ) ii++ ; /* make table, insert strings */ dt = new_Dtable( ii ) ; for( ii=0 ; ii < nn ; ii++ ) addto_Dtable( la[ii] , lb[ii] , dt ) ; NI_free_element(nel) ; return dt ; }
NI_group *SUMA_FreeAfniSurfaceObject(NI_group *aSO) { static char FuncName[]={"SUMA_FreeAfniSurfaceObject"}; SUMA_ENTRY; if (aSO) NI_free_element(aSO); SUMA_RETURN(NULL); }
/* (broken out from AFNI_start_fetching_url) 22 Mar 2016 [rickr] */ static int vc_check_too_soon(void) { NI_element *nel=NULL; char *rhs; int last_time, dtime; nel = AFNI_read_vctime() ; if( nel == NULL ) return 0; rhs = NI_get_attribute(nel , "version_check_time"); if( rhs == NULL ) return 0; last_time = strtol(rhs,NULL,10); dtime = ((int)time(NULL)) - last_time; /* too soon to worry */ if( dtime >= 0 && dtime < VDELAY ) { NI_free_element(nel); return 1; } /* warn on version change */ rhs = NI_get_attribute(nel,"version_string") ; /* 27 Jan 2003 */ if( rhs != NULL && strcmp(rhs,AVERZHN) != 0 ){ fprintf(stderr, "\n** Your AFNI version changed from %s to %s since last check\n", rhs , AVERZHN ) ; } /* possibly update global motd_old */ rhs = NI_get_attribute(nel,"motd") ; /* 29 Nov 2005 */ if( rhs != NULL ) { if( motd_old ) free(motd_old); motd_old = strdup(rhs) ; } NI_free_element(nel); return 0; }
/* NIML workprocess. - Read and process any new data from open connection. The void * pointer thereiselvis is expected to point to a properly initialized communication structure. (If the return is True, that means don't call this workproc again. If the return is False, that means call this workproc again.......) -------------------------------------------------------------------------*/ int Hallo_niml_workproc( void *thereiselvis ) { static char FuncName[]={"Hallo_niml_workproc"}; int nn, id; void *nini ; static int nwarn=0; char tmpcom[100], *nel_track; NI_element *nel ; int LocalHead = 0; COMM_STRUCT *cs=NULL; cs = (COMM_STRUCT *)thereiselvis; /* check if stream has gone bad */ nn = NI_stream_goodcheck( cs->NimlStream , 1 ) ; if( nn < 0 ){ /* first check in case we are dealing with the intermittent AFNI disruption */ if (1) { NI_stream_close( cs->NimlStream ) ; cs->NimlStream = NULL ; /* try again, a way to get around the weird disruption in SHM connection*/ fprintf(stderr,"Attempting recovery...\n"); cs->Connected = 0; /* Retry calling function */ if (!SendToSuma(cs, NULL, 0)) { /* buzz SUMA */ fprintf (stderr,"Failed to re-initiate call suma\n"); } nn = NI_stream_goodcheck( cs->NimlStream , 1 ) ; } else { fprintf(stderr, "SUMA connection stream gone bad.\n" ); } } if( nn < 0 ){ /* is bad */ if (cs->NimlStream) NI_stream_close( cs->NimlStream ) ; cs->NimlStream = NULL ; /* this will get checked next time */ fprintf(stderr,"Stream gone bad. Stream closed. \n"); } else if (nn == 0) { /* waiting, come back later */ fprintf(stderr,"Waiting on stream\n"); } else { /* if here, stream is good; see if there is any data to be read */ if (cs->NimlStream_flag & SUMA_FLAG_WAITING) { cs->NimlStream_flag = SUMA_FLAG_CONNECTED; fprintf(stderr, "++ NIML connection opened from %s on port %d \n", NI_stream_name(cs->NimlStream), cs->TCP_port) ; } nn = NI_stream_hasinput( cs->NimlStream , 1 ) ; if( nn > 0 ){ /* has data */ int ct = NI_clock_time() ; if (LocalHead) fprintf(stderr,"%s: reading data stream", FuncName) ; nini = NI_read_element( cs->NimlStream , 1 ) ; /* read it */ if (LocalHead) fprintf( stderr, " time=%d ms\n", NI_clock_time()-ct) ; ct = NI_clock_time() ; if( nini != NULL ) { nel = (NI_element *)nini ; if (LocalHead) { fprintf( stderr, "%s: name=%s vec_len=%d vec_filled=%d, vec_num=%d\n", FuncName, nel->name, nel->vec_len, nel->vec_filled, nel->vec_num ); } if (!Hallo_process_NIML_data( nini )) { fprintf(stderr, "Error %s: Failed in SUMA_process_NIML_data.\n", FuncName); } } NI_free_element( nini ) ; if (LocalHead) fprintf(stderr,"processing time=%d ms\n",NI_clock_time()-ct) ; } } /* Return flag for function calling the workprocess */ if (!cs->NimlStream) { return(1); /* Don't call workprocess back */ } else { return (0); /* Call workprocess back */ } }
/* Function that sends to SUMA NIML formatted commands */ int SendToSuma (COMM_STRUCT *cs, NI_group *ngru, int action) { static char FuncName[]={"SendToSuma"}; static float etm = 0.0; static int i_in = 0; char stmp[500]; static struct timeval tt; float *f=NULL; int n=-1, WaitClose, WaitMax, *ip = NULL; float wtm; int good = 1; int LocalHead = 0; /* fprintf (stderr, "%s: LocalHead = %d\n", FuncName, LocalHead); */ if (action == 0) { /* initialization of connection */ NI_element *nel = NULL; fprintf(stdout,"Setting up for communication with SUMA ...\n"); cs->Send = 1; if (!niml_call (cs)) { fprintf (stderr,"Failed in SUMA_niml_call\n"); /* connection flag is reset in SUMA_niml_call */ cs->Send = 0; return(0); } nel = NI_new_data_element("StartTracking", 0); cs->TrackID = 1; /* that's the index for StartTracking command */ NI_set_attribute(nel,"ni_stream_name", cs->StreamName ); sprintf(stmp, "%d", cs->TrackID); NI_set_attribute(nel,"Tracking_ID", stmp); if (NI_write_element( cs->NimlStream , nel, cs->comm_NI_mode ) < 0) { fprintf (stderr,"Failed to start tracking.\nContinuing...\n"); } if (nel) NI_free_element(nel); nel = NULL; /* start the workprocess for this program */ fprintf(stderr,"Here you can register the workprocess for listening\n" "with your program's main loop. See the comments in \n" "the main() function of this program regarding function\n" "Hallo_niml_workproc()\n\n"); ++i_in; return(1); } if (action == 1) { /* action == 1, send data mode */ if (!i_in) { fprintf (stderr,"You must call SUMA_SendToSuma with action 0 " "before action 1.\nNo Communcation cleanup done.\n"); cs->Send = 0; return(0); } if (!ngru) { fprintf (stderr,"Nothing to send!\n"); return(0); } /* make sure stream is still OK */ if (NI_stream_goodcheck ( cs->NimlStream , 1 ) < 0) { cs->GoneBad = 1; fprintf(stdout,"Communication stream gone bad.\n" "Shutting down communication.\n"); cs->Send = 0; return(1); /* returning without error since program should continue */ } /* add tracking (not that important)*/ ++cs->TrackID; sprintf(stmp,"%d", cs->TrackID); NI_set_attribute (ngru, "Tracking_ID", stmp); #if NIML_DEBUG /* writes every element to a text file for debugging ... */ { NI_stream ns; /* Test writing results in asc, 1D format */ if (LocalHead) fprintf(stderr," %s:-\nWriting ascii 1D ...\n" , FuncName); /* open the stream */ sprintf(stmp, "file:niml_dbg_asc_TID_%d_.1D",cs->TrackID); ns = NI_stream_open( stmp , "w" ) ; if( ns == NULL ){ fprintf (stderr,"Error %s:\nCan't open Test_write_asc_1D!\n" , FuncName); return(0); } /* write out the element */ if (NI_write_element( ns , ngru , NI_TEXT_MODE | NI_HEADERSHARP_FLAG ) < 0) { fprintf (stderr,"Error %s:\nFailed in NI_write_element\n" , FuncName); return(0); } /* close the stream */ NI_stream_close( ns ) ; } #endif if (cs->nelps > 0) { /* make sure that you are not sending elements too fast */ if (!etm) { etm = 100000.0; /* first pass, an eternity */ if (LocalHead) fprintf (stdout,"%s: Initializing timer\n", FuncName); etime(&tt, 0); } else { if (LocalHead) fprintf (stdout,"%s: Calculating etm\n", FuncName); etm = etime(&tt, 1); } wtm = 1./cs->nelps - etm; if (wtm > 0) { /* wait */ if (LocalHead) fprintf (stdout, "%s: Sleeping by %f to meet refresh rate...\n", FuncName, wtm); NI_sleep((int)(wtm*1000)); } } /* send it to SUMA */ if (LocalHead) fprintf (stdout,"Sending element %d comm_NI_mode = %d...\n", cs->TrackID, cs->comm_NI_mode); if (NI_write_element( cs->NimlStream , ngru, cs->comm_NI_mode ) < 0) { fprintf(stderr,"Failed updating SUMA...\n"); } if (LocalHead) { if (cs->nelps > 0) fprintf (stdout, " element %d sent (%f sec)\n", cs->TrackID, etime(&tt, 1)); else fprintf (stdout," element %d sent \n", cs->TrackID); } if (cs->nelps > 0) { if (LocalHead) fprintf (stdout,"%s: Resetting time...\n", FuncName); etime(&tt, 0); /* start the timer */ } ++i_in; return(1); }/* action == 1 */ if (action == 2) { NI_element *nel=NULL; if (i_in < 2) { fprintf (stderr,"You must call SUMA_SendToSuma with action 0 and 1" " before action 2.\nNo Communcation cleanup done.\n"); cs->Send = 0; return(0); } /* reset static variables */ i_in = 0; etm = 0.0; /* close the stream*/ if (cs->Send && !cs->GoneBad) { /* stop tracking */ nel = NI_new_data_element("StopTracking", 0); NI_set_attribute(nel,"ni_stream_name", cs->StreamName); if (NI_write_element( cs->NimlStream , nel, cs->comm_NI_mode ) < 0) { fprintf (stderr,"Failed to stop tracking.\nContinuing...\n"); } if (nel) NI_free_element(nel); nel = NULL; /* tell suma you're done with that stream */ nel = NI_new_data_element("CloseKillStream",0); if (!nel) { fprintf (stderr,"Failed to create nel"); return(0); } NI_set_attribute (nel, "ni_stream_name", cs->StreamName); if (NI_write_element( cs->NimlStream , nel, cs->comm_NI_mode ) < 0) { fprintf (stderr,"Failed updating SUMA...\n"); } if (nel) NI_free_element(nel) ; nel = NULL; /* now wait till stream goes bad */ Wait_Till_Stream_Goes_Bad(cs, 1000, 5000, 1); NI_stream_close(cs->NimlStream); cs->NimlStream = NULL; cs->NimlStream_flag = 0; cs->TrackingID = 0; cs->Send = 0; cs->GoneBad = 0; cs->nelps = -1.0; cs->TrackID = 0; } return(1); } /* should not get here */ fprintf (stderr,"Flow error.\nThis should not be\n"); return(0); }
int main( int argc , char *argv[] ) { NI_stream ns ; void *nini = NULL, *vel=NULL; NI_element *nel=NULL; char *strm=NULL, *attr=NULL; int nn, mode = NI_TEXT_MODE, shhh=0, exact=1; FILE *outf = stdout; char *aa=NULL, *select_attr=NULL, *select_attr_val=NULL; int dodup = 0, nodata=0, dostderr=1, isfile=0; int stat = 0, excl = 0; nn = 1; while (nn < argc && argv[nn][0] == '-') { if (!strcmp(argv[nn], "-help") || !strcmp(argv[nn], "-h")) { usage_niccc(strlen(argv[nn]) > 3 ? 2:1); exit(0); } if (!strcmp(argv[nn],"-dup")) { dodup = 1; ++nn; continue; } if (!strcmp(argv[nn],"-nodata")) { nodata = 0; ++nn; continue; } if (!strcmp(argv[nn],"-stdout")) { dostderr = 0; ++nn; continue; } if (!strcmp(argv[nn],"-#")) { mode = mode|NI_HEADERSHARP_FLAG; ++nn; continue; } if (!strcmp(argv[nn],"-quiet")) { shhh=1; ++nn; continue; } if (!strcmp(argv[nn],"-f")) { isfile=1; ++nn; continue; } if (!strcmp(argv[nn],"-s")) { isfile=2; ++nn; continue; } if (!strcmp(argv[nn],"-attribute")) { ++nn; if (nn >= argc) { fprintf(stderr,"Need attribute after -attribute\n"); exit(1); } attr=argv[nn]; ++nn; continue; } if (!strcmp(argv[nn],"-nel_from_string")) { ++nn; if (nn >= argc) { fprintf(stderr,"Need string after -nel_from_string\n"); exit(1); } nini = (NI_element *)NI_read_element_fromstring(argv[nn]); ++nn; continue; } if (!strcmp(argv[nn],"-skip_nel_with_attr") || !strcmp(argv[nn],"-find_nel_with_attr")) { if (strstr(argv[nn],"-find")) { excl=0; } else { excl=1; } ++nn; if (nn+1 >= argc) { fprintf(stderr, "Need attribute and value after -skip_nel_with_attr\n"); exit(1); } select_attr=argv[nn++]; select_attr_val = argv[nn]; ++nn; continue; } if (!strcmp(argv[nn],"-match")) { ++nn; if (nn >= argc) { fprintf(stderr,"Need parameter after -match\n"); exit(1); } if (!strcmp(argv[nn],"exact")) exact = 1; else if (!strcmp(argv[nn],"partial")) exact = 0; else { fprintf(stderr,"%s is not a valid value for -match. \n" "Use either exact or partial\n", argv[nn]); exit(1); } ++nn; continue; } ERROR_message("Bad option %s. See niccc -help for details.\n", argv[nn]); suggest_best_prog_option(argv[0], argv[nn]); exit(1); } if( argc < 2 ){ ERROR_exit("Too few options"); } if (nodata) mode = mode&NI_HEADERONLY_FLAG; if (nn >= argc) { fprintf(stderr,"Usage: niccc [-dup] streamspec\n");exit(1); } strm = (char *) realloc(strm, (strlen(argv[nn])+32)*sizeof(char)); if (isfile == 2) { sprintf(strm,"str:"); ns = NI_stream_open( strm , "r" ) ; NI_stream_setbuf( ns , argv[nn] ) ; } else { if (isfile == 1) { sprintf(strm,"file:%s",argv[nn]); } else { strcpy(strm, argv[nn]); } ns = NI_stream_open( strm, "r" ) ; if( ns == NULL ){ fprintf(stderr,"*** niccc: NI_stream_open fails for %s\n", strm) ; if (THD_is_file(strm)) { fprintf(stderr, " It looks like %s is a file.\n" " Make sure you use option -f before it\n", strm) ; } exit(1) ; } } /*** NI_stream_setbufsize( ns , 6666 ) ; ***/ while(1){ nn = NI_stream_goodcheck( ns , 1 ) ; if( nn < 0 ){ if (strncmp(strm,"file:",5) && strncmp(strm,"str:",4)) { fprintf(stderr,"\n*** niccc: Stream %s fails\n", strm); exit(1); } else { exit(stat); } } if( nn == 0 ){ NI_sleep(5); continue; } /* waiting for Godot */ if (dostderr) outf = stderr; if ( (nn = NI_stream_readcheck( ns , 1 ) ) > 0) { /* check for data */ if (!excl) { stat = 1; /* using -find, exit with status if not found */ } else { stat = 0; /* you got something, exit well */ } while( (nini = NI_read_element( ns , 2 )) ) { if (select_attr) { if ((aa = NI_get_attribute(nini, select_attr))) { if (!strcmp(aa,select_attr_val)) { /* match */ if (excl) goto NEXT; else stat = 0; /* found something */ } else if (!excl) goto NEXT; /* no match */ } } if (attr) { if (exact) { aa = NI_get_attribute(nini, attr); if (aa) { if (shhh) fprintf(outf,"%s\n", aa); else fprintf(outf,"%s: %s\n",attr, aa); exit(0); } else { if (!shhh) fprintf(stderr,"%s: Not found.\n", attr); exit(1); } } else { int tt=NI_element_type(nini) ; int nn, nfound=0; if( tt == NI_ELEMENT_TYPE ){ nel=(NI_element *)nini; for( nn=0 ; nn < nel->attr_num ; nn++ ) { if( strncmp(nel->attr_lhs[nn],attr, strlen(attr)) == 0 ) { if (shhh) fprintf(outf,"%s\n", nel->attr_rhs[nn]); else fprintf(outf,"%s: %s\n", nel->attr_lhs[nn], nel->attr_rhs[nn]); ++nfound; } } if (nfound) exit(0); else { if (!shhh) fprintf(stderr,"%s: Not found.\n", attr); exit(1); } } else { if (strncmp(strm,"file:",5)) { fprintf(stderr,"\n*** niccc: not ready for non elements\n"); exit(1); } else { exit(1); } } } } if (dodup) { if (!shhh) fprintf(stderr, "*** niccc: duplication returned element:\n"); vel = NI_duplicate(nini, 1); NI_free_element( nini ) ; nini=NULL; NIML_to_terminal( vel, mode, dostderr ) ; } else { if (!shhh) fprintf(stderr,"*** niccc: reading returned element:\n") ; NIML_to_terminal( nini, mode, dostderr ) ; } NEXT: if (nini) NI_free_element( nini ) ; nini=NULL; if (vel) NI_free_element( vel ); vel = NULL; } } } /* while stream is good */ }
int main(int argc, char *argv[]) { int i,j,k,m,n,aa,ii,jj,kk,mm,rr; int iarg; int nmask1=0; int nmask2=0; THD_3dim_dataset *insetFA = NULL, *insetV1 = NULL, *insetMD = NULL, *insetL1 = NULL; THD_3dim_dataset *insetEXTRA=NULL; THD_3dim_dataset *mset2=NULL; THD_3dim_dataset *mset1=NULL; THD_3dim_dataset *outsetMAP=NULL, *outsetMASK=NULL; char *prefix="tracky"; int LOG_TYPE=0; char in_FA[300]; char in_V1[300]; char in_MD[300]; char in_L1[300]; int EXTRAFILE=0; // switch for whether other file is input as WM map char OUT_bin[300]; char OUT_tracstat[300]; char prefix_mask[300]; char prefix_map[300]; // FACT algopts FILE *fout0; float MinFA=0.2,MaxAngDeg=45,MinL=20.0; float MaxAng; int SeedPerV[3]={2,2,2}; int ArrMax=0; float tempvmagn; int Nvox=-1; // tot number vox int Dim[3]={0,0,0}; // dim in each dir int Nseed=0,M=30,bval=1000; int DimSeed[3]; // number of seeds there will be float Ledge[3]; // voxel edge lengths int *ROI1, *ROI2; short int *temp_arr; char *temp_byte; int **Tforw, **Tback; int **Ttot; float **flTforw, **flTback; float ****coorded; int ****INDEX; int len_forw, len_back; // int count of num of squares through float phys_forw[1], phys_back[1]; int idx; float ave_tract_len, ave_tract_len_phys; int inroi1, inroi2, KEEPIT; // switches for detecting int in[3]; // to pass to trackit float physin[3]; // also for trackit, physical loc, int totlen; float totlen_phys; int Numtract; int READS_in; float READS_fl; int end[2][3]; int test_ind[2][3]; int roi3_ct=0, id=0; float roi3_mu_MD = 0.,roi3_mu_RD = 0.,roi3_mu_L1 = 0.,roi3_mu_FA = 0.; float roi3_sd_MD = 0.,roi3_sd_RD = 0.,roi3_sd_L1 = 0.,roi3_sd_FA = 0.; float tempMD,tempFA,tempRD,tempL1; char dset_or[4] = "RAI"; THD_3dim_dataset *dsetn; int TV_switch[3] = {0,0,0}; TAYLOR_BUNDLE *tb=NULL; TAYLOR_TRACT *tt=NULL; char *mode = "NI_fast_binary"; NI_element *nel=NULL; int dump_opts=0; tv_io_header header1 = {.id_string = "TRACK\0", .origin = {0,0,0}, .n_scalars = 3, .scal_n[0] = "FA", .scal_n[1] = "MD", .scal_n[2] = "L1", .n_properties = 0, .vox_to_ras = {{0.,0.,0.,0.},{0.,0.,0.,0.}, {0.,0.,0.,0.},{0.,0.,0.,0.}}, // reset this later based on actual data set .voxel_order = "RAI\0", .invert_x = 0, .invert_y = 0, .invert_z = 0, .swap_xy = 0, .swap_yz = 0, .swap_zx = 0, .n_count = 0, .version = 2, .hdr_size = 1000}; // for testing names... char *postfix[4]={"+orig.HEAD\0",".nii.gz\0",".nii\0","+tlrc.HEAD\0"}; int FOUND =-1; int RECORD_ORIG = 0; float Orig[3] = {0.0,0.0,0.0}; mainENTRY("3dTrackID"); machdep(); // **************************************************************** // **************************************************************** // load AFNI stuff // **************************************************************** // **************************************************************** INFO_message("version: MU"); /** scan args **/ if (argc == 1) { usage_TrackID(1); exit(0); } iarg = 1; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0 ) { usage_TrackID(strlen(argv[iarg])>3 ? 2:1); exit(0); } if( strcmp(argv[iarg],"-verb") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-verb'") ; set_tract_verb(atoi(argv[iarg])); iarg++ ; continue ; } if( strcmp(argv[iarg],"-write_opts") == 0) { dump_opts=1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-rec_orig") == 0) { RECORD_ORIG=1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-tract_out_mode") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-tract_out_mode'") ; if (strcmp(argv[iarg], "NI_fast_binary") && strcmp(argv[iarg], "NI_fast_text") && strcmp(argv[iarg], "NI_slow_binary") && strcmp(argv[iarg], "NI_slow_text") ) { ERROR_message("Bad value (%s) for -tract_out_mode",argv[iarg]); exit(1); } mode = argv[iarg]; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask1") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask1'") ; mset1 = THD_open_dataset( argv[iarg] ) ; if( mset1 == NULL ) ERROR_exit("Can't open mask1 dataset '%s'", argv[iarg]) ; DSET_load(mset1) ; CHECK_LOAD_ERROR(mset1) ; nmask1 = DSET_NVOX(mset1) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask2") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask2'") ; mset2 = THD_open_dataset( argv[iarg] ) ; if( mset2 == NULL ) ERROR_exit("Can't open mask2 dataset '%s'", argv[iarg]) ; DSET_load(mset2) ; CHECK_LOAD_ERROR(mset2) ; nmask2 = DSET_NVOX(mset2) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-prefix'"); prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal name after '-prefix'"); iarg++ ; continue ; } if( strcmp(argv[iarg],"-input") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-input'"); for( i=0 ; i<4 ; i++) { sprintf(in_FA,"%s_FA%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_FA)) { FOUND = i; break; } } insetFA = THD_open_dataset(in_FA) ; if( (insetFA == NULL ) || (FOUND==-1)) ERROR_exit("Can't open dataset '%s': for FA.",in_FA); DSET_load(insetFA) ; CHECK_LOAD_ERROR(insetFA) ; Nvox = DSET_NVOX(insetFA) ; Dim[0] = DSET_NX(insetFA); Dim[1] = DSET_NY(insetFA); Dim[2] = DSET_NZ(insetFA); Ledge[0] = fabs(DSET_DX(insetFA)); Ledge[1] = fabs(DSET_DY(insetFA)); Ledge[2] = fabs(DSET_DZ(insetFA)); Orig[0] = DSET_XORG(insetFA); Orig[1] = DSET_YORG(insetFA); Orig[2] = DSET_ZORG(insetFA); // check tot num vox match (as proxy for dims...) if( (Nvox != nmask1) || (Nvox != nmask2) ) ERROR_exit("Input dataset does not match both mask volumes!"); // this stores the original data file orientation for later use, // as well since we convert everything to RAI temporarily, as // described below header1.voxel_order[0]=ORIENT_typestr[insetFA->daxes->xxorient][0]; header1.voxel_order[1]=ORIENT_typestr[insetFA->daxes->yyorient][0]; header1.voxel_order[2]=ORIENT_typestr[insetFA->daxes->zzorient][0]; for( i=0 ; i<3 ; i++) { header1.dim[i] = Dim[i]; header1.voxel_size[i] = Ledge[i]; // will want this when outputting file later for TrackVis. TV_switch[i] = !(dset_or[i]==header1.voxel_order[i]); } dset_or[3]='\0'; FOUND = -1; for( i=0 ; i<4 ; i++) { sprintf(in_V1,"%s_V1%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_V1)) { FOUND = i; break; } } insetV1 = THD_open_dataset(in_V1); if( insetV1 == NULL ) ERROR_exit("Can't open dataset '%s':V1",in_V1); DSET_load(insetV1) ; CHECK_LOAD_ERROR(insetV1) ; FOUND = -1; for( i=0 ; i<4 ; i++) { sprintf(in_L1,"%s_L1%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_L1)) { FOUND = i; break; } } insetL1 = THD_open_dataset(in_L1); if( insetL1 == NULL ) ERROR_exit("Can't open dataset '%s':L1",in_L1); DSET_load(insetL1) ; CHECK_LOAD_ERROR(insetL1) ; FOUND = -1; for( i=0 ; i<4 ; i++) { sprintf(in_MD,"%s_MD%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_MD)) { FOUND = i; break; } } insetMD = THD_open_dataset(in_MD); if( insetMD == NULL ) ERROR_exit("Can't open dataset '%s':MD",in_MD); DSET_load(insetMD) ; CHECK_LOAD_ERROR(insetMD) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-algopt") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-algopt'"); if (!(nel = ReadTractAlgOpts(argv[iarg]))) { ERROR_message("Failed to read options in %s\n", argv[iarg]); exit(19); } if (NI_getTractAlgOpts(nel, &MinFA, &MaxAngDeg, &MinL, SeedPerV, &M, &bval)) { ERROR_message("Failed to get options"); exit(1); } NI_free_element(nel); nel=NULL; iarg++ ; continue ; } if( strcmp(argv[iarg],"-logic") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-logic'"); INFO_message("ROI logic type is: %s",argv[iarg]); if( strcmp(argv[iarg],"AND") == 0 ) LOG_TYPE = 1; else if( strcmp(argv[iarg],"OR") == 0 ) LOG_TYPE = 0; else if( strcmp(argv[iarg],"ALL") == 0 ) LOG_TYPE = -1; else ERROR_exit("Illegal after '-logic': need 'OR' or 'AND'"); iarg++ ; continue ; } //@@ if( strcmp(argv[iarg],"-extra_set") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-extra_set'"); EXTRAFILE = 1; // switch on insetEXTRA = THD_open_dataset(argv[iarg]); if( (insetEXTRA == NULL ) ) ERROR_exit("Can't open dataset '%s': for extra set.",argv[iarg]); DSET_load(insetEXTRA) ; CHECK_LOAD_ERROR(insetEXTRA) ; if( !((Dim[0] == DSET_NX(insetEXTRA)) && (Dim[1] == DSET_NY(insetEXTRA)) && (Dim[2] == DSET_NZ(insetEXTRA)))) ERROR_exit("Dimensions of extra set '%s' don't match those of the DTI prop ones ('%s', etc.).",argv[iarg], in_FA); iarg++ ; continue ; } ERROR_message("Bad option '%s'\n",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } if (iarg < 4) { ERROR_message("Too few options. Try -help for details.\n"); exit(1); } if (dump_opts) { nel = NI_setTractAlgOpts(NULL, &MinFA, &MaxAngDeg, &MinL, SeedPerV, &M, &bval); WriteTractAlgOpts(prefix, nel); NI_free_element(nel); nel=NULL; } // Process the options a little for( i=0 ; i<3 ; i++) DimSeed[i] = Dim[i]*SeedPerV[i]; Nseed = Nvox*SeedPerV[0]*SeedPerV[1]*SeedPerV[2]; // convert to cos of rad value for comparisons, instead of using acos() MaxAng = cos(CONV*MaxAngDeg); // switch to add header-- option for now, added Sept. 2012 // for use with map_TrackID to map tracks to different space if(RECORD_ORIG) { for( i=0 ; i<3 ; i++) header1.origin[i] = Orig[i]; } // at some point, we will have to convert indices into // pseudo-locations; being forced into this choice means that // different data set orientations would be represented differently // and incorrectly in some instances... so, for now, we'll resample // everything to RAI, and then resample back later. guess this will // just slow things down slightly. // have all be RAI for processing here if(TV_switch[0] || TV_switch[1] || TV_switch[2]) { dsetn = r_new_resam_dset(insetFA, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetFA); insetFA=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(insetMD, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetMD); insetMD=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(insetV1, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetV1); insetV1=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(insetL1, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetL1); insetL1=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(mset1, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(mset1); mset1=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(mset2, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(mset2); mset2=dsetn; dsetn=NULL; if(EXTRAFILE) { dsetn = r_new_resam_dset(insetEXTRA, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetEXTRA); insetEXTRA=dsetn; dsetn=NULL; } } // **************************************************************** // **************************************************************** // make arrays for tracking // **************************************************************** // **************************************************************** // for temp storage array, just a multiple of longest dimension! if(Dim[0] > Dim[1]) ArrMax = Dim[0] * 4; else ArrMax = Dim[1] * 4; if(4*Dim[2] > ArrMax) ArrMax = Dim[2] * 4; ROI1 = (int *)calloc(Nvox, sizeof(int)); ROI2 = (int *)calloc(Nvox, sizeof(int)); temp_arr = (short int *)calloc(Nvox, sizeof(short int)); temp_byte = (char *)calloc(Nvox, sizeof(char)); // temp storage whilst tracking Tforw = calloc(ArrMax, sizeof(Tforw)); for(i=0 ; i<ArrMax ; i++) Tforw[i] = calloc(3, sizeof(int)); Ttot = calloc(2*ArrMax , sizeof(Ttot)); for(i=0 ; i<2*ArrMax ; i++) Ttot[i] = calloc(3, sizeof(int)); Tback = calloc(ArrMax, sizeof(Tback)); for(i=0 ; i<ArrMax ; i++) Tback[i] = calloc(3, sizeof(int)); // temp storage whilst tracking, physical loc flTforw = calloc(ArrMax, sizeof(flTforw)); for(i=0 ; i<ArrMax ; i++) flTforw[i] = calloc(3, sizeof(int)); flTback = calloc(ArrMax,sizeof(flTback)); for(i=0 ; i<ArrMax ; i++) flTback[i] = calloc(3, sizeof(int)); if( (ROI1 == NULL) || (ROI2 == NULL) || (temp_arr == NULL) || (Tforw == NULL) || (Tback == NULL) || (flTforw == NULL) || (flTback == NULL) || (Ttot == NULL)) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(12); } coorded = (float ****) calloc( Dim[0], sizeof(float ***) ); for ( i = 0 ; i < Dim[0] ; i++ ) coorded[i] = (float ***) calloc( Dim[1], sizeof(float **) ); for ( i = 0 ; i < Dim[0] ; i++ ) for ( j = 0 ; j < Dim[1] ; j++ ) coorded[i][j] = (float **) calloc( Dim[2], sizeof(float *) ); for ( i=0 ; i<Dim[0] ; i++ ) for ( j=0 ; j<Dim[1] ; j++ ) for ( k= 0 ; k<Dim[2] ; k++ ) //3 comp of V1 and FA coorded[i][j][k] = (float *) calloc( 4, sizeof(float) ); INDEX = (int ****) calloc( Dim[0], sizeof(int ***) ); for ( i = 0 ; i < Dim[0] ; i++ ) INDEX[i] = (int ***) calloc( Dim[1], sizeof(int **) ); for ( i = 0 ; i < Dim[0] ; i++ ) for ( j = 0 ; j < Dim[1] ; j++ ) INDEX[i][j] = (int **) calloc( Dim[2], sizeof(int *) ); for ( i=0 ; i<Dim[0] ; i++ ) for ( j=0 ; j<Dim[1] ; j++ ) for ( k= 0 ; k<Dim[2] ; k++ ) INDEX[i][j][k] = (int *) calloc( 4, sizeof(int) ); // this statement will never be executed if allocation fails above if( (INDEX == NULL) || (coorded == NULL) ) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(122); } for(i=0 ; i<Nvox ; i++) { if(THD_get_voxel( mset1, i, 0) >0.5){ ROI1[i] = 1; } if(THD_get_voxel( mset2, i, 0) >0.5) ROI2[i] = 1; } // set up eigvecs in 3D coord sys, // mark off where ROIs are and keep index handy idx=0; for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) { for( m=0 ; m<3 ; m++ ) coorded[i][j][k][m] = THD_get_voxel(insetV1, idx, m); if(EXTRAFILE) coorded[i][j][k][3] = THD_get_voxel(insetEXTRA, idx, 0); else coorded[i][j][k][3] = THD_get_voxel(insetFA, idx, 0); // make sure that |V1| == 1 for all eigenvects, otherwise it's /// a problem in the tractography; currently, some from // 3dDWItoDT do not have this property... tempvmagn = sqrt(coorded[i][j][k][0]*coorded[i][j][k][0]+ coorded[i][j][k][1]*coorded[i][j][k][1]+ coorded[i][j][k][2]*coorded[i][j][k][2]); if( tempvmagn<0.99 ) for( m=0 ; m<3 ; m++ ) coorded[i][j][k][m]/= tempvmagn; INDEX[i][j][k][0] =idx; // first value is the index itself if( ROI1[idx]==1 ) INDEX[i][j][k][1]=1; // second value identifies ROI1 mask else INDEX[i][j][k][1]=0; if( ROI2[idx]==1 ) INDEX[i][j][k][2]=1; // third value identifies ROI2 mask else INDEX[i][j][k][2]=0; // fourth value will be counter for number of kept tracks // passing through INDEX[i][j][k][3] = 0; idx+= 1; } // ************************************************************* // ************************************************************* // Beginning of main loop // ************************************************************* // ************************************************************* Numtract = 0; ave_tract_len = 0.; ave_tract_len_phys = 0.; sprintf(OUT_bin,"%s.trk",prefix); if( (fout0 = fopen(OUT_bin, "w")) == NULL) { fprintf(stderr, "Error opening file %s.",OUT_bin); exit(16); } fwrite(&header1,sizeof(tv_io_header),1,fout0); if (get_tract_verb()) { INFO_message("Begin tracking..."); } tb = AppCreateBundle(NULL, 0, NULL, insetFA); // start bundle id = 0; for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) if(coorded[i][j][k][3] >= MinFA) { for( ii=0 ; ii<SeedPerV[0] ; ii++ ) for( jj=0 ; jj<SeedPerV[1] ; jj++ ) for( kk=0 ; kk<SeedPerV[2] ; kk++ ) { in[0] = i; in[1] = j; in[2] = k; physin[0] = ((float) in[0] + (0.5 + (float) ii)/SeedPerV[0])*Ledge[0]; physin[1] = ((float) in[1] + (0.5 + (float) jj)/SeedPerV[1])*Ledge[1]; physin[2] = ((float) in[2] + (0.5 + (float) kk)/SeedPerV[2])*Ledge[2]; len_forw = TrackIt(coorded, in, physin, Ledge, Dim, MinFA, MaxAng, ArrMax, Tforw, flTforw, 1, phys_forw); // reset, because it's changed in TrackIt func in[0] = i; in[1] = j; in[2] = k; physin[0] = ((float) in[0] + (0.5 + (float) ii)/SeedPerV[0])*Ledge[0]; physin[1] = ((float) in[1] + (0.5 + (float) jj)/SeedPerV[1])*Ledge[1]; physin[2] = ((float) in[2] + (0.5 + (float) kk)/SeedPerV[2])*Ledge[2]; len_back = TrackIt(coorded, in, physin, Ledge, Dim, MinFA, MaxAng, ArrMax, Tback, flTback, -1, phys_back); KEEPIT = 0; // a simple switch totlen = len_forw+len_back-1; // NB: overlap of starts totlen_phys = phys_forw[0] + phys_back[0]; if( totlen_phys >= MinL ) { // glue together for simpler notation later for( n=0 ; n<len_back ; n++) { // all of this rr = len_back-n-1; // read in backward for(m=0;m<3;m++) Ttot[rr][m] = Tback[n][m]; } for( n=1 ; n<len_forw ; n++){// skip first->overlap rr = n+len_back-1; // put after for(m=0;m<3;m++) Ttot[rr][m] = Tforw[n][m]; } // <<So close and orthogonal condition>>: // test projecting ends, to see if they abut ROI. for(m=0;m<3;m++) { //actual projected ends end[1][m] = 2*Ttot[totlen-1][m]-Ttot[totlen-2][m]; end[0][m] = 2*Ttot[0][m]-Ttot[1][m]; // default choice, just retest known ends // as default test_ind[1][m] = test_ind[0][m] = Ttot[0][m]; } tt = Create_Tract(len_back, flTback, len_forw, flTforw, id, insetFA); ++id; if (LOG_TYPE == -1) { KEEPIT = 1; } else { inroi1 = 0; // check forw for( n=0 ; n<len_forw ; n++) { if(INDEX[Tforw[n][0]][Tforw[n][1]][Tforw[n][2]][1]==1){ inroi1 = 1; break; } else continue; } if( inroi1==0 ){// after 1st half, check 2nd half for( m=0 ; m<len_back ; m++) { if(INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][1]==1){ inroi1 = 1; break; } else continue; } } // after 1st&2nd halves, check bound/neigh if( inroi1==0 ) { if(INDEX[test_ind[1][0]][test_ind[1][1]][test_ind[1][2]][1]==1) inroi1 = 1; if(INDEX[test_ind[0][0]][test_ind[0][1]][test_ind[0][2]][1]==1) inroi1 = 1; } if( ((LOG_TYPE ==0) && (inroi1 ==0)) || ((LOG_TYPE ==1) && (inroi1 ==1))) { // have to check in ROI2 inroi2 = 0; // check forw for( n=0 ; n<len_forw ; n++) { if(INDEX[Tforw[n][0]][Tforw[n][1]][Tforw[n][2]][2]==1){ inroi2 = 1; break; } else continue; } //after 1st half, check 2nd half if( inroi2==0 ) { for( m=0 ; m<len_back ; m++) { if(INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][2]==1){ inroi2 = 1; break; } else continue; } } // after 1st&2nd halves, check bound/neigh if( inroi2==0 ) { if(INDEX[test_ind[1][0]][test_ind[1][1]][test_ind[1][2]][2]==1) inroi2 = 1; if(INDEX[test_ind[0][0]][test_ind[0][1]][test_ind[0][2]][2]==1) inroi2 = 1; } // for both cases, need to see it here to keep if( inroi2 ==1 ) KEEPIT = 1; // otherwise, it's gone } else if((LOG_TYPE ==0) && (inroi1 ==1)) KEEPIT = 1; } } // by now, we *know* if we're keeping this or not. if( KEEPIT == 1 ) { tb = AppCreateBundle(tb, 1, tt, NULL); tt = Free_Tracts(tt, 1); READS_in = totlen; fwrite(&READS_in,sizeof(READS_in),1,fout0); for( n=0 ; n<len_back ; n++) { //put this one in backwords, to make it connect m = len_back - 1 - n; for(aa=0 ; aa<3 ; aa++) { // recenter phys loc for trackvis, if nec... // just works this way (where they define // origin) READS_fl = flTback[m][aa]; if(!TV_switch[aa]) READS_fl = Ledge[aa]*Dim[aa]-READS_fl; fwrite(&READS_fl,sizeof(READS_fl),1,fout0); } mm = INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][0]; READS_fl =THD_get_voxel(insetFA, mm, 0); // FA fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetMD, mm, 0); // MD fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetL1, mm, 0); // L1 fwrite(&READS_fl,sizeof(READS_fl),1,fout0); // count this voxel for having a tract INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][3]+= 1; } for( m=1 ; m<len_forw ; m++) { for(aa=0 ; aa<3 ; aa++) { // recenter phys loc for trackvis, if nec... READS_fl = flTforw[m][aa]; if(!TV_switch[aa]) READS_fl = Ledge[aa]*Dim[aa]-READS_fl; fwrite(&READS_fl,sizeof(READS_fl),1,fout0); } mm = INDEX[Tforw[m][0]][Tforw[m][1]][Tforw[m][2]][0]; READS_fl =THD_get_voxel(insetFA, mm, 0); // FA fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetMD, mm, 0); // MD fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetL1, mm, 0); // L1 fwrite(&READS_fl,sizeof(READS_fl),1,fout0); // count this voxel for having a tract INDEX[Tforw[m][0]][Tforw[m][1]][Tforw[m][2]][3]+= 1; } ave_tract_len+= totlen; ave_tract_len_phys+= totlen_phys; Numtract+=1; } } } fclose(fout0); if (get_tract_verb()) { INFO_message("Done tracking, have %d tracks.", tb->N_tracts); Show_Taylor_Bundle(tb, NULL, 3); } if (!Write_Bundle(tb,prefix,mode)) { ERROR_message("Failed to write the bundle"); } // ************************************************************** // ************************************************************** // Some simple stats on ROIs and outputs // ************************************************************** // ************************************************************** for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) { if( INDEX[i][j][k][3]>=1 ) { tempMD = THD_get_voxel(insetMD,INDEX[i][j][k][0],0); tempFA = THD_get_voxel(insetFA,INDEX[i][j][k][0],0); tempL1 = THD_get_voxel(insetL1,INDEX[i][j][k][0],0); tempRD = 0.5*(3*tempMD-tempL1); roi3_mu_MD+= tempMD; roi3_mu_FA+= tempFA; roi3_mu_L1+= tempL1; roi3_mu_RD+= tempRD; roi3_sd_MD+= tempMD*tempMD; roi3_sd_FA+= tempFA*tempFA; roi3_sd_L1+= tempL1*tempL1; roi3_sd_RD+= tempRD*tempRD; roi3_ct+= 1; } } if(roi3_ct > 0 ) { // !!!! make into afni file roi3_mu_MD/= (float) roi3_ct; roi3_mu_FA/= (float) roi3_ct; roi3_mu_L1/= (float) roi3_ct; roi3_mu_RD/= (float) roi3_ct; roi3_sd_MD-= roi3_ct*roi3_mu_MD*roi3_mu_MD; roi3_sd_FA-= roi3_ct*roi3_mu_FA*roi3_mu_FA; roi3_sd_L1-= roi3_ct*roi3_mu_L1*roi3_mu_L1; roi3_sd_RD-= roi3_ct*roi3_mu_RD*roi3_mu_RD; roi3_sd_MD/= (float) roi3_ct-1; roi3_sd_FA/= (float) roi3_ct-1; roi3_sd_L1/= (float) roi3_ct-1; roi3_sd_RD/= (float) roi3_ct-1; roi3_sd_MD = sqrt(roi3_sd_MD); roi3_sd_FA = sqrt(roi3_sd_FA); roi3_sd_L1 = sqrt(roi3_sd_L1); roi3_sd_RD = sqrt(roi3_sd_RD); sprintf(OUT_tracstat,"%s.stats",prefix); if( (fout0 = fopen(OUT_tracstat, "w")) == NULL) { fprintf(stderr, "Error opening file %s.",OUT_tracstat); exit(19); } fprintf(fout0,"%d\t%d\n",Numtract,roi3_ct); fprintf(fout0,"%.3f\t%.3f\n",ave_tract_len/Numtract, ave_tract_len_phys/Numtract); // as usual, these next values would have to be divided by the // bval to get their actual value in standard phys units fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_FA,roi3_sd_FA); fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_MD,roi3_sd_MD); fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_RD,roi3_sd_RD); fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_L1,roi3_sd_L1); fclose(fout0); sprintf(prefix_map,"%s_MAP",prefix); sprintf(prefix_mask,"%s_MASK",prefix); outsetMAP = EDIT_empty_copy( mset1 ) ; EDIT_dset_items( outsetMAP , ADN_datum_all , MRI_short , ADN_prefix , prefix_map , ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMAP)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMAP)); outsetMASK = EDIT_empty_copy( mset1 ) ; EDIT_dset_items( outsetMASK , ADN_datum_all , MRI_byte , ADN_prefix , prefix_mask , ADN_none ) ; if(!THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMASK)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMASK)); m=0; for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) { temp_arr[m]=INDEX[i][j][k][3]; if(temp_arr[m]>0.5) temp_byte[m]=1; else temp_byte[m]=0; m++; } // re-orient the data as original inputs // (this function copies the pointer) EDIT_substitute_brick(outsetMAP, 0, MRI_short, temp_arr); temp_arr=NULL; if(TV_switch[0] || TV_switch[1] || TV_switch[2]) { dsetn = r_new_resam_dset(outsetMAP, NULL, 0.0, 0.0, 0.0, header1.voxel_order, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(outsetMAP); outsetMAP=dsetn; dsetn=NULL; } EDIT_dset_items( outsetMAP , ADN_prefix , prefix_map , ADN_none ) ; THD_load_statistics(outsetMAP ); if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMAP)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMAP)); tross_Make_History( "3dTrackID" , argc , argv , outsetMAP) ; THD_write_3dim_dataset(NULL, NULL, outsetMAP, True); // re-orient the data as original inputs EDIT_substitute_brick(outsetMASK, 0, MRI_byte, temp_byte); temp_byte=NULL; if(TV_switch[0] || TV_switch[1] || TV_switch[2]) { dsetn = r_new_resam_dset(outsetMASK, NULL, 0.0, 0.0, 0.0, header1.voxel_order, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(outsetMASK); outsetMASK=dsetn; dsetn=NULL; } EDIT_dset_items( outsetMASK , ADN_prefix , prefix_mask , ADN_none ) ; THD_load_statistics(outsetMASK); if(!THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMASK)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMASK)); tross_Make_History( "3dTrackID" , argc , argv , outsetMASK) ; THD_write_3dim_dataset(NULL, NULL, outsetMASK, True); INFO_message("Number of tracts found = %d",Numtract) ; } else INFO_message("\n No Tracts Found!!!\n"); // ************************************************************ // ************************************************************ // Freeing // ************************************************************ // ************************************************************ // !!! need to free afni-sets? DSET_delete(insetFA); DSET_delete(insetMD); DSET_delete(insetL1); DSET_delete(insetV1); DSET_delete(insetEXTRA); //DSET_delete(outsetMAP); //DSET_delete(outsetMASK); DSET_delete(mset2); DSET_delete(mset1); free(prefix); free(insetV1); free(insetFA); free(mset1); free(mset2); free(insetEXTRA); free(ROI1); free(ROI2); free(temp_byte); for( i=0 ; i<ArrMax ; i++) { free(Tforw[i]); free(Tback[i]); free(flTforw[i]); free(flTback[i]); } free(Tforw); free(Tback); free(flTforw); free(flTback); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) for( k=0 ; k<Dim[2] ; k++) free(coorded[i][j][k]); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) free(coorded[i][j]); for( i=0 ; i<Dim[0] ; i++) free(coorded[i]); free(coorded); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) for( k=0 ; k<Dim[2] ; k++) free(INDEX[i][j][k]); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) free(INDEX[i][j]); for( i=0 ; i<Dim[0] ; i++) free(INDEX[i]); free(INDEX); free(temp_arr); // need to free for( i=0 ; i<2*ArrMax ; i++) free(Ttot[i]); free(Ttot); //free(mode); return 0; }
int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"FSread_annot"}; int kar, Showct, testmode; char *fname = NULL, *fcmap = NULL, *fdset = NULL, *froi = NULL, *fcol = NULL, *ctfile=NULL, sbuf[1024]={""}; SUMA_Boolean SkipCoords = NOPE, brk; SUMA_DSET *dset=NULL; int lbl1,lbl2, ver, hemi, FSdefault; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; /* 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); } /* parse command line */ kar = 1; fname = NULL; froi = NULL; fcmap = NULL; fcol = NULL; brk = NOPE; ctfile = NULL; Showct = 0; testmode = 0; lbl1 = -1; lbl2 = -1; ver = -1; FSdefault = 0; hemi=0; while (kar < argc) { /* loop accross command ine options */ /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/ if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) { usage_SUMA_FSread_annot_Main(); exit (0); } if (!brk && (strcmp(argv[kar], "-show_FScmap") == 0)) { Showct = 1; brk = YUP; } if (!brk && (strcmp(argv[kar], "-testmode") == 0)) { testmode = 1; brk = YUP; } if (!brk && (strcmp(argv[kar], "-input") == 0)) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -input\n"); exit (1); } fname = argv[kar]; brk = YUP; } if (!brk && (strcmp(argv[kar], "-FScmap") == 0)) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -FScmap\n"); exit (1); } ctfile = argv[kar]; if (!strcmp(ctfile,"FS_DEFAULT")) { char *eee = getenv("FREESURFER_HOME"); if (!eee) { SUMA_S_Err("Environment variable FREESURFER_HOME not set.\n" "Cannot locate FreeSurferColorLUT.txt\n"); exit (1); } else { sprintf(sbuf, "%s/FreeSurferColorLUT.txt", eee); ctfile = sbuf; FSdefault = 1; SUMA_S_Notev("Using %s\n", ctfile); } } brk = YUP; } if (!brk && (strcmp(argv[kar], "-FSversion") == 0)) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -FSversion\n"); exit (1); } if (strstr(argv[kar],"2009")) ver = 2009; else if (strstr(argv[kar],"2005")) ver = 2005; else { fprintf (SUMA_STDERR, "Bad value for -FSversion of %s (looking for 2005 or 2009)\n", argv[kar]); exit (1); } brk = YUP; } if (!brk && (strcmp(argv[kar], "-hemi") == 0)) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -hemi\n"); exit (1); } if (strstr(argv[kar],"lh")) hemi = -1; else if (strstr(argv[kar],"rh")) hemi = 1; else { fprintf (SUMA_STDERR, "Bad value for -hemi of %s (looking for lh or rh)\n", argv[kar]); exit (1); } brk = YUP; } if (!brk && (strcmp(argv[kar], "-FScmaprange") == 0)) { kar ++; if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need 2 argument after -FScmaprange\n"); exit (1); } lbl1 = atoi(argv[kar]); ++kar; lbl2 = atoi(argv[kar]); if (lbl1 > lbl2 || lbl1 < -1) { fprintf (SUMA_STDERR, "Bad value for -FScmaprange of [%d %d]\n", lbl1, lbl2); exit (1); } brk = YUP; } if (!brk && (strcmp(argv[kar], "-roi_1D") == 0)) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -ROI_1D\n"); exit (1); } froi = argv[kar]; brk = YUP; } if (!brk && ( (strcmp(argv[kar], "-prefix") == 0) || (strcmp(argv[kar], "-dset") == 0) ) ) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -dset\n"); exit (1); } fdset = argv[kar]; brk = YUP; } if (!brk && (strcmp(argv[kar], "-cmap_1D") == 0)) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -cmap_1D\n"); exit (1); } fcmap = argv[kar]; brk = YUP; } if (!brk && (strcmp(argv[kar], "-col_1D") == 0)) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -col_1D\n"); exit (1); } fcol = argv[kar]; brk = YUP; } if (!brk) { fprintf (SUMA_STDERR, "Error %s:\n" "Option %s not understood. Try -help for usage\n", FuncName, argv[kar]); exit (1); } else { brk = NOPE; kar ++; } } if (!fname) { SUMA_SL_Err("No input file specified."); exit(1); } if (ver == -1) { /* guess at version */ if (strstr(fname,"2009")) { ver = 2009; SUMA_S_Notev("Guessed FS annot version of %d\n", ver); } else if (strstr(fname,"2005")) { ver = 2005; SUMA_S_Notev("Guessed FS annot version of %d\n", ver); } else { SUMA_S_Notev("Assuming FS annot version of %d\n", ver); } } if (hemi == 0) { if (strstr(fname,"lh.")) { hemi = -1; SUMA_S_Note("Guessed left hemisphere"); } else if (strstr(fname,"rh.")) { SUMA_S_Note("Guessed right hemisphere"); hemi = 1; } else { if (ver == 2009) { hemi = -1; SUMA_S_Note("Assuming left hemisphere.\n"); } else { /* leave it not set */ } } } if (ver == 2009 && !ctfile) { char *eee = getenv("FREESURFER_HOME"); if (!eee) { SUMA_S_Warn("Environment variable FREESURFER_HOME not set.\n" "Cannot locate FreeSurferColorLUT.txt\n"); } else { sprintf(sbuf, "%s/FreeSurferColorLUT.txt", eee); ctfile = sbuf; SUMA_S_Notev("Using %s\n", ctfile); } } if (lbl1 < 0 && lbl2 < 0) { /* need some setup */ if (ver == 2009) { if (hemi == -1) { lbl1 = 13100; lbl2 = 13199; SUMA_S_Notev("Setting -FScmaprange to [%d %d]\n", lbl1, lbl2); } else if (hemi == 1) { lbl1 = 14100; lbl2 = 14199; SUMA_S_Notev("Setting -FScmaprange to [%d %d]\n", lbl1, lbl2); } else { SUMA_S_Warn("-FScmaprange is not set.\n" "You may need to set it, check results.\n"); } } else if (ver == 2005 && FSdefault) { if (hemi == -1) { lbl1 = 3100; lbl2 = 3199; SUMA_S_Notev("Setting -FScmaprange to [%d %d]\n", lbl1, lbl2); } else if (hemi == 1) { lbl1 = 4100; lbl2 = 4199; SUMA_S_Notev("Setting -FScmaprange to [%d %d]\n", lbl1, lbl2); } else { SUMA_S_Warn("-FScmaprange is not set.\n" "You may need to set it, check results.\n"); } } } if (!fcmap && !froi && !fcol && !Showct && !fdset) { SUMA_SL_Err("Nothing to do.\n" "Use either -cmap_1D or \n" " -roi_1D or -col_1D or \n" " -show_FScmap options."); exit(1); } if (fdset) { int exists = 0; char *ooo=NULL; exists = SUMA_WriteDset_NameCheck_s (fdset, NULL, SUMA_ASCII_NIML, 0, &ooo); if (exists != 0 && !THD_ok_overwrite()) { SUMA_S_Errv("Output dataset %s exists.\n", ooo); SUMA_free(ooo); ooo=NULL; exit(1); } } if (froi) { if (SUMA_filexists(froi) && !THD_ok_overwrite()) { fprintf( SUMA_STDERR, "Error %s: File %s exists, will not overwrite.\n", FuncName, froi); SUMA_RETURN (NOPE); } } if (fcmap) { if (SUMA_filexists(fcmap) && !THD_ok_overwrite()) { fprintf( SUMA_STDERR, "Error %s: File %s exists, will not overwrite.\n", FuncName, fcmap); SUMA_RETURN (NOPE); } } if (fcol) { if (SUMA_filexists(fcol) && !THD_ok_overwrite()) { fprintf( SUMA_STDERR, "Error %s: File %s exists, will not overwrite.\n", FuncName, fcol); SUMA_RETURN (NOPE); } } if (!SUMA_readFSannot (fname, froi, fcmap, fcol, Showct, ctfile, lbl1, lbl2, &dset)) { SUMA_S_Err("Failed reading annotation file (or output file exists)"); exit(1); } if (!dset && fdset) { SUMA_S_Err("Have no dset to write"); exit(1); } if (fdset) { if (AFNI_yesenv("AFNI_NIML_TEXT_DATA")) { SUMA_WriteDset_eng(fdset, dset, SUMA_ASCII_NIML, 1, 1, 1); } else { SUMA_WriteDset_eng(fdset, dset, SUMA_BINARY_NIML, 1, 1, 1); } } if (testmode) { int key, indx, ism, suc; SUMA_COLOR_MAP *SM2=NULL, *SM=NULL; char *s=NULL, stmp[256]; SUMA_PARSED_NAME *sname=NULL; NI_group *ngr=NULL; SUMA_S_Note("Testing Chunk Begins"); /* check */ if (!SUMA_is_Label_dset(dset, &ngr)) { SUMA_S_Err("Dset is no label dset"); exit(1); } /* write it */ /* play with the colormap */ if (ngr) { if (!(SM = SUMA_NICmapToCmap(ngr))){ SUMA_S_Err("Failed to create SUMA colormap"); exit(1); } ngr = NULL; /* that's a copy of what was in dset, do not free it */ if (!SUMA_CreateCmapHash(SM)) { SUMA_S_Err("Failed to create hash"); exit(1); } /* Now pretend you are retrieving the index in cmap of some key */ for (ism=0; ism < SM->N_M[0]; ++ism) { /* the key is coming from SM, because I store all keys there But key normally comes from a certain node's value */ key = SM->idvec[ism]; indx = SUMA_ColMapKeyIndex(key, SM); if (indx < 0) { SUMA_S_Errv("Hashkey %d not found\n", key); } else { fprintf(SUMA_STDERR, "hashed id %d --> index %d\n" "known id %d --> index %d\n", key, indx, key, ism); } } /* Now try it with an unknown key */ key = -13; indx = SUMA_ColMapKeyIndex(key, SM); if (indx < 0) { fprintf(SUMA_STDERR, "id %d is not in the hash table, as expected\n", key); } else { SUMA_S_Errv("Should not have found %d\n", key); } SUMA_S_Note("Now Show it to me"); s = SUMA_ColorMapVec_Info (&SM, 1, 2); if (s) { fprintf(SUMA_STDERR,"%s", s); SUMA_free(s); s = NULL; } SUMA_S_Notev("Now turn it to niml (%s)\n", SM->Name); ngr = SUMA_CmapToNICmap(SM); sname = SUMA_ParseFname(SM->Name, NULL); snprintf(stmp, 128*sizeof(char), "file:%s.niml.cmap", sname->FileName_NoExt); NEL_WRITE_TX(ngr, stmp, suc); if (!suc) { SUMA_S_Errv("Failed to write %s\n", stmp); } SUMA_Free_Parsed_Name(sname); sname = NULL; SUMA_S_Note("Now turn niml colormap to SUMA's colormap"); SM2 = SUMA_NICmapToCmap(ngr); SUMA_S_Note("Now Show it to me2"); s = SUMA_ColorMapVec_Info (&SM2, 1, 2); if (s) { fprintf(SUMA_STDERR,"%s", s); SUMA_free(s); s = NULL; } NI_free_element(ngr); ngr=NULL; SUMA_Free_ColorMap(SM); SM = NULL; SUMA_Free_ColorMap(SM2); SM2 = NULL; } SUMA_S_Note("Testing Chunk End"); } if (dset) SUMA_FreeDset(dset); dset = NULL; exit(0); }
int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"SurfClust"}; int kar, SO_read, *ni=NULL, N_ni, cnt, i, *nip=NULL, N_Spec = 0; float *data_old = NULL, *far = NULL, *nv=NULL, *nt = NULL; void *SO_name = NULL; SUMA_SurfaceObject *SO = NULL, *SOnew = NULL; MRI_IMAGE *im = NULL; SUMA_DSET_FORMAT iform; SUMA_SURFCLUST_OPTIONS *Opt; SUMA_SurfSpecFile *Spec=NULL; DList *list = NULL; SUMA_DSET *dset = NULL; float *NodeArea = NULL; FILE *clustout=NULL; char *ClustOutName = NULL, *params=NULL, stmp[200]; char sapa[32]={""}, sapd[32]={""}, sapn[32]={""}, sap[100]={""}; SUMA_GENERIC_ARGV_PARSE *ps=NULL; SUMA_Boolean LocalHead = NOPE; 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, "-spec;-i;-t;-sv;-s;"); Opt = SUMA_SurfClust_ParseInput (argv, argc, ps); if (argc < 6) { SUMA_S_Err("Too few options"); usage_SUMA_SurfClust(0); exit (1); } if (Opt->DistLim >= 0.0) { sprintf(sapd, "_r%.1f", Opt->DistLim); } else { sprintf(sapd, "_e%d", -(int)Opt->DistLim); } if (Opt->AreaLim < 0) { sapa[0]='\0'; } else { sprintf(sapa, "_a%.1f", Opt->AreaLim); } if (Opt->NodeLim < 0) { sapn[0]='\0'; } else { sprintf(sapn, "_n%d", Opt->NodeLim); } sprintf(sap, "%s%s%s", sapd, sapa, sapn); if (Opt->WriteFile) { sprintf(stmp,"_ClstTable%s.1D", sap); ClustOutName = SUMA_append_string(Opt->out_prefix, stmp); if (SUMA_filexists(ClustOutName) && !THD_ok_overwrite()) { fprintf (SUMA_STDERR, "Error %s:\n" "Output file %s exists, will not overwrite.\n", FuncName, ClustOutName); exit(1); } } Spec = SUMA_IO_args_2_spec(ps, &N_Spec); if (N_Spec == 0) { SUMA_S_Err("No surfaces found."); exit(1); } if (N_Spec != 1) { SUMA_S_Err("Multiple spec at input."); exit(1); } if (Spec->N_Surfs != 1) { SUMA_S_Err("1 and only 1 surface expected at input"); exit(1); } SUMA_LH("Loading surface..."); SO = SUMA_Load_Spec_Surf(Spec, 0, ps->sv[0], 0); if (!SO) { fprintf (SUMA_STDERR,"Error %s:\n" "Failed to find surface\n" "in spec file. \n", FuncName ); exit(1); } if (!SUMA_SurfaceMetrics(SO, "EdgeList", NULL)) { SUMA_S_Err("Failed to compute edgelist"); exit(1); } NodeArea = SUMA_CalculateNodeAreas(SO, NULL); if (!NodeArea) { SUMA_S_Err("Failed to calculate Node Areas.\n"); exit(1); } /* load the data */ iform = SUMA_NO_DSET_FORMAT; dset = SUMA_LoadDset_s (Opt->in_name, &iform, 0); if (LocalHead) SUMA_ShowDset(dset, 0, NULL); if (!dset) { SUMA_S_Err( "Failed to load dataset.\n" "Make sure file exists\n" "and is of the specified\n" "format."); exit(1); } if (!SUMA_OKassign(dset, SO)) { SUMA_SL_Err("Failed to assign data set to surface."); exit(1); } /* get the node index column */ nip = SUMA_GetNodeDef(dset); N_ni = SDSET_VECLEN(dset); if (!nip) { SUMA_S_Err("Failed to find node index column"); exit(1); } /* copy nip's contents because you will be modifying in the thresholding below */ ni = (int *)SUMA_malloc(N_ni*sizeof(int)); memcpy (ni, nip, N_ni*sizeof(int)); nv = SUMA_DsetCol2Float(dset, Opt->labelcol, 0); if (!nv) { SUMA_S_Err("Failed to find node value column"); exit(1); } /* any thresholding ? */ if (Opt->DoThreshold > SUMA_NO_THRESH) { nt = SUMA_DsetCol2Float(dset, Opt->tind, 0); if (!nt) { SUMA_S_Err("Failed to find threshold column"); exit(1); } cnt = 0; if (Opt->DoThreshold == SUMA_LESS_THAN) { if (Opt->update) fprintf( SUMA_STDERR, "%s: Thresholding at %f...\n", FuncName, Opt->ThreshR[0]); for (i=0;i<N_ni; ++i) { if (nt[i] >= Opt->ThreshR[0]) { ni[cnt] = ni[i]; nv[cnt] = nv[i]; ++cnt; } } } else if (Opt->DoThreshold == SUMA_ABS_LESS_THAN) { SUMA_LH("ABS Thresholding at %f...", Opt->ThreshR[0]); for (i=0;i<N_ni; ++i) { if (fabs(nt[i]) >= Opt->ThreshR[0]) { ni[cnt] = ni[i]; nv[cnt] = nv[i]; ++cnt; } } } else if (Opt->DoThreshold == SUMA_THRESH_INSIDE_RANGE) { SUMA_LH("Range Thresholding at %f %f...", Opt->ThreshR[0], Opt->ThreshR[1]); for (i=0;i<N_ni; ++i) { if (nt[i] >= Opt->ThreshR[0] && nt[i] <= Opt->ThreshR[1]) { ni[cnt] = ni[i]; nv[cnt] = nv[i]; ++cnt; } } } else if (Opt->DoThreshold == SUMA_THRESH_OUTSIDE_RANGE) { SUMA_LH("Ex Range Thresholding at %f %f...", Opt->ThreshR[0], Opt->ThreshR[1]); for (i=0;i<N_ni; ++i) { if (nt[i] < Opt->ThreshR[0] || nt[i] > Opt->ThreshR[1]) { ni[cnt] = ni[i]; nv[cnt] = nv[i]; ++cnt; } } } else { SUMA_S_Err("Not ready for threshold mode of %d", Opt->DoThreshold); } N_ni = cnt; } if (Opt->update) { Opt->update = -(N_ni * Opt->update / 100); /* make it negative before you begin a clustering operation */ if (LocalHead) { fprintf( SUMA_STDERR, "Update parameter, once every %d nodes\n" "%d nodes to work with.\n", -(int)Opt->update, N_ni); } } /* make the call */ list = SUMA_FindClusters (SO, ni, nv, N_ni, -1, Opt, NodeArea); if (!list) { SUMA_S_Err("Failed in SUMA_FindClusters"); exit(1); } if (list->size) { /* sort the list */ if (!SUMA_Sort_ClustersList (list, Opt->SortMode)) { SUMA_S_Err("Failed to sort cluster list"); exit(1); } } /* Show the results */ params = SUMA_HistString(FuncName, argc, argv, NULL); if (Opt->WriteFile) { if (0) { /* You can also write a NIML formatted cluster table with */ NI_element *nel=NULL; int suc; char sbuf[512]={""}; nel = SUMA_SurfClust_list_2_nel(list, 0, params, NULL); snprintf(sbuf, 510, "file:%s%s.niml.clstbl", Opt->out_prefix, sap); NEL_WRITE_TXH(nel, sbuf, suc); NI_free_element(nel); nel=NULL; } clustout = fopen(ClustOutName, "w"); if (!clustout) { fprintf (SUMA_STDERR, "Error %s:\n" "Failed to open %s for writing.\n" "Check permissions.\n", FuncName, ClustOutName); exit(1); } SUMA_Show_SurfClust_list(list, clustout, 0, params, NULL); fclose(clustout);clustout = NULL; } else SUMA_Show_SurfClust_list(list, NULL, 0, params, NULL); if (!list->size) { /* nothing left to do, quit */ exit(0); } if (Opt->OutROI) { SUMA_DSET *dset_roi = NULL; char *ROIprefix = NULL; char *NameOut = NULL; sprintf(stmp,"_ClstMsk%s", sap); ROIprefix = SUMA_append_string(Opt->out_prefix, stmp); /* Call this function, write out the resultant dset to disk then cleanup */ dset_roi = SUMA_SurfClust_list_2_DsetMask(SO, list, Opt->FullROIList, ROIprefix); if (!dset_roi) { SUMA_S_Err("NULL dset_roi"); exit(1); } if (Opt->prepend_node_index) {/* prepend node index? */ if (!SUMA_InsertDsetNelCol ( dset_roi, "Node Index Copy", SUMA_NODE_INT, (void *)(dset_roi->inel->vec[0]), NULL ,1, 0)) { SUMA_S_Err("Failed to insert column"); } if (LocalHead) SUMA_ShowDset(dset_roi,0, NULL); } NameOut = SUMA_WriteDset_s ( ROIprefix, dset_roi, Opt->oform, THD_ok_overwrite(), 0); if (!NameOut) { SUMA_SL_Err("Failed to write dataset."); exit(1); } SUMA_FreeDset((void *)dset_roi); dset_roi = NULL; if (NameOut) SUMA_free(NameOut); NameOut = NULL; if (ROIprefix) SUMA_free(ROIprefix); ROIprefix = NULL; } if (Opt->OutClustDset) { SUMA_DSET *dset_clust = NULL; char *Clustprefix = NULL; char *NameOut = NULL; sprintf(stmp,"_Clustered%s", sap); Clustprefix = SUMA_append_string(Opt->out_prefix, stmp); /* Call this function, write out the resultant dset to disk then cleanup */ dset_clust = SUMA_MaskDsetByClustList( dset, SO, list, Opt->FullROIList, Clustprefix); if (!dset_clust) { SUMA_S_Err("NULL dset_clust"); exit(1); } NameOut = SUMA_WriteDset_s ( Clustprefix, dset_clust, Opt->oform, THD_ok_overwrite(), 0); if (!NameOut) { SUMA_SL_Err("Failed to write dataset."); exit(1); } SUMA_FreeDset((void *)dset_clust); dset_clust = NULL; if (NameOut) SUMA_free(NameOut); NameOut = NULL; if (Clustprefix) SUMA_free(Clustprefix); Clustprefix = NULL; } if (ClustOutName) SUMA_free(ClustOutName); ClustOutName = NULL; if (list) dlist_destroy(list); SUMA_free(list); list = NULL; if (ni) SUMA_free(ni); ni = NULL; if (nv) SUMA_free(nv); nv = NULL; if (nt) SUMA_free(nt); nt = NULL; if (Opt->out_prefix) SUMA_free(Opt->out_prefix); Opt->out_prefix = NULL; if (Opt) SUMA_free_SurfClust_Opt(Opt); if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL; if (dset) SUMA_FreeDset((void *)dset); dset = NULL; if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) { SUMA_SL_Err("DO Cleanup Failed!"); } exit(0); }
SEXP R_THD_load_dset(SEXP Sfname, SEXP Opts) { SEXP Rdset, brik, head, names, opt, node_list=R_NilValue; int i=0, ip=0, sb, cnt=0, *iv=NULL, kparts=2; char *fname = NULL, *head_str; NI_group *ngr=NULL; NI_element *nel=NULL; char *listels[3] = {"head","brk","index_list"}; /* the brk is on purpose for backward compatibility */ double *dv=NULL; float *fv=NULL; THD_3dim_dataset *dset = NULL; int debug=0; if (!debug) debug = get_odebug(); /* get the options list, maybe */ PROTECT(Opts = AS_LIST(Opts)); if ((opt = getListElement(Opts,"debug")) != R_NilValue) { debug = (int)INTEGER_VALUE(opt); if (debug>2) set_odebug(debug); if (debug>1) INFO_message("Debug is %d\n", debug); } /* get the filename */ PROTECT(Sfname = AS_CHARACTER(Sfname)); fname = R_alloc(strlen(CHAR(STRING_ELT(Sfname,0)))+1, sizeof(char)); strcpy(fname, CHAR(STRING_ELT(Sfname,0))); /* open dset */ dset = THD_open_dataset(fname); if (dset) { if (debug > 1) INFO_message("Dset %s was loaded 2\n", fname); } else { ERROR_message("Dset %s could not be loaded\n", fname); UNPROTECT(2); return(R_NilValue); } /* form one long header string */ ngr = THD_nimlize_dsetatr(dset); PROTECT(head = allocVector(STRSXP, ngr->part_num)); for (ip=0,i=0; i<ngr->part_num; ++i) { switch( ngr->part_typ[i] ){ /*-- a sub-group ==> recursion! --*/ case NI_GROUP_TYPE: break ; case NI_ELEMENT_TYPE: nel = (NI_element *)ngr->part[i] ; head_str = NI_write_element_tostring(nel); if (debug > 1) fprintf(stderr,"%s\n", head_str); SET_STRING_ELT(head, ip, mkChar(head_str)); ++ip; free(head_str); break; default: break; } } NI_free_element(ngr); if (debug > 1) fprintf(stderr,"Forming data array of %d elements\n", DSET_NVOX(dset)*DSET_NVALS(dset)); /* form one long array of data */ PROTECT(brik = NEW_NUMERIC(DSET_NVOX(dset)*DSET_NVALS(dset))); dv = NUMERIC_POINTER(brik); EDIT_floatize_dataset(dset); for (cnt=0, sb=0; sb<DSET_NVALS(dset); ++sb) { if (!(fv = (float *)DSET_BRICK_ARRAY(dset,sb))) { ERROR_message("NULL brick array %d!\n", sb); UNPROTECT(4); return(R_NilValue); } if (debug > 1) fprintf(stderr,"Filling sb %d\n", sb); for (i=0; i<DSET_NVOX(dset); ++i) { dv[cnt++] = fv[i]; if (debug > 1) { if (debug > 2 || i<10) { fprintf(stderr,"%f\t", fv[i]); } } } if (debug == 2) fprintf(stderr,"...\n"); else if (debug > 2) fprintf(stderr,"\n"); } /* how about an index list ? */ if (dset->dblk->nnodes && dset->dblk->node_list) { if (debug > 1) fprintf(stderr,"Copying %d node indices\n", dset->dblk->nnodes); PROTECT(node_list = NEW_INTEGER(dset->dblk->nnodes)); iv = INTEGER_POINTER(node_list); memcpy(iv, dset->dblk->node_list, dset->dblk->nnodes*sizeof(int)); kparts = 3; } else { kparts = 2; if (debug > 1) fprintf(stderr,"No node indices %d %p\n", dset->dblk->nnodes, dset->dblk->node_list); } /* done with dset, dump it */ DSET_delete(dset); /* form output list */ PROTECT(names = allocVector(STRSXP,kparts)); for (i=0; i<kparts; ++i) { SET_STRING_ELT(names, i, mkChar(listels[i])); } PROTECT(Rdset = allocVector(VECSXP,kparts)); SET_VECTOR_ELT(Rdset, 0, head); SET_VECTOR_ELT(Rdset, 1, brik); if (node_list != R_NilValue) SET_VECTOR_ELT(Rdset, 2, node_list); setAttrib(Rdset, R_NamesSymbol, names); if (debug > 1) fprintf(stderr,"Unprotecting...\n"); if (kparts==3) UNPROTECT(7); else UNPROTECT(6); return(Rdset); }
THD_3dim_dataset * THD_open_nifti( char *pathname ) { THD_3dim_dataset *dset=NULL ; nifti_image *nim ; int ntt , nbuc , nvals ; int use_qform = 0 , use_sform = 0, form_code = 0 ; int statcode = 0 , datum , iview , ibr ; int scale_data = 0 ; /* flag based on scl_slope and inter 20 Jun 2008 */ int xform_data = 0; THD_ivec3 orixyz , nxyz ; THD_fvec3 dxyz , orgxyz ; THD_mat33 R ; mat44 ijk_to_dicom44 ; char *ppp , prefix[THD_MAX_PREFIX] ; char form_priority = 'S' ; /* 23 Mar 2006 */ static int n_xform_warn=0; ENTRY("THD_open_nifti") ; /*-- open input file --*/ { /* set the nifti_io debug level 8 Apr 2005 [rickr] */ char * ept = my_getenv("AFNI_NIFTI_DEBUG"); if( ept != NULL ) nifti_set_debug_level(atoi(ept)); } nifti_set_alter_cifti(1) ; /* if CIFTI, shift dims 23 Jul 2015 [rickr] */ nim = nifti_image_read( pathname, 0 ) ; if( nim == NULL || nim->nifti_type == 0 ) RETURN(NULL) ; /*-- extract some useful AFNI-ish information from the nim struct --*/ /* we must have at least 2 spatial dimensions */ /* this should be okay 11 Jun 2007 */ /* if( nim->nx < 2 || nim->ny < 2 ) RETURN(NULL) ; */ /* 4th dimension = time; 5th dimension = bucket: these are mutually exclusive in AFNI at present */ ntt = nim->nt ; nbuc = nim->nu ; /* nt and nu might be 0 now (see irritating niftilib 1.17 update) */ /* so ensure that ntt and nbuc are positive 02 Mar 2006 [rickr] */ if( ntt <= 0 ) ntt = 1; if( nbuc <= 0 ) nbuc = 1; if( nim->nz <= 0 ) nim->nz = 1 ; /* 03 Mar 2006: RWCox */ if( ntt > 1 && nbuc > 1 ){ fprintf(stderr, "** AFNI can't deal with 5 dimensional NIfTI(%s)\n", pathname ) ; RETURN(NULL) ; } nvals = MAX(ntt,nbuc) ; /* collapse higher-dimensional datasets 23 Jul 2015 [rickr] */ /* (this includes CIFTI) */ if( nim->nv > 1 ) nvals *= nim->nv; if( nim->nw > 1 ) nvals *= nim->nw; if( ntt > 1 ) ntt = nvals; else nbuc = nvals; /* determine type of dataset values: if we are scaling, or if the data type in the NIfTI file is something AFNI can't handle, then the result will be floats */ /* do not scale if slope is 0 or if slope is 1 and inter is 0 */ if( !isfinite(nim->scl_slope) || !isfinite(nim->scl_inter) ){ fprintf(stderr,"** bad scl_slope and inter = %f, %f, ignoring...\n", nim->scl_slope, nim->scl_inter); } else { scale_data = nim->scl_slope != 0.0 && (nim->scl_slope != 1.0 || nim->scl_inter != 0.0) ; } { char *eee = getenv("AFNI_NIFTI_SCALE") ; if( eee != NULL && toupper(*eee) == 'N' ) scale_data = 0 ; } switch( nim->datatype ){ default: fprintf(stderr, "** AFNI can't handle NIFTI datatype=%d (%s) in file %s\n", nim->datatype, nifti_datatype_string(nim->datatype), pathname ); RETURN(NULL) ; break ; case DT_UINT8: datum = scale_data ? MRI_float : MRI_byte ; xform_data = scale_data; break ; case DT_INT16: datum = scale_data ? MRI_float : MRI_short ; xform_data = scale_data; break ; case DT_FLOAT32: datum = MRI_float ; break ; case DT_COMPLEX64: datum = MRI_complex ; break ; case DT_RGB24: datum = MRI_rgb ; break ; case DT_INT8: /* NIfTI-1 data types that AFNI can't handle directly */ case DT_UINT16: case DT_INT32: case DT_UINT32: case DT_FLOAT64: datum = MRI_float ; xform_data = 1 ; break ; #if 0 case DT_COMPLEX128: /* this case would be too much like real work */ fprintf(stderr, "** AFNI convert NIFTI_datatype=%d (%s) in file %s to COMPLEX64\n", nim->datatype, nifti_datatype_string(nim->datatype), pathname ); datum = MRI_complex ; break ; #endif } if( xform_data && !AFNI_noenv("AFNI_NIFTI_TYPE_WARN")) { if (!n_xform_warn || AFNI_yesenv("AFNI_NIFTI_TYPE_WARN")) {/* ZSS 04/11 */ fprintf(stderr, "** AFNI converts NIFTI_datatype=%d (%s) in file %s to FLOAT32\n", nim->datatype, nifti_datatype_string(nim->datatype), pathname ); if (!AFNI_yesenv("AFNI_NIFTI_TYPE_WARN")) { fprintf(stderr, " Warnings of this type will be muted for this session.\n" " Set AFNI_NIFTI_TYPE_WARN to YES to see them all, NO to see none.\n"); } } ++n_xform_warn; } /* check for statistics code */ if( nim->intent_code >= NIFTI_FIRST_STATCODE && nim->intent_code <= NIFTI_LAST_STATCODE ){ if( nim->intent_code > FUNC_PT_TYPE ){ fprintf(stderr, "** AFNI doesn't understand NIFTI statistic type %d (%s) in file %s\n", nim->intent_code , nifti_intent_string(nim->intent_code) , pathname ) ; } else { statcode = nim->intent_code ; if( nbuc > 1 ){ fprintf(stderr, "** AFNI doesn't support NIFTI voxel-dependent statistic parameters" " in file %s\n" , pathname ) ; statcode = 0 ; } } } /* 23 Mar 2006: set qform or sform as having priority -- RWCox */ ppp = my_getenv("NIFTI_FORM_PRIORITY") ; if( ppp == NULL ) ppp = getenv("AFNI_FORM_PRIORITY") ; if( ppp == NULL ) ppp = getenv("AFNI_NIFTI_PRIORITY") ; if( ppp == NULL ) ppp = getenv("AFNI_NIFTI_FORM") ; if( ppp == NULL ) ppp = getenv("AFNI_NIFTI_FORM_PRIORITY") ; if( ppp != NULL ){ char fp = toupper(*ppp) ; if( fp == 'S' || fp == 'Q' ) form_priority = fp ; else WARNING_message("Illegal NIFTI_FORM_PRIORITY='%s'",ppp) ; } /** 24 Mar 2006: check determs of qform and sform, if have both **/ if( nim->qform_code > 0 && nim->sform_code > 0 ){ float qdet , sdet ; LOAD_MAT(R, nim->qto_xyz.m[0][0] , nim->qto_xyz.m[0][1] , nim->qto_xyz.m[0][2] , nim->qto_xyz.m[1][0] , nim->qto_xyz.m[1][1] , nim->qto_xyz.m[1][2] , nim->qto_xyz.m[2][0] , nim->qto_xyz.m[2][1] , nim->qto_xyz.m[2][2] ) ; qdet = MAT_DET(R) ; LOAD_MAT(R, nim->sto_xyz.m[0][0] , nim->sto_xyz.m[0][1] , nim->sto_xyz.m[0][2] , nim->sto_xyz.m[1][0] , nim->sto_xyz.m[1][1] , nim->sto_xyz.m[1][2] , nim->sto_xyz.m[2][0] , nim->sto_xyz.m[2][1] , nim->sto_xyz.m[2][2] ) ; sdet = MAT_DET(R) ; if( qdet*sdet < 0.0f ) WARNING_message("NIfTI('%s'): Qform/Sform handedness differ; %c wins!", pathname , form_priority ) ; } /* KRH 07/11/05 -- adding ability to choose spatial transform from the options of qform, sform, bothform, or noform. If qform is present, it will be used. If qform is absent, but sform present, then the sform will be modified to be an orthogonal rotation and used. If both qform and sform are absent, then we will have an error. Previously assumed qform present. */ /* 23 Mar 2006: use form_priority to choose between them */ if ((nim->qform_code > 0) && (nim->sform_code > 0) ) { if( form_priority == 'Q' ) { use_qform = 1 ; use_sform = 0 ; } else { use_qform = 0 ; use_sform = 1 ; } } else if (nim->qform_code > 0){ use_qform = 1 ; use_sform = 0 ; } else if (nim->sform_code > 0){ use_qform = 0 ; use_sform = 1 ; } else { use_qform = 0 ; use_sform = 0 ; WARNING_message( "NO spatial transform (neither qform nor sform), in NIfTI file '%s'" , pathname ) ; } /** now take NIfTI-1.1 coords and transform to AFNI codes **/ if (use_qform) { float orgx, orgy, orgz ; form_code = nim->qform_code; /* determine orientation from the qto_xyz matrix, which transforms (i,j,k) voxel indexes to (x,y,z) LPI coordinates */ LOAD_MAT(R, -nim->qto_xyz.m[0][0] , /* negate x and y */ -nim->qto_xyz.m[0][1] , /* coefficients, */ -nim->qto_xyz.m[0][2] , /* since AFNI works */ -nim->qto_xyz.m[1][0] , /* with RAI coords, */ -nim->qto_xyz.m[1][1] , /* but NIFTI uses */ -nim->qto_xyz.m[1][2] , /* LPI coordinates. */ nim->qto_xyz.m[2][0] , /* [Which is my own] */ nim->qto_xyz.m[2][1] , /* [damn fault!!!!!] */ nim->qto_xyz.m[2][2] ) ; LOAD_MAT44(ijk_to_dicom44, -nim->qto_xyz.m[0][0] , /* negate x and y */ -nim->qto_xyz.m[0][1] , /* coefficients, */ -nim->qto_xyz.m[0][2] , /* since AFNI works */ -nim->qto_xyz.m[0][3] , -nim->qto_xyz.m[1][0] , /* with RAI coords, */ -nim->qto_xyz.m[1][1] , /* but NIFTI uses */ -nim->qto_xyz.m[1][2] , /* LPI coordinates. */ -nim->qto_xyz.m[1][3] , nim->qto_xyz.m[2][0] , /* [Which is my own] */ nim->qto_xyz.m[2][1] , /* [damn fault!!!!!] */ nim->qto_xyz.m[2][2] , nim->qto_xyz.m[2][3] ) ; orixyz = THD_matrix_to_orientation( R ) ; /* compute orientation codes */ iview = NIFTI_code_to_view(nim->qform_code); /* load the offsets and the grid spacings */ if (ORIENT_xyz[orixyz.ijk[0]] == 'z' ) { orgx = nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[0]] - 1][3] ; } else { orgx = - nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[0]] - 1][3] ; } if (ORIENT_xyz[orixyz.ijk[1]] == 'z' ) { orgy = nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[1]] - 1][3] ; } else { orgy = - nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[1]] - 1][3] ; } if (ORIENT_xyz[orixyz.ijk[2]] == 'z' ) { orgz = nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[2]] - 1][3] ; } else { orgz = - nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[2]] - 1][3] ; } LOAD_FVEC3( orgxyz , orgx , orgy , orgz ) ; #if 0 LOAD_FVEC3( orgxyz , -nim->qto_xyz.m[0][3] , /* again, negate */ -nim->qto_xyz.m[1][3] , /* x and y coords */ nim->qto_xyz.m[2][3] ) ; #endif /* AFNI space units are always mm */ if( nim->xyz_units == NIFTI_UNITS_METER ){ nim->dx *= 1000.0 ; nim->dy *= 1000.0 ; nim->dz *= 1000.0 ; } else if( nim->xyz_units == NIFTI_UNITS_MICRON ){ nim->dx *= 0.001 ; nim->dy *= 0.001 ; nim->dz *= 0.001 ; } LOAD_FVEC3( dxyz , (ORIENT_sign[orixyz.ijk[0]]=='+') ? nim->dx : -nim->dx , (ORIENT_sign[orixyz.ijk[1]]=='+') ? nim->dy : -nim->dy , (ORIENT_sign[orixyz.ijk[2]]=='+') ? nim->dz : -nim->dz ) ; } else if (use_sform) { int orimap[7] = { 6 , 1 , 0 , 2 , 3 , 4 , 5 } ; int oritmp[3] ; float dxtmp, dytmp, dztmp ; float xmax, ymax, zmax ; float orgx, orgy, orgz ; float fig_merit, ang_merit ; form_code = nim->sform_code; /* convert sform to nifti orientation codes */ /* n2 10 Jul, 2015 [rickr] */ nifti_dmat44_to_orientation(nim->sto_xyz, &oritmp[0], &oritmp[1], &oritmp[2] ) ; /* convert nifti orientation codes to AFNI codes and store in vector */ LOAD_IVEC3( orixyz , orimap[oritmp[0]] , orimap[oritmp[1]] , orimap[oritmp[2]] ) ; /* assume original view if there's no talairach id present */ iview = NIFTI_code_to_view(nim->sform_code); /* load the offsets and the grid spacings */ if (ORIENT_xyz[orixyz.ijk[0]] == 'z' ) { orgx = nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[0]] - 1][3] ; } else { orgx = - nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[0]] - 1][3] ; } if (ORIENT_xyz[orixyz.ijk[1]] == 'z' ) { orgy = nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[1]] - 1][3] ; } else { orgy = - nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[1]] - 1][3] ; } if (ORIENT_xyz[orixyz.ijk[2]] == 'z' ) { orgz = nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[2]] - 1][3] ; } else { orgz = - nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[2]] - 1][3] ; } LOAD_FVEC3( orgxyz , orgx , orgy , orgz ) ; #if 0 LOAD_FVEC3( orgxyz , -nim->sto_xyz.m[0][3] , /* again, negate */ -nim->sto_xyz.m[1][3] , /* x and y coords */ nim->sto_xyz.m[2][3] ) ; #endif #define MAXNUM(a,b) ( (a) > (b) ? (a):(b)) #define MAX3(a,b,c) ( (MAXNUM(a,b)) > (MAXNUM(a,c)) ? (MAXNUM(a,b)):(MAXNUM(a,c))) #define MINNUM(a,b) ( (a) < (b) ? (a):(b)) #define MIN3(a,b,c) ( (MINNUM(a,b)) < (MINNUM(a,c)) ? (MINNUM(a,b)):(MINNUM(a,c))) dxtmp = sqrt ( nim->sto_xyz.m[0][0] * nim->sto_xyz.m[0][0] + nim->sto_xyz.m[1][0] * nim->sto_xyz.m[1][0] + nim->sto_xyz.m[2][0] * nim->sto_xyz.m[2][0] ) ; xmax = MAX3(fabs(nim->sto_xyz.m[0][0]),fabs(nim->sto_xyz.m[1][0]),fabs(nim->sto_xyz.m[2][0])) / dxtmp ; dytmp = sqrt ( nim->sto_xyz.m[0][1] * nim->sto_xyz.m[0][1] + nim->sto_xyz.m[1][1] * nim->sto_xyz.m[1][1] + nim->sto_xyz.m[2][1] * nim->sto_xyz.m[2][1] ) ; ymax = MAX3(fabs(nim->sto_xyz.m[0][1]),fabs(nim->sto_xyz.m[1][1]),fabs(nim->sto_xyz.m[2][1])) / dytmp ; dztmp = sqrt ( nim->sto_xyz.m[0][2] * nim->sto_xyz.m[0][2] + nim->sto_xyz.m[1][2] * nim->sto_xyz.m[1][2] + nim->sto_xyz.m[2][2] * nim->sto_xyz.m[2][2] ) ; zmax = MAX3(fabs(nim->sto_xyz.m[0][2]),fabs(nim->sto_xyz.m[1][2]),fabs(nim->sto_xyz.m[2][2])) / dztmp ; fig_merit = MIN3(xmax,ymax,zmax) ; ang_merit = acos (fig_merit) * 180.0 / 3.141592653 ; #if 0 if (fabs(ang_merit) > .01) { WARNING_message ( "qform not present in:\n" " '%s'\n" " oblique sform used, and the worst axis is\n" " %f degrees from plumb.\n" " If you are performing spatial transformations on this dset, \n" " or viewing/combining it with volumes of differing obliquity,\n" " you should consider running: \n" " 3dWarp -deoblique \n" " on this and other oblique datasets in the same session.\n" ,pathname, ang_merit ) ; } #endif if( nim->xyz_units == NIFTI_UNITS_METER ){ dxtmp *= 1000.0 ; dytmp *= 1000.0 ; dztmp *= 1000.0 ; } else if( nim->xyz_units == NIFTI_UNITS_MICRON ){ dxtmp *= 0.001 ; dytmp *= 0.001 ; dztmp *= 0.001 ; } LOAD_FVEC3( dxyz , (ORIENT_sign[orixyz.ijk[0]]=='+') ? dxtmp : -dxtmp , (ORIENT_sign[orixyz.ijk[1]]=='+') ? dytmp : -dytmp , (ORIENT_sign[orixyz.ijk[2]]=='+') ? dztmp : -dztmp ) ; LOAD_MAT44(ijk_to_dicom44, -nim->sto_xyz.m[0][0] , /* negate x and y */ -nim->sto_xyz.m[0][1] , /* coefficients, */ -nim->sto_xyz.m[0][2] , /* since AFNI works */ -nim->sto_xyz.m[0][3] , -nim->sto_xyz.m[1][0] , /* with RAI coords, */ -nim->sto_xyz.m[1][1] , /* but NIFTI uses */ -nim->sto_xyz.m[1][2] , /* LPI coordinates. */ -nim->sto_xyz.m[1][3] , nim->sto_xyz.m[2][0] , /* [Which is my own] */ nim->sto_xyz.m[2][1] , /* [damn fault!!!!!] */ nim->sto_xyz.m[2][2] , nim->sto_xyz.m[2][3] ) ; } else { /* NO SPATIAL XFORM. BAD BAD BAD BAD BAD BAD. */ float dxtmp, dytmp, dztmp ; /* if pixdim data are present, use them in order to set pixel dimensions. otherwise, set the dimensions to 1 unit. */ dxtmp = ((nim->pixdim[1] > 0) ? nim->pixdim[1] : 1) ; dytmp = ((nim->pixdim[2] > 0) ? nim->pixdim[2] : 1) ; dztmp = ((nim->pixdim[3] > 0) ? nim->pixdim[3] : 1) ; if( nim->xyz_units == NIFTI_UNITS_METER ){ dxtmp *= 1000.0 ; dytmp *= 1000.0 ; dztmp *= 1000.0 ; } else if( nim->xyz_units == NIFTI_UNITS_MICRON ){ dxtmp *= 0.001 ; dytmp *= 0.001 ; dztmp *= 0.001 ; } /* set orientation to LPI by default */ LOAD_IVEC3( orixyz , 1 , 2 , 4 ) ; LOAD_FVEC3( dxyz , (ORIENT_sign[orixyz.ijk[0]]=='+') ? dxtmp : -dxtmp , (ORIENT_sign[orixyz.ijk[1]]=='+') ? dytmp : -dytmp , (ORIENT_sign[orixyz.ijk[2]]=='+') ? dztmp : -dztmp ) ; iview = NIFTI_default_view(); /* set origin to 0,0,0 */ LOAD_FVEC3( orgxyz , 0 , 0 , 0 ) ; /* put scaled identity matrix by default */ LOAD_MAT44(ijk_to_dicom44, dxtmp, 0.0, 0.0, 0.0, 0.0, dytmp, 0.0, 0.0, 0.0, 0.0, dztmp, 0.0 ); } /*-- make an AFNI dataset! --*/ dset = EDIT_empty_copy(NULL) ; ppp = THD_trailname(pathname,0) ; /* strip directory */ MCW_strncpy( prefix , ppp , THD_MAX_PREFIX ) ; /* to make prefix */ /* You need to set the path too before, if you loaded ~/tmp/joe.nii the path appeared to be ./joe.nii, troubling in multiple instances. ZSS Dec 2011 */ THD_init_diskptr_names( dset->dblk->diskptr , THD_filepath(pathname) , NULL , prefix , dset->view_type , True ); nxyz.ijk[0] = nim->nx ; /* grid dimensions */ nxyz.ijk[1] = nim->ny ; nxyz.ijk[2] = nim->nz ; dset->idcode.str[0] = 'N' ; /* overwrite 1st 3 bytes with something special */ dset->idcode.str[1] = 'I' ; dset->idcode.str[2] = 'I' ; MCW_hash_idcode( pathname , dset ) ; /* 06 May 2005 */ EDIT_dset_items( dset , ADN_prefix , prefix , ADN_datum_all , datum , ADN_nxyz , nxyz , ADN_xyzdel , dxyz , ADN_xyzorg , orgxyz , ADN_xyzorient , orixyz , ADN_malloc_type , DATABLOCK_MEM_MALLOC , ADN_view_type , iview , ADN_type , (statcode != 0) ? HEAD_FUNC_TYPE : HEAD_ANAT_TYPE , ADN_none ) ; /* copy transformation matrix to dataset structure */ /* moved after setting grid 4 Apr 2014 [rickr,drg] */ dset->daxes->ijk_to_dicom_real = ijk_to_dicom44; /* not a time dependent dataset */ if( ntt < 2 ){ EDIT_dset_items( dset , ADN_nvals , nbuc , ADN_datum_all , datum , ADN_func_type , (statcode != 0) ? FUNC_BUCK_TYPE : ANAT_BUCK_TYPE , ADN_none ) ; } else { /* is a time dependent dataset */ if( nim->time_units == NIFTI_UNITS_MSEC ){ nim->dt *= 0.001 ; nim->toffset *= 0.001 ; } else if( nim->time_units == NIFTI_UNITS_USEC ){ nim->dt *= 1.e-6 ; nim->toffset *= 1.e-6 ; } EDIT_dset_items( dset , ADN_nvals , ntt , ADN_ntt , ntt , ADN_datum_all , datum , ADN_ttorg , nim->toffset , /* 12 Oct 2007 [rickr] */ ADN_ttdel , nim->dt , ADN_ttdur , 0.0 , ADN_tunits , UNITS_SEC_TYPE , ADN_func_type , (statcode != 0) ? FUNC_FIM_TYPE : ANAT_EPI_TYPE , ADN_none ) ; /* if present, add stuff about the slice-timing offsets */ if( nim->slice_dim == 3 && /* AFNI can only deal with */ nim->slice_code > 0 && /* slice timing offsets */ nim->slice_duration > 0.0 && /* along the k-axis of */ nim->slice_start >= 0 && /* the dataset volume */ nim->slice_start < nim->nz && nim->slice_end > nim->slice_start && nim->slice_end < nim->nz ){ float *toff=(float *)calloc(sizeof(float),nim->nz) , tsl ; int kk ; if( nim->time_units == NIFTI_UNITS_MSEC ) nim->slice_duration *= 0.001; else if( nim->time_units == NIFTI_UNITS_USEC ) nim->slice_duration *= 1.e-6; /* set up slice time offsets in the divers orders */ switch( nim->slice_code ){ case NIFTI_SLICE_SEQ_INC: tsl = 0.0 ; for( kk=nim->slice_start ; kk <= nim->slice_end ; kk++ ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } break ; case NIFTI_SLICE_SEQ_DEC: tsl = 0.0 ; for( kk=nim->slice_end ; kk >= nim->slice_end ; kk-- ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } break ; case NIFTI_SLICE_ALT_INC: tsl = 0.0 ; for( kk=nim->slice_start ; kk <= nim->slice_end ; kk+=2 ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } for( kk=nim->slice_start+1 ; kk <= nim->slice_end ; kk+=2 ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } break ; case NIFTI_SLICE_ALT_INC2: tsl = 0.0 ; for( kk=nim->slice_start+1 ; kk <= nim->slice_end ; kk+=2 ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } for( kk=nim->slice_start ; kk <= nim->slice_end ; kk+=2 ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } break ; case NIFTI_SLICE_ALT_DEC: tsl = 0.0 ; for( kk=nim->slice_end ; kk >= nim->slice_start ; kk-=2 ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } for( kk=nim->slice_end-1 ; kk >= nim->slice_start ; kk-=2 ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } break ; case NIFTI_SLICE_ALT_DEC2: tsl = 0.0 ; for( kk=nim->slice_end-1 ; kk >= nim->slice_start ; kk-=2 ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } for( kk=nim->slice_end ; kk >= nim->slice_start ; kk-=2 ){ toff[kk] = tsl ; tsl += nim->slice_duration ; } break ; } EDIT_dset_items( dset , ADN_nsl , nim->nz , ADN_zorg_sl , orgxyz.xyz[2] , ADN_dz_sl , dxyz.xyz[2] , ADN_toff_sl , toff , ADN_none ) ; free(toff) ; } /* end of slice timing stuff */ } /* end of 3D+time dataset stuff */ /* set atlas space based on NIFTI s/qform code */ NIFTI_code_to_space(form_code,dset); /* add statistics, if present */ if( statcode != 0 ){ for( ibr=0 ; ibr < nvals ; ibr++ ) EDIT_STATAUX4(dset,ibr,statcode,nim->intent_p1,nim->intent_p2,nim->intent_p3,0) ; } /*-- flag to read data from disk using NIFTI functions --*/ dset->dblk->diskptr->storage_mode = STORAGE_BY_NIFTI ; strcpy( dset->dblk->diskptr->brick_name , pathname ) ; dset->dblk->diskptr->byte_order = nim->byteorder ; #if 0 for( ibr=0 ; ibr < nvals ; ibr++ ){ /* make sub-brick labels */ sprintf(prefix,"%s[%d]",tname,ibr) ; EDIT_BRICK_LABEL( dset , ibr , prefix ) ; } #endif /** 10 May 2005: see if there is an AFNI extension; if so, load attributes from it and then edit the dataset appropriately **/ { int ee ; /* extension index */ /* scan extension list to find the first AFNI extension */ for( ee=0 ; ee < nim->num_ext ; ee++ ) if( nim->ext_list[ee].ecode == NIFTI_ECODE_AFNI && nim->ext_list[ee].esize > 32 && nim->ext_list[ee].edata != NULL ) break ; /* if found an AFNI extension ... */ if( ee < nim->num_ext ){ char *buf = nim->ext_list[ee].edata , *rhs , *cpt ; int nbuf = nim->ext_list[ee].esize - 8 ; NI_stream ns ; void *nini ; NI_group *ngr , *nngr ; /* if have data, it's long enough, and starts properly, then ... */ if( buf != NULL && nbuf > 32 && strncmp(buf,"<?xml",5)==0 ){ if( buf[nbuf-1] != '\0' ) buf[nbuf-1] = '\0' ; /* for safety */ cpt = strstr(buf,"?>") ; /* find XML prolog close */ if( cpt != NULL ){ /* if found it, then ... */ ns = NI_stream_open( "str:" , "r" ) ; NI_stream_setbuf( ns , cpt+2 ) ; /* start just after prolog */ nini = NI_read_element(ns,1) ; /* get root element */ NI_stream_close(ns) ; if( NI_element_type(nini) == NI_GROUP_TYPE ){ /* must be a group */ ngr = (NI_group *)nini ; if( strcmp(ngr->name,"AFNI_attributes") == 0 ){ /* root is OK */ nngr = ngr ; } else { /* search in group for proper element */ int nn ; void **nnini ; nn = NI_search_group_deep( ngr , "AFNI_attributes" , &nnini ) ; if( nn <= 0 ) nngr = NULL ; else { nngr = (NI_group *)nnini[0]; NI_free(nnini); } } if( NI_element_type(nngr) == NI_GROUP_TYPE ){ /* have good name */ rhs = NI_get_attribute( nngr , "self_idcode" ) ; if( rhs == NULL ) rhs = NI_get_attribute( nngr , "AFNI_idcode" ) ; if( rhs != NULL ) /* set dataset ID code from XML attribute */ MCW_strncpy( dset->idcode.str , rhs , MCW_IDSIZE ) ; rhs = NI_get_attribute( nngr , "NIfTI_nums" ) ; /* check if */ if( rhs != NULL ){ /* dataset dimensions */ char buf[128] ; /* were altered */ sprintf(buf,"%ld,%ld,%ld,%ld,%ld,%d" , /* 12 May 2005 */ nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->datatype ); if( strcmp(buf,rhs) != 0 ){ static int nnn=0 ; if(nnn==0){fprintf(stderr,"\n"); nnn=1;} fprintf(stderr, "** WARNING: NIfTI file %s dimensions altered since " "AFNI extension was added\n",pathname ) ; } } THD_dblkatr_from_niml( nngr , dset->dblk ); /* load attributes */ THD_datablock_apply_atr( dset ) ; /* apply to dataset struct */ } NI_free_element( ngr ) ; /* get rid of the root element */ } /* end of if found a group element at the root */ } /* end of if extension data array had an XML prolog close */ } /* end of if had a good extension data array */ } /* end of if had an AFNI extension */ } /* end of processing extensions */ /* return unpopulated dataset */ nifti_image_free(nim) ; RETURN(dset) ; }
int main( int argc , char *argv[] ) { char *drive_afni[128] ; int ndrive=0 , iarg=1 ; char host[1024]="localhost", nsname[2048], *geomstr, *cpt, temp[32] ; int dt=1000 , ctold,ctnew , ctzero ; int verbose=0 , kk,nn , nvox,nval , do_accum=0 ; THD_3dim_dataset *dset ; NI_element *nel ; MRI_IMAGE *fim ; float *far ; char *targname="niml_feedme" ; /*-- help the ignorant user --*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: niml_feedme [options] dataset\n" "\n" "* Sends volumes from the dataset to AFNI via the NIML socket interface.\n" "* You must run AFNI with the command 'afni -niml' so that the program\n" " will be listening for the socket connection.\n" "* Inside AFNI, the transmitted dataset will be named 'niml_feedme'.\n" "* For another way to send image data to AFNI, see progam rtfeedme.\n" "* At present, there is no way to attach statistical parameters to\n" " a transmitted volume.\n" "* This program sends all volumes in float format, simply because\n" " that's easy for me. But you can also send byte, short, and\n" " complex valued volumes.\n" "* This program is really just a demo; it has little practical use.\n" "\n" "OPTIONS:\n" " -host sname = Send data, via TCP/IP, to AFNI running on the\n" " computer system 'sname'. By default, uses the\n" " current system (localhost), if you don't use this\n" " option.\n" "\n" " -dt ms = Tries to maintain an inter-transmit interval of 'ms'\n" " milliseconds. The default is 1000 msec per volume.\n" "\n" " -verb = Be (very) talkative about actions.\n" "\n" " -accum = Send sub-bricks so that they accumulate in AFNI.\n" " The default is to create only a 1 volume dataset\n" " inside AFNI, and each sub-brick just replaces\n" " that one volume when it is received.\n" "\n" " -target nam = Change the dataset name transmitted to AFNI from\n" " 'niml_feedme' to 'nam'.\n" "\n" " -drive cmd = Send 'cmd' as a DRIVE_AFNI command.\n" " * If cmd contains blanks, it must be in 'quotes'.\n" " * Multiple -drive options may be used.\n" " * These commands will be sent to AFNI just after\n" " the first volume is transmitted.\n" " * See file README.driver for a list of commands.\n" "\n" "EXAMPLE: Send volumes from a 3D+time dataset to AFNI:\n" "\n" " niml_feedme -dt 1000 -verb -accum -target Elvis \\\n" " -drive 'OPEN_WINDOW axialimage' \\\n" " -drive 'OPEN_WINDOW axialgraph' \\\n" " -drive 'SWITCH_UNDERLAY Elvis' \\\n" " timeseries+orig\n" "\n" "Author: RW Cox -- July 2009\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } mainENTRY("niml_feedme") ; /*-- scan arguments --*/ while( iarg < argc && argv[iarg][0] == '-' ){ if( strncmp(argv[iarg],"-target",5) == 0 ){ targname = strdup(argv[++iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-drive") == 0 ){ drive_afni[ndrive++] = argv[++iarg] ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-host") == 0 ){ strcpy( host , argv[++iarg] ) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-dt") == 0 ){ dt = (int)strtod(argv[++iarg],NULL) ; if( dt < 9 ) dt = 9 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-verbose",4) == 0 ){ verbose = 1 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-accum",4) == 0 ){ do_accum = 1 ; iarg++ ; continue ; } ERROR_exit("Unrecognized option: %s",argv[iarg]) ; } if( iarg >= argc ) ERROR_exit("No dataset on command line?!") ; /*-- read in the dataset --*/ dset = THD_open_dataset( argv[iarg] ) ; if( dset == NULL ) ERROR_exit("Can't open dataset '%s'",argv[iarg]) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) ERROR_exit("Can't load dataset '%s'",argv[iarg]) ; cpt = EDIT_get_geometry_string(dset) ; geomstr = strdup(cpt) ; /* describes geometry of dataset grid */ if( verbose ) INFO_message("geometry string = '%s'",geomstr) ; nvox = DSET_NVOX(dset); /* number of voxels in dataset */ nval = DSET_NVALS(dset); /* number of sub-bricks in dataset */ /*-- this stuff is one-time-only setup of the I/O to AFNI --*/ atexit(NF_exit) ; /* call this when program ends */ signal(SIGINT ,NF_sigfunc) ; /* setup signal handler */ signal(SIGBUS ,NF_sigfunc) ; /* for fatal errors */ signal(SIGSEGV,NF_sigfunc) ; signal(SIGTERM,NF_sigfunc) ; /* name of NIML stream (socket) to open */ sprintf( nsname , "tcp:%s:%d" , host , get_port_named("AFNI_DEFAULT_LISTEN_NIML")); /* open the socket (i.e., dial the telephone call) */ fprintf(stderr,"opening NIML stream '%s' ",nsname) ; NF_stream = NI_stream_open( nsname , "w" ) ; /* loop until AFNI connects (answers the call), printing a '.' every 1/2 second to keep the user happy */ while(1){ kk = NI_stream_writecheck( NF_stream , 500 ) ; if( kk == 1 ){ fprintf(stderr," connected!\n") ; break ; } if( kk < 0 ){ fprintf(stderr," ** connection fails **\n") ; exit(1) ; } fprintf(stderr,".") ; } /*-- Create VOLUME_DATA NIML element to hold the brick data --*/ nel = NI_new_data_element( "VOLUME_DATA" , nvox ) ; /* add attributes to the element to help AFNI construct the dataset */ /* define the grid of the dataset */ NI_set_attribute( nel , "geometry_string" , geomstr ) ; /* define the name of the dataset */ NI_set_attribute( nel , "target_name" , targname ) ; /* all sub-bricks in the input dataset will be sent to be sub-brick #0 in the dataset inside AFNI -- if you don't want this behavior, and want the dataset inside AFNI to keep growing, then don't set this attribute! */ if( !do_accum ) NI_set_attribute( nel , "index" , "0" ) ; /* +tlrc view? [default in AFNI is +orig view] */ if( dset->view_type == VIEW_TALAIRACH_TYPE ) NI_set_attribute( nel , "view" , "tlrc" ) ; /**-- loop over sub-bricks and send them to AFNI --*/ ctzero = NI_clock_time() ; /* for later reference */ if( verbose ) INFO_message("Starting sub-brick loop") ; for( kk=0 ; kk < nval ; kk++ ){ ctold = NI_clock_time() ; /* clock time at start of work (ms) */ /* get a float copy of the kk-th sub-brick */ fim = THD_extract_float_brick( kk , dset ) ; DSET_unload_one(dset,kk) ; /* unload this sub-brick now */ if( fim == NULL ){ /* should never happen */ ERROR_message("Can't get sub-brick #%d?? -- skipping",kk) ; NI_sleep(dt) ; continue ; } /* copy the float data into the NIML element for transmission */ far = MRI_FLOAT_PTR(fim) ; if( kk == 0 ) /* first time: create data column in element */ NI_add_column( nel , NI_FLOAT , far ) ; else /* later times: overwrite nel data column */ memcpy( nel->vec[0] , far , sizeof(float)*nvox ) ; mri_free(fim) ; /* done with this now [data all copied to nel] */ /* set sub-brick index in AFNI if doing accumulation */ if( do_accum ){ sprintf(temp,"%d",kk) ; NI_set_attribute( nel , "index" , temp ) ; } /*** send the data element to AFNI ***/ nn = NI_write_element( NF_stream , nel , NI_BINARY_MODE ) ; /* if something bad happened in the transmission, report it */ if( nn <= 0 ){ ERROR_message("Can't write sub-brick #%d to AFNI!",kk) ; break ; } /*** first time through ==> do the '-drive' commands now by sending processing instructions ***/ if( kk == 0 && ndrive > 0 ){ int ii ; NI_procins *npi ; if( verbose ) ININFO_message("Sending %d 'drive_afni' elements now",ndrive) ; npi = NI_new_processing_instruction( "DRIVE_AFNI" ) ; NI_sleep(1) ; /* give AFNI a msec to digest the data */ for( ii=0 ; ii < ndrive ; ii++ ){ NI_set_attribute( npi , "cmd" , drive_afni[ii] ) ; (void)NI_write_element( NF_stream , npi , NI_TEXT_MODE ) ; } NI_free_element(npi) ; /* delete this struct from the world! */ } ctnew = NI_clock_time() ; /* clock time now */ if( verbose ) ININFO_message("Sent %d bytes for sub-brick #%d in %d ms", nn , kk , ctnew-ctold ) ; NI_sleep( dt - (ctnew-ctold) ) ; /* sleep so that time delay is right */ } /* end of loop over sub-bricks */ /** summarize, do some cleanup, and exit stage left **/ if( verbose && kk > 0 ){ float dtav = (NI_clock_time()-ctzero) / (float)kk ; INFO_message("Transmission finished: %.1f ms = average time per volume",dtav) ; } NI_free_element(nel) ; /* destroy the data element */ DSET_delete(dset) ; /* destroy the dataset */ exit(0) ; }