1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 /*
8 Plugin to edit an AFNI dataset. This plugin is an interactive version
9 of batch program 3dmerge.
10
11 File: plug_edit.c
12 Author: B. Douglas Ward
13 Date: 15 May 1997
14
15
16 Mod: Added Erode/Dilate option to sever narrow connecting path
17 between clusters, by first eroding the outer layer of voxels,
18 then restoring voxels near the main body of the cluster.
19 Author: B. Douglas Ward
20 Date: 18 June 1998
21 */
22
23
24 #include "afni.h"
25
26 #ifndef ALLOW_PLUGINS
27 # error "Plugins not properly set up -- see machdep.h"
28 #endif
29
30 #define MEGA 1048576 /* 2^20 */
31
32 char * EDIT_main( PLUGIN_interface * ) ;
33
34
35 static char helpstring[] =
36 "Purpose: AFNI plugin to edit data and return new dataset.\n"
37 "Inputs: \n"
38 " Dataset Input and Output datasets\n"
39 " Input Input dataset that must already be in memory \n"
40 " Prefix Prefix for output file name \n"
41 " Session Write output into specified directory (default=./) \n"
42 " Clip Clip intensities in range (lower,upper) to zero \n"
43 " Unscaled Do not apply any automatic scaling factor \n"
44 " Threshold Use threshold sub-brick to censor the intensities \n"
45 " Blur Gaussian blur using specified function width \n"
46 " Zero Vol UL Zero out entries inside the 3D volume defined by: \n"
47 " Zero Vol LL xLL <= x <=xUL, yLL <= y <=yUL, zLL <= z <= zUL \n"
48 " Cluster Form clusters and clip off data not in clusters \n"
49 " Type Options for setting voxel intensities within a cluster \n"
50 " Radius Max. distance for 2 voxels to be connected in a cluster \n"
51 " MinVol Min. volume for a cluster to survive \n"
52 " Erode/Dilate Sever narrow connecting paths between clusters \n"
53 " % Voxels Min. % of active 'neighbors' for a voxel to survive \n"
54 " Dilate Restore voxels near main body of cluster \n"
55 " Filter Filter voxel intensities \n"
56 " Type Defines filter action \n"
57 " Radius Voxel intensity is effected by voxels within this radius\n"
58 " Multiply Multiply intensities by the given factor\n"
59 " Datum Coerce output data to be stored as the given type \n"
60 " Keep Thr Copy the threshold sub-brick into the output dataset \n"
61 " Thr Blur Apply Gaussian blur function to threshold data sub-brick \n"
62 " Thr Filter Apply specified filter to threshold data sub-brick \n"
63 " Thr Datum Coerce threshold data sub-brick to be stored as given type\n"
64 "Author -- BD Ward"
65 ;
66
67
68 /*---------------------------------------------------------------------------*/
69 /*
70 Set up the interface to the user
71 */
72
73
74 DEFINE_PLUGIN_PROTOTYPE
75
PLUGIN_init(int ncall)76 PLUGIN_interface * PLUGIN_init( int ncall )
77 {
78 /*----- plugin option labels -----*/
79 char * boolean_types[2] = {"False", "True"};
80 char * blur_types[3] = {"Sigma", "RMS", "FWHM"};
81 char * cluster_types[7] = {"Keep", "Mean", "Max", "AMax", "SMax", "Size",
82 "Order"};
83 char * filter_types[6] = {"Mean", "NZMean", "Max", "AMax", "SMax", "Aver" };
84 char * brick_types[2] = {"Intensity", "Threshold"};
85 char * datum_types[3] = {"Byte", "Short", "Float"};
86
87 PLUGIN_interface * plint ;
88
89
90 if( ncall > 0 ) return NULL ; /* only one interface */
91 CHECK_IF_ALLOWED("3DEDIT","3D Edit") ; /* 30 Sep 2016 */
92
93 /*-- set titles and call point --*/
94 plint = PLUTO_new_interface( "3D Edit" , "Dataset Editing" , helpstring ,
95 PLUGIN_CALL_VIA_MENU , EDIT_main ) ;
96
97 PLUTO_add_hint( plint , "Edit Dataset Contents" ) ;
98
99 PLUTO_set_sequence( plint , "A:newdset:edit" ) ;
100
101 /*---- line 1 of input: Dataset -----*/
102 PLUTO_add_option (plint, "Dataset", "Dataset", TRUE);
103 PLUTO_add_hint( plint , "Choose input and output" ) ;
104
105 PLUTO_add_dataset (plint, "Input",
106 ANAT_ALL_MASK, FUNC_ALL_MASK,
107 DIMEN_3D_MASK | BRICK_ALLREAL_MASK);
108 PLUTO_add_hint( plint , "Choose input dataset" ) ;
109
110 PLUTO_add_string (plint, "Prefix", 0, NULL, 19);
111 PLUTO_add_hint( plint , "Name output dataset" ) ;
112
113 PLUTO_add_string (plint, "Session", 0, NULL, 19);
114 PLUTO_add_hint( plint , "Name output directory" ) ;
115
116 /*----- line 2 of input: Options -----*/
117 PLUTO_add_option (plint, "Options", "Options", FALSE);
118 PLUTO_add_hint( plint , "Preprocessing steps" ) ;
119
120 PLUTO_add_string (plint, "Thr->Int", 2, boolean_types, 0);
121 PLUTO_add_hint( plint , "Copy threshold over intensity brick?" ) ;
122
123 PLUTO_add_string (plint, "No Neg", 2, boolean_types, 0);
124 PLUTO_add_hint( plint , "Zero out negative values?" ) ;
125
126 PLUTO_add_string (plint, "Abs Value", 2, boolean_types, 0);
127 PLUTO_add_hint( plint , "Take absolute value?" ) ;
128
129 /*----- line 3 of input: Clipping -----*/
130 PLUTO_add_option (plint, "Clip", "Clip", FALSE);
131 PLUTO_add_hint( plint , "Zero out values in some range" ) ;
132
133 PLUTO_add_number (plint, "Lower", -99999, 99999, 0, 0, TRUE);
134 PLUTO_add_hint( plint , "Values above this => zero" ) ;
135
136 PLUTO_add_number (plint, "Upper", -99999, 99999, 0, 0, TRUE);
137 PLUTO_add_hint( plint , "Values below this => zero" ) ;
138
139 PLUTO_add_string (plint, "Unscaled?", 2, boolean_types, 0);
140 PLUTO_add_hint( plint , "Don't apply scaling factors?" ) ;
141
142 /*----- line 4 of input: Threshold -----*/
143 PLUTO_add_option (plint, "Threshold", "Threshold" , FALSE);
144 PLUTO_add_hint( plint , "Zero out if threshold brick too small" ) ;
145
146 PLUTO_add_number (plint, "Cutoff" , 0, 10000, 2, 50, TRUE);
147 PLUTO_add_hint( plint , "Threshold values < this => 0" ) ;
148
149 /*----- line 5 of input: Blurring -----*/
150 PLUTO_add_option (plint, "Blur", "Blur", FALSE);
151 PLUTO_add_hint( plint , "Gaussian convolution" ) ;
152
153 PLUTO_add_string (plint, "Format", 3, blur_types, 0);
154 PLUTO_add_hint( plint , "How blur width is specified" ) ;
155
156 PLUTO_add_number (plint, "Width(mm)", 0, 500, 1, 20, TRUE);
157 PLUTO_add_hint( plint , "Range of blurring function" ) ;
158
159 /*----- line 6 of input: Zero Volume -----*/
160 PLUTO_add_option (plint, "Zero Vol UL", "Zero Vol UL", FALSE);
161 PLUTO_add_number (plint, "x Upper", -999, 999, 0, 0, TRUE);
162 PLUTO_add_number (plint, "y Upper", -999, 999, 0, 0, TRUE);
163 PLUTO_add_number (plint, "z Upper", -999, 999, 0, 0, TRUE);
164
165 /*----- line 7 of input: Zero Volume -----*/
166 PLUTO_add_option (plint, "Zero Vol LL", "Zero Vol LL", FALSE);
167 PLUTO_add_number (plint, "x Lower", -999, 999, 0, 0, TRUE);
168 PLUTO_add_number (plint, "y Lower", -999, 999, 0, 0, TRUE);
169 PLUTO_add_number (plint, "z Lower", -999, 999, 0, 0, TRUE);
170
171 /*----- line 8 of input: Cluster Parameters -----*/
172 PLUTO_add_option (plint, "Cluster", "Cluster", FALSE);
173 PLUTO_add_hint( plint , "Find and reject small clusters" ) ;
174
175 PLUTO_add_string (plint, "Type", 7, cluster_types, 0);
176 PLUTO_add_hint( plint , "How to process data inside clusters" ) ;
177
178 PLUTO_add_number (plint, "Radius(mm)", 0, 100, 1, 20, TRUE);
179 PLUTO_add_hint( plint , "Max distance between 'neighbors'" ) ;
180
181 PLUTO_add_number (plint, "MinVol(ul)", 0, 1000, -1, 100, TRUE);
182 PLUTO_add_hint( plint , "Min size for cluster to survive" ) ;
183
184 /*----- line 8a of input: Erosion/Dilation option -----*/ /* 18 June 1998 */
185 PLUTO_add_option (plint, "Erode/Dilate", "Erode/Dilate", FALSE);
186 PLUTO_add_hint (plint , "Sever narrow connecting paths between clusters");
187
188 PLUTO_add_number (plint, "% Voxels", 0, 100, 0, 50, TRUE);
189 PLUTO_add_hint (plint,
190 "Min % of active 'neighbors' for a voxel to survive");
191
192 PLUTO_add_string (plint, "Dilate?", 2, boolean_types, 0);
193 PLUTO_add_hint (plint , "Restore voxels near main body of cluster");
194
195 /*----- line 9 of input: Filtering -----*/
196 PLUTO_add_option (plint, "Filter", "Filter", FALSE);
197 PLUTO_add_string (plint, "Type", 6, filter_types, 0);
198 PLUTO_add_number (plint, "Radius(mm)", 0, 100, 1, 20, TRUE);
199
200 /*----- line 10 of input: Multiply -----*/
201 PLUTO_add_option (plint, "Multiply", "Multiply", FALSE);
202 PLUTO_add_number (plint, "Factor", -99999, 99999, 0, 1, TRUE);
203
204 /*----- line 11 of input: Datum -----*/
205 PLUTO_add_option (plint, "Datum", "Datum", FALSE);
206 PLUTO_add_string (plint, "Type", 3, datum_types, 1);
207
208 /*----- line 12 of input: Keep Threshold -----*/
209 PLUTO_add_option (plint, "Keep Thr", "Keep Thr", FALSE);
210 PLUTO_add_string (plint, "Keep?", 2, boolean_types, 0);
211
212 /*----- line 13 of input: Threshold Blur -----*/
213 PLUTO_add_option (plint, "Thr Blur", "Thr Blur", FALSE);
214 PLUTO_add_string (plint, "Format", 3, blur_types, 0);
215 PLUTO_add_number (plint, "Width(mm)", 0, 100, 1, 20, TRUE);
216
217 /*----- line 14 of input: Threshold Filter -----*/
218 PLUTO_add_option (plint, "Thr Filter", "Thr Filter", FALSE);
219 PLUTO_add_string (plint, "Type", 6, filter_types, 0);
220 PLUTO_add_number (plint, "Radius(mm)", 0, 100, 1, 20, TRUE);
221
222 /*----- line 15 of input: Threshold Datum -----*/
223 PLUTO_add_option (plint, "Thr Datum", "Thr Datum", FALSE);
224 PLUTO_add_string (plint, "Type", 3, datum_types, 1);
225
226 return plint ;
227 }
228
229
230 /*---------------------------------------------------------------------------*/
231 /*
232 Routine to read the editing options.
233 */
234
EDIT_opts(PLUGIN_interface * plint,THD_3dim_dataset ** dset,EDIT_options * edopt,char ** new_prefix,char ** new_session,int * datum,int * keepthr,int * thrdatum)235 char * EDIT_opts
236 (
237 PLUGIN_interface * plint, /* plugin interface */
238 THD_3dim_dataset ** dset, /* original dataset */
239 EDIT_options * edopt, /* the editing options */
240 char ** new_prefix, /* output file name for edited dataset */
241 char ** new_session, /* output directory name */
242 int * datum, /* output intensity sub-brick data type */
243 int * keepthr, /* boolean for keep threshold sub-brick */
244 int * thrdatum /* output threshold sub-brick data type */
245 )
246
247 {
248 char * tag; /* plugin option tag */
249 char * str; /* input string */
250 float rmm; /* cluster or filter radius (mm) */
251 float vmul; /* cluster minimum volume (ul) */
252 float thresh; /* threshold level */
253 MCW_idcode * idc ; /* dataset id code */
254 int ival; /* integer value input */
255 float bot, top; /* clip option limits */
256 float blur; /* Gaussian blur function width */
257 float fval; /* input floating point value */
258 float dx, dy, dz, dxyz; /* voxel dimensions */
259 float x1, x2, y1, y2, z1, z2; /* zero volume limits */
260 float pv; /* pv % voxels within rmm must be active */
261
262
263 /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/
264 if( plint == NULL )
265 return
266 "*********************\n"
267 "EDIT_opts: NULL input\n"
268 "*********************";
269
270
271 /*--------- go to first input line ---------*/
272 tag = PLUTO_get_optiontag(plint) ;
273 if( (tag==NULL) || (strcmp(tag,"Dataset") != 0) )
274 return
275 "*********************************\n"
276 "EDIT_opts: Bad dataset option tag\n"
277 "*********************************";
278
279 idc = PLUTO_get_idcode(plint) ;
280 (*dset) = PLUTO_find_dset(idc) ;
281 if( (*dset) == NULL )
282 return
283 "****************************\n"
284 "EDIT_opts: Bad input dataset\n"
285 "****************************";
286
287 if (DSET_NUM_TIMES((*dset)) > 1)
288 return
289 "*************************************************\n"
290 "EDIT_opts: Unable to edit time-dependent datasets\n"
291 "*************************************************";
292
293 /*----- get the dimensions -----*/
294 dx = fabs((*dset)->daxes->xxdel);
295 dy = fabs((*dset)->daxes->yydel);
296 dz = fabs((*dset)->daxes->zzdel);
297 dxyz = dx*dy*dz ;
298
299
300 str = PLUTO_get_string(plint);
301 if (str != NULL)
302 {
303 if( ! PLUTO_prefix_ok(str) )
304 return
305 "*********************\n"
306 "EDIT_opts: bad prefix\n"
307 "*********************";
308 else
309 *new_prefix = str;
310 }
311
312 str = PLUTO_get_string(plint);
313 if (str != NULL)
314 {
315 *new_session = str;
316 }
317
318
319 /*------ loop over remaining options, check their tags, process them -----*/
320 do
321 {
322 tag = PLUTO_get_optiontag(plint) ;
323 if( tag == NULL ) break ;
324
325
326 /*----- Miscellaneous Options -----*/
327 if (strcmp (tag, "Options") == 0)
328 {
329 str = PLUTO_get_string(plint);
330 if (strcmp (str, "True") == 0)
331 {
332 if (DSET_THRESH_INDEX(*dset) < 0)
333 return
334 "*********************************************\n"
335 "EDIT_opts: Dataset has no threshold sub-brick\n"
336 "*********************************************";
337 else
338 edopt->thtoin = 1;
339 }
340 else
341 edopt->thtoin = 0;
342
343 str = PLUTO_get_string(plint);
344 if (strcmp (str, "True") == 0)
345 edopt->noneg = 1;
346 else
347 edopt->noneg = 0;
348
349 str = PLUTO_get_string(plint);
350 if (strcmp (str, "True") == 0)
351 edopt->abss = 1;
352 else
353 edopt->abss = 0;
354
355 continue;
356 }
357
358
359 /*----- Clip Option -----*/
360 if (strcmp(tag,"Clip") == 0)
361 {
362 bot = PLUTO_get_number(plint);
363 top = PLUTO_get_number(plint);
364 str = PLUTO_get_string(plint);
365
366 if (bot >= top)
367 return
368 "**********************************************************\n"
369 "EDIT_opts: First clip value must be less than second value\n"
370 "**********************************************************";
371
372 edopt->clip_bot = bot;
373 edopt->clip_top = top;
374
375 if (strcmp (str, "True") == 0)
376 edopt->clip_unscaled = 1;
377 else
378 edopt->clip_unscaled = 0;
379
380 continue;
381 }
382
383
384 /*----- Threshold Option -----*/
385 if (strcmp(tag,"Threshold") == 0)
386 {
387 thresh = PLUTO_get_number(plint) ;
388
389 if (thresh < 0.0)
390 return
391 "******************************\n"
392 "EDIT_opts: Bad Threshold input\n"
393 "******************************";
394
395 if( thresh > 0.0 && DSET_THRESH_INDEX(*dset) < 0 )
396 return
397 "*********************************************\n"
398 "EDIT_opts: Dataset has no threshold sub-brick\n"
399 "*********************************************";
400
401 edopt->thresh = thresh;
402 edopt->thbot = -thresh; /* 26 Dec 2007 */
403
404 continue;
405 }
406
407
408 /*----- Blur Option -----*/
409 if (strcmp(tag,"Blur") == 0)
410 {
411 str = PLUTO_get_string(plint);
412 blur = PLUTO_get_number(plint);
413
414 if (blur <= 0.0 )
415 return
416 "*****************************\n"
417 "EDIT_opts: Illegal Blur input\n"
418 "*****************************";
419
420 if (strcmp(str,"Sigma") == 0)
421 edopt->blur = blur;
422 else
423 if (strcmp(str,"RMS") == 0)
424 edopt->blur = RMS_TO_SIGMA(blur);
425 else
426 if (strcmp(str,"FWHM") == 0)
427 edopt->blur = FWHM_TO_SIGMA(blur);
428 else
429 return
430 "******************************\n"
431 "EDIT_opts: Illegal Blur option\n"
432 "******************************";
433
434 continue;
435 }
436
437
438 /*----- Zero Volume Option -----*/
439 if (strcmp(tag, "Zero Vol UL") == 0)
440 {
441 x2 = PLUTO_get_number(plint);
442 y2 = PLUTO_get_number(plint);
443 z2 = PLUTO_get_number(plint);
444
445 tag = PLUTO_get_optiontag(plint);
446 if (strcmp(tag, "Zero Vol LL") == 0)
447 {
448 x1 = PLUTO_get_number(plint);
449 y1 = PLUTO_get_number(plint);
450 z1 = PLUTO_get_number(plint);
451 }
452 else
453 return
454 "***************************\n"
455 "EDIT_opts: Need Zero Vol LL\n"
456 "***************************";
457
458 edopt->zv_x1 = x1; edopt->zv_x2 = x2;
459 edopt->zv_y1 = y1; edopt->zv_y2 = y2;
460 edopt->zv_z1 = z1; edopt->zv_z2 = z2;
461 edopt->do_zvol = 1;
462 continue;
463 }
464
465
466 if (strcmp(tag, "Zero Vol LL") == 0)
467 {
468 return
469 "***************************\n"
470 "EDIT_opts: Need Zero Vol UL\n"
471 "***************************";
472 }
473
474
475 /*----- Cluster Option -----*/
476 if (strcmp(tag,"Cluster") == 0)
477 {
478 str = PLUTO_get_string(plint);
479 rmm = PLUTO_get_number(plint) ;
480 vmul = PLUTO_get_number(plint) ;
481
482 if ( (rmm < dx) && (rmm < dy) && (rmm < dz) )
483 return
484 "***********************************\n"
485 "EDIT_opts: Cluster rmm is too small\n"
486 "***********************************";
487
488 if (vmul <= dxyz)
489 return
490 "************************************\n"
491 "EDIT_opts: Cluster vmul is too small\n"
492 "************************************";
493
494 edopt->clust_rmm = rmm;
495 edopt->clust_vmul = vmul;
496
497 if (strcmp(str,"Keep") == 0)
498 edopt->edit_clust = ECFLAG_SAME;
499 else
500 if (strcmp(str,"Mean") == 0)
501 edopt->edit_clust = ECFLAG_MEAN;
502 else
503 if (strcmp(str,"Max") == 0)
504 edopt->edit_clust = ECFLAG_MAX;
505 else
506 if (strcmp(str,"AMax") == 0)
507 edopt->edit_clust = ECFLAG_AMAX;
508 else
509 if (strcmp(str,"SMax") == 0)
510 edopt->edit_clust = ECFLAG_SMAX;
511 else
512 if (strcmp(str,"Size") == 0)
513 edopt->edit_clust = ECFLAG_SIZE;
514 else
515 if (strcmp(str,"Order") == 0)
516 edopt->edit_clust = ECFLAG_ORDER;
517 else
518 if (strcmp(str,"Depth") == 0)
519 edopt->edit_clust = ECFLAG_DEPTH;
520 else
521 return
522 "*********************************\n"
523 "EDIT_opts: Illegal Cluster option\n"
524 "*********************************";
525
526 continue;
527 }
528
529
530 /*----- Erosion/Dilation Option -----*/
531 if (strcmp(tag,"Erode/Dilate") == 0)
532 {
533 pv = PLUTO_get_number(plint);
534 if ((pv > 0.0) && (edopt->clust_rmm <= 0.0))
535 return
536 "******************************************************\n"
537 "EDIT_opts: Erode/Dilate requires use of Cluster option\n"
538 "******************************************************";
539 else
540 edopt->erode_pv = pv / 100.0;
541
542 str = PLUTO_get_string(plint);
543 if (strcmp (str, "True") == 0)
544 {
545 if (pv <= 0.0)
546 return
547 "**********************************************\n"
548 "EDIT_opts: Dilate requires use of Erode option\n"
549 "**********************************************";
550 else
551 edopt->dilate = 1;
552 }
553 else
554 edopt->dilate = 0;
555
556 continue;
557 }
558
559
560 /*----- Filter Option -----*/
561 if (strcmp(tag,"Filter") == 0)
562 {
563 str = PLUTO_get_string(plint);
564 rmm = PLUTO_get_number(plint) ;
565
566 if ( (rmm < dx) && (rmm < dy) && (rmm < dz) )
567 return
568 "**********************************\n"
569 "EDIT_opts: Filter rmm is too small\n"
570 "**********************************";
571
572 edopt->filter_rmm = rmm;
573
574 if (strcmp(str,"Mean") == 0)
575 edopt->filter_opt = FCFLAG_MEAN;
576 else
577 if (strcmp(str,"NZMean") == 0)
578 edopt->filter_opt = FCFLAG_NZMEAN;
579 else
580 if (strcmp(str,"Max") == 0)
581 edopt->filter_opt = FCFLAG_MAX;
582 else
583 if (strcmp(str,"AMax") == 0)
584 edopt->filter_opt = FCFLAG_AMAX;
585 else
586 if (strcmp(str,"SMax") == 0)
587 edopt->filter_opt = FCFLAG_SMAX;
588 else
589 if (strcmp(str,"Aver") == 0) /* 07 Jan 1998 */
590 edopt->filter_opt = FCFLAG_AVER;
591 else
592 return
593 "********************************\n"
594 "EDIT_opts: Illegal Filter option\n"
595 "********************************";
596
597 continue;
598 }
599
600
601 /*----- Multiply Option -----*/
602 if (strcmp(tag,"Multiply") == 0)
603 {
604 fval = PLUTO_get_number(plint);
605
606 if (fval == 0.0)
607 return
608 "*****************************\n"
609 "EDIT_opts: Bad Multiply input\n"
610 "*****************************";
611
612 edopt->mult = fval;
613
614 continue;
615 }
616
617
618 /*----- Datum Type Option -----*/
619 if (strcmp(tag, "Datum") == 0)
620 {
621 str = PLUTO_get_string(plint);
622 if (strcmp(str,"Byte") == 0)
623 *datum = MRI_byte;
624 else
625 if (strcmp(str,"Short") == 0)
626 *datum = MRI_short;
627 else
628 if (strcmp(str,"Float") == 0)
629 *datum = MRI_float;
630 else
631 {
632 return
633 "*****************************\n"
634 "EDIT_opts: Illegal Datum type\n"
635 "*****************************";
636 }
637
638 continue;
639 }
640
641
642 /*----- Keep Threshold Option -----*/
643 if (strcmp(tag,"Keep Thr") == 0)
644 {
645 str = PLUTO_get_string(plint);
646 if (strcmp (str, "True") == 0)
647 {
648 if (DSET_THRESH_INDEX(*dset) < 0)
649 return
650 "*********************************************\n"
651 "EDIT_opts: Dataset has no threshold sub-brick\n"
652 "*********************************************";
653 else
654 *keepthr = 1;
655 }
656 else
657 *keepthr = 0;
658
659 continue;
660 }
661
662
663 /*----- Threshold Blur Option -----*/
664 if (strcmp(tag,"Thr Blur") == 0)
665 {
666 if (DSET_THRESH_INDEX(*dset) < 0)
667 return
668 "*********************************************\n"
669 "EDIT_opts: Dataset has no threshold sub-brick\n"
670 "*********************************************";
671
672 str = PLUTO_get_string(plint);
673 blur = PLUTO_get_number(plint) ;
674
675 if (blur <= 0.0 )
676 return
677 "***************************************\n"
678 "EDIT_opts: Illegal Threshold Blur input\n"
679 "***************************************";
680
681 if (strcmp(str,"Sigma") == 0)
682 edopt->thrblur = blur;
683 else
684 if (strcmp(str,"RMS") == 0)
685 edopt->thrblur = RMS_TO_SIGMA(blur);
686 else
687 if (strcmp(str,"FWHM") == 0)
688 edopt->thrblur = FWHM_TO_SIGMA(blur);
689 else
690 return
691 "******************************\n"
692 "EDIT_opts: Illegal Blur option\n"
693 "******************************";
694
695 *keepthr = 1;
696
697 continue;
698 }
699
700
701 /*----- Threshold Filter Option -----*/
702 if (strcmp(tag,"Thr Filter") == 0)
703 {
704 if (DSET_THRESH_INDEX(*dset) < 0)
705 return
706 "*********************************************\n"
707 "EDIT_opts: Dataset has no threshold sub-brick\n"
708 "*********************************************";
709
710 str = PLUTO_get_string(plint);
711 rmm = PLUTO_get_number(plint) ;
712
713 if ( (rmm < dx) && (rmm < dy) && (rmm < dz) )
714 return
715 "**************************************\n"
716 "EDIT_opts: Thr Filter rmm is too small\n"
717 "**************************************";
718
719 edopt->thrfilter_rmm = rmm;
720
721 if (strcmp(str,"Mean") == 0)
722 edopt->thrfilter_opt = FCFLAG_MEAN;
723 else
724 if (strcmp(str,"NZMean") == 0)
725 edopt->thrfilter_opt = FCFLAG_NZMEAN;
726 else
727 if (strcmp(str,"Max") == 0)
728 edopt->thrfilter_opt = FCFLAG_MAX;
729 else
730 if (strcmp(str,"AMax") == 0)
731 edopt->thrfilter_opt = FCFLAG_AMAX;
732 else
733 if (strcmp(str,"SMax") == 0)
734 edopt->thrfilter_opt = FCFLAG_SMAX;
735 else
736 if (strcmp(str,"Aver") == 0) /* 07 Jan 1998 */
737 edopt->thrfilter_opt = FCFLAG_AVER;
738 else
739 return
740 "************************************\n"
741 "EDIT_opts: Illegal Thr Filter option\n"
742 "************************************";
743
744 *keepthr = 1;
745
746 continue;
747 }
748
749
750 /*----- Threshold Datum Type Option -----*/
751 if (strcmp(tag, "Thr Datum") == 0)
752 {
753 if (DSET_THRESH_INDEX(*dset) < 0)
754 return
755 "*********************************************\n"
756 "EDIT_opts: Dataset has no threshold sub-brick\n"
757 "*********************************************";
758
759 str = PLUTO_get_string(plint);
760 if (strcmp(str,"Byte") == 0)
761 *thrdatum = MRI_byte;
762 else
763 if (strcmp(str,"Short") == 0)
764 *thrdatum = MRI_short;
765 else
766 if (strcmp(str,"Float") == 0)
767 *thrdatum = MRI_float;
768 else
769 {
770 return
771 "***************************************\n"
772 "EDIT_opts: Illegal Threshold Datum type\n"
773 "***************************************";
774 }
775
776 *keepthr = 1;
777
778 continue;
779 }
780
781
782 /*----- Illegal Option -----*/
783 else
784 {
785 return
786 "***********************************\n"
787 "EDIT_opts: Illegal optiontag found!\n"
788 "***********************************";
789 }
790
791 } while(1) ;
792
793
794 /*---------- End of input options ----------*/
795
796 return NULL;
797 }
798
799
800 /*---------------------------------------------------------------------------*/
801 /*
802 Main routine for this plugin (will be called from AFNI).
803 */
804
EDIT_main(PLUGIN_interface * plint)805 char * EDIT_main( PLUGIN_interface * plint )
806 {
807 EDIT_options PE_edopt;
808 int PE_keepthr = 0;
809 int PE_datum = ILLEGAL_TYPE;
810 int PE_thdatum = ILLEGAL_TYPE;
811 int PE_be_quiet = 0;
812 char * PE_output_session = NULL;
813 char * PE_output_prefix = NULL;
814
815
816 int nx,ny,nz , nxyz , ii , ival;
817 THD_3dim_dataset * old_dset = NULL, * dset=NULL , * new_dset=NULL ;
818 int datum ;
819 float fimfac , fimfacinv , first_fimfac , thrfac ;
820 int output_datum , output_thdatum ;
821 int input_datum , input_thdatum , first_datum ;
822
823 float thr_stataux[MAX_STAT_AUX] ;
824 char * str;
825
826
827
828 /*-- set up for dataset editing --*/
829 INIT_EDOPT( &PE_edopt ) ;
830
831
832 /*----- read input options -----*/
833 str = EDIT_opts (plint, &old_dset, &PE_edopt,
834 &PE_output_prefix, &PE_output_session, &PE_datum,
835 &PE_keepthr, &PE_thdatum);
836 if (str != NULL) return (str);
837
838 /*----- make a copy of the original dataset -----*/
839 dset = PLUTO_copy_dset (old_dset, NULL);
840 DSET_unload (old_dset);
841
842 /*----- get the dimensions -----*/
843 nx = dset->daxes->nxx ;
844 ny = dset->daxes->nyy ;
845 nz = dset->daxes->nzz ; nxyz = nx*ny*nz ;
846
847
848 ival = DSET_PRINCIPAL_VALUE(dset) ;
849 input_datum = DSET_BRICK_TYPE(dset,ival) ;
850 if (PE_datum >= 0) output_datum = PE_datum ;
851 else output_datum = input_datum ;
852
853 new_dset = EDIT_empty_copy( dset ) ;
854
855 EDIT_dset_items( new_dset ,
856 ADN_prefix , PE_output_prefix ,
857 ADN_label1 , PE_output_prefix ,
858 ADN_directory_name , PE_output_session ,
859 ADN_none ) ;
860 strcat( new_dset->self_name , "(PE)" ) ;
861
862 { char * his = PLUTO_commandstring(plint) ;
863 tross_Copy_History( dset , new_dset ) ;
864 tross_Append_History( new_dset, his ) ; free(his) ;
865 }
866
867 if( ! PE_keepthr && new_dset->dblk->nvals > 1 )
868 EDIT_dset_items( new_dset ,
869 ADN_nvals , 1 ,
870 ADN_func_type , FUNC_FIM_TYPE ,
871 ADN_none ) ;
872
873 if ( PE_keepthr && ISFUNC(new_dset) && FUNC_HAVE_THR(new_dset->func_type) )
874 {
875 ii = FUNC_ival_thr[dset->func_type] ;
876 input_thdatum = DSET_BRICK_TYPE(dset,ii) ;
877 if (PE_thdatum >= 0) output_thdatum = PE_thdatum ;
878 else output_thdatum = input_thdatum ;
879 }
880 else
881 {
882 output_thdatum = input_thdatum = ILLEGAL_TYPE ;
883 }
884
885 if ( THD_is_file(new_dset->dblk->diskptr->header_name) )
886 {
887 fprintf(stderr,
888 "*** Output file %s already exists -- cannot continue!\n",
889 new_dset->dblk->diskptr->header_name ) ;
890 return("*** Output file already exists -- cannot continue!");
891 /*EXIT(1) ;*/
892 }
893
894 if (! PE_be_quiet)
895 {
896 printf("-- editing input dataset in memory (%.1f MB)",
897 ((double)dset->dblk->total_bytes) / MEGA ) ;
898 fflush(stdout) ;
899 }
900
901
902 EDIT_one_dataset( dset , &PE_edopt ) ; /* all the real work */
903
904
905 if (! PE_be_quiet) { printf(".\n") ; fflush(stdout) ; }
906
907
908 /** Coerce the output data type into a new brick, if needed **/
909 ival = DSET_PRINCIPAL_VALUE(dset) ;
910 ii = DSET_PRINCIPAL_VALUE(new_dset) ;
911
912 if( input_datum == output_datum )
913 {
914 /*
915 Attach the brick of the input dataset to the brick of the output.
916 This isn't exactly kosher, but we are exiting almost immediately.
917 */
918 if (! PE_be_quiet)
919 printf ("connecting edited input to be output \n");
920 mri_fix_data_pointer (DSET_ARRAY(dset,ival), DSET_BRICK(new_dset,ii));
921 DSET_BRICK_FACTOR(new_dset,ii) = DSET_BRICK_FACTOR(dset,ival);
922 }
923 else
924 {
925 /** Must create a new brick and do the conversion **/
926 void * dfim , * efim ;
927 float etop ;
928
929 if(! PE_be_quiet)
930 {
931 printf("-- coercing output datum to be %s\n",
932 MRI_TYPE_name[output_datum]);
933 }
934
935 efim = DSET_ARRAY(dset,ival) ;
936 dfim = (void *) XtMalloc( mri_datum_size(output_datum) * nxyz ) ;
937
938 fimfac = EDIT_coerce_autoscale( nxyz , input_datum , efim ,
939 output_datum , dfim ) ;
940
941 DSET_BRICK_FACTOR(new_dset,ii) = (fimfac != 0.0 && fimfac != 1.0)
942 ? 1.0/fimfac : 0.0 ;
943
944 EDIT_substitute_brick( new_dset , ii , output_datum , dfim ) ;
945 mri_free( DSET_BRICK(dset,ival) ) ;
946 }
947
948 /** Now do the threshold data **/
949
950 if( output_thdatum >= 0 )
951 {
952 ival = FUNC_ival_thr[ dset->func_type] ;
953 ii = FUNC_ival_thr[new_dset->func_type] ;
954
955 if( input_thdatum == output_thdatum )
956 {
957 if (! PE_be_quiet)
958 printf ("connecting input and output thresholds \n") ;
959 mri_fix_data_pointer (DSET_ARRAY(dset,ival),DSET_BRICK(new_dset,ii));
960 DSET_BRICK_FACTOR(new_dset,ii) = DSET_BRICK_FACTOR(dset,ival) ;
961 }
962 else
963 {
964 void * dfim , * efim ;
965
966 if( ! PE_be_quiet )
967 {
968 printf("-- coercing threshold datum to be %s\n",
969 MRI_TYPE_name[output_thdatum]);
970 }
971
972 efim = DSET_ARRAY(dset,ival) ;
973 dfim = (void *) XtMalloc( mri_datum_size(output_thdatum) * nxyz ) ;
974
975 switch( output_thdatum )
976 {
977 default: fprintf(stderr,"** illegal output_thdatum = %d\n",
978 output_thdatum);
979 return("** illegal output_thdatum");
980 /* EXIT(1) ;*/
981
982 case MRI_float:
983 fimfacinv = 0.0 ;
984 fimfac = DSET_BRICK_FACTOR(dset,ival) ;
985 if( fimfac == 0.0 )
986 {
987 fimfac = (input_thdatum == MRI_short)
988 ? 1.0/FUNC_scale_short[dset->func_type]
989 : (input_thdatum == MRI_byte)
990 ? 1.0/FUNC_scale_byte[dset->func_type] : 0.0 ;
991 }
992 break ;
993
994 case MRI_short:
995 if( input_datum == MRI_float )
996 {
997 fimfac = FUNC_scale_short[new_dset->func_type] ;
998 fimfacinv = 1.0 / fimfac ;
999 }
1000 else
1001 if( input_datum == MRI_byte )
1002 {
1003 fimfac = ((float)FUNC_scale_short[new_dset->func_type])
1004 / FUNC_scale_byte[new_dset->func_type] ;
1005 fimfacinv = 1.0 / FUNC_scale_short[new_dset->func_type] ;
1006 }
1007 else
1008 {
1009 fprintf(stderr,
1010 "** illegal input_thdatum = %d\n",input_thdatum);
1011 return("** illegal input_thdatum");
1012 /* EXIT(1) ;*/
1013 }
1014 break ;
1015
1016 case MRI_byte:
1017 if( input_datum == MRI_float )
1018 {
1019 fimfac = FUNC_scale_byte[new_dset->func_type] ;
1020 fimfacinv = 1.0 / fimfac ;
1021 }
1022 else
1023 if( input_datum == MRI_short )
1024 {
1025 fimfac = ((float)FUNC_scale_byte[new_dset->func_type])
1026 / FUNC_scale_short[new_dset->func_type] ;
1027 fimfacinv = 1.0 / FUNC_scale_byte[new_dset->func_type] ;
1028 }
1029 else
1030 {
1031 fprintf(stderr,"** illegal input_thdatum = %d\n",
1032 input_thdatum);
1033 return("** illegal input_thdatum");
1034 /* EXIT(1) ;*/
1035 }
1036 break;
1037 }
1038
1039 EDIT_coerce_scale_type( nxyz , fimfac ,
1040 DSET_BRICK_TYPE(dset,ival),efim ,
1041 output_thdatum,dfim );
1042
1043 DSET_BRICK_FACTOR(new_dset,ii) = fimfacinv;
1044 EDIT_substitute_brick( new_dset , ii , output_thdatum , dfim );
1045 mri_free( DSET_BRICK(dset,ival) );
1046 }
1047 }
1048
1049 if (! PE_be_quiet)
1050 printf("-- Writing edited dataset:%s\n" , DSET_BRIKNAME(new_dset) ) ;
1051
1052 ival = PLUTO_add_dset( plint , new_dset , DSET_ACTION_MAKE_CURRENT ) ;
1053
1054 if (ival)
1055 {
1056 THD_delete_3dim_dataset( new_dset , False ) ;
1057 return
1058 "*********************************************\n"
1059 "EDIT_main: failure to add new dataset to AFNI\n"
1060 "*********************************************" ;
1061 }
1062 else
1063 return (NULL) ;
1064
1065 }
1066
1067
1068
1069
1070
1071