1 #include "afni.h"
2 
3 #ifndef ALLOW_PLUGINS
4 #  error "Plugins not properly set up -- see machdep.h"
5 #endif
6 
7 /***********************************************************************
8   Plugin to plot averages over ROIs.
9 ************************************************************************/
10 
11 static int                tsgraph_num=0 ;
12 static MEM_topshell_data *tsgraph_mtd=NULL ;
13 
14 static void ROIPLOT_tsgraph_draw   (void) ;
15 static void ROIPLOT_tsgraph_mtdkill( MEM_topshell_data * mp ) ;
16 
17 static char * ROIPLOT_main( PLUGIN_interface * ) ;
18 
19 static char helpstring[] =
20    " Purpose: Plot averages over ROIs.\n"
21    "\n"
22    " INPUTS\n"
23    " ------\n"
24    " Source: Defines where the data to be averaged over the ROIs comes from.\n"
25    "   Dataset = Where to get time series values from\n"
26    "   Start   = 1st sub-brick index to extract\n"
27    "   Stop    = Last sub-brick index to extract\n"
28    "\n"
29    " Two methods are available to define the ROIs from which dataset values\n"
30    " will be extracted.  Only one of these can be used at a time:\n"
31    "\n"
32    " Cluster: Clusters of contiguous voxels are extracted (as in 3dclust),\n"
33    " -------- and these are used for the ROIs.\n"
34    "   From   = Dataset to define the clusters in\n"
35    "   Index  = Sub-brick index to define the clusters in\n"
36    "   Thresh = Minimum value to accept in the sub-brick\n"
37    "   rmm   }= Clustering radius and\n"
38    "   vmul  }= minimum cluster volume\n"
39    "\n"
40    " Values: ROIs are defined by common values stored in a dataset, as\n"
41    " ------- might be generated by the 'Draw Dataset' plugin.\n"
42    "   From   = Dataset to define the ROIs\n"
43    "   Index  = Sub-brick index to define the ROIs\n"
44    "   Min   }= Range of values to\n"
45    "   Max   }= use for the ROIS\n"
46    " *** N.B.: Values selection is NOT YET IMPLEMENTED ***\n"
47    "\n"
48    " Author -- RW Cox - April 2002"
49 ;
50 
51 /***********************************************************************
52    Set up the interface to the user
53 ************************************************************************/
54 
55 
56 DEFINE_PLUGIN_PROTOTYPE
57 
PLUGIN_init(int ncall)58 PLUGIN_interface * PLUGIN_init( int ncall )
59 {
60    PLUGIN_interface * plint ;
61 
62    if( ncall > 0 ) return NULL ;  /* only one interface */
63 
64    CHECK_IF_ALLOWED("ROIPLOT","ROI Plot") ;  /* 30 Sep 2016 */
65 
66    /*-- set titles and call point --*/
67 
68    plint = PLUTO_new_interface( "ROI Plot" , "Plot Average Timeseries over ROI" ,
69                                  helpstring ,
70                                  PLUGIN_CALL_VIA_MENU , ROIPLOT_main  ) ;
71 
72    PLUTO_short_choose(plint) ;
73    PLUTO_short_number(plint) ;
74 
75    PLUTO_add_hint( plint , "Plot Average Timeseries over ROI" ) ;
76 
77    PLUTO_set_sequence( plint , "A:afniinfo:dset" ) ;
78 
79    PLUTO_set_runlabels( plint , "Plot+Keep" , "Plot+Close" ) ;  /* 04 Nov 2003 */
80 
81    /*-- first line of input --*/
82 
83    PLUTO_add_option( plint , "Source" , "Source" , TRUE ) ;
84    PLUTO_add_dataset(plint , "Timeseries" ,
85                                     ANAT_ALL_MASK , FUNC_ALL_MASK ,
86                                     DIMEN_4D_MASK | BRICK_ALLREAL_MASK ) ;
87 
88    PLUTO_add_number( plint , "Start" , 0,99999,0 , 0    ,1 ) ;
89    PLUTO_add_number( plint , "Stop"  , 0,99999,0 , 99999,1 ) ;
90 
91    /*-- second line of input --*/
92 
93    PLUTO_add_option( plint  , "Cluster" , "Cluster" , FALSE ) ;
94    PLUTO_add_dataset( plint , "From" ,
95                                     ANAT_ALL_MASK , FUNC_ALL_MASK ,
96                                     DIMEN_ALL_MASK | BRICK_ALLREAL_MASK ) ;
97    PLUTO_add_number( plint , "Index" , 0,99999,0 ,  0,1 ) ;
98    PLUTO_add_number( plint , "Thresh", 0,9999 ,1 ,  1,1 ) ;
99    PLUTO_add_number( plint , "rmm"   , 0,99   ,1 , 11,1 ) ;
100    PLUTO_add_number( plint , "vmul"  , 0,9999,-1 , 20,1 ) ;
101 
102    /*-- third line of input --*/
103 
104    PLUTO_add_option( plint  , "Values" , "Values" , FALSE ) ;
105    PLUTO_add_dataset( plint , "From" ,
106                                     ANAT_ALL_MASK , FUNC_ALL_MASK ,
107                                     DIMEN_ALL_MASK | BRICK_ALLREAL_MASK ) ;
108    PLUTO_add_number( plint , "Index" , 0,99999,0 ,  0,1 ) ;
109    PLUTO_add_number( plint , "Min"   , 0,99999,0 , 0    ,1 ) ;
110    PLUTO_add_number( plint , "Max"   , 0,99999,0 , 99999,1 ) ;
111 
112    return plint ;
113 }
114 
115 /***************************************************************************
116   Main routine for this plugin (will be called from AFNI).
117 ****************************************************************************/
118 
ROIPLOT_main(PLUGIN_interface * plint)119 static char * ROIPLOT_main( PLUGIN_interface * plint )
120 {
121    MCW_idcode *idc ;
122    THD_3dim_dataset *input_dset , *mask_dset ;
123    int iv_start,iv_stop , nvox , iv_mask ;
124    float thr,rmm,vmul    , dx,dy,dz ;
125    int val_min , val_max , nx,ny,nz , ii,jj , nt,nc ;
126    char *tag ;
127    MCW_cluster_array *clustar ;
128    MRI_IMAGE *flim ;
129    float     *flar , **yar , *xar , xcm,ycm,zcm ;
130    char      **nam_yyy ;
131    MEM_plotdata * mp ;
132 
133 #define MAX_NC 7
134 
135    /*--------------------------------------------------------------------*/
136    /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/
137 
138    if( plint == NULL )
139       return "*************************\n"
140              "ROIPLOT_main:  NULL input\n"
141              "*************************"  ;
142 
143    /*-- read 1st line --*/
144 
145    PLUTO_next_option(plint) ;
146    idc        = PLUTO_get_idcode(plint) ;
147    input_dset = PLUTO_find_dset(idc) ;
148    if( input_dset == NULL )
149       return "*********************************\n"
150              "ROIPLOT_main:  bad Source dataset\n"
151              "*********************************"  ;
152 
153    iv_start = (int) PLUTO_get_number(plint) ;
154    iv_stop  = (int) PLUTO_get_number(plint) ;
155    if( iv_stop >= DSET_NVALS(input_dset) ) iv_stop = DSET_NVALS(input_dset)-1 ;
156    if( iv_start >= iv_stop )
157       return "***********************************\n"
158              "ROIPLOT_main:  bad Start/Stop range\n"
159              "***********************************" ;
160    DSET_load(input_dset) ;
161    if( DSET_ARRAY(input_dset,iv_stop) == NULL )
162       return "****************************************\n"
163              "ROIPLOT_main:  can't load Source dataset\n"
164              "****************************************"  ;
165 
166    nx   = input_dset->daxes->nxx ; dx = fabs(input_dset->daxes->xxdel) ;
167    ny   = input_dset->daxes->nyy ; dy = fabs(input_dset->daxes->yydel) ;
168    nz   = input_dset->daxes->nzz ; dz = fabs(input_dset->daxes->zzdel) ;
169    nvox = nx*ny*nz ;
170 
171    /*-- read next lines --*/
172 
173    tag = PLUTO_get_optiontag(plint) ;
174    if( tag == NULL )
175       return "***********************************"
176              "ROIPLOT_main: no ROI selection made\n"
177              "***********************************"   ;
178 
179    /*--------------------------------------*/
180 
181    if( strcmp(tag,"Cluster") == 0 ){
182      float *vfim ;
183      MCW_cluster_array *clbig ;
184      MCW_cluster *cl ;
185      int ptmin ;
186 
187      idc       = PLUTO_get_idcode(plint) ;
188      mask_dset = PLUTO_find_dset(idc) ;
189      if( mask_dset == NULL )
190        return "**********************************\n"
191               "ROIPLOT_main:  bad Cluster dataset\n"
192               "**********************************"  ;
193      if( DSET_NVOX(mask_dset) != nvox )
194        return "******************************************************\n"
195               "ROIPLOT_main:  Source and Cluster datasets don't match\n"
196               "******************************************************"  ;
197      iv_mask = (int) PLUTO_get_number(plint) ;
198      if( iv_mask >= DSET_NVALS(mask_dset) )
199        return "********************************\n"
200               "ROIPLOT_main:  bad Cluster index\n"
201               "*********************************"  ;
202      DSET_load(mask_dset) ;
203      if( DSET_ARRAY(mask_dset,iv_mask) == NULL )
204         return "*****************************************\n"
205                "ROIPLOT_main:  can't load Cluster dataset\n"
206                "*****************************************\n" ;
207 
208      thr  = PLUTO_get_number(plint) ;
209      rmm  = PLUTO_get_number(plint) ;
210      vmul = PLUTO_get_number(plint) ;
211 
212      vfim = (float *) malloc(sizeof(float)*nx*ny*nz) ;
213      EDIT_coerce_scale_type( nvox ,
214                              DSET_BRICK_FACTOR(mask_dset,iv_mask) ,
215                              DSET_BRICK_TYPE(mask_dset,iv_mask) ,
216                              DSET_ARRAY(mask_dset,iv_mask) ,
217                              MRI_float , vfim ) ;
218      if( thr > 0.0 ){
219        for( ii=0 ; ii < nvox ; ii++ )
220          if( fabs(vfim[ii]) < thr ) vfim[ii] = 0.0 ;
221      }
222 
223      clustar = MCW_find_clusters( nx,ny,nz , dx,dy,dz ,
224                                   MRI_float , vfim , rmm ) ;
225      free(vfim) ;
226 
227      if( clustar == NULL )
228         return "********************************\n"
229                "ROIPLOT_main:  no Clusters found\n"
230                "********************************\n" ;
231 
232      /* edit for volume */
233 
234      ptmin = (int) (vmul / (dx*dy*dz) + 0.99) ;
235      INIT_CLARR(clbig) ;
236      for( ii=0 ; ii < clustar->num_clu ; ii++ ){
237        cl = clustar->clar[ii] ;
238        if( cl != NULL && cl->num_pt >= ptmin ){ /* big enough */
239           ADDTO_CLARR(clbig,cl) ;               /* copy pointer */
240           clustar->clar[ii] = NULL ;            /* null out original */
241        }
242      }
243      DESTROY_CLARR(clustar) ;
244      clustar = clbig ;
245      if( clustar == NULL || clustar->num_clu == 0 ){
246        printf("** NO CLUSTERS FOUND ***\n") ;
247        if( clustar != NULL ) DESTROY_CLARR(clustar) ;
248        return "********************************\n"
249               "ROIPLOT_main:  no Clusters found\n"
250               "********************************\n" ;
251      }
252      SORT_CLARR(clustar) ;
253 
254    /*--------------------------------------*/
255 
256    } else if( strcmp(tag,"Values") == 0 ){
257      idc       = PLUTO_get_idcode(plint) ;
258      mask_dset = PLUTO_find_dset(idc) ;
259      if( mask_dset == NULL )
260        return "*********************************\n"
261               "ROIPLOT_main:  bad Values dataset\n"
262               "*********************************"  ;
263      if( DSET_NVOX(mask_dset) != nvox )
264        return "*****************************************************\n"
265               "ROIPLOT_main:  Source and Values datasets don't match\n"
266               "*****************************************************"  ;
267      iv_mask = (int) PLUTO_get_number(plint) ;
268      if( iv_mask >= DSET_NVALS(mask_dset) )
269        return "*******************************\n"
270               "ROIPLOT_main:  bad Values index\n"
271               "********************************"  ;
272      DSET_load(mask_dset) ;
273      if( DSET_ARRAY(mask_dset,iv_mask) == NULL )
274         return "****************************************\n"
275                "ROIPLOT_main:  can't load Values dataset\n"
276                "****************************************\n" ;
277 
278      val_min = (int) PLUTO_get_number(plint) ;
279      val_max = (int) PLUTO_get_number(plint) ;
280      if( val_max < val_min ) val_max = val_min ;
281 
282      /* must build cluster here */
283 
284      return "****************************************\n"
285             "ROIPLOT_main:  Values NOT IMPLEMENT YET!\n"
286             "****************************************\n" ;
287 
288    } else {
289      return "*******************************\n"
290             "ROIPLOT_main: no ROI selection?\n"
291             "********************************"  ;
292    }
293 
294    /* check for too many options */
295 
296    tag = PLUTO_get_optiontag(plint) ;
297    if( tag != NULL )
298       PLUTO_popup_transient(plint,"\n"
299                                   "+++++++ WARNING ++++++++\n"
300                                   " Using Cluster option;\n"
301                                   " Ignoring Values option\n"  ) ;
302 
303    /* extract average time series */
304 
305    flim = THD_average_timeseries( clustar , input_dset ) ;
306 
307    if( flim == NULL ){
308      DESTROY_CLARR(clustar) ;
309      return "***********************************************\n"
310             "ROIPLOT_main:  Can't extract average timeseries\n"
311             "***********************************************\n" ;
312    }
313 
314    nc   = flim->ny ; if( nc > MAX_NC ) nc = MAX_NC ;
315    nt   = flim->nx ;
316    flar = MRI_FLOAT_PTR(flim) ;
317    yar  = (float **) malloc(sizeof(float *)*nc) ;
318    for( ii=0 ; ii < nc ; ii++ ) yar[ii] = flar + (ii*nt+iv_start) ;
319    xar  = (float *) malloc(sizeof(float)*nt) ;
320    for( ii=0 ; ii < nt ; ii++ ) xar[ii] = ii ;
321    nam_yyy = (char **) malloc(sizeof(char *)*nc) ;
322    for( ii=0 ; ii < nc ; ii++ ){
323       xcm = ycm = zcm = 0.0 ;
324       for( jj=0 ; jj < clustar->clar[ii]->num_pt ; jj++ ){
325         xcm += clustar->clar[ii]->i[ii] ;
326         ycm += clustar->clar[ii]->j[ii] ;
327         zcm += clustar->clar[ii]->k[ii] ;
328       }
329       xcm /= clustar->clar[ii]->num_pt ;
330       ycm /= clustar->clar[ii]->num_pt ;
331       zcm /= clustar->clar[ii]->num_pt ;
332       nam_yyy[ii] = malloc(256) ;
333       sprintf(nam_yyy[ii],"%d voxels\n"
334                           "_{ijk: %d %d %d}" ,
335               clustar->clar[ii]->num_pt ,
336               (int)(xcm+0.499) , (int)(ycm+0.499) , (int)(zcm+0.499) ) ;
337    }
338    DESTROY_CLARR(clustar);
339 
340    mp = plot_ts_mem( iv_stop-iv_start+1 , xar+iv_start ,
341                      nc,TSP_SEPARATE_YBOX,yar ,
342                      NULL,NULL,NULL,nam_yyy ) ;
343 
344    for( ii=0 ; ii < nc ; ii++ ) free(nam_yyy[ii]) ;
345    free(nam_yyy);
346    free(xar); free(yar); mri_free(flim);
347 
348    if( mp == NULL )
349      return "******************************************\n"
350             "ROIPLOT_main:  Can't create in-memory plot\n"
351             "******************************************\n" ;
352 
353    memplot_to_topshell( plint->im3d->dc->display , mp , NULL ) ;
354 
355    return NULL ;
356 }
357 
358 /*------------------------------------------------------------------*/
359 
360 /*------------------------------------------------------------------*/
361