14.2.1. Taylor et al. (2025). Go Figure: Transparency in neuroscience images preserves context …¶
Introduction¶
Here we present commands used in the following paper:
- Go Figure: Transparency in neuroscience images preserves context and clarifies interpretation.Paul A. Taylor, Himanshu Aggarwal, Peter Bandettini, Marco Barilari, Molly Bright, Cesar Caballero-Gaudes, Vince Calhoun, Mallar Chakravarty, Gabriel Devenyi, Jennifer Evans, Eduardo Garza-Villarreal, Jalil Rasgado-Toledo, Remi Gau, Daniel Glen, Rainer Goebel, Javier Gonzalez-Castillo, Omer Faruk Gulban, Yaroslav Halchenko, Daniel Handwerker, Taylor Hanayik, Peter Lauren, David Leopold, Jason Lerch, Christian Mathys, Paul McCarthy, Anke McLeod, Amanda Mejia, Stefano Moia, Thomas Nichols, Cyril Pernet, Luiz Pessoa, Bettina Pfleiderer, Justin Rajendra, Laura Reyes, Richard Reynolds, Vinai Roopchansingh, Chris Rorden, Brian Russ, Benedikt Sundermann, Bertrand Thirion, Salvatore Torrisi, Gang Chen (2025).
Abstract: Visualizations are vital for communicating scientific results. Historically, neuroimaging figures have only depicted regions that surpass a given statistical threshold. This practice substantially biases interpretation of the results and subsequent meta-analyses, particularly towards non-reproducibility. Here we advocate for a “transparent thresholding” approach that not only highlights statistically significant regions but also includes subthreshold locations, which provide key experimental context. This balances the dual needs of distilling modeling results and enabling informed interpretations for modern neuroimaging. We present four examples that demonstrate the many benefits of transparent thresholding, including: removing ambiguity, decreasing hypersensitivity to non-physiological features, catching potential artifacts, improving cross-study comparisons, reducing non-reproducibility biases, and clarifying interpretations. We also demonstrate the many software packages that implement transparent thresholding, several of which were added or streamlined recently as part of this work. A point-counterpoint discussion addresses issues with thresholding raised in real conversations with researchers in the field. We hope that by showing how transparent thresholding can drastically improve the interpretation (and reproducibility) of neuroimaging findings, more researchers will adopt this method.
Study keywords: neuroimaging, visualization, transparent thresholds, interpretability, reproducibility, understanding, quality control, meta-analysis
Main programs:
afni_proc.py
, @chauffeur_afni
, afni
, 3dFWHMx
,
3dClusterize
Download scripts¶
afni_proc.py
and visualization
in Ex. 4:View scripts¶
These scripts can be run on either a desktop or slurm-managed HPC cluster (like NIH’s Biowulf). Please see the related GitHub repo for the associated run_*.tcsh scripts, which complement these by potentially looping over many subjects.
do_21_ap.tcsh
¶
This is one example of running afni_proc.py on the salmon dataset.
1#!/bin/tcsh
2
3# DESC: run AP to fully process FMRI data (here, for the salmon scan)
4
5# Process a single subj+ses pair. Run it from its partner run*.tcsh script.
6# Run on a slurm/swarm system (like Biowulf) or on a desktop.
7
8# ---------------------------------------------------------------------------
9
10# use slurm? 1 = yes, 0 = no (def: use if available)
11set use_slurm = $?SLURM_CLUSTER_NAME
12
13# ----------------------------- biowulf-cmd ---------------------------------
14if ( $use_slurm ) then
15 # load modules: ***** add any other necessary ones
16 source /etc/profile.d/modules.csh
17 module load afni
18
19 # set N_threads for OpenMP
20 setenv OMP_NUM_THREADS $SLURM_CPUS_ON_NODE
21endif
22# ---------------------------------------------------------------------------
23
24# initial exit code; we don't exit at fail, to copy partial results back
25set ecode = 0
26
27# set relevant environment variables
28setenv AFNI_COMPRESSOR GZIP # zip BRIK dsets
29
30# ---------------------------------------------------------------------------
31# top level definitions (constant across demo)
32# ---------------------------------------------------------------------------
33
34# labels
35set subj = $1
36set ses = $2
37
38# for convenience, "full" subj ID and path
39set subjid = ${subj}_${ses}
40set subjpa = ${subj}/${ses}
41
42# upper directories
43set dir_inroot = ${PWD:h} # one dir above scripts/
44set dir_log = ${dir_inroot}/logs
45set dir_basic = ${dir_inroot}/data_00_basic
46set dir_ap = ${dir_inroot}/data_21_ap
47
48# subject directories
49set sdir_basic = ${dir_basic}/${subjpa}
50set sdir_func = ${sdir_basic}/func
51set sdir_anat = ${sdir_basic}/anat
52set sdir_ap = ${dir_ap}/${subjpa}
53
54# supplementary directory (reference data, etc.)
55###set dir_suppl = ${dir_inroot}/supplements
56###set template = ${dir_suppl}/*****
57
58# set output directory
59set sdir_out = ${sdir_ap}
60set lab_out = 21_ap
61
62# --------------------------------------------------------------------------
63# data and control variables
64# --------------------------------------------------------------------------
65
66# dataset inputs
67
68set dset_anat = ${sdir_anat}/${subjid}*T1w_ROT.nii.gz
69set task_name = checkbrd
70set all_epi = ( ${sdir_func}/${subjid}*task-${task_name}_run*.nii.gz )
71
72set epi_tr = `3dinfo -tr ${all_epi[1]}` # TR of EPI data
73
74# control variables
75set nt_rm = 3 # number of time points to remove at start
76set blur_size = 4.0 # blur size in mm (here, 2x min vox dim)
77set final_dxyz = 2.0 # final voxel size (isotropic dim)
78set cen_motion = 0.2 # censor threshold for motion (enorm)
79set cen_outliers = 0.05 # censor threshold for outlier frac
80
81# calculate offset for stim timing, since removing pre-steady state TRs
82set toffset = `echo " -1.0 * ${epi_tr} * ${nt_rm} " | bc`
83echo "++ Removing ${nt_rm} vols"
84echo " -> since TR=${epi_tr} s, we use stim time offset: ${toffset} s"
85
86
87# check available N_threads and report what is being used
88set nthr_avail = `afni_system_check.py -disp_num_cpu`
89set nthr_using = `afni_check_omp`
90
91echo "++ INFO: Using ${nthr_using} of available ${nthr_avail} threads"
92
93# ----------------------------- biowulf-cmd --------------------------------
94if ( $use_slurm ) then
95 # try to use /lscratch for speed; store "real" output dir for later copy
96 if ( -d /lscratch/$SLURM_JOBID ) then
97 set usetemp = 1
98 set sdir_BW = ${sdir_out}
99 set sdir_out = /lscratch/$SLURM_JOBID/${subjid}
100
101 # prep for group permission reset
102 \mkdir -p ${sdir_BW}
103 set grp_own = `\ls -ld ${sdir_BW} | awk '{print $4}'`
104 else
105 set usetemp = 0
106 endif
107endif
108# ---------------------------------------------------------------------------
109
110# ---------------------------------------------------------------------------
111# run programs
112# ---------------------------------------------------------------------------
113
114# make output directory and go to it
115\mkdir -p ${sdir_out}
116cd ${sdir_out}
117
118# ----- create command script with AP cmd
119set run_script = ap.cmd.${subj}
120
121cat << EOF >! ${run_script}
122
123# AP: salmon processing
124#
125# NOTES
126#
127# + The anatomical was pre-rotated to have better alignment with FOV
128# axes, for viewing. Therefore, we apply that same rotation as a
129# pre-rotation to the EPI dsets during EPI-anatomical alignment.
130#
131# + Because the EPI and anatomical have similar contrast here, we use
132# 'lpa+ZZ' as the EPI-anatomical alignment cost function (typically,
133# it would be 'lpc+ZZ', since EPIs and anatomicals often have
134# inverse tissue contrasts)
135#
136# + We turned off skullstripping for this dset
137#
138# + Input vox are 2.0x2.0x2.5 mm
139# - chosen blur was 2x min voxel dim (so, 4 mm), on larger side of
140# typical single echo recommendation
141# - final voxel size chosen as 2 mm iso (no need to really upsample)
142#
143# + Not using '-radial_correlate_blocks tcat volreg'
144#
145# + Not using a template (just subject anatomical)
146
147afni_proc.py \
148 -subj_id ${subj} \
149 -dsets ${all_epi} \
150 -copy_anat ${dset_anat} \
151 -anat_has_skull no \
152 -blocks despike tshift align volreg blur mask scale \
153 regress \
154 -tcat_remove_first_trs ${nt_rm} \
155 -align_opts_aea -cost lpa+ZZ \
156 -pre_matrix ${sdir_anat}/mat_rot_anat.1D \
157 -volreg_align_to MIN_OUTLIER \
158 -volreg_align_e2a \
159 -volreg_warp_dxyz ${final_dxyz} \
160 -volreg_compute_tsnr yes \
161 -mask_epi_anat yes \
162 -blur_size ${blur_size} \
163 -regress_stim_times ${sdir_func}/stim_${task_name}.1D \
164 -regress_stim_labels ${task_name} \
165 -regress_basis 'BLOCK(10,1)' \
166 -regress_stim_times_offset ${toffset} \
167 -regress_compute_fitts \
168 -regress_make_ideal_sum sum_ideal.1D \
169 -regress_motion_per_run \
170 -regress_censor_motion ${cen_motion} \
171 -regress_censor_outliers ${cen_outliers} \
172 -regress_est_blur_epits \
173 -regress_est_blur_errts \
174 -regress_run_clustsim no \
175 -html_review_style pythonic \
176 -execute
177EOF
178
179if ( ${status} ) then
180 set ecode = 1
181 goto COPY_AND_EXIT
182endif
183
184# ----- execute AP command to make processing script
185
186tcsh -xef ${run_script} |& tee output.ap.cmd.${subj}
187
188if ( ${status} ) then
189 set ecode = 2
190 goto COPY_AND_EXIT
191endif
192
193# ----- execute the proc script, saving text info
194
195time tcsh -xef proc.${subj} |& tee output.proc.${subj}
196
197if ( ${status} ) then
198 set ecode = 3
199 goto COPY_AND_EXIT
200endif
201
202echo "++ FINISHED ${lab_out}"
203
204# ---------------------------------------------------------------------------
205
206COPY_AND_EXIT:
207
208# ----------------------------- biowulf-cmd --------------------------------
209if ( $use_slurm ) then
210 # if using /lscratch, copy back to "real" location
211 if( ${usetemp} && -d ${sdir_out} ) then
212 echo "++ Used /lscratch"
213 echo "++ Copy from: ${sdir_out}"
214 echo " to: ${sdir_BW}"
215 \cp -pr ${sdir_out}/* ${sdir_BW}/.
216
217 # reset group permission
218 chgrp -R ${grp_own} ${sdir_BW}
219 endif
220endif
221# ---------------------------------------------------------------------------
222
223if ( ${ecode} ) then
224 echo "++ BAD FINISH: ${lab_out} (ecode = ${ecode})"
225else
226 echo "++ GOOD FINISH: ${lab_out}"
227endif
228
229exit ${ecode}
do_50_clust.tcsh
¶
This is one example of running 3dClustSim on a processed dataset, as well as using @chauffeur_afni to make snapshots (including internally running 3dClusterize and controlling transparent thresholding).
1#!/bin/tcsh
2
3# DESC: run AP to fully process FMRI data (here, for the salmon scan)
4
5# Process a single subj+ses pair. Run it from its partner run*.tcsh script.
6# Run on a slurm/swarm system (like Biowulf) or on a desktop.
7
8# ---------------------------------------------------------------------------
9
10# use slurm? 1 = yes, 0 = no (def: use if available)
11set use_slurm = $?SLURM_CLUSTER_NAME
12
13# ----------------------------- biowulf-cmd ---------------------------------
14if ( $use_slurm ) then
15 # load modules: ***** add any other necessary ones
16 source /etc/profile.d/modules.csh
17 module load afni
18
19 # set N_threads for OpenMP
20 setenv OMP_NUM_THREADS $SLURM_CPUS_ON_NODE
21endif
22# ---------------------------------------------------------------------------
23
24# initial exit code; we don't exit at fail, to copy partial results back
25set ecode = 0
26
27# set relevant environment variables
28setenv AFNI_COMPRESSOR GZIP # zip BRIK dsets
29
30# ---------------------------------------------------------------------------
31# top level definitions (constant across demo)
32# ---------------------------------------------------------------------------
33
34# labels
35set subj = $1
36set ses = $2
37
38# for convenience, "full" subj ID and path
39set subjid = ${subj}_${ses}
40set subjpa = ${subj}/${ses}
41
42# upper directories
43set dir_inroot = ${PWD:h} # one dir above scripts/
44set dir_log = ${dir_inroot}/logs
45set dir_basic = ${dir_inroot}/data_00_basic
46set dir_ap = ${dir_inroot}/data_21_ap
47set dir_clust = ${dir_inroot}/data_50_clust
48
49# subject directories
50set sdir_basic = ${dir_basic}/${subjpa}
51set sdir_func = ${sdir_basic}/func
52set sdir_anat = ${sdir_basic}/anat
53set sdir_ap = ${dir_ap}/${subjpa}
54set sdir_clust = ${dir_clust}/${subjpa}
55
56# supplementary directory (reference data, etc.)
57###set dir_suppl = ${dir_inroot}/supplements
58###set template = ${dir_suppl}/*****
59
60# ** set output directory
61set sdir_out = ${sdir_clust}
62set lab_out = 50_clust
63
64# --------------------------------------------------------------------------
65# data and control variables
66# --------------------------------------------------------------------------
67
68# dataset inputs
69
70# data to copy to output/working dir
71set resdir = ${sdir_ap}/${subj}.results
72set dset_anat = anat_final.${subj}+orig.HEAD
73set dset_stats = stats.sub-000+orig.HEAD
74set dset_errts = errts.${subj}+orig.HEAD
75set dset_fin_epi = final_epi_vr_base_min_outlier+orig.HEAD
76set file_xmat = X.xmat.1D
77
78# control variables
79
80# ----- set cluster parameters
81set csim_NN = "2" # neighborhood definition (face+edge)
82set csim_sided = "bisided" # 2sided test, sep pos/neg
83set csim_pthr = 0.001 # voxelwise thr in 3dClustSim
84set csim_alpha = 0.05 # nominal FDR
85
86set nclust_simple = 3 # simple cluster extent
87
88
89# check available N_threads and report what is being used
90set nthr_avail = `afni_system_check.py -disp_num_cpu`
91set nthr_using = `afni_check_omp`
92
93echo "++ INFO: Using ${nthr_using} of available ${nthr_avail} threads"
94
95# ----------------------------- biowulf-cmd --------------------------------
96if ( $use_slurm ) then
97 # try to use /lscratch for speed; store "real" output dir for later copy
98 if ( -d /lscratch/$SLURM_JOBID ) then
99 set usetemp = 1
100 set sdir_BW = ${sdir_out}
101 set sdir_out = /lscratch/$SLURM_JOBID/${subjid}
102
103 # prep for group permission reset
104 \mkdir -p ${sdir_BW}
105 set grp_own = `\ls -ld ${sdir_BW} | awk '{print $4}'`
106 else
107 set usetemp = 0
108 endif
109endif
110# ---------------------------------------------------------------------------
111
112# ---------------------------------------------------------------------------
113# run programs
114# ---------------------------------------------------------------------------
115
116# make output directory, go to it, and copy some data in
117\mkdir -p ${sdir_out}
118cd ${sdir_out}
119echo "++ Running in : ${PWD}"
120
1213dcopy -overwrite ${resdir}/${dset_anat} .
1223dcopy -overwrite ${resdir}/${dset_stats} .
1233dcopy -overwrite ${resdir}/${dset_errts} .
1243dcopy -overwrite ${resdir}/${dset_fin_epi} .
125\cp ${resdir}/${file_xmat} .
126
127if ( ${status} ) then
128 set ecode = 1
129 goto COPY_AND_EXIT
130endif
131
132# the final mask here has a lot of holes, so we make a new one and
133# also run some cluster simulations again, in that mask.
134
135# ----- make WB mask for final EPI results
136
137# name of whole brain mask to create
138set mask_wb = mask_anat_in_epi_final.nii.gz
139
140# calc from anat dset extent
1413dAutomask \
142 -overwrite \
143 -prefix mask_anat.nii.gz ${dset_anat}
144
1453dresample \
146 -overwrite \
147 -prefix mask_anat_in_epi.nii.gz \
148 -master ${dset_fin_epi} \
149 -rmode NN \
150 -input mask_anat.nii.gz
151
152# dilate+shrink, filling holes
1533dmask_tool \
154 -overwrite \
155 -prefix mask_anat_in_epi_dil.nii.gz \
156 -dilate_inputs 3 -3 \
157 -input mask_anat_in_epi.nii.gz
158
159# make sure mask overlaps with where EPI data exists
1603dcalc \
161 -overwrite \
162 -a mask_anat_in_epi_dil.nii.gz \
163 -b ${dset_fin_epi} \
164 -expr 'a*bool(b)' \
165 -prefix ${mask_wb}
166
167if ( ${status} ) then
168 set ecode = 2
169 goto COPY_AND_EXIT
170endif
171
172# ----- make dset for image ulay (autobox and smooth slightly)
173
174# don't waste image space on empty regions
1753dAutobox \
176 -overwrite \
177 -prefix mask_anat_abox.nii.gz \
178 -npad 10 \
179 -noclust mask_anat.nii.gz
180
1813dZeropad \
182 -overwrite \
183 -prefix anat_aboxed.nii.gz \
184 -master mask_anat_abox.nii.gz \
185 ${dset_anat}
186
187# smooth the anatomical a bit, for underlaying in images
1883dLocalstat \
189 -overwrite \
190 -nbhd "SPHERE(1)" \
191 -stat osfilt \
192 -prefix anat_aboxed_osfilt.nii.gz \
193 anat_aboxed.nii.gz
194
195if ( ${status} ) then
196 set ecode = 3
197 goto COPY_AND_EXIT
198endif
199
200# ----- calculate ACF within WB mask
201
202# same way afni_proc.py creates this (and only do this
203
204if ( ! -f new_blur_est.${subj}.1D ) then # START_ACF
205 touch new_blur_est.${subj}.1D
206
207 set nepi = 2
208 set runs = (`count -digits 2 1 ${nepi}`)
209
210 # restrict to uncensored TRs, per run
211 foreach run ( $runs )
212 set trs = `1d_tool.py -infile X.xmat.1D -show_trs_uncensored encoded \
213 -show_trs_run $run`
214 if ( $trs == "" ) continue
215 3dFWHMx \
216 -overwrite \
217 -detrend -mask ${mask_wb} \
218 -ACF new_files_3dFWout.3dFWHMx.ACF.errts.r$run.1D \
219 errts.${subj}+orig"[$trs]" >> new_blur_est.${subj}.1D
220 end
221
222 # get average of ACF params across runs: first 3 values from ACF rows
223 # only
224 set blur_est = ( `3dTstat -mean -prefix - \
225 new_blur_est.${subj}.1D'[0..2]{1,3}'\'` )
226
227 echo "++ blur est : ${blur_est}"
228
229 # this is kinda slow, so don't repeat
230 3dClustSim \
231 -overwrite \
232 -both \
233 -mask ${mask_wb} \
234 -acf ${blur_est} \
235 -prefix ClustSim
236
237 if ( ${status} ) then
238 set ecode = 4
239 goto COPY_AND_EXIT
240 endif
241
242endif # END_ACF
243
244set clust_thrvol = `1d_tool.py -verb 0 \
245 -infile ClustSim.NN${csim_NN}_${csim_sided}.1D \
246 -csim_pthr ${csim_pthr} \
247 -csim_alpha ${csim_alpha}`
248
249echo "++ MCC nvoxels : ${clust_thrvol}"
250
251# ----- clusterize for two cases
252
253# this is now just informational, and for WB mask cases, since we
254# have the @chauffeur cmds include clusterize directly, below
255
256# No multiple comparisons correction:
257# only voxelwise thresholding, no cluster thresholding (clust thr = 3)
2583dClusterize \
259 -overwrite \
260 -nosum \
261 -1Dformat \
262 -inset stats.${subj}+orig.HEAD \
263 -idat "checkbrd#0_Coef" \
264 -ithr "checkbrd#0_Tstat" \
265 -NN ${csim_NN} \
266 -clust_nvox ${nclust_simple} -${csim_sided} p=${csim_pthr} \
267 -pref_map Clust_map_NO_MCC_mskd.nii.gz \
268 -pref_dat Clust_dat_NO_MCC_mskd.nii.gz \
269 -mask ${mask_wb} > Clust_table_NO_MCC_mskd.1D
270
271# Using multiple comparisons correction:
272# both voxelwise and clusterwise thresholding
2733dClusterize \
274 -overwrite \
275 -nosum \
276 -1Dformat \
277 -inset stats.${subj}+orig.HEAD \
278 -idat "checkbrd#0_Coef" \
279 -ithr "checkbrd#0_Tstat" \
280 -NN ${csim_NN} \
281 -clust_nvox ${clust_thrvol} -${csim_sided} p=${csim_pthr} \
282 -pref_map Clust_map_YES_MCC_mskd.nii.gz \
283 -pref_dat Clust_dat_YES_MCC_mskd.nii.gz \
284 -mask ${mask_wb} > Clust_table_YES_MCC_mskd.1D
285
286if ( ${status} ) then
287 set ecode = 5
288 goto COPY_AND_EXIT
289endif
290
291# ----- Make images of cluster outputs
292
293set ulay = anat_aboxed_osfilt.nii.gz
294set olay = ${dset_stats}
295
296# from earlier checks, we saw that Cluster #2 from one of hte runs
297# above was a nice location to view
298set coords = ( `3dCM -Icent Clust_map_NO_MCC_mskd.nii.gz'<3>'` )
299
300# these settings are constant across all imgs
301set img_params = ( \
302 -cbar Reds_and_Blues_Inv \
303 -ulay_range 0% 130% \
304 -thr_olay_p2stat 0.001 \
305 -thr_olay_pside bisided \
306 -blowup 4 \
307 -opacity 9 \
308 -montx 1 \
309 -monty 1 \
310 -set_dicom_xyz ${coords} \
311 -olay_boxed_color 'limegreen' \
312 -set_xhairs OFF \
313 -no_cor \
314 -label_mode 0 \
315 -label_size 0 )
316
317# Make images for various cases:
318# ... like transparent thresholding: ON or OFF
319set all_ab = ( Yes No )
320# ... cluster size thr: simple (3 voxels), or derived from 3dClustSim, above
321set all_nclust = ( ${nclust_simple} ${clust_thrvol} )
322# ... overlay type: coefficient/effect estimate, or t-stat
323set all_otype = ( Coef Tstat )
324
325foreach ab ( ${all_ab} )
326 foreach nclust ( ${all_nclust} )
327 foreach otype ( ${all_otype} )
328 set alpha = ${ab}
329 set boxed = ${ab}
330 set nnn = `printf "%03d" ${nclust}`
331
332 # olay range of colorbar
333 if ( "${otype}" == "Tstat" ) then
334 set frange = 4.5
335 else
336 set frange = 3
337 endif
338
339 # apply WB mask or not
340 if ( "${ab}" == "No" ) then
341 set optmask = "-mask ${mask_wb}"
342 set mmm = WB
343 else
344 set optmask = ""
345 set mmm = None
346 endif
347
348 # descriptive output prefix
349 set opref = img_v3_salmon_alpha-${alpha}_boxed-${boxed}
350 set opref = ${opref}_olay-${otype}_mask-${mmm}_clustn-${nnn}
351
352 @chauffeur_afni \
353 -ulay ${ulay} \
354 -olay ${olay} \
355 -prefix ${opref} \
356 -clusterize "-NN 2 -clust_nvox ${nclust} ${optmask}" \
357 -func_range ${frange} \
358 -set_subbricks 0 "checkbrd#0_${otype}" "checkbrd#0_Tstat" \
359 -olay_alpha ${alpha} \
360 -olay_boxed ${boxed} \
361 -prefix ${opref} \
362 ${img_params}
363
364 if ( ${status} ) then
365 set ecode = 5
366 goto COPY_AND_EXIT
367 endif
368 end
369 end
370end
371
372echo "++ FINISHED ${lab_out}"
373
374# ---------------------------------------------------------------------------
375
376COPY_AND_EXIT:
377
378# ----------------------------- biowulf-cmd --------------------------------
379if ( $use_slurm ) then
380 # if using /lscratch, copy back to "real" location
381 if( ${usetemp} && -d ${sdir_out} ) then
382 echo "++ Used /lscratch"
383 echo "++ Copy from: ${sdir_out}"
384 echo " to: ${sdir_BW}"
385 \cp -pr ${sdir_out}/* ${sdir_BW}/.
386
387 # reset group permission
388 chgrp -R ${grp_own} ${sdir_BW}
389 endif
390endif
391# ---------------------------------------------------------------------------
392
393if ( ${ecode} ) then
394 echo "++ BAD FINISH: ${lab_out} (ecode = ${ecode})"
395else
396 echo "++ GOOD FINISH: ${lab_out}"
397endif
398
399exit ${ecode}