1 /*plug_permtest.c - AFNI plugin that applies a permutation test to a 3D+time
2   dataset to create a fizt dataset.
3   Copyright (c) 2000 - 2005 Matthew Belmonte
4 
5   This program is free software; you can redistribute it and/or
6   modify it under the terms of the GNU General Public License
7   as published by the Free Software Foundation; either version 2
8   of the License, or (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19   If you find this program useful, please send mail to Matthew Belmonte
20   <belmonte@mit.edu>.
21 */
22 
23 #define NUM_ITERS 10000
24 #define NUM_COORDS 2
25 
26 #define BLAST 33333.0
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <math.h>
32 #include <string.h>
33 #include "afni.h"
34 
35 /*a macro that wraps THD_pval_to_stat() (which in turn evaluates to a call to
36   the one-tailed probability-to-z-score function normal_p2t()) so that it
37   behaves like Gary Perlman's two-tailed zcrit() function in Netlib*/
38 #define critz(p) \
39    (((p) >= 0.5)? THD_pval_to_stat(2.0*(1.0-(p)), FUNC_ZT_TYPE, (float *)0) \
40 		: -THD_pval_to_stat(2.0*(p), FUNC_ZT_TYPE, (float *)0))
41 
42 static char help[] =
43   "This plugin implements a permutation test, a nonparametric statistical\n"
44   "method that avoids the pitfall of over-correcting for multiple comparisons\n"
45   "since it implicitly takes into account spatial correlations in the data.\n"
46   "If you use this software, please take a moment to send mail to the author,\n"
47   "belmonte@mit.edu, and cite the following paper in your report:\n\n"
48 
49   "Matthew K Belmonte and Deborah A Yurgelun-Todd, `Permutation Testing Made\n"
50   "Practical for Functional Magnetic Resonance Image Analysis',\n"
51   "IEEE Transactions on Medical Imaging 20(3):243-248 (March 2001).\n\n"
52 
53 "USAGE\n\n"
54 
55   "`Input' is the echo-planar dataset for which the permutation test is to be\n"
56   "computed.\n\n"
57 
58   "`Ideal' is the ideal time series against which the echo-planar data are to\n"
59   "be correlated.\n\n"
60 
61   "`Ort', an optional parameter, is a time series to which the echo-planar\n"
62   "data are to be orthogonalised.  This feature is useful when one wants to\n"
63   "analyse responses to two superposed conditions independently.  (Note that\n"
64   "the data are always detrended, i.e. orthogonalised to a linear series --\n"
65   "this optional orthogonalisation is in addition to the detrending step.)\n\n"
66 
67   "`Output' is the output dataset.  The activation data saved in this dataset\n"
68   "consist of a sub-brick of regression coefficients and a sub-brick of\n"
69   "probability values.  As AFNI provides no standard format for storing\n"
70   "probabilities, these are mapped to z-scores and the entire dataset is\n"
71   "saved as a FIZT dataset.\n\n"
72 
73   "`alpha level' is the tail probability at which to stop marking voxels as\n"
74   "activated.  (Note that the slider in the `Define Overlay' panel will\n"
75   "have no effect below this value.)  You should avoid setting this value\n"
76   "very high, lest the Phase 3 algorithm run out of substitute points in too\n"
77   "many cases (for an explanation of substitutes, see the article cited above).\n\n"
78 
79   "`AR order', an optional parameter, is the order (i.e. the number of\n"
80   "samples of look-back) of the autoregressive model used to remove noise\n"
81   "colouring from the fMRI time series before permuting it, and to restore\n"
82   "this colouring after permutation.  At field strengths (B0) of 3 Tesla or\n"
83   "more, or repetition times (TR) of 2 seconds or less, autocorrelation can\n"
84   "be non-negligible and you therefore should select this option.  In most\n"
85   "cases an autoregressive order of 1 should suffice, though you may want to\n"
86   "try going up to 3.  You can experiment with greater orders by examining\n"
87   "the automatically generated files DSET_autocorrelation.1D and\n"
88   "DSET_autoregression.1D, where DSET is the name of the 3D+time dataset to\n"
89   "which you've just applied the permutation test; if the Nth autocorrelation\n"
90   "coefficient is near zero then you can safely restrict the autoregressive\n"
91   "model to order N-1.  (In extreme cases the program will detect this\n"
92   "condition and decrease the model order automatically.)\n"
93 	"\tAutoregressive modelling was suggested early on as a method of\n"
94   "correcting for coloured noise as a preparatory step to permutation testing\n"
95   "of fMRI time series [1].  Although methods based around permuting in a\n"
96   "wavelet domain leave residuals that are more temporally independent in\n"
97   "comparison to those left by autoregressive methods [2], it's uclear how\n"
98   "much of this residual temporal dependence arises from coloured noise\n"
99   "versus how much may reflect the presence of (subthreshold) signal.\n"
100   "Recently it's been shown that wavelet methods, like Fourier methods, may\n"
101   "tend to underestimate thresholds for statistical significance (and\n"
102   "therefore risk producing false positive results) when the permuted series\n"
103   "include frequency-localised BOLD signal as well as noise [3] -- a\n"
104   "condition that applies especially in block designs.  For these reasons as\n"
105   "as well as for simplicity of implementation, I've chosen to implement here\n"
106   "autoregressive rather than wavelet whitening.\n"
107   "[1] JJ Locascio, PJ Jennings, CI Moore, S Corkin, `Time Series Analysis in\n"
108   "    the Time Domain and Resampling Methods for Studies of Functional\n"
109   "    Magnetic Resonance Brain Imaging', Human Brain Mapping 5(3):168-193\n"
110   "    (1997).\n"
111   "[2] ET Bullmore, C Long, J Suckling, J Fadili, G Calvert, F Zelaya,\n"
112   "    TA Carpenter, MJ Brammer, `Colored Noise and Computational Inference\n"
113   "    in Neurophysiological (fMRI) Time Series Analysis: Resampling Methods\n"
114   "    in Time and Wavelet Domains', Human Brain Mapping 12(2):61-78\n"
115   "    (February 2001).\n"
116   "[3] O Friman, C-F Westin, `Resampling fMRI Time Series', NeuroImage\n"
117   "    25(3):859-867 (15 April 2005).\n\n"
118 
119   "`AR exclude', an optional parameter which has effect only when `AR order'\n"
120   "has been specified, is a vector of flags in which non-zero values specify\n"
121   "that the corresponding elements of the fMRI time series are to be excluded\n"
122   "from the autocorrelation computation.  If this parameter is not specified,\n"
123   "all time points are included.  Normally you won't need to specify this\n"
124   "parameter, although it may be useful in some block designs in which the\n"
125   "noise structure depends on the experimental condition.\n\n"
126 
127   "`two-tailed', `one-tailed positive', and `one-tailed negative' select the\n"
128   "tail(s) of interest.  Exactly one of these options must be selected.\n\n"
129 
130   "`Mask', an optional parameter, is a FIM dataset whose three spatial\n"
131   "dimensions match those of the echo-planar dataset.  Only those\n"
132   "coordinates whose mask values are between 1 and the largest positive\n"
133   "short integer are included in the permutation test.  These inclusion\n"
134   "limits can be overridden using the optional `least mask value' and\n"
135   "`greatest mask value' parameters.  Mask datasets can be generated\n"
136   "automatically using the Threshold plugin (q.v.), or using 3dAutomask.\n\n"
137 
138 "AUTHOR\n\n"
139 
140   "This plugin was written by Matthew Belmonte <belmonte@mit.edu> of the\n"
141   "MIT Student Information Processing Board, supported by a grant from the\n"
142   "National Alliance for Autism Research.\n\n"
143 
144 "REVISION HISTORY\n\n"
145 
146   "2.0  7 November 2005   added autoregressive correction for coloured noise\n"
147   "1.3  20 January 2005   added support for 3dAutomask and other byte-valued masks\n"
148   "1.2  19 December 2002  fixed a dtree bug that caused a rare crash in phase 3\n"
149   "1.1  14 June 2001      cosmetic changes only\n"
150   "1.0  4 January 2001    initial release\n\n"
151 
152 "SEE ALSO\n\n"
153 
154   "Threshold Plugin  or  3dAutomask program\n"
155   "Draw Dataset Plugin\n"
156   "(These normally are applied before the permutation test.)",
157 
158 	    hint[] = "compute FIM with permutation test",
159 	    input_label[] = "Input",
160 	    ts_label[] = "Ideal",
161 	    ort_label[] = "Ort",
162 	    output_label[] = "Output",
163 	    alpha_label[] = "alpha level (0,1]",
164 	    AR_order_label[] = "AR order",
165 	    AR_excl_label[] = "AR exclude",
166 	    tails2[] = "two-tailed",
167 	    tails1pos[] = "one-tailed positive",
168 	    tails1neg[] = "one-tailed negative",
169 	    mask_label[] = "Mask",
170 	    masklo_label[] = "least mask value",
171 	    maskhi_label[] = "greatest mask value";
172 
173 /*data structures for trees*/
174 
175 /*singly-indexed tree: ordered on correlations*/
176 typedef struct _snode {
177 	double corr;			/*correlation (key)*/
178 	int coords;			/*coordinates: x+xdim*(y+ydim*z) */
179 	struct _snode *left, *right;	/*children*/
180 	} SNODE;
181 
182 typedef struct {
183 	SNODE *mem,			/*base address of tree node storage*/
184 	      *next,			/*next free tree storage address*/
185 	      *root;			/*==tree_mem if tree is non-null*/
186 	int xdim, ydim;			/*maximum coordinate values*/
187 	} STREE;
188 
189 #define stree_null(t) ((t)->root == (SNODE *)0)
190 
191 typedef struct {			/*pairs (r, (x,y,z))*/
192 	double corr;
193 	int coords;
194 	} CLIST;
195 
196 /*doubly-indexed tree: ordered on correlations and on coordinates*/
197 typedef struct _dnode {
198 	CLIST *data;			/*correlations and coordinates*/
199 	int dlen;			/*# of valid entries in data[]*/
200 	int size;			/*size of this correlation subtree*/
201 	struct _dnode *corr_lchild,	/*children in correlation tree*/
202 		      *corr_rchild,
203 		      *corr_parent,	/*parent in correlation tree*/
204 		      *coord_lchild,	/*children in coordinate tree*/
205 		      *coord_rchild;
206 	} DNODE;
207 
208 typedef struct {
209 	DNODE *mem,			/*base address of tree node storage*/
210 	      *next,			/*next free tree storage address*/
211 	      *corr_root, *coord_root;	/*==mem if tree is non-null*/
212 	int xdim, ydim;			/*maximum coordinate values*/
213 	} DTREE;
214 
215 #define dtree_size(t) (((t)->corr_root == (DNODE *)0)? 0: ((t)->corr_root->size))
216 
217 /*encoding and decoding functions for mapping a triple to a single integer*/
218 #define coord_encode(x, y, z, xdim, ydim) ((x) + (xdim)*((y) + (ydim)*(z)))
219 
coord_decode(int coords,int * x,int * y,int * z,int xdim,int ydim)220 static void coord_decode(int coords, int *x, int *y, int *z, int xdim, int ydim)
221   {
222   *x = coords % xdim;
223   coords /= xdim;
224   *y = coords % ydim;
225   *z = coords / ydim;
226   }
227 
228 #define sign(x) (((x)<0)? -1: 1)
229 
230 #ifdef PERMTEST_DEBUG
231 
232 /*flush output buffers on SIGUSR1 - useful for batch debugging*/
233 #include <signal.h>
flush(int sig)234 static void flush(int sig)
235   {
236   fflush(stdout);
237   fflush(stderr);
238   signal(SIGUSR1, flush);
239   }
240 
241 /*slave routine to stree_traverse()*/
rcsv_stree_traverse(SNODE * t,int indent)242 void rcsv_stree_traverse(SNODE *t, int indent)
243   {
244   register int i;
245   while(t)
246     {
247     for(i = 0; i != indent; i++)
248       putchar(' ');
249     indent += 2;
250     printf("%lx: corr=%f coords=%d left=%lx right=%lx\n", (long)t, t->corr, t->coords, (long)(t->left), (long)(t->right));
251     rcsv_stree_traverse(t->left, indent);
252     t = t->right;
253     }
254   }
255 
256 /*Print a traversal of the given stree.*/
stree_traverse(STREE * t)257 void stree_traverse(STREE *t)
258   {
259   printf("t=%lx\n  mem=%lx  next=%lx = mem+%ld  root=%lx xdim=%d ydim=%d\n",
260 	(long)t,
261 	(long)(t->mem),
262 	(long)(t->next),
263 	(((long)(t->next))-(long)(t->mem))/sizeof(SNODE),
264 	(long)(t->root),
265 	t->xdim, t->ydim);
266   rcsv_stree_traverse(t->root, 0);
267   putchar('\n');
268   }
269 
270 /*slave routine to dtree_traverse()*/
rcsv_dtree_traverse(DNODE * t,int indent,int order)271 void rcsv_dtree_traverse(DNODE *t, int indent, int order)
272   {
273   register int i;
274   while(t)
275     {
276     for(i = 0; i != indent; i++)
277       putchar(' ');
278     indent += 2;
279     printf("%lx: data=", (long)t);
280     for(i = 0; i != t->dlen; i++)
281       printf("%f %d ", t->data[i].corr, t->data[i].coords);
282     printf("size=%d corr_lchild=%lx corr_rchild=%lx corr_parent=%lx coord_lchild=%lx coord_rchild=%lx\n", t->size, (long)(t->corr_lchild), (long)(t->corr_rchild), (long)(t->corr_parent), (long)(t->coord_lchild), (long)(t->coord_rchild));
283     if(order)
284       {
285       rcsv_dtree_traverse(t->coord_lchild, indent, order);
286       t = t->coord_rchild;
287       }
288     else
289       {
290       rcsv_dtree_traverse(t->corr_lchild, indent);
291       t = t->corr_rchild;
292       }
293     }
294   }
295 
296 /*Print a traversal of a dtree.  Use corr links if order=0, coord links if
297   order=1.*/
dtree_traverse(DTREE * t,int order)298 void dtree_traverse(DTREE *t, int order)
299   {
300   printf("t=%lx\n  mem=%lx  next=%lx = mem+%ld  coord_root=%lx corr_root=%lx xdim=%d ydim=%d\n",
301 	(long)t,
302 	(long)(t->mem),
303 	(long)(t->next),
304 	(((long)(t->next))-(long)(t->mem))/sizeof(DNODE),
305 	(long)(t->coord_root),
306 	(long)(t->corr_root),
307 	t->xdim, t->ydim);
308   rcsv_dtree_traverse((order? t->coord_root: t->corr_root), 0, order);
309   putchar('\n');
310   }
311 
312 /*slave routine to dtree_check_sizes()*/
rcsv_dtree_check_sizes(DNODE * t)313 int rcsv_dtree_check_sizes(DNODE *t)
314   {
315   int s;
316   if(t)
317     {
318     s = 1+rcsv_dtree_check_sizes(t->corr_lchild)+rcsv_dtree_check_sizes(t->corr_rchild);
319     if(s != t->size)
320       {
321       printf("%lx->size = %d should be %d\n", (long)t, t->size, s);
322       fflush(stdout);
323       }
324     return(t->size);
325     }
326   return 0;
327   }
328 
329 /*Check that the size fields of a dtree are consistent with each other and with
330   the structure of the tree.*/
dtree_check_sizes(DTREE * t)331 int dtree_check_sizes(DTREE *t)
332   {
333   return(rcsv_dtree_check_sizes(t->corr_root));
334   }
335 
336 /*slave routine to dtree_circtest()*/
rcsv_dtree_circtest(DNODE * t,DNODE * mem,char * mark,int n,int order)337 void rcsv_dtree_circtest(DNODE *t, DNODE *mem, char *mark, int n, int order)
338   {
339   register int m;
340   while(t)
341     {
342     m = (int)((((long)t)-(long)mem)/(((long)(mem+1))-((long)mem)));
343     if((m >= n) || (m < 0))
344       printf("out-of-bounds reference %lx (mem+%d)\n", (long)t, m);
345     else if(mark[m])
346       printf("duplicate reference %lx (mem+%d)\n", (long)t, m);
347     else
348       {
349       mark[m] = 1;
350       if(order)
351 	{
352 	rcsv_dtree_circtest(t->coord_lchild, mem, mark, n, order);
353 	t = t->coord_rchild;
354 	}
355       else
356 	{
357 	rcsv_dtree_circtest(t->corr_lchild, mem, mark, n, order);
358 	t = t->corr_rchild;
359 	}
360       }
361     }
362   }
363 
364 /*Test the given dtree for circular or out-of-bounds references.  Use corr links
365   if order=0, coord links if order=1.*/
dtree_circtest(DTREE * t,int order)366 void dtree_circtest(DTREE *t, int order)
367   {
368   char *mark;
369   int n;
370   n = (int)((((long)(t->next))-(long)(t->mem))/(((long)(t->mem+1))-((long)(t->mem))));
371   mark = calloc(n, 1);
372   if(mark)
373     {
374     rcsv_dtree_circtest((order? t->coord_root: t->corr_root), t->mem, mark, n, order);
375     free(mark);
376     }
377   else
378     fprintf(stderr, "dtree_circtest: couldn't calloc mark\n");
379   }
380 
381 /*slave routine to dtree_check_parent_pointers()*/
rcsv_dtree_check_parent_pointers(DNODE * t)382 int rcsv_dtree_check_parent_pointers(DNODE *t)
383   {
384   int bad;
385   bad = 0;
386   while(t != (DNODE *)0)
387     {
388     if(t->corr_lchild)
389       {
390       if(t->corr_lchild->corr_parent != t)
391 	{
392 	printf("%lx->corr_lchild = %lx, but %lx->corr_parent = %lx\n",
393 	  (long)t, (long)(t->corr_lchild), (long)(t->corr_lchild),
394 	  (long)(t->corr_lchild->corr_parent));
395 	bad = 1;
396 	}
397       if(rcsv_dtree_check_parent_pointers(t->corr_lchild)) bad = 1;
398       }
399     if((t->corr_rchild) && (t->corr_rchild->corr_parent != t))
400       {
401       printf("%lx->corr_rchild = %lx, but %lx->corr_parent = %lx\n",
402 	(long)t, (long)(t->corr_rchild), (long)(t->corr_rchild),
403 	(long)(t->corr_rchild->corr_parent));
404       bad = 1;
405       }
406     t = t->corr_rchild;
407     }
408   return bad;
409   }
410 
411 /*Verify that the corr_parent fields inside t are consistent with the
412   corr_lchild and corr_rchild fields.*/
dtree_check_parent_pointers(DTREE * t)413 int dtree_check_parent_pointers(DTREE *t)
414   {
415   return(rcsv_dtree_check_parent_pointers(t->corr_root));
416   }
417 
418 /*Print hex dump of an IEEE double-precision floating-point number, MSB first.*/
fdump(double * x)419 void fdump(double *x)
420   {
421   double test = 2.0;
422   int i;
423   register char *c;
424   c = (char *)x;
425   if(*(char *)&test)
426     for(i = 7; i >= 0; i--)
427       printf("%02x", c[i]&0xff);
428   else
429     for(i = 0; i != 8; i++)
430       printf("%02x", c[i]&0xff);
431   }
432 
433 #endif
434 
435 /*Which metric is used for comparison of correlation values depends on which
436   tail(s) of the distribution interest us.  For the two-tailed case, our
437   `maximum' should be the most extreme value from either tail, so we use the
438   absolute value function fabs() from libm.  For the negative one-tailed case,
439   our `maximum' should be the most negative value, so we use the negation
440   function neg().  For the positive one-tailed case, our maximum should be the
441   most positive value, so we use the identity function id().*/
442 
id(double r)443 static double id(double r)
444   {
445   return(r);
446   }
447 
neg(double r)448 static double neg(double r)
449   {
450   return(-r);
451   }
452 
453 static double (*magnitude)(double);
454 
455 /*Allocate storage and initialise a tree that can contain up to nelem nodes.*/
stree_create(int xdim,int ydim,int nelem)456 static STREE *stree_create(int xdim, int ydim, int nelem)
457   {
458   STREE *t;
459   t = (STREE *)malloc(sizeof(*t));
460   if(t == (STREE *)0)
461     return((STREE *)0);
462   t->mem = (SNODE *)calloc(nelem, sizeof(*(t->mem)));
463   if(t->mem == (SNODE *)0)
464     {
465     free(t);
466     return((STREE *)0);
467     }
468   t->next = t->mem;
469   t->root = (SNODE *)0;
470   t->xdim = xdim;
471   t->ydim = ydim;
472   return(t);
473   }
474 
475 /*Deallocate a tree.*/
stree_destroy(STREE * t)476 static void stree_destroy(STREE *t)
477   {
478   free(t->mem);
479   free(t);
480   }
481 
482 /*Insert the given value into the tree.*/
stree_insert(STREE * t,double r,int x,int y,int z)483 static void stree_insert(STREE *t, double r, int x, int y, int z)
484   {
485   register SNODE **p;
486   double rmag;
487   p = &(t->root);
488   rmag = (*magnitude)(r);
489 /*inv: The path from t->root to p is labelled with values whose magnitudes
490   bound or equal that of r.*/
491   while(*p != (SNODE *)0)
492     p = (rmag < (*magnitude)((*p)->corr))? &((*p)->left): &((*p)->right);
493   t->next->corr = r;
494   t->next->coords = coord_encode(x, y, z, t->xdim, t->ydim);
495   t->next->left = (SNODE *)0;
496   t->next->right = (SNODE *)0;
497   *p = t->next++;
498   }
499 
500 /*Delete the maximum correlation value from the given tree, and return that
501   value and its associated coordinates.*/
stree_extract_max(STREE * t,int * x,int * y,int * z)502 static double stree_extract_max(STREE *t, int *x, int *y, int *z)
503   {
504   register SNODE **p, **pp;
505   SNODE *target;
506   if(t->root == (SNODE *)0)
507     {
508     fprintf(stderr, "Error: STREE underflow\n- this happens when every voxel in the brain has been identified as activated\n");
509     return(0.0);
510     }
511   if((t->root->left == (SNODE *)0) && (t->root->right == (SNODE *)0))
512     {
513     target = t->root;
514     t->root = (SNODE *)0;
515     t->next = t->mem;
516     }
517   else
518     {
519     p = &(t->root);
520   /*inv: **pp and **p are successive links in a chain of right children
521     beginning at t->root.*/
522     do
523       {
524       pp = p;
525       p = &((*p)->right);
526       } while((*p) != (SNODE *)0);
527     target = *pp;
528     *pp = (*pp)->left;
529     }
530   coord_decode(target->coords, x, y, z, t->xdim, t->ydim);
531   return(target->corr);
532   }
533 
534 /*Allocate storage and initialise a dtree that can contain up to nelem nodes.*/
dtree_create(int xdim,int ydim,int nelem)535 static DTREE *dtree_create(int xdim, int ydim, int nelem)
536   {
537   DTREE *t;
538   t = (DTREE *)malloc(sizeof(*t));
539   if(t == (DTREE *)0)
540     return((DTREE *)0);
541   t->mem = (DNODE *)calloc(nelem, sizeof(*(t->mem)));
542   if(t->mem == (DNODE *)0)
543     {
544     free(t);
545     return((DTREE *)0);
546     }
547   t->next = t->mem;
548   t->corr_root = (DNODE *)0;
549   t->coord_root = (DNODE *)0;
550   t->xdim = xdim;
551   t->ydim = ydim;
552   return(t);
553   }
554 
555 /*Deallocate a dtree.*/
dtree_destroy(DTREE * t)556 static void dtree_destroy(DTREE *t)
557   {
558   free(t->mem);
559   free(t);
560   }
561 
562 /*Insert the given value into the dtree, using the given storage location.*/
dtree_insert_at_node(DTREE * t,DNODE * node)563 static void dtree_insert_at_node(DTREE *t, DNODE *node)
564   {
565   register DNODE **p,			/*pointer into the coord tree*/
566 		 *q, *qparent;		/*pointers to adjacent corr tree nodes*/
567   p = &(t->coord_root);
568 /*inv: The path from t->coord_root to *p is labelled with values that bound or
569   equal node->data->coords.*/
570   while(*p != (DNODE *)0)
571     p = ((node->data->coords > (*p)->data->coords)? &((*p)->coord_rchild): &((*p)->coord_lchild));
572 /*link the node into the coord tree*/
573   node->coord_lchild = (DNODE *)0;
574   node->coord_rchild = (DNODE *)0;
575   *p = node;
576 /*link the node into the corr tree*/
577   node->size = 1;
578   node->corr_lchild = (DNODE *)0;
579   node->corr_rchild = (DNODE *)0;
580   if(t->corr_root == (DNODE *)0)
581     {
582   /*insertion into an empty tree is a special case*/
583     node->corr_parent = (DNODE *)0;
584     t->corr_root = node;
585     }
586   else
587     {
588     q = t->corr_root;
589   /*inv: The path from t->corr_root to q is labelled with values that bound or
590     equal r.*/
591     do
592       {
593       q->size++;
594       qparent = q;
595       q = ((node->data->corr > q->data->corr)? q->corr_rchild: q->corr_lchild);
596       } while(q != (DNODE *)0);
597   /*link the node into the correlation tree*/
598     node->corr_parent = qparent;
599     if(node->data->corr > qparent->data->corr)
600       qparent->corr_rchild = node;
601     else
602       qparent->corr_lchild = node;
603     }
604   }
605 
606 static int num_coords;
607 
608 /*Insert the given value into the dtree.*/
dtree_insert(DTREE * t,CLIST * clist)609 static void dtree_insert(DTREE *t, CLIST *clist)
610   {
611   t->next->data = clist;
612   t->next->dlen = num_coords;
613   dtree_insert_at_node(t, t->next++);
614   }
615 
616 static int num_coords_exhausted;
617 
618 /*p points to a coord_lchild, coord_rchild, or coord_root field that is to be
619   unlinked from its coord children and its corr children and corr parent within
620   the tree t.*/
dtree_unlink_node(DTREE * t,DNODE ** p)621 void dtree_unlink_node(DTREE *t, DNODE **p)
622   {
623   register DNODE **q;
624   DNODE *node, *parent, *temp;
625   node = *p;
626   if(node->coord_lchild == (DNODE *)0)
627     *p = node->coord_rchild;
628   else if(node->coord_rchild == (DNODE *)0)
629     *p = node->coord_lchild;
630   else
631     {
632   /*inv: *q is the rightmost node at the current level in the left subtree of
633     (*p).*/
634     for(q = &(node->coord_lchild); (*q)->coord_rchild != (DNODE *)0; q = &((*q)->coord_rchild))
635       ;
636     (*q)->coord_rchild = node->coord_rchild;
637     *p = *q;
638     if(q != &(node->coord_lchild))
639       {
640       DNODE *temp;
641       temp = (*q)->coord_lchild;
642       (*q)->coord_lchild = node->coord_lchild;
643       *q = temp;
644       }
645     }
646 /*The node has been unlinked from the coord tree.  Now unlink it from the corr
647   tree, using a procedure analogous to that which was implemented above for the
648   coord tree.  First, decrement the size counts from the current position back
649   to the corr root:*/
650   for(parent = node->corr_parent; parent != (DNODE *)0; parent = parent->corr_parent)
651     parent->size--;
652 /*Make p point to the link that leads into the subtree rooted at node.*/
653   p = ((node->corr_parent == (DNODE *)0)? &(t->corr_root):
654 	(node == node->corr_parent->corr_lchild)?
655 		&(node->corr_parent->corr_lchild):
656 		&(node->corr_parent->corr_rchild));
657 /*The cases of fewer than two children are easy to handle:*/
658   if(node->corr_lchild == (DNODE *)0)
659     {
660     if(node->corr_rchild)
661       node->corr_rchild->corr_parent = node->corr_parent;
662     *p = node->corr_rchild;
663     }
664   else if(node->corr_rchild == (DNODE *)0)
665     {
666     if(node->corr_lchild)
667       node->corr_lchild->corr_parent = node->corr_parent;
668     *p = node->corr_lchild;
669     }
670 /*In the two-child case, we find the rightmost node of the left subtree and
671   promote it.*/
672   else
673     {
674   /*inv: *q is the rightmost node at the current level in the left subtree of
675     (*p).*/
676     for(q = &(node->corr_lchild); (*q)->corr_rchild != (DNODE *)0; q = &((*q)->corr_rchild))
677       (*q)->size--;
678     (*q)->corr_rchild = node->corr_rchild;
679     if(node->corr_rchild)
680       node->corr_rchild->corr_parent = *q;
681     *p = *q;
682     parent = (*q)->corr_parent;
683     (*q)->corr_parent = node->corr_parent;
684     if(q != &(node->corr_lchild))
685       {
686   /*If the left subtree of the rightmost node is non-null, promote it to fill
687     the place that has just been vacated by the promoted rightmost node.*/
688       temp = (*q)->corr_lchild;
689       (*q)->corr_lchild = node->corr_lchild;
690       node->corr_lchild->corr_parent = *q;
691       *q = temp;
692       if(temp)
693 	temp->corr_parent = parent;
694       }
695     (*p)->size = 1
696 	+ ((*p)->corr_lchild? (*p)->corr_lchild->size: 0)
697 	+ ((*p)->corr_rchild? (*p)->corr_rchild->size: 0);
698     }
699   }
700 
701 /*Delete from the dtree all nodes that are labelled with the given coordinates.
702   For each of the deleted nodes, if any substitute coordinates remain in the
703   coordinate list, use those substitute coordinates to re-insert the node into
704   the dtree.  Otherwise increment num_coords_exhausted.*/
dtree_delete_coords(DTREE * t,int x,int y,int z,short * deleted)705 static void dtree_delete_coords(DTREE *t, int x, int y, int z, short *deleted)
706 /*deleted[x+xdim*(y+ydim*z)] is nonzero iff (x,y,z) has not yet been deleted*/
707   {
708   register DNODE **p,			/*pointer into coord tree*/
709 		 *del;			/*pointer to deleted node*/
710   int target_coords_not_found,		/*flag indicates coords not yet found*/
711       coords;				/*encoded form of target coordinates*/
712   coords = coord_encode(x, y, z, t->xdim, t->ydim);
713   p = &(t->coord_root);
714   target_coords_not_found = 1;
715 /*inv: All remaining nodes whose coordinates match the target coords are in the
716   subtree rooted at *p.  All matching nodes outside this subtree have been
717   replaced by nodes with substitute coordinates and correlations.*/
718   while(target_coords_not_found && (*p != (DNODE *)0))
719     {
720     if(coords > (*p)->data->coords)
721       p = &((*p)->coord_rchild);
722     else if(coords < (*p)->data->coords)
723       p = &((*p)->coord_lchild);
724     else
725       {
726     /*found a matching node*/
727       target_coords_not_found = 0;
728       do
729 	{
730 	del = *p;
731 	dtree_unlink_node(t, p); /*note: *p != del after this call!*/
732       /*re-insert the node with substitute data, if any substitutes remain*/
733 	do {del->dlen--; del->data++;
734       /*check that substitutes haven't been exhausted (dlen != 0) and the
735 	coordinates associated with the substitute at the head of the list are
736 	still not valid (deleted[del->data->coords] != 0)*/
737 	   } while((del->dlen != 0) && deleted[del->data->coords]);
738       /*If valid substitute data are available, re-insert this node using those
739 	substitutes.  Otherwise, increment the count of occurrences of failed
740 	substitutions.*/
741 	if(del->dlen != 0)
742 	  dtree_insert_at_node(t, del);
743 	else
744 	  num_coords_exhausted++;
745 	} while(*p && (coords == (*p)->data->coords));
746 /*By clearing the flag target_coords_not_found on entry to the inner loop, we
747   ensure that the outer loop will terminate once the inner loop's guard has
748   become false.  The correctness of this strategy depends on the structure of
749   the auxiliary routine dtree_unlink_node() and on the following line in
750   dtree_insert_at_node() above:
751     p = ((node->data->coords > (*p)->data->coords)? &((*p)->coord_rchild):
752 						    &((*p)->coord_lchild));
753   This line makes sets of equal coordinates into *left*-recursive rather than
754   right-recursive trees, and accordingly, dtree_unlink_node() looks in the
755   *left* subtree for a node to promote into the place of the deleted node as
756   (*p).*/
757       }
758     }
759   }
760 
761 /*Return a fraction in the interval (0,1) that describes the ordinal position
762   that the given correlation value would occupy within the ordered contents of
763   the dtree, were it to be added to the tree.*/
dtree_position(DTREE * t,double r)764 static double dtree_position(DTREE *t, double r)
765   {
766   register DNODE *p;
767   register int rank;
768   p = t->corr_root;
769   if((p == (DNODE *)0) || (p->size == 1))
770     return(0.5);
771   rank = 0;
772 /*inv: rank/2 is the number of correlation values in the tree that are less
773   than r and are not within the subtree rooted at p, plus half of the number
774   of correlation values in the tree that equal r and are not within the subtree
775   rooted at p.*/
776   while(p != (DNODE *)0)
777     if(r > p->data->corr)
778       {
779       rank += 2*(1+(p->corr_lchild? p->corr_lchild->size: 0));
780       p = p->corr_rchild;
781       }
782     else
783       {
784       if(r == p->data->corr)
785 	rank++; /*values equal to the target count only half*/
786       p = p->corr_lchild;
787       }
788   if(rank == 2*t->corr_root->size)
789     rank--;
790   else if(rank == 0)
791     rank++;
792   return(rank / (2.0*t->corr_root->size));
793   }
794 
795 /*Randomly permute the integer array a[0..n-1].
796   Richard Durstenfeld, `Algorithm 235: Random Permutation [G6]',
797   Communications of the Association for Computing Machinery 7:7:420 (1964).*/
shuffle(int * a,int n)798 static void shuffle(int *a, int n)
799   {
800   register int i, j, b;
801   for(i = n-1; i != 0; i--)
802     {
803     j = (int)(random()%(i+1));
804     b = a[i]; a[i] = a[j]; a[j] = b;
805     }
806   }
807 
808 /*Prepare static sums for correlate().*/
correlate_prep(float * x,float * y,int nxy,double * sy,double * syy)809 static void correlate_prep(float *x, float *y, int nxy, double *sy, double *syy)
810   {
811   register int n;	/*length of time series, excluding ignored points*/
812   *sy = *syy = 0.0;
813   n = 0;
814   while(nxy--)
815     {
816     if(*x < BLAST)
817       {
818       *syy += *y**y;
819       *sy += *y;
820       n++;
821       }
822     x++; y++;
823     }
824   *syy -= *sy**sy/n;
825   }
826 
827 /*Correlate the ideal time series x with the actual time series y, where both
828   series are of length nxy.  If the pointers r, m, and b are non-null, they
829   receive, respectively, the correlation coefficient and the slope and
830   intercept of the regression line.  A call to correlate() must be preceded by
831   calls to correlate_prep() of the following forms:
832   correlate_prep(x, y, nxy, &sx, &sxx);
833   correlate_prep(x, y, nxy, &sy, &syy);*/
correlate(float * x,float * y,int nxy,double sx,double sxx,double sy,double syy,double * r,double * m,double * b)834 static void correlate(
835 	float *x,	/*ideal time series (points >= BLAST are ignored)*/
836 	float *y,	/*actual time series*/
837 	int nxy,	/*length of time series (including any ignored points)*/
838 	double sx,	/*sum of x[i] | 0<=i<nxy and x[i]<BLAST*/
839 	double sxx,	/*sum of x[i]^2 | 0<=i<nxy and x[i]<BLAST*/
840 	double sy,	/*sum of y[i] | 0<=i<nxy and x[i]<BLAST*/
841 	double syy,	/*sum of y[i]^2 | 0<=i<nxy and x[i]<BLAST*/
842 	double *r,	/*correlation coefficient*/
843 	double *m,	/*slope*/
844 	double *b)	/*intercept*/
845   {
846   register double sxy;
847   register int n;	/*length of time series, excluding ignored points*/
848   double slope;
849   if(sxx == 0.0)
850     {
851     if(r) *r = 0.0;
852     if(m) *m = 0.0;
853     if(b)
854       {
855       n = 0;
856       while(nxy--)
857 	if(x[nxy] < BLAST)
858 	  n++;
859       *b = sy/n;
860       }
861     }
862   else
863     {
864     sxy = 0.0;
865     n = 0;
866     while(nxy--)
867       {
868       if(*x < BLAST)
869 	{
870 	sxy += *x**y;
871 	n++;
872 	}
873       x++; y++;
874       }
875     sxy -= sx*sy/n;
876     if(r)
877       *r = ((syy == 0.0)? 0.0: (sxy/sqrt(sxx*syy)));
878     slope = sxy/sxx;
879     if(m) *m = slope;
880     if(b) *b = (sy - slope*sx)/n;
881     }
882   }
883 
884 /*Orthogonalise y to x, where m and b have been set by a call to correlate().
885   Store the result in new_y (which may point to the same location as y, in the
886   case in which the original value of y need not be saved).  For linear
887   detrending, input x[i] = i, 0<=i<n.*/
orthogonalise(float * x,float * y,float * new_y,int n,double m,double b)888 static void orthogonalise(float *x, float *y, float *new_y, int n, double m, double b)
889   {
890   while(n--)
891     if(x[n] < BLAST)
892       new_y[n] = y[n]-(m*x[n]+b);
893   }
894 
895 /*Initialise the numerator sums (*cov)[0..order-1], the denominator sum *var,
896   the number of included time points *n_incl, and optionally the exclusion
897   vector excl[order..n-1], for an AR(order) autocorrelation computation.  If
898   the pointer excl_0 is non-null then excl_0[0..n-1] is a time series whose
899   elements are non-zero iff the corresponding element of the fMRI time series
900   is to be excluded from the autocorrelation computation.  (For example, in the
901   context of a block design it may be desirable to exclude expected intervals of
902   activation, and to include only expected baseline intervals.)  Compute
903   excl[order..n-1] such that excl_0[t] ==> excl[max(t, order) .. min(t+order,
904   n-1)]  for all i in [0, n-1], that is, the exclusion of a time point also
905   excludes the following 'order' time points.  (This requirement ensures that
906   looking back at lagging points yields valid data.)  ((*excl)-order) and *cov
907   are dynamically allocated; the calling routine is responsible for invoking
908   autocorrelate_finish() after the last call to autocorrelate_compute() to free
909   ((*excl)-order), and for freeing *cov itself once the correlations are no
910   longer needed.  Return 0 if successful, 1 if out of memory.*/
911 /*          K&R to ANSI from Greg Balls   7 Aug 2006 [rickr] */
autocorrelate_init(float * excl_0,int n,int order,char ** excl,double ** cov,double * var,int * n_incl)912 static int autocorrelate_init(float *excl_0, int n, int order, char **excl,
913                               double **cov, double *var, int *n_incl)
914   {
915   register int t, k;
916   *cov = (double *)calloc(order, sizeof(**cov));
917   if(*cov == (double *)0)
918     return(1);
919 /*no need to zero (*cov)[0..order-1], since calloc() has already done so*/
920   *var = 0.0;
921   *n_incl = n-order;
922   if(excl_0 != (float *)0)
923     {
924     *excl = calloc(n, sizeof(**excl));
925     if(*excl == (char *)0)
926       {
927       free(*cov);
928       return(1);
929       }
930   /*no need to initialise (*excl)[] to 0, since calloc() has already done so*/
931   /*compute (*excl)[] at its lower boundary*/
932     for(t = 0; t != order; t++)
933       if(excl_0[t] != 0.0)
934 	{
935 	for(k = order-t; k <= order; k++)
936 	  (*excl)[t+k] = 1;
937 	*n_incl -= t+1;
938 	}
939   /*compute (*excl)[] between its boundaries*/
940     while(t < n-order)
941       {
942       if(excl_0[t] != 0.0)
943 	{
944 	for(k = 0; k <= order; k++)
945 	  (*excl)[t+k] = 1;
946 	*n_incl -= order+1;
947 	}
948       t++;
949       }
950   /*compute (*excl)[] at its upper boundary*/
951     while(t < n)
952       {
953       if(excl_0[t] != 0.0)
954 	{
955 	for(k = 0; k < n-t; k++)
956 	  (*excl)[t+k] = 1;
957 	*n_incl -= n-t;
958 	}
959       t++;
960       }
961     }
962   else
963     *excl = (char *)0;
964   return(0);
965   }
966 
967 /*Given ts[0..n-1], a voxel's detrended fMRI time series, and optionally
968   excl[0..n-1], a vector of flags computed by autocorrelate_init() that signify
969   exclusion from the autocorrelation computation, accumulate data from this
970   voxel's time series into the numerator sums cov[0..order-1] and the
971   denominator sum var for computing autocorrelation coefficients in an AR(order)
972   model.*/
973 /*          K&R to ANSI from Greg Balls   7 Aug 2006 [rickr] */
autocorrelate_sum(float * ts,int n,int n_incl,int order,char * excl,double * cov,double * var)974 static void autocorrelate_sum(
975     float  *ts,	    /* detrended fMRI time series from one voxel */
976     int     n,	    /* length of ts[] */
977     int     n_incl, /* number of 0's in excl[0..n-1],  */
978                     /*     else n-order if no excl[] */
979     int     order,  /* AR order - i.e., number of lags modelled in r[]*/
980     char   *excl,   /* excl[i]=0 <==> include ts[i] in autocorrelation */
981                     /*     computation*/
982     double *cov,/*cov[k-1] accumulates Sigma[(ts[i]-ts_avg)*(ts[i-k]-ts_avg)],*/
983                 /*		       !excl[i] & !excl[i-k], order<=i<n*/
984     double *var	/**  var accumulates Sigma[(ts[i]-ts_avg)^2],		*/
985 		/*  		     !excl[i] & !excl[i-k], order<=i<n	*/
986 )
987   {
988   register int t,	/*time index*/
989 	k;		/*AR lag index*/
990   double avg,		/*average of ts[] over all included time points*/
991 	excursion;	/*current sample's excursion from the mean*/
992   avg = 0.0;
993   if(excl == (char *)0)
994     {
995   /*if no exclusion vector has been provided, then all points are included*/
996     for(t = order; t < n; t++)
997       avg += ts[t];
998     avg /= n_incl;
999     for(t = order; t < n; t++)
1000       {
1001       excursion = ts[t]-avg;
1002       for(k = order; k; k--)
1003 	cov[k-1] += excursion*(ts[t-k]-avg);
1004       *var += excursion*excursion;
1005       }
1006     }
1007   else
1008     {
1009   /*exclude the points specified by the exclusion vector*/
1010     for(t = order; t < n; t++)
1011       if(!excl[t])
1012 	avg += ts[t];
1013     avg /= n_incl;
1014     for(t = order; t < n; t++)
1015       if(!excl[t])
1016 	{
1017 	excursion = ts[t]-avg;
1018 	for(k = order; k; k--)
1019 	  cov[k-1] += excursion*(ts[t-k]-avg);
1020 	*var += excursion*excursion;
1021 	}
1022     }
1023   }
1024 
1025 /*Finish the autocorrelation computation by dividing the numerator sums
1026   cov[0..order-1] by the denominator sum var, and leaving the resulting
1027   autocorrelations in cov[0..order-1].  Check for autocorrelations that are
1028   impossible (|r| > 1, possible in the event of some weird accumulation of
1029   rounding errors), or physiologically implausible (|r| = 1 or r < 0).  If such
1030   values are found, eliminate them from the model by decreasing the model's
1031   order (*order).  Also, deallocate the storage used for excl[order..n-1].*/
autocorrelate_finish(int * order,char * excl,double * cov,double var)1032 static void autocorrelate_finish(int *order, char *excl, double *cov,
1033                                  double var)
1034 /* int *order; char *excl; double *cov, var; */
1035   {
1036   register int k;
1037   if(excl != (char *)0)
1038     free(excl);			/*exclusion vector is no longer needed*/
1039   k = *order;
1040   while(k--)
1041     {
1042     cov[k] /= var;
1043     if((cov[k] >= 1.0) || (cov[k] < 0.0))
1044       {
1045       fprintf(stderr, "Suspect AR(%d) autocorrelation %f; restricting model to AR(%d)\n", k+1, cov[k], k);
1046 #ifdef AR_DEBUG
1047       fprintf(stderr, "\tDEBUG MODE: OVERRIDING THIS RESTRICTION\n");
1048 #else
1049       *order = k;
1050 #endif
1051       }
1052     }
1053   }
1054 
1055 /*Solve the system of equations represented by the augmented matrix
1056   m[0..n-1][0..n] (in row-major order), using simple Gaussian elimination.
1057   (n is assumed to be small enough so that LU decomposition wouldn't yield any
1058   substantial increase in speed.)  If m is singular, 1 is returned.  If m is
1059   non-singular, 0 is returned and the solutions are left in m[0..n-1][n].*/
1060 /*          K&R to ANSI from Greg Balls   7 Aug 2006 [rickr] */
solve(double ** m,int n)1061 static int solve(double **m, int n)
1062 /* double **m; int n; */
1063   {
1064   register int i, j, k;
1065   int singular;
1066   double *tmprow;
1067   singular = 0;
1068 /*inv: m is a linear combination of the original m, and
1069        for all i where 0<=i<j, (m[ii]=1 and m[i][i+1..n-1]=0)*/
1070   for(j = 0; (!singular) && (j != n); j++)
1071     {
1072   /*inv: m[j..i-1][j]=0*/
1073     for(i = j; (i != n) && (m[i][j] == 0.0); i++)
1074       ;
1075     if(i == n)
1076       singular = 1;
1077     else
1078       {
1079     /*m[i][j] is the topmost nonzero element in column j - if row i isn't
1080       already the top row, make it the top row by exchanging rows:*/
1081       if(i != j)
1082 	{
1083 	tmprow = m[i];
1084 	m[i] = m[j];
1085 	m[j] = tmprow;
1086 	}
1087     /*m[j][j] is nonzero; multiply row j by 1/m[j][j] to make m[j][j]=1*/
1088       for(i = n; i != j; i--)
1089 	m[j][i] /= m[j][j];
1090       m[j][j] = 1.0;
1091     /*subtract scalar multiples of row j from rows j+1..n-1 so as to make
1092       the lower column m[j+1..n-1][j]=0*/
1093     /*inv: m is a linear combination of the original m, and m[j+1..i-1][j]=0*/
1094       for(i = j+1; i != n; i++)
1095 	{
1096 	for(k = n; k != j; k--)
1097 	  m[i][k] -= m[i][j]*m[j][k];
1098 	m[i][j]= 0.0;
1099 	}
1100       }
1101     }
1102   if(!singular)
1103     {
1104   /*inv: m is a linear combination of the original m with rows j+1..n-1 solved*/
1105     for(j = n-1; j; j--)
1106     /*inv: m is a linear combination of the original m and m[0..i-1][j]=0*/
1107       for(i = 0; i != j; i++)
1108 	{
1109 	m[i][n] -= m[i][j]*m[j][n];
1110 	m[i][j] = 0.0;
1111 	}
1112     }
1113   return(singular);
1114   }
1115 
1116 /*On entry, r[0..order-1] are the autocorrelation coefficients for lags
1117   1..order.  On successful exit, 0 is returned and r[0..order-1] are the
1118   autoregression coefficients for lags 1..order - i.e., they implement the
1119   AR(order) model ts[t] = r[0]*ts[t-1] + r[1]*ts[t-2] + ...
1120   + r[order-1]*ts[t-order] + e(t).  If a singular matrix is encountered,
1121   or if a memory allocation error arises, r[] is zeroed and 1 is returned.*/
1122 /*          K&R to ANSI from Greg Balls   7 Aug 2006 [rickr] */
yule_walker(double * r,int order)1123 static int yule_walker(
1124     double *r, /* r[0..order-1] are the autocorrelations for lags 1..order */
1125     int order )
1126   {
1127   register int i, k;
1128   int retval;
1129   double **m;	/*the Yule-Walker matrix*/
1130 /*allocate storage for all rows m[0..order-1]*/
1131   m = (double **)calloc(order, sizeof(*m));
1132   if(m == (double **)0)
1133     retval = 1;
1134   else
1135     {
1136   /*set up row pointers*/
1137     *m = (double *)calloc(order*(order+1), sizeof(**m));
1138     if(*m == (double *)0)
1139       {
1140       free(m);
1141       retval = 1;
1142       }
1143     else
1144       {
1145       for(i = 1; i != order; i++)
1146 	m[i] = m[i-1]+order+1;		/*1 extra column for augmented matrix*/
1147       for(i = 0; i != order; i++)
1148         {
1149         for(k = i-1; k >= 0; k--)
1150 	  m[i][k] = r[i-k-1];		/*m[i][i-1..0] = r[0..i-1]*/
1151         m[i][i] = 1.0;			/*diagonal is 1*/
1152         for(k = i+1; k != order; k++)
1153 	  m[i][k] = r[k-i-1];		/*m[i][i+1..order-1] = r[0..order-2-i]*/
1154         m[i][k] = r[i];			/*rightmost column is r[0..order-1]*/
1155         }
1156 
1157 #ifdef AR_DEBUG
1158 {int i, j; printf("\nYULE-WALKER MATRIX:\n");
1159 for(i=0; i!=order; i++){
1160   for(j=0; j!=1+order; j++) printf("%f ", m[i][j]);
1161   putchar('\n');}}
1162 #endif
1163 
1164       retval = solve(m, order);
1165 
1166 #ifdef AR_DEBUG
1167 {int i, j; printf("YULE-WALKER SOLUTION:\n");
1168 for(i=0; i!=order; i++){
1169   for(j=0; j!=1+order; j++) printf("%f ", m[i][j]);
1170   putchar('\n');}}
1171 #endif
1172 
1173       if(retval == 0)
1174     /*read out autoregression coefficients*/
1175         for(i = 0; i != order; i++)
1176 	  r[i] = m[i][order];
1177       free(*m);
1178       free(m);
1179       }
1180     }
1181 /*if there was a singularity or a memory error, zero r[]*/
1182   if(retval)
1183     for(i = 0; i != order; i++)
1184       r[i] = 0.0;
1185   return(retval);
1186   }
1187 
1188 /*Apply the AR(order) autoregression coefficients reg[0..order-1] to whiten the
1189   coloured time series coloured[0..n-1].  Place the result in white[0..n-1].
1190   coloured[] and white[] must be distinct storage.*/
1191 /*          K&R to ANSI from Greg Balls   7 Aug 2006 [rickr] */
whiten(const float * coloured,float * white,int n,double * reg,int order)1192 static void whiten(
1193     const float *coloured,	/*coloured[0..n-1] (source)*/
1194     float *white,		/*white[0..n-1] (destination)*/
1195     int n,
1196     double *reg,		/*reg[0..order-1] (AR(order) regression coeff.*/
1197     int order)
1198   {
1199   register int t, k;
1200   *white = *coloured;
1201   for(t = 1; t < order; t++)
1202     {
1203     white[t] = coloured[t];
1204     for(k = 0; k != order; k++)
1205       white[t] -= reg[k]*coloured[(t-k<=0)? 0: (t-k-1)];
1206     }
1207   while(t < n)
1208     {
1209     white[t] = coloured[t];
1210     for(k = 0; k != order; k++)
1211       white[t] -= reg[k]*coloured[t-k-1];
1212     t++;
1213     }
1214   }
1215 
1216 /*Apply the AR(order) autoregression coefficients reg[0..order-1] to colour
1217   the white time series white[0..n-1].  Place the result in coloured[0..n-1].
1218   coloured[] and white[] must be distinct storage.*/
colour(float * coloured,const float * white,int n,double * reg,int order)1219 static void colour(
1220     float *coloured,	/*coloured[0..n-1] (source)*/
1221     const float *white,	/*white[0..n-1] (destination)*/
1222     int n,
1223     double *reg,	/*reg[0..order-1] (AR(order) regression coeff.*/
1224     int order)
1225   {
1226   register int t, k;
1227   *coloured = *white;
1228   for(t = 1; t < order; t++)
1229     {
1230     coloured[t] = white[t];
1231     for(k = 0; k != order; k++)
1232       coloured[t] += reg[k]*coloured[(t-k<=0)? 0: (t-k-1)];
1233     }
1234   while(t < n)
1235     {
1236     coloured[t] = white[t];
1237     for(k = 0; k != order; k++)
1238       coloured[t] += reg[k]*coloured[t-k-1];
1239     t++;
1240     }
1241   }
1242 
1243 /*Write vec[0..len-1] to the ASCII file whose name is filename_prefix
1244   concatenated with filename_suffix concatenated with ".1D".*/
write_1D_file(const double * vec,int len,const char * filename_prefix,const char * filename_suffix)1245 static int write_1D_file(
1246     const double *vec,
1247     int len,
1248     const char *filename_prefix,
1249     const char *filename_suffix)
1250   {
1251   register int i, j;
1252   FILE *fp;
1253   char filename[1+MAXPATHLEN];
1254   for(i = 0; filename_prefix[i] != '\0'; i++)
1255     filename[i] = filename_prefix[i];
1256   for(j = 0; filename_suffix[j] != '\0'; j++)
1257     filename[i++] = filename_suffix[j];
1258   filename[i++] = '.';
1259   filename[i++] = '1';
1260   filename[i++] = 'D';
1261   filename[i++] = '\0';
1262   fp = fopen(filename, "w");
1263   if(fp == NULL)
1264     {
1265     perror(filename);
1266     return(1);
1267     }
1268   while(len--)
1269     fprintf(fp, "%f\n", *(vec++));
1270   fclose(fp);
1271   return(0);
1272   }
1273 
1274 #ifdef AR_DEBUG
1275 
1276 /*test driver: writes a coloured time series to "permtest_autoregr_series.dat",
1277   writes this time series' autocorrelation coefficients to "_autocorrelation"
1278   and its autoregression coefficients to "_autoregression", then writes the
1279   corresponding whitened time series to "permtest_autoregr_whitened.dat" and
1280   the recoloured time series to "permtest_autoregr_recoloured.dat" and prints
1281   the autocorrelation coefficients of this recoloured time series.*/
AR_test()1282 void AR_test()
1283   {
1284   FILE *tsfile;
1285   const int tslen = 200;
1286   int i, j, k;
1287   float ts[tslen],	/*original, coloured time series*/
1288 	white[tslen],	/*whitened time series*/
1289 	excl_0[tslen];	/*time points to be excluded from the computation*/
1290   char *excl;		/*excl_0[] with time lags of length 'order'*/
1291   double *r,		/*covariances, autocorrelations, autoregressions*/
1292 	var,		/*variance*/
1293 	e0, e1, e2, e3;	/*additive coloured noise terms*/
1294   int order,		/*autoregressive order*/
1295 	n_incl;		/*# of included (i.e. non-excluded) points*/
1296   order = 3;
1297   tsfile = fopen("permtest_autoregr_series.dat", "w");
1298   if(tsfile == NULL) exit(1);
1299   e1 = e2 = e3 = 0.0;
1300   for(i = 0; i != tslen; i++)
1301     {
1302   /*10% + 20% + 30% = 60% coloured noise plus 40% white noise:*/
1303     e0 = 0.1*e3 + 0.2*e2 + 0.3*e1 + 0.4*((random()/(double)RAND_MAX)-0.5);
1304     ts[i] = e0		/*	+sin((2.0*3.14159*i)/(tslen-order))	*/ ;
1305     e3 = e2; e2 = e1; e1 = e0;
1306     fprintf(tsfile, "%f\n", ts[i]);
1307     }
1308   fclose(tsfile);
1309   j = order*order;
1310   k = 0;
1311 /*alternating included and excluded blocks of 9 samples each:*/
1312   for(i = 0; i != tslen; i++, j--)
1313     {
1314     if(j == 0)
1315       {
1316       j = order*order;
1317       k = !k;
1318       }
1319     excl_0[i] = k;
1320     }
1321   if(autocorrelate_init((float *)0, tslen, order, &excl, &r, &var, &n_incl))
1322     {
1323     fprintf(stderr, "autocorrelate_init: out of memory\n");
1324     return(1);
1325     }
1326   autocorrelate_sum(ts, tslen, n_incl, order, excl, r, &var);
1327   autocorrelate_finish(&order, excl, r, var);
1328   write_1D_file(r, order, "", "autocorrelation");
1329   if(order)
1330     {
1331     if(yule_walker(r, order))
1332       /*this never happens*/
1333       fprintf(stderr,
1334 	"Cannot compute autoregression; Yule-Walker matrix is singular.\n");
1335     else
1336       {
1337       write_1D_file(r, order, "", "autoregression");
1338       whiten(ts, white, tslen, r, order);
1339       tsfile = fopen("permtest_autoregr_whitened.dat", "w");
1340       if(tsfile == NULL) exit(1);
1341       for(i = 0; i != tslen; i++)
1342 	fprintf(tsfile, "%f\n", white[i]);
1343       fclose(tsfile);
1344       colour(ts, white, tslen, r, order);
1345       tsfile = fopen("permtest_autoregr_recoloured.dat", "w");
1346       if(tsfile == NULL) exit(1);
1347       for(i = 0; i != tslen; i++)
1348 	fprintf(tsfile, "%f\n", ts[i]);
1349       fclose(tsfile);
1350       }
1351     free(r);
1352     if(autocorrelate_init((float *)0, tslen, order, &excl, &r, &var, &n_incl))
1353       {
1354       fprintf(stderr, "autocorrelate_init: out of memory\n");
1355       return(1);
1356       }
1357     autocorrelate_sum(white, tslen, n_incl, order, excl, r, &var);
1358     for(i = 1; i <= order; i++)
1359       printf("\t\tAR(%d)", i);
1360     autocorrelate_finish(&order, excl, r, var);
1361     printf("\nautocorrelations:");
1362     for(i = 0; i != order; i++)
1363       printf("\t%f", r[i]);
1364     putchar('\n');
1365     }
1366   free(r);
1367   }
1368 
1369 #endif
1370 
1371 /*Compute the permutation test.  Return 0 if successful, 1 if error.*/
PERMTEST_compute(PLUGIN_interface * plint,THD_3dim_dataset * dset,MRI_IMAGE * ref_ts,MRI_IMAGE * ort_ts,double pcrit,int one_tailed,short ** intensities,short ** zvals,double * fim_scale,THD_3dim_dataset * mask,float masklo,float maskhi,int verbose,int AR_order,MRI_IMAGE * AR_excl_ts)1372 static int PERMTEST_compute(
1373   PLUGIN_interface *plint,	/*AFNI plugin interface*/
1374   THD_3dim_dataset *dset,	/*AFNI 3D+time dataset*/
1375   MRI_IMAGE *ref_ts,		/*reference time series*/
1376   MRI_IMAGE *ort_ts,		/*time series against which to orthogonalise*/
1377   double pcrit,			/*critical probability*/
1378   int one_tailed,	/*-1=one-tailed (-), 0=two-tailed, 1=one-tailed (+)*/
1379 	/*returned parameters:*/
1380   short **intensities,		/*address of pointer to intensities*/
1381   short **zvals,		/*address of pointer to z-scores*/
1382   double *fim_scale,		/*scaling factor for intensities*/
1383   THD_3dim_dataset *mask,	/*mask dataset, or NULL for no mask*/
1384   float masklo,			/*lower and upper bounds on masked range*/
1385   float maskhi,
1386   int verbose,		/*1 for verbose info on coordinates, 0 otherwise*/
1387   int AR_order,			/*autoregressive model order*/
1388   MRI_IMAGE *AR_excl_ts)	/*autoregression exclusion flags*/
1389   {
1390   register int t, iter, xyz;	/*indices and counters*/
1391   int x=0, y=0, z,
1392       xdim, ydim, zdim,		/*spatial dimensions*/
1393       tdim,			/*temporal dimension of dataset*/
1394       tsize,			/*# of included (< BLAST) points, tsize<=tdim*/
1395       ignore,			/*# of ignored (>=BLAST) pts at head of series*/
1396       t2,
1397       *tindex,			/*temporal sequence of all included images*/
1398       *sequence;		/*permuted temporal sequence*/
1399   float *vox_xyz,		/*time series for one voxel*/
1400 	*AR_ts=NULL,			/*time series after whitening or colouring*/
1401 	*vox,			/*3D+time data indexed by z,y,x,t*/
1402 	*ts,		      /*storage for linear series (ts[t]=t, 0<=t<tsize),
1403 				 and later for randomised time series*/
1404 	*fit_coeff,		/*fit coefficients*/
1405 	mask_val;		/*value of mask at current voxel*/
1406   STREE *actual_corr;
1407   DTREE *randomised_corr;
1408   CLIST *coord_mem,			/*data area for coord-corr pair lists*/
1409 	*coord_next;			/*next free location in coord_mem*/
1410   double sx_trend, sx_ref, sx_ort, *sy,	/*correlation parameters*/
1411 	 sxx_trend, sxx_ref, sxx_ort, *syy,
1412 	 corr, slope, intercept,	/*regression coefficients*/
1413 	 max_corr;			/*correlation w/ max absolute value*/
1414   int percent_done, prev_percent_done,	/*statistics for progress meter*/
1415       not_done;
1416 
1417 /*variables for the autoregression computation*/
1418   double *AR=NULL,			/*autoregression coefficients*/
1419 	  AR_var;		/*variance*/
1420   int AR_n_incl=0;		/*# of points included in covariance calc.*/
1421   char *AR_excl=NULL;		/*flags at each time point, 1=excluded*/
1422 
1423 /*set dimensions*/
1424   xdim = dset->daxes->nxx;
1425   ydim = dset->daxes->nyy;
1426   zdim = dset->daxes->nzz;
1427   tdim = DSET_NUM_TIMES(dset);
1428   switch(one_tailed)
1429     {
1430     case -1: magnitude = neg; break;
1431     case 0: magnitude = fabs; break;
1432     case 1: magnitude = id;
1433     }
1434   num_coords = NUM_COORDS;
1435   num_coords_exhausted = 0;
1436   if(ort_ts != (MRI_IMAGE *)0) /*need to save extra points if orthogonalising*/
1437     num_coords *= 2;
1438 /*allocate storage for functional intensities*/
1439   *intensities = (short *)calloc(xdim*ydim*zdim, sizeof(**intensities));
1440   if(*intensities == (short *)0)
1441     return 1;
1442 /*allocate storage for z-scores*/
1443   *zvals = (short *)calloc(xdim*ydim*zdim, sizeof(**zvals));
1444   if(*zvals == (short *)0)
1445     {
1446     free(*intensities);
1447     return 1;
1448     }
1449   /*no need to initialise (*zvals)[] to zeroes, since calloc() does it for us*/
1450   /*Initialise temporal sequences:  `tindex' is a mapping from the time index
1451     used in statistical tests to the time index used for storage in the AFNI
1452     dataset; it excludes ignored time points.  `sequence' is initially the same
1453     as tindex but will be permuted during each iteration of the resampling
1454     procedure.*/
1455   tindex = (int *)calloc(tdim, sizeof(*tindex));
1456   if(tindex == (int *)0)
1457     {
1458     free(*zvals);
1459     free(*intensities);
1460     return 1;
1461     }
1462   sequence = (int *)calloc(tdim, sizeof(*sequence));
1463   if(sequence == (int *)0)
1464     {
1465     free(tindex);
1466     free(*zvals);
1467     free(*intensities);
1468     return 1;
1469     }
1470   for((t = 0), (tsize = 0); t != tdim; t++)
1471     if(MRI_FLOAT_PTR(ref_ts)[t] < BLAST)
1472       {
1473       tindex[tsize] = t;
1474       sequence[tsize++] = t;
1475       }
1476   if(tsize < 4)		/*make sure we have enough points for regression*/
1477     {
1478     free(sequence);
1479     free(tindex);
1480     free(*zvals);
1481     free(*intensities);
1482     fprintf(stderr, "ERROR: %d time points aren't enough to perform regression\n", tsize);
1483     return 1;
1484     }
1485 /*initialise data*/
1486   vox = (float *)calloc(xdim*ydim*zdim*tdim, sizeof(*vox));
1487   if(vox == (float *)0)
1488     {
1489     free(sequence);
1490     free(tindex);
1491     free(*zvals);
1492     free(*intensities);
1493     return 1;
1494     }
1495   sy = (double *)calloc(xdim*ydim*zdim, sizeof(*sy));
1496   if(sy == (double *)0)
1497     {
1498     free(vox);
1499     free(sequence);
1500     free(tindex);
1501     free(*zvals);
1502     free(*intensities);
1503     return 1;
1504     }
1505   syy = (double *)calloc(xdim*ydim*zdim, sizeof(*syy));
1506   if(syy == (double *)0)
1507     {
1508     free(sy);
1509     free(vox);
1510     free(sequence);
1511     free(tindex);
1512     free(*zvals);
1513     free(*intensities);
1514     return 1;
1515     }
1516   ts = (float *)calloc(tdim, sizeof(*ts));
1517   if(ts == (float *)0)
1518     {
1519     free(syy);
1520     free(sy);
1521     free(vox);
1522     free(sequence);
1523     free(tindex);
1524     free(*zvals);
1525     free(*intensities);
1526     return 1;
1527     }
1528   actual_corr = stree_create(xdim, ydim, xdim*ydim*zdim);
1529   if(actual_corr == (STREE *)0)
1530     {
1531     free(syy);
1532     free(sy);
1533     free(ts);
1534     free(vox);
1535     free(sequence);
1536     free(tindex);
1537     free(*zvals);
1538     free(*intensities);
1539     return 1;
1540     }
1541   fit_coeff = (float *)calloc(xdim*ydim*zdim, sizeof(*fit_coeff));
1542   if(fit_coeff == (float *)0)
1543     {
1544     stree_destroy(actual_corr);
1545     free(syy);
1546     free(sy);
1547     free(ts);
1548     free(vox);
1549     free(sequence);
1550     free(tindex);
1551     free(*zvals);
1552     free(*intensities);
1553     return 1;
1554     }
1555 
1556 /******************************************************************************
1557  * PHASE 1: Copy data, remove linear trend, optionally orthogonalise against  *
1558  *	    a user-supplied series, and correlate with the ideal series.      *
1559  ******************************************************************************/
1560   for(ignore = 0; MRI_FLOAT_PTR(ref_ts)[ignore] >= BLAST; ignore++)
1561     ;
1562 /*linear series to use in detrending*/
1563   for(t = 0; t != tdim; t++)
1564     ts[t] = (float)t;
1565 /*sum of the linear series, and sum of its squares*/
1566   sx_trend = (double)(((tdim-1)*tdim - (ignore-1)*ignore)/2);
1567   sxx_trend = ((double)((tdim*(tdim*(2*tdim-3)+1) - ignore*(ignore*(2*ignore-3)+1))/6)) - sx_trend*sx_trend/(tdim-ignore);
1568 /*compute the sum and sum of squares of the ideal time series*/
1569   correlate_prep(MRI_FLOAT_PTR(ref_ts)+ignore, MRI_FLOAT_PTR(ref_ts)+ignore, tdim-ignore, &sx_ref, &sxx_ref);
1570 /*compute the sum and sum of squares of the orthogonal series, if specified*/
1571   if(ort_ts != (MRI_IMAGE *)0)
1572     correlate_prep(MRI_FLOAT_PTR(ort_ts), MRI_FLOAT_PTR(ort_ts), tdim, &sx_ort, &sxx_ort);
1573   *fim_scale = 0.0;
1574   mask_val = masklo;
1575 /*if autoregressive correction for coloured noise has been requested,
1576   iniialise the autoregression computation:*/
1577   if(AR_order && autocorrelate_init(((AR_excl_ts != (MRI_IMAGE *)0)?
1578 					MRI_FLOAT_PTR(AR_excl_ts)+ignore:
1579 					(float *)0),
1580     tdim-ignore, AR_order, &AR_excl, &AR, &AR_var, &AR_n_incl))
1581     {
1582     fprintf(stderr, "autocorrelate_init: out of memory\n");
1583     return 1;
1584     }
1585   xyz = 0;
1586   for(z = 0; z !=  zdim; z++)
1587     for(y = 0; y != ydim; y++)
1588       for(x = 0; x != xdim; x++)
1589 	{
1590 	if(mask != NULL)
1591 	  {
1592 	/*fetch the mask brick's scaling factor...*/
1593 	  mask_val = DSET_BRICK_FACTOR(mask, 0);
1594 	  if(mask_val == 0.0)
1595 	    mask_val = 1.0;
1596 	/*...and multiply it by the mask datum at coordinates (x, y, z)*/
1597 	  if(DSET_BRICK_TYPE(mask, 0) == MRI_short)
1598 	    mask_val *= ((short *)DSET_ARRAY(mask, 0))[xyz];
1599 	  else
1600 	    mask_val *= ((char *)DSET_ARRAY(mask, 0))[xyz];
1601 	  }
1602 	if((mask_val >= masklo) && (mask_val <= maskhi))
1603 	  {
1604 	  vox_xyz = vox + tdim*xyz;
1605 	  for(t = 0; t != tdim; t++)
1606 	    {
1607 	  /*fetch the time series brick's scaling factor...*/
1608 	    vox_xyz[t] = DSET_BRICK_FACTOR(dset, t);
1609 	    if(vox_xyz[t] == 0.0)
1610 	      vox_xyz[t] = 1.0;
1611 	  /*...and multiply it by the time series datum at (x, y, z, t)*/
1612 	    vox_xyz[t] *= ((short *)DSET_ARRAY(dset, t))[xyz];
1613 	    }
1614 	/*detrend*/
1615 	  correlate_prep(ts+ignore, vox_xyz+ignore, tdim-ignore, sy+xyz, syy+xyz);
1616 	  correlate(ts+ignore, vox_xyz+ignore, tdim-ignore, sx_trend, sxx_trend, sy[xyz], syy[xyz], (double *)0, &slope, &intercept);
1617 	  orthogonalise(ts, vox_xyz, vox_xyz, tdim, slope, intercept+slope*ignore);
1618 	/*remove the orthogonalisation time series, if one has been supplied*/
1619 	  if(ort_ts != (MRI_IMAGE *)0)
1620 	    {
1621 	    correlate_prep(MRI_FLOAT_PTR(ort_ts), vox_xyz, tdim, sy+xyz, syy+xyz);
1622 	    correlate(MRI_FLOAT_PTR(ort_ts), vox_xyz, tdim, sx_ort, sxx_ort, sy[xyz], syy[xyz], (double *)0, &slope, &intercept);
1623 	    orthogonalise(MRI_FLOAT_PTR(ort_ts), vox_xyz, vox_xyz, tdim, slope, intercept);
1624 	    }
1625 	/*correlate*/
1626 	  correlate_prep(MRI_FLOAT_PTR(ref_ts)+ignore, vox_xyz+ignore, tdim-ignore, sy+xyz, syy+xyz);
1627 	  correlate(MRI_FLOAT_PTR(ref_ts)+ignore, vox_xyz+ignore, tdim-ignore, sx_ref, sxx_ref, sy[xyz], syy[xyz], &corr, &slope, (double *)0);
1628 	/*save regression coefficient*/
1629 	  fit_coeff[xyz] = slope;
1630 	/*retain greatest slope for use in computing scaling factor*/
1631 	  slope = fabs(slope);
1632 	  if(slope > *fim_scale)
1633 	    *fim_scale = slope;
1634 	/*save correlation coefficient*/
1635 	  stree_insert(actual_corr, corr, x, y, z);
1636 	/*compute sums for autocorregression computation, if requested*/
1637 	  if(AR_order)
1638 	    autocorrelate_sum(vox_xyz+ignore, tdim-ignore, AR_n_incl, AR_order, AR_excl, AR, &AR_var);
1639 	  }
1640 	xyz++;
1641 	}
1642 /*if autoregression has been requested, compute autocorrelations from sums...*/
1643   if(AR_order)
1644     autocorrelate_finish(&AR_order, AR_excl, AR, AR_var);
1645 /*...& solve the Yule-Walker equations to derive autoregression coefficients
1646   (note that autocorrelate_finish() may have decreased AR_order, perhaps all
1647   the way to zero, if it has detected unrealistic autocorrelations)*/
1648   if(AR_order)
1649     {
1650   /*write the autocorrelation coefficients to a .1D file*/
1651     write_1D_file(AR, AR_order, DSET_FILECODE(dset), "_autocorrelation");
1652     if(yule_walker(AR, AR_order))
1653       {
1654       /*this never happens*/
1655       fprintf(stderr,
1656 	"Cannot compute autoregression; Yule-Walker matrix is singular.\n");
1657       AR_order = 0;
1658       }
1659     else
1660       {
1661     /*write the autoregression coefficients to a .1D file*/
1662       write_1D_file(AR, AR_order, DSET_FILECODE(dset), "_autoregression");
1663     /*apply the Yule-Walker autoregression coefficients to whiten the time
1664       series at each voxel, iterating through the voxels just as in the loop
1665       above*/
1666       AR_ts = (float *)calloc(tdim, sizeof(*AR_ts));
1667       if(AR_ts == (float *)0)
1668 	{
1669 	fprintf(stderr, "Cannot apply autoregression: out of memory\n");
1670 	AR_order = 0;
1671 	}
1672       else
1673 	{
1674 	xyz = 0;
1675 	for(z = 0; z !=  zdim; z++)
1676 	  for(y = 0; y != ydim; y++)
1677 	    for(x = 0; x != xdim; x++)
1678 	      {
1679 	      if(mask != NULL)
1680 		{
1681 	    /*fetch the mask brick's scaling factor...*/
1682 		mask_val = DSET_BRICK_FACTOR(mask, 0);
1683 		if(mask_val == 0.0)
1684 		  mask_val = 1.0;
1685 	    /*...and multiply it by the mask datum at coordinates (x, y, z)*/
1686 		if(DSET_BRICK_TYPE(mask, 0) == MRI_short)
1687 		  mask_val *= ((short *)DSET_ARRAY(mask, 0))[xyz];
1688 		else
1689 		  mask_val *= ((char *)DSET_ARRAY(mask, 0))[xyz];
1690 		}
1691 	      if((mask_val >= masklo) && (mask_val <= maskhi))
1692 		{
1693 		vox_xyz = vox + tdim*xyz;
1694 		for(t = 0; t != tdim; t++)
1695 		  {
1696 		/*fetch the time series brick's scaling factor...*/
1697 		  vox_xyz[t] = DSET_BRICK_FACTOR(dset, t);
1698 		  if(vox_xyz[t] == 0.0)
1699 		    vox_xyz[t] = 1.0;
1700 		/*...and multiply it by the time series datum at (x, y, z, t)*/
1701 		  vox_xyz[t] *= ((short *)DSET_ARRAY(dset, t))[xyz];
1702 		  }
1703 	      /*whiten, and copy the result over the original, coloured data*/
1704 		whiten(vox_xyz, AR_ts, tdim, AR, AR_order);
1705 		for(t = 0; t != tdim; t++)
1706 		  vox_xyz[t] = AR_ts[t];
1707 		}
1708 	      xyz++;
1709 	      }
1710 	}
1711       }
1712     }
1713 /*make sure that the mask left us *some* voxels*/
1714   if(stree_null(actual_corr))
1715     {
1716     fprintf(stderr, "PERMTEST: All voxels are masked!\n");
1717     return 1;
1718     }
1719   *fim_scale /= MRI_TYPE_maxval[MRI_short];
1720 /*copy fit coefficients for all voxels, scaled for storage in shorts*/
1721   for(t = 0; t != xdim*ydim*zdim; t++)
1722     (*intensities)[t] = (short)(fit_coeff[t] / *fim_scale);
1723   free(fit_coeff);
1724   randomised_corr = dtree_create(xdim, ydim, NUM_ITERS);
1725   if(randomised_corr == (DTREE *)0)
1726     {
1727     stree_destroy(actual_corr);
1728     free(syy);
1729     free(sy);
1730     free(ts);
1731     free(vox);
1732     free(sequence);
1733     free(tindex);
1734     free(*zvals);
1735     free(*intensities);
1736     return 1;
1737     }
1738   coord_mem = (CLIST *)calloc(NUM_ITERS*num_coords, sizeof(*coord_mem));
1739   if(coord_mem == (CLIST *)0)
1740     {
1741     dtree_destroy(randomised_corr);
1742     stree_destroy(actual_corr);
1743     free(syy);
1744     free(sy);
1745     free(ts);
1746     free(vox);
1747     free(sequence);
1748     free(tindex);
1749     free(*zvals);
1750     free(*intensities);
1751     return 1;
1752     }
1753   coord_next = coord_mem;
1754 /*initialise progress meter*/
1755   prev_percent_done = -1;
1756   PLUTO_popup_meter(plint);
1757 
1758 /******************************************************************************
1759  * PHASE 2: Compute the empirical distribution.				      *
1760  ******************************************************************************/
1761   for(iter = 0; iter != NUM_ITERS; iter++)
1762     {
1763     percent_done = (100*iter)/NUM_ITERS;
1764     if(percent_done > prev_percent_done)
1765       {
1766       prev_percent_done = percent_done;
1767       PLUTO_set_meter(plint, percent_done);
1768       }
1769     shuffle(sequence, tsize);
1770     for(t = 0; t != num_coords; t++)
1771       coord_next[t].corr = 0.0;
1772     xyz = 0;
1773     for(z = 0; z !=  zdim; z++)
1774       for(y = 0; y != ydim; y++)
1775 	for(x = 0; x != xdim; x++)
1776 	  {
1777 	  if(mask != NULL)
1778 	    {
1779 	  /*fetch the mask brick's scaling factor...*/
1780 	    mask_val = DSET_BRICK_FACTOR(mask, 0);
1781 	    if(mask_val == 0.0)
1782 	      mask_val = 1.0;
1783 	  /*...and multiply it by the mask datum at coordinates (x, y, z)*/
1784 	    if(DSET_BRICK_TYPE(mask, 0) == MRI_short)
1785 	      mask_val *= ((short *)DSET_ARRAY(mask, 0))[xyz];
1786 	    else
1787 	      mask_val *= ((char *)DSET_ARRAY(mask, 0))[xyz];
1788 	    }
1789 	  if((mask_val >= masklo) && (mask_val <= maskhi))
1790 	    {
1791 	    vox_xyz = vox + tdim*xyz;
1792 	  /*apply the autoregression coefficients to re-colour the permuted
1793 	    time series before correlating*/
1794 	    if(AR_order)
1795 	      {
1796 	    /*fetch the time series, in the permuted order given by sequence[],
1797 	      but with ignored and excluded points copied in their original
1798 	      positions - these are needed in order to fill in the whole array
1799 	      so that colour() below will have valid data at each time point.*/
1800 	      for(t = 0; t != ignore; t++)
1801 		ts[t] = vox_xyz[t];
1802 	      for(t2 = 0; t != tdim; t++)
1803 		ts[t] = ((MRI_FLOAT_PTR(ref_ts)[t] < BLAST)?
1804 			  vox_xyz[sequence[t2++]]:
1805 			  vox_xyz[t]);
1806 	    /*colour the permuted time series*/
1807 	      colour(AR_ts, ts, tdim, AR, AR_order);
1808 	    /*copy the coloured series into the work space*/
1809 	      for(t = 0; t != tdim; t++)
1810 		ts[t] = AR_ts[t];
1811 	    /*compute new sums for the permuted & re-coloured time series*/
1812 	      correlate_prep(MRI_FLOAT_PTR(ref_ts)+ignore, ts+ignore, tdim-ignore, sy+xyz, syy+xyz);
1813 	      }
1814 	    else
1815 	      {
1816 	    /*fetch the time series, in the permuted order given by sequence[]*/
1817 	      for((t = ignore), (t2 = 0); t != tdim; t++)
1818 		if(MRI_FLOAT_PTR(ref_ts)[t] < BLAST)
1819 		  ts[t] = vox_xyz[sequence[t2++]];
1820 	      }
1821 	    correlate(MRI_FLOAT_PTR(ref_ts)+ignore, ts+ignore, tdim-ignore, sx_ref, sxx_ref, sy[xyz], syy[xyz], &corr, (double *)0, (double *)0);
1822 	  /*Since num_coords is tiny, any sorting algorithm faster
1823 	    than linear insertion wouldn't be worth the trouble.*/
1824 	    for(t = 0; t < num_coords; t++)
1825 	      if((*magnitude)(corr) > (*magnitude)(coord_next[t].corr))
1826 		{
1827 		t2 = t;
1828 		while(++t != num_coords)
1829 		  {
1830 		  coord_next[t].corr = coord_next[t-1].corr;
1831 		  coord_next[t].coords = coord_next[t-1].coords;
1832 		  }
1833 		coord_next[t2].corr = corr;
1834 		coord_next[t2].coords = coord_encode(x, y, z, xdim, ydim);
1835 		}
1836 	    }
1837 	  xyz++;
1838 	  }
1839     dtree_insert(randomised_corr, coord_next);
1840     if(verbose)
1841       printf("iter=%d max_corr=%f\n", iter, coord_next->corr);
1842     coord_next += num_coords;
1843     }
1844 #ifdef PERMTEST_DEBUG
1845   dtree_traverse(randomised_corr, 0);	/*dump distribution to stdout*/
1846 #endif
1847   if(AR_order)
1848     free(AR_ts);
1849   PLUTO_set_meter(plint, 100);
1850 
1851 /******************************************************************************
1852  * PHASE 3: Rank correlations from the actual data set within the empirical   *
1853  *	    distribution.						      *
1854  ******************************************************************************/
1855   do
1856     {
1857     not_done = 0;
1858   /*extract the most significant *correlation* (in [-1,1])*/
1859     max_corr = stree_extract_max(actual_corr, &x, &y, &z);
1860   /*map it to an adjusted *probability* (in [0,1])*/
1861     corr = dtree_position(randomised_corr, max_corr);
1862     if(verbose)
1863       printf("(%2d,%2d,%2d) raw r=%f adjusted p=%f", x, y, z, max_corr, corr);
1864     if(((one_tailed == 0) && (fabs(corr-0.5) >= 0.5-pcrit/2.0))
1865      ||((one_tailed == -1) && (corr <= pcrit))
1866      ||((one_tailed == 1) && (corr >= 1.0-pcrit)))
1867 	{
1868 	slope = critz(corr);
1869 	if(verbose)
1870 	  printf(" zcrit=%f\n", slope);
1871 	(*zvals)[x + xdim*(y + ydim*z)] = (short)(slope*FUNC_ZT_SCALE_SHORT);
1872 	not_done = 1;
1873 /******************************************************************************
1874  *percent completion of this phase of the algorithm can be expressed as follows:
1875  *	100.0 * ((one_tailed == 1)? 1.0-corr:				      *
1876  *		  ((one_tailed == 0) && (corr > 0.5))?			      *
1877  *		    2.0*(1.0-corr):					      *
1878  *		      corr) / pcrit;					      *
1879  ******************************************************************************/
1880       /*since this point is now defined as activated, exclude its data from the
1881 	empirical distribution*/
1882 	dtree_delete_coords(randomised_corr, x, y, z, *zvals);
1883 	}
1884     } while(not_done && (dtree_size(randomised_corr) > NUM_ITERS/2));
1885 			/*^^^ stop if we've deleted too many coordinates ^^^*/
1886   if(verbose)
1887     putchar('\n');
1888   free(coord_mem);
1889   dtree_destroy(randomised_corr);
1890   stree_destroy(actual_corr);
1891   free(syy);
1892   free(sy);
1893   free(ts);
1894   free(vox);
1895   free(sequence);
1896   free(tindex);
1897   return 0;
1898   }
1899 
1900 /*In the event of a conflict with some future revision of the AFNI widgets
1901   code, PERMTEST_set_logo() and PERMTEST_reset_logo() can be redefined as null
1902   functions and everything will still work right (though it would be a shame to
1903   lose the free advertising!).*/
1904 
1905 static Pixmap sipb_pixmap;		/*pixmap of SIPB logo*/
1906 
PERMTEST_set_logo(PLUGIN_interface * plint)1907 static void PERMTEST_set_logo(PLUGIN_interface *plint)
1908   {
1909   Pixel bg_pix=0, fg_pix=0;			/*colours from control window*/
1910 #define sipb_width 90
1911 #define sipb_height 90
1912   static char sipb_bits[] = {		/*bitmap of SIPB logo*/
1913   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1914   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1915   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1916   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1917   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1918   0x1f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xff, 0x03,
1919   0x1f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xf8, 0x03,
1920   0x1f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xf0, 0x03,
1921   0x1f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xf0, 0x03,
1922   0x3f, 0x00, 0x0c, 0xf0, 0x00, 0x7c, 0x00, 0x7e, 0x00, 0x03, 0xe0, 0x03,
1923   0x7f, 0x00, 0x18, 0xf0, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x0f, 0xe0, 0x03,
1924   0x7f, 0x00, 0x30, 0xf0, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x1f, 0xe0, 0x03,
1925   0xff, 0x00, 0x60, 0xf0, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x1f, 0xe0, 0x03,
1926   0xff, 0x01, 0x60, 0xf0, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x0f, 0xe0, 0x03,
1927   0xff, 0x03, 0xc0, 0xff, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x0f, 0xe0, 0x03,
1928   0xff, 0x07, 0x80, 0xff, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x03, 0xe0, 0x03,
1929   0xff, 0x0f, 0x00, 0xff, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x00, 0xf0, 0x03,
1930   0xff, 0x1f, 0x00, 0xff, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x00, 0xf8, 0x03,
1931   0xff, 0x3f, 0x00, 0xff, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x00, 0xe0, 0x03,
1932   0xff, 0x3f, 0x00, 0xff, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x00, 0xe0, 0x03,
1933   0xff, 0x1f, 0x80, 0xff, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x03, 0xc0, 0x03,
1934   0xff, 0x0f, 0xc0, 0xff, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x0f, 0xc0, 0x03,
1935   0xff, 0x07, 0xe0, 0xff, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x1f, 0xc0, 0x03,
1936   0xff, 0x03, 0x70, 0xf0, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x03,
1937   0xff, 0x01, 0x78, 0xf0, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x03,
1938   0xff, 0x00, 0x3c, 0xf0, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x1f, 0xc0, 0x03,
1939   0x7f, 0x00, 0x00, 0xf0, 0x01, 0xfe, 0x00, 0xff, 0x00, 0x0f, 0xc0, 0x03,
1940   0x3f, 0x00, 0x00, 0xf0, 0x00, 0x7c, 0x00, 0x7e, 0x00, 0x07, 0xc0, 0x03,
1941   0x1f, 0x00, 0x00, 0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x00, 0xe0, 0x03,
1942   0x1f, 0x00, 0x00, 0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x00, 0xf0, 0x03,
1943   0x1f, 0x00, 0x00, 0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x00, 0xf8, 0x03,
1944   0x1f, 0x00, 0x00, 0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x00, 0xff, 0x03,
1945   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1946   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1947   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1948   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1949   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1950   0xff, 0xff, 0x40, 0xfe, 0x3f, 0x9f, 0x04, 0xfe, 0xff, 0xff, 0xff, 0x03,
1951   0xff, 0xff, 0x73, 0xfe, 0x3f, 0x8e, 0x9c, 0xff, 0xff, 0xff, 0xff, 0x03,
1952   0xff, 0xff, 0x73, 0x38, 0x3e, 0x8e, 0x9c, 0xff, 0xff, 0xff, 0xff, 0x03,
1953   0xff, 0xff, 0x73, 0x92, 0x3c, 0x84, 0x9c, 0xff, 0xff, 0xff, 0xff, 0x03,
1954   0xff, 0xff, 0x73, 0x12, 0x3c, 0x95, 0x9c, 0xff, 0xff, 0xff, 0xff, 0x03,
1955   0xff, 0xff, 0x73, 0x92, 0x3f, 0x91, 0x9c, 0xff, 0xff, 0xff, 0xff, 0x03,
1956   0xff, 0xff, 0x73, 0x92, 0x3c, 0x9b, 0x9c, 0xff, 0xff, 0xff, 0xff, 0x03,
1957   0xff, 0xff, 0x73, 0x32, 0x3e, 0x9b, 0x9c, 0xff, 0xff, 0xff, 0xff, 0x03,
1958   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1959   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1960   0xff, 0xff, 0xc3, 0xfc, 0x9f, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0x03,
1961   0xff, 0xff, 0x99, 0xfc, 0x9f, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0x03,
1962   0xff, 0xff, 0xf1, 0x48, 0x86, 0xb1, 0x8c, 0xff, 0xff, 0xff, 0xff, 0x03,
1963   0xff, 0xff, 0xc3, 0x4c, 0x92, 0x24, 0xc9, 0xff, 0xff, 0xff, 0xff, 0x03,
1964   0xff, 0xff, 0x8f, 0x4c, 0x9a, 0x20, 0xc9, 0xff, 0xff, 0xff, 0xff, 0x03,
1965   0xff, 0xff, 0x9d, 0x4c, 0x9a, 0x3c, 0xc9, 0xff, 0xff, 0xff, 0xff, 0x03,
1966   0xff, 0xff, 0x99, 0x4c, 0x92, 0x24, 0xc9, 0xff, 0xff, 0xff, 0xff, 0x03,
1967   0xff, 0xff, 0xc3, 0x99, 0x86, 0x31, 0x99, 0xff, 0xff, 0xff, 0xff, 0x03,
1968   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1969   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1970   0xff, 0xff, 0xe1, 0x1f, 0xff, 0xff, 0xff, 0x99, 0xff, 0xff, 0xff, 0x03,
1971   0xff, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x03,
1972   0xff, 0xff, 0xb3, 0x8c, 0xb1, 0x48, 0x8e, 0x91, 0xb1, 0xfc, 0xff, 0x03,
1973   0xff, 0xff, 0x33, 0xc9, 0x24, 0x92, 0x34, 0x99, 0x24, 0xf9, 0xff, 0x03,
1974   0xff, 0xff, 0x33, 0xc9, 0x24, 0x93, 0x0c, 0x99, 0x24, 0xf9, 0xff, 0x03,
1975   0xff, 0xff, 0x33, 0xc9, 0x24, 0x93, 0x24, 0x99, 0x24, 0xf9, 0xff, 0x03,
1976   0xff, 0xff, 0x33, 0xc9, 0x24, 0x93, 0x24, 0x99, 0x24, 0xf9, 0xff, 0x03,
1977   0xff, 0xff, 0x21, 0xc9, 0x31, 0x93, 0x4c, 0x92, 0x31, 0xf9, 0xff, 0x03,
1978   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1979   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1980   0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x03,
1981   0xff, 0xff, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1982   0xff, 0xff, 0x99, 0x12, 0xc7, 0x38, 0x8e, 0x29, 0xa7, 0xff, 0xff, 0x03,
1983   0xff, 0xff, 0x99, 0x48, 0x52, 0x92, 0x24, 0x49, 0x92, 0xff, 0xff, 0x03,
1984   0xff, 0xff, 0xc1, 0x4c, 0x72, 0x30, 0x8e, 0x49, 0x9a, 0xff, 0xff, 0x03,
1985   0xff, 0xff, 0xf9, 0x4c, 0x72, 0xfe, 0x3c, 0x49, 0x9a, 0xff, 0xff, 0x03,
1986   0xff, 0xff, 0xf9, 0x4c, 0x52, 0x92, 0x24, 0x49, 0x92, 0xff, 0xff, 0x03,
1987   0xff, 0xff, 0xf9, 0x1c, 0xc7, 0x38, 0x8e, 0x49, 0x86, 0xff, 0xff, 0x03,
1988   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x03,
1989   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0x03,
1990   0xff, 0xff, 0xc1, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1991   0xff, 0xff, 0x99, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1992   0xff, 0xff, 0x99, 0x71, 0x2c, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1993   0xff, 0xff, 0xc1, 0xa4, 0x89, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1994   0xff, 0xff, 0x99, 0x64, 0xc8, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1995   0xff, 0xff, 0x99, 0x24, 0xc9, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1996   0xff, 0xff, 0x99, 0x24, 0xc9, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1997   0xff, 0xff, 0xc1, 0x71, 0xc2, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1998   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
1999   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
2000   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
2001   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
2002   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
2003   };
2004   /*Initialise SIPB logo, in the current controller window only.  Leave all
2005     other controller windows with the default MCW logo.  (Adapted from
2006     afni_widg:AFNI_make_widgets).*/
2007   XtVaGetValues(plint->im3d->vwid->top_form,
2008 		XmNforeground, &bg_pix,     /*note reversal of fg & bg colours*/
2009 		XmNbackground, &fg_pix, NULL);
2010   sipb_pixmap = XCreatePixmapFromBitmapData(
2011 		XtDisplay(plint->im3d->vwid->top_shell),
2012 		RootWindowOfScreen(XtScreen(plint->im3d->vwid->top_shell)),
2013 		sipb_bits, sipb_width, sipb_height,
2014 		fg_pix, bg_pix,
2015 		DefaultDepthOfScreen(XtScreen(plint->im3d->vwid->top_shell)));
2016 /*shameless self-aggrandisement (adapted from afni:AFNI_set_cursor)*/
2017   XtVaSetValues(plint->im3d->vwid->picture, XmNlabelPixmap, sipb_pixmap, NULL);
2018   }
2019 
PERMTEST_reset_logo(PLUGIN_interface * plint)2020 static void PERMTEST_reset_logo(PLUGIN_interface *plint)
2021   {
2022   XtVaSetValues(plint->im3d->vwid->picture, XmNlabelPixmap, XmUNSPECIFIED_PIXMAP, NULL);
2023   XFreePixmap(XtDisplay(plint->im3d->vwid->top_shell), sipb_pixmap);
2024   }
2025 
PERMTEST_main(PLUGIN_interface * plint)2026 char *PERMTEST_main(PLUGIN_interface *plint)
2027   {
2028   int t;
2029   char *prefix;
2030   MRI_IMAGE *ref_time_series, *orthogonal_time_series, *AR_excl_time_series;
2031   THD_3dim_dataset *dset, *mask, *new_dset;
2032   short *intensities, *zvals;
2033   double fim_scale,			/*scaling factor for short image data*/
2034 	 pcrit;				/*alpha level*/
2035   char *optiontag;			/*one of tails2, tails1pos, tails1neg*/
2036   int one_tailed,			/*0, 1, or -1*/
2037 	AR_order;			/*autoregressive model order*/
2038   float masklo, maskhi;			/*bounds on mask dataset*/
2039   static char tails_err[] = "exactly one of two-tailed, one-tailed positive, or one-tailed negative must be chosen";
2040 
2041 #ifdef PERMTEST_DEBUG
2042   void (*handler)(int);
2043 #endif
2044 
2045   if(plint == (PLUGIN_interface *)0)
2046     return "PERMTEST_main: null input";
2047 
2048 /*Make sure that the input dataset exists and is stored in a format that we can
2049   understand (MRI_short)*/
2050   PLUTO_next_option(plint);
2051   dset = PLUTO_find_dset(PLUTO_get_idcode(plint));
2052   if(dset == (THD_3dim_dataset *)0)
2053     return "bad dataset";
2054   for(t = 0; t != dset->dblk->nvals; t++)
2055 /*to do: make copies of this routine that work on MRI_byte and on MRI_float*/
2056     if(DSET_BRICK_TYPE(dset, t) != MRI_short)
2057       return("permutation test on non-short values is not implemented");
2058 
2059 /*Make sure that the time series exists and is stored in a format that we can
2060   understand (MRI_float), and contains enough points to cover the time
2061   dimension of the specified dataset*/
2062   PLUTO_next_option(plint);
2063   ref_time_series = PLUTO_get_timeseries(plint);
2064   if((ref_time_series == (MRI_IMAGE *)0)
2065    ||(ref_time_series->kind != MRI_float)
2066    ||(ref_time_series->nx < DSET_NUM_TIMES(dset)))
2067     return("bad time series");
2068 
2069 /*Read the orthogonalisation time series, if it exists*/
2070   optiontag = PLUTO_get_optiontag(plint);
2071   if(strcmp(optiontag, ort_label))
2072     orthogonal_time_series = (MRI_IMAGE *)0;
2073   else
2074     {
2075     orthogonal_time_series = PLUTO_get_timeseries(plint);
2076     if((orthogonal_time_series == (MRI_IMAGE *)0)
2077      ||(orthogonal_time_series->kind != MRI_float)
2078      ||(orthogonal_time_series->nx < DSET_NUM_TIMES(dset)))
2079       return("bad ort");
2080     PLUTO_next_option(plint);
2081     }
2082 
2083 /*Make sure that the prefix specified for the new dataset is a valid prefix*/
2084   prefix = PLUTO_get_string(plint);
2085   if(!PLUTO_prefix_ok(prefix))
2086     return("bad prefix");
2087 
2088 /*Read the alpha level*/
2089   PLUTO_next_option(plint);
2090   pcrit = PLUTO_get_number(plint);
2091 
2092 /*Read the autoregressive model order, if autoregression has been specified*/
2093   optiontag = PLUTO_get_optiontag(plint);
2094   if(strcmp(optiontag, AR_order_label))
2095     AR_order = 0;
2096   else
2097     {
2098     AR_order = (int)PLUTO_get_number(plint);
2099     optiontag = PLUTO_get_optiontag(plint);
2100     }
2101 
2102 /*Read the autoregression exclusion flags vector, if it exists*/
2103   if(strcmp(optiontag, AR_excl_label))
2104     AR_excl_time_series = (MRI_IMAGE *)0;
2105   else
2106     {
2107     AR_excl_time_series = PLUTO_get_timeseries(plint);
2108     if((AR_excl_time_series == (MRI_IMAGE *)0)
2109      ||(AR_excl_time_series->kind != MRI_float)
2110      ||(AR_excl_time_series->nx < DSET_NUM_TIMES(dset)))
2111       return("bad AR exclusion vector");
2112     optiontag = PLUTO_get_optiontag(plint);
2113     }
2114 
2115 /*Exactly one of two-tailed, one-tailed positive, one-tailed negative*/
2116   if(optiontag == (char *)0)
2117     return(tails_err);
2118   if(strcmp(optiontag, tails2))
2119     {
2120     if(strcmp(optiontag, tails1pos))
2121       {
2122       if(strcmp(optiontag, tails1neg))
2123 	return(tails_err);
2124       else
2125 	one_tailed = -1;
2126       }
2127     else
2128       one_tailed = 1;
2129     }
2130   else
2131     one_tailed = 0;
2132   optiontag = PLUTO_get_optiontag(plint);
2133   if((optiontag != (char *)0) && strcmp(optiontag, mask_label))
2134     return(tails_err);
2135 
2136 /*Optional mask dataset*/
2137   masklo = 1.0;
2138   maskhi = 32767.0;
2139   if(optiontag == (char *)0)
2140     mask = (THD_3dim_dataset *)0;
2141   else
2142     {
2143     mask = PLUTO_find_dset(PLUTO_get_idcode(plint));
2144     if(mask == (THD_3dim_dataset *)0)
2145       return("bad mask");
2146     if((DSET_BRICK_TYPE(mask, 0) != MRI_short)
2147     && (DSET_BRICK_TYPE(mask, 0) != MRI_byte))
2148       return("mask brick type must be byte or short integer");
2149     optiontag = PLUTO_get_optiontag(plint);
2150     if(optiontag != (char *)0)
2151       {
2152       if(strcmp(optiontag, masklo_label))
2153 	maskhi = PLUTO_get_number(plint);
2154       else
2155 	{
2156 	masklo = PLUTO_get_number(plint);
2157 	if(PLUTO_get_optiontag(plint) != (char *)0)
2158 	  maskhi = PLUTO_get_number(plint);
2159 	}
2160       }
2161     DSET_load(mask);
2162     }
2163 
2164 #ifdef PERMTEST_DEBUG
2165   handler = signal(SIGUSR1, flush);
2166 #endif
2167 
2168 /*toot our own horn :-)*/
2169   PERMTEST_set_logo(plint);
2170 /*Make sure source dataset is in memory*/
2171   DSET_load(dset);
2172   if(PERMTEST_compute(plint, dset, ref_time_series, orthogonal_time_series, pcrit, one_tailed, &intensities, &zvals, &fim_scale, mask, masklo, maskhi, 0, AR_order, AR_excl_time_series))
2173     {
2174     PERMTEST_reset_logo(plint);
2175     return("out of memory");
2176     }
2177   if(num_coords_exhausted)
2178     printf("%d of %d points (%d%%) were deleted from the distribution due to\nexhausted coordinates.  If this fraction is larger than about 10%%, consider\nrecompiling plug_permtest.so with a NUM_COORDS larger than the current value of\n%d.\n", num_coords_exhausted, NUM_ITERS, (100*num_coords_exhausted+NUM_ITERS/2)/NUM_ITERS, NUM_COORDS);
2179 
2180 /*create the output dataset*/
2181   new_dset = EDIT_empty_copy(dset);
2182   if(EDIT_dset_items(new_dset,
2183 	ADN_prefix, prefix,
2184 	ADN_malloc_type, DATABLOCK_MEM_MALLOC, /*hold in r/w memory*/
2185 	ADN_datum_all, MRI_short,	/*store as (scaled) short ints*/
2186 	ADN_nvals, 2,			/*2 sub-bricks: intensity + z-score*/
2187 	ADN_ntt, 0,			/*no time dimension*/
2188 	ADN_type, ISHEAD(dset)?
2189 	  HEAD_FUNC_TYPE: GEN_FUNC_TYPE, /*functional image*/
2190 	ADN_func_type, FUNC_ZT_TYPE,	/*intensity + z-score*/
2191 	ADN_none))
2192     {
2193     PERMTEST_reset_logo(plint);
2194     return("EDIT_dset_items error");
2195     }
2196   EDIT_BRICK_LABEL(new_dset, 0, "Fit Coef");
2197   mri_fix_data_pointer(intensities, DSET_BRICK(new_dset, 0));
2198   EDIT_BRICK_FACTOR(new_dset, 0, (float)fim_scale);
2199   EDIT_BRICK_LABEL(new_dset, 1, "z-score");
2200   EDIT_BRICK_TO_FIZT(new_dset, 1);
2201   mri_fix_data_pointer(zvals, DSET_BRICK(new_dset, 1));
2202   EDIT_BRICK_FACTOR(new_dset, 1, (float)(1.0/FUNC_ZT_SCALE_SHORT));
2203   DSET_overwrite(new_dset);
2204   PLUTO_add_dset(plint, new_dset, DSET_ACTION_MAKE_CURRENT);
2205 #ifdef PERMTEST_DEBUG
2206   signal(SIGUSR1, handler);
2207 #endif
2208   PERMTEST_reset_logo(plint);
2209   return (char *)0;
2210   }
2211 
2212 
2213 DEFINE_PLUGIN_PROTOTYPE
2214 
PLUGIN_init(int ncall)2215 PLUGIN_interface *PLUGIN_init(int ncall)
2216   {
2217   PLUGIN_interface *plint;
2218   if(ncall > 0) return (PLUGIN_interface *)0;	/*only one interface*/
2219   CHECK_IF_ALLOWED("PERMUTATIONTEST","Permutation Test") ;  /* 30 Sep 2016 */
2220 /*set titles and entry point*/
2221   plint = PLUTO_new_interface("Permutation Test", hint, help, PLUGIN_CALL_VIA_MENU, PERMTEST_main);
2222   PLUTO_add_hint(plint, hint);
2223 /*first line of dialogue box: input dataset*/
2224   PLUTO_add_option(plint, input_label, input_label, TRUE);
2225   PLUTO_add_dataset(plint, "Dataset", ANAT_SPGR_MASK | ANAT_EPI_MASK, 0, DIMEN_4D_MASK | BRICK_SHORT_MASK);
2226 /*second line of dialogue box: input time series*/
2227   PLUTO_add_option(plint, ts_label, ts_label, TRUE);
2228   PLUTO_add_timeseries(plint, "Reference Time Series");
2229 /*third line of dialogue box: time series against which to orthogonalise*/
2230   PLUTO_add_option(plint, ort_label, ort_label, FALSE);
2231   PLUTO_add_timeseries(plint, "Orthogonalisation Time Series");
2232 /*fourth line of dialogue box: output dataset*/
2233   PLUTO_add_option(plint, output_label, output_label, TRUE);
2234   PLUTO_add_string(plint, "Prefix", 0, (char **)0, 19);
2235 /*fifth line of dialogue box: alpha level (range 10^-4..1, default 0.05)*/
2236   PLUTO_add_option(plint, alpha_label, alpha_label, TRUE);
2237   PLUTO_add_number(plint, "alpha level", 1, 10000, 4, 500, 1);
2238 /*sixth line of dialogue box: autoregressive model order*/
2239   PLUTO_add_option(plint, AR_order_label, AR_order_label, FALSE);
2240   PLUTO_add_number(plint, "autoregressive model order", 0, 32, 0, 1, 1);
2241 /*seventh line of dialogue box: autoregression exclusion vector*/
2242   PLUTO_add_option(plint, AR_excl_label, AR_excl_label, FALSE);
2243   PLUTO_add_timeseries(plint, "Autoregression Exclusion Flags");
2244 /*penultimate lines of dialogue box: tail options*/
2245   PLUTO_add_option(plint, tails2, tails2, FALSE);
2246   PLUTO_add_option(plint, tails1pos, tails1pos, FALSE);
2247   PLUTO_add_option(plint, tails1neg, tails1neg, FALSE);
2248 /*last lines of dialogue box: mask dataset and bounds*/
2249   PLUTO_add_option(plint, mask_label, mask_label, FALSE);
2250   PLUTO_add_dataset(plint, "mask dataset", 0, FUNC_FIM_MASK, DIMEN_3D_MASK | BRICK_SHORT_MASK | BRICK_BYTE_MASK);
2251   PLUTO_add_option(plint, masklo_label, masklo_label, FALSE);
2252   PLUTO_add_number(plint, "voxel is masked if >=", 0, 0x7fff, 0, 1, 1);
2253   PLUTO_add_option(plint, maskhi_label, maskhi_label, FALSE);
2254   PLUTO_add_number(plint, "voxel is masked if <=", 0, 0x7fff, 0, 1, 1);
2255   return plint;
2256   }
2257