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 #include "afni.h"
8 
9 #ifndef ALLOW_PLUGINS
10 #  error "Plugins not properly set up -- see machdep.h"
11 #endif
12 
13 /***********************************************************************
14   Simple plugin to copy a dataset and make a new one.
15 ************************************************************************/
16 
17 static char * COPY_main( PLUGIN_interface * ) ;
18 
19 static char helpstring[] =
20    " Purpose: Creating a copy of a dataset.\n"
21    " Inputs:\n"
22    " Dataset = A dataset in the current session that exists in memory\n"
23    "               (not warp-on-demand).\n"
24    " Prefix  = Filename prefix to be used for the output dataset.\n"
25    " Fill    = How to fill voxel data in new dataset:\n"
26    "             Data [All] = copy all sub-bricks from input\n"
27    "             Zero [All] = fill all sub-bricks with zero\n"
28    "             Zero [One] = make new dataset have only 1 sub-brick,\n"
29    "                          and fill with zero -- this is useful for\n"
30    "                          creating mask datasets using the\n"
31    "                          'Draw Dataset' plugin.\n"
32    " Type    = Lets you change the 'type' of the output dataset, for\n"
33    "             example from anat to func.\n"
34    " Datum   = Lets you set the data type of the new brick.  This will\n"
35    "             only work when using \"Zero [All]\" or \"Zero [One]\"\n"
36    "             Fill modes.\n"
37    "Author -- RWCox"
38 ;
39 
40 #define NFILL 3
41 static char * fill_options[NFILL] = { "Data [All]" , "Zero [All]" , "Zero [One]" } ;
42 
43 #define NDTYPE 4
44 static char * dtype_options[NDTYPE] = {
45   "byte" , "short" , "float" , "complex" } ;
46 static int    dtype_kinds[NDTYPE] = {
47   MRI_byte , MRI_short , MRI_float , MRI_complex } ;
48 
49 /***********************************************************************
50    Set up the interface to the user
51 ************************************************************************/
52 
53 
54 DEFINE_PLUGIN_PROTOTYPE
55 
PLUGIN_init(int ncall)56 PLUGIN_interface * PLUGIN_init( int ncall )
57 {
58    PLUGIN_interface * plint ;
59 
60    if( ncall > 0 ) return NULL ;  /* only one interface */
61    CHECK_IF_ALLOWED("DATASETCOPY","Dataset Copy") ;  /* 30 Sep 2016 */
62 
63    /*-- set titles and call point --*/
64 
65    plint = PLUTO_new_interface( "Dataset Copy" , "Make a Copy of a Dataset" , helpstring ,
66                                  PLUGIN_CALL_VIA_MENU , COPY_main  ) ;
67 
68    PLUTO_add_hint( plint , "Make a Copy of a Dataset" ) ;
69 
70    PLUTO_set_sequence( plint , "A:newdset:copy" ) ;
71 
72    PLUTO_set_runlabels( plint , "Copy+Keep" , "Copy+Close" ) ;  /* 04 Nov 2003 */
73 
74    /*-- first line of input: Dataset --*/
75 
76    PLUTO_add_option( plint , "Input" , "Input" , TRUE ) ;
77    PLUTO_add_dataset(plint , "Dataset" ,
78                                     ANAT_ALL_MASK , FUNC_ALL_MASK ,
79                                     DIMEN_ALL_MASK | BRICK_ALLTYPE_MASK ) ;
80 
81    /*-- second line of input: Prefix for output dataset --*/
82 
83    PLUTO_add_option( plint , "Output" , "Output" , TRUE ) ;
84    PLUTO_add_string( plint , "Prefix" , 0,NULL , 19 ) ;
85 
86    /*-- third line of input: Fill option --*/
87 
88    PLUTO_add_option( plint , "Data Fill" , "Data Fill" , FALSE ) ;
89    PLUTO_add_string( plint , "Method" ,  NFILL,fill_options , 0 ) ;
90 
91    /*-- fourth line of input: Type option --*/
92 
93    PLUTO_add_option( plint , "Dataset" , "Dataset" , FALSE ) ;
94    PLUTO_add_string( plint , "Type" , NUM_DSET_TYPES,DSET_prefixstr , 0 ) ;
95 
96    /*-- fifth line of input: Datum option --*/
97 
98    PLUTO_add_option( plint , "Datum" , "Datum" , FALSE ) ;
99    PLUTO_add_string( plint , "Datum" , NDTYPE,dtype_options, 2 ) ;
100 
101    return plint ;
102 }
103 
104 /***************************************************************************
105   Main routine for this plugin (will be called from AFNI).
106 ****************************************************************************/
107 
COPY_main(PLUGIN_interface * plint)108 static char * COPY_main( PLUGIN_interface * plint )
109 {
110    char * tag , * new_prefix , * cpt ;
111    MCW_idcode * idc ;
112    THD_3dim_dataset * dset , * new_dset ;
113    int ival , zfill=0 , ftyp=-1 , dtyp=-1, type_index=-1, data_type=-1 ;
114 
115    /*--------------------------------------------------------------------*/
116    /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/
117 
118    if( plint == NULL )
119       return "**********************\n"
120              "COPY_main:  NULL input\n"
121              "**********************"  ;
122 
123    PLUTO_next_option(plint) ;
124    idc  = PLUTO_get_idcode(plint) ;
125    dset = PLUTO_find_dset(idc) ;
126    if( dset == NULL )
127       return "*****************************\n"
128              "COPY_main:  bad input dataset\n"
129              "*****************************"  ;
130 
131    dtyp = dset->type ;
132 
133    PLUTO_next_option(plint) ;
134    new_prefix = PLUTO_get_string(plint) ;
135    if( ! PLUTO_prefix_ok(new_prefix) )
136       return "**********************\n"
137              "COPY_main:  bad prefix\n"
138              "**********************"  ;
139 
140    tag = PLUTO_get_optiontag(plint) ;
141    while( tag != NULL ){
142 
143       if( strcmp(tag,"Data Fill") == 0 ){
144          cpt   = PLUTO_get_string(plint) ;
145          if( cpt != NULL )
146             zfill = PLUTO_string_index( cpt , NFILL , fill_options ) ;
147       }
148 
149       else if( strcmp(tag,"Dataset") == 0 ){
150          cpt  = PLUTO_get_string(plint) ;
151          ftyp = PLUTO_string_index( cpt , NUM_DSET_TYPES,DSET_prefixstr ) ;
152          if( ftyp >= 0 ){
153             if( ftyp <= LAST_FUNC_TYPE ){
154                dtyp = HEAD_FUNC_TYPE ;
155             } else {
156                ftyp -= (LAST_FUNC_TYPE+1) ;  /* 14 Jul 1998 */
157                dtyp  = HEAD_ANAT_TYPE ;
158             }
159          }
160       }
161 
162       else if( strcmp(tag, "Datum") == 0 ){
163          cpt  = PLUTO_get_string(plint) ;
164 	 type_index = PLUTO_string_index( cpt, NDTYPE, dtype_options ) ;
165 	 if ( (type_index >= 0) && (type_index < NDTYPE) )
166 	    data_type = dtype_kinds[type_index] ;
167       }
168 
169       tag = PLUTO_get_optiontag(plint) ;
170    }
171 
172    /*------------------------------------------------------*/
173    /*---------- At this point, the inputs are OK ----------*/
174 
175    /*-- make a new dataset --*/
176 
177    if( zfill == 0 ){
178       new_dset = PLUTO_copy_dset( dset , new_prefix ) ;
179    } else {
180       new_dset = EDIT_empty_copy( dset ) ;
181 
182       if( ISFUNCTYPE(dtyp) && ( zfill == 2 ) )
183          ftyp = FUNC_FIM_TYPE ;  /* 14 Jul 1998 */
184    }
185 
186    if( new_dset == NULL )
187       return  "****************************************\n"
188               "COPY_main:  failed to copy input dataset\n"
189               "****************************************"  ;
190 
191    DSET_unload( dset ) ;  /* unload old one from memory */
192 
193    /*--- modify dataset, if desired ---*/
194 
195    if( ftyp >= 0 ) EDIT_dset_items( new_dset ,
196                                        ADN_type      , dtyp ,
197                                        ADN_func_type , ftyp ,
198                                     ADN_none ) ;
199 
200    /*--- change type of data stored ---*/
201 
202    if ( (data_type >= 0) )
203    {
204       if ( zfill )
205          EDIT_dset_items( new_dset ,
206                              ADN_datum_all, data_type,
207                           ADN_none ) ;
208       else{
209          DSET_delete(new_dset) ;
210 
211          return  "****************************************************\n"
212                  "COPY_main:  Cannot change type of non-zeroed dataset\n"
213                  "****************************************************"  ;
214       }
215    }
216 
217    /* if 'Zero [All]' or 'Zero [One]' */
218 
219    if( zfill ) {
220       int ityp , nbytes , nvals , ival ;
221       void * new_brick , * bp ;
222 
223       EDIT_dset_items( new_dset ,
224                           ADN_prefix , new_prefix ,
225                           ADN_label1 , new_prefix ,
226                        ADN_none ) ;
227 
228       if ( zfill == 2 ) { /* for 'Zero [One]' case - just make one brick */
229          EDIT_dset_items( new_dset ,
230                              ADN_nvals  , 1 ,
231                              ADN_ntt    , 0 ,
232                           ADN_none ) ;
233       }
234 
235       nvals = DSET_NVALS(new_dset) ;
236 
237       for ( ival = 0 ; ival < nvals ; ival++)        /* get memory for bricks */
238       {                                              /* and zero fill */
239          ityp      = DSET_BRICK_TYPE(new_dset,ival) ;
240          nbytes    = DSET_BRICK_BYTES(new_dset,ival) ;   /* how much data */
241          new_brick = malloc( nbytes ) ;
242          EDIT_substitute_brick( new_dset , ival , ityp , new_brick ) ;
243 
244          bp     = DSET_BRICK_ARRAY(new_dset,ival) ;  /* brick pointer */
245          EDIT_BRICK_FACTOR(new_dset,ival,0.0) ;      /* brick factor  */
246          memset( bp , 0 , nbytes ) ;
247       }
248    }
249 
250    { char *his ;
251      tross_Copy_History( dset , new_dset ) ;
252      his = PLUTO_commandstring( plint ) ;
253      tross_Append_History( new_dset , his ) ; free(his) ;
254    }
255 
256    ival = PLUTO_add_dset( plint , new_dset , DSET_ACTION_MAKE_CURRENT ) ;
257 
258    if( ival ){
259       THD_delete_3dim_dataset( new_dset , False ) ;
260       return "**********************************************\n"
261              "COPY_main:  failure to add new dataset to AFNI\n"
262              "**********************************************" ;
263    }
264 
265    /*-- done successfully!!! --*/
266 
267    return NULL ;
268 }
269