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 #include "afni_plugin.h"
9 
10 #ifndef ALLOW_PLUGINS
11 #  error "Plugins not properly set up -- see machdep.h"
12 #endif
13 
14 /***********************************************************************
15   Plugin to extract 3D brick data
16 ************************************************************************/
17 typedef struct
18 	{
19 		  int nxx;			/* number of voxels in the x direction */
20 		  int nyy;			/* number of voxels in the y direction */
21 		  int nzz;			/* number of voxels in the z direction */
22 		  char *dsetname; /* prefix of data set analyzed */
23 		  int errcode;		/* error code number returned from function */
24 		  int out;			/* flag for writing to a file */
25 		  int format;
26 		  int iloc;
27 		  int xloc;
28 		  int yloc;
29 		  int zloc;
30 		  int fimonly;		/* set to 1 if no threshold is available */
31 		  int DoInt;
32 		  int DoThres;
33 		  int DoInd;
34 		  int intind;
35 		  int	thrind;
36 		  int Nsub;
37 		  int isanat;
38 		  int isfunc;
39 		  float mini, maxi, minth, maxth;
40 		  char * strout;
41 		  FILE * outfile;
42 		  FILE * outlogfile;
43 		  char outname[PLUGIN_MAX_STRING_RANGE]; /* output data file name */
44 	}extract_data;
45 
46 
47 static char helpstring[] =
48   "                   3Ddump98 Plugin\n"
49   "This plugin is used to write to an ascii file the data present in AFNI bricks.\n"
50   "You can apply intenstity or threshold masks to the voxel data that is being extracted.\n\n"
51   "Plugin Inputs:\n\n"
52   "   1- Dataset :\n"
53   "      3D brick  -> 3D AFNI brick of the type :\n"
54   "                    fim, fith, fico, fbuc, etc...\n"
55   "                    spgr, epan.\n\n"
56   "   2- SubBrick info : (Optional) \n"
57   "      Intensity -> Index of the subbrick to be used\n"
58   "                   as an intensity subbrick.\n"
59   "      Threshold -> Index of the subbrick to be used \n"
60   "                   as a threshold subbrick.\n"
61   "   While the subbrick indices are obvious when dealing with most bricks\n"
62   "   You might need to specified them for bricks of the type bucket\n\n"
63   "   3- Intensity Mask : (optional) \n"
64   "      Minimum   -> Minimum boundary for intensity value (inclusive)\n"
65   "      Maximum   -> Maximum boundary for intensity value (inclusive)\n"
66   "   Data from voxels with intensity between Minimum and Maximum \n"
67   "   are written to 'Filename'.\n\n"
68   "   4- Threshold Mask : (optional) \n"
69   "      Minimum   -> Minimum boundary for threshold value (inclusive)\n"
70   "      Maximum   -> Maximum boundary for threshold value (inclusive)\n"
71   "   Data from voxels with threshold value between Minimum and Maximum \n"
72   "   are written to 'Filename'.\n\n"
73   "   5- Output : \n"
74   "      Filename  -> Name of ascii output file. \n"
75   "                   If no name is specified, the default is\n"
76   "                   the prefix of the inbut brick with the \n"
77   "                   extension '.3Ddump' appended at the end.\n"
78   "                   A LOG file, 'Filename.log' is also written to disk.\n"
79   "                   The log file contains all the parameters settings used\n"
80   "                   for generating 'Filename'.\n"
81   "                   The format of 'Filename' is as follows :\n"
82   "                   1- Voxel Index (VI) : Each voxel in an AFNI brick has a unique index.\n"
83   "                                         Indices map directly to XYZ coordinates.\n"
84   "                                         See AFNI plugin documentations for more info.\n"
85   "                   2..4- Voxel coordinates (X Y Z) : Those are the voxel slice coordinates.\n"
86   "                                                     You can see these coordinates in the upper left side\n"
87   "                                                     of the AFNI window. To do so, you must first switch the\n"
88   "                                                     voxel coordinate units from mm to slice coordinates.\n"
89   "                                                     Define Datamode -> Misc -> Voxel Coords ?\n"
90   "                                                     PS: The coords that show up in the graph window\n"
91   "                                                     could be different from those in the upper left side \n"
92   "                                                     of AFNI's main window.\n"
93   "                   5..n- Subbrick values (Sb1 Sb2 ... Sbn) : Voxel values at each subbrick.\n\n"
94   "If you have/find questions/comments/bugs about the plugin, \n"
95   "send me an E-mail: ziad@image.bien.mu.edu\n\n"
96   "                    Ziad Saad   Nov. 9 97, latest update Aug. 26 99.\n\n"
97 ;
98 
99 /* Significant update Aug. 26 99 */
100 /* The indexing into Storear has been swapped (columns became rows and rows columns.
101 That's because each subbrick was not stored in a vector on N elements, rather in N vectors
102 of 1 element each. That made the allocation process very slow, especially now that Bob has
103 malloc and calloc going through his own macros. */
104 
105 /*-------- strings for output format  and some definitions -----------*/
106 
107 static char * yn_strings[] = { "n" , "y" };
108 
109 #define NUM_YN_STRINGS (sizeof(yn_strings)/sizeof(char *))
110 
111 #define YUP  1
112 #define NOPE 0
113 
114 #define ERROR_FILEWRITE		2
115 #define ERROR_OPTIONS		3
116 
117 /*---------- prototypes for internal routines ----------*/
118 static int filexists (char *);
119 
120 static char * DUMP_main( PLUGIN_interface * ) ;
121 
122 static int Dumpit( extract_data* , THD_3dim_dataset * ) ;
123 
124 static void write_ud (extract_data*);
125 
126 static char **allocate2D (int rows,int cols,int element_size);
127 
128 static void free2D(char **a,int rows);
129 
130 static int equal_strings (char *s1,char *s2);
131 
132 
133 /***********************************************************************
134    Set up the interface to the user
135 ************************************************************************/
136 
137 DEFINE_PLUGIN_PROTOTYPE
138 
PLUGIN_init(int ncall)139 PLUGIN_interface * PLUGIN_init( int ncall )
140 {
141    PLUGIN_interface * plint ;
142 
143    CHECK_IF_ALLOWED("3DDUMP98","3D Dump98") ;  /* 30 Sep 2016 */
144 
145    if( ncall > 0 ) return NULL ;  /* only one interface */
146 
147    /*-- set titles and call point --*/
148 
149    plint = PLUTO_new_interface( "3D Dump98" , "Ascii dump of 3D Dataset" , helpstring ,
150                                  PLUGIN_CALL_VIA_MENU , DUMP_main  ) ;
151 
152    PLUTO_set_runlabels( plint , "Dump+Keep" , "Dump+Close" ) ;  /* 04 Nov 2003 */
153 
154    /*-- first line of input: Dataset --*/
155 
156    PLUTO_add_option( plint , "Dataset" , "Dataset" , TRUE ) ;
157    PLUTO_add_dataset(plint , "3D brick" ,
158                                     ANAT_ALL_MASK  ,  FUNC_ALL_MASK ,
159                                     SESSION_ALL_MASK |
160                                     DIMEN_ALL_MASK   | BRICK_ALLREAL_MASK ) ;
161 
162 	/*-- second line of input: intensity and threshold brick indices --*/
163 
164 
165 	PLUTO_add_option( plint ,
166                      "SubBrik info" ,  /* label at left of input line */
167                      "Index" ,  /* tag to return to plugin */
168                      FALSE       /* is this mandatory? */
169                    ) ;
170 	PLUTO_add_number( plint ,
171                     "Intensity" ,  /* label next to chooser */
172                     1 ,         /* smallest possible value */
173                     10000 ,        /* largest possible value (inactivated for now)*/
174                     0 ,         /* decimal shift (none in this case) */
175                     0 ,         /* default value */
176                     FALSE       /* allow user to edit value? */
177                   ) ;
178 
179 	PLUTO_add_number( plint ,
180                     "Threshold" ,  /* label next to chooser */
181                     1 ,         /* smallest possible value */
182                     10000 ,        /* largest possible value (inactivated for now)*/
183                     0 ,         /* decimal shift (none in this case) */
184                     2 ,         /* default value */
185                     FALSE       /* allow user to edit value? */
186                   ) ;
187 	/*-- Third line of input: intensity mask --*/
188 
189    PLUTO_add_option( plint ,
190                      "Intensity Mask" ,  /* label at left of input line */
191                      "Intensity" ,  /* tag to return to plugin */
192                      FALSE       /* is this mandatory? */
193                    ) ;
194 
195    PLUTO_add_number( plint ,
196                     "Minimum" ,  /* label next to chooser */
197                     -100000 ,         /* smallest possible value */
198                     100000 ,        /* largest possible value (inactivated for now)*/
199                     0 ,         /* decimal shift (none in this case) */
200                     0 ,         /* default value */
201                     TRUE       /* allow user to edit value? */
202                   ) ;
203 
204 	PLUTO_add_number( plint ,
205                     "Maximum" ,  /* label next to chooser */
206                     -10000 ,         /* smallest possible value */
207                     10000 ,        /* largest possible value (inactivated for now)*/
208                     0 ,         /* decimal shift (none in this case) */
209                     0 ,         /* default value */
210                     TRUE       /* allow user to edit value? */
211                   ) ;
212 
213    /*-- Fourth line of input: threshold mask --*/
214 
215    PLUTO_add_option( plint ,
216                      "Threshold Mask" ,  /* label at left of input line */
217                      "Threshold" ,  /* tag to return to plugin */
218                      FALSE       /* is this mandatory? */
219                    ) ;
220 
221    PLUTO_add_number( plint ,
222                     "Minimum" , /* label next to chooser */
223                     -10000 ,    /* smallest possible value */
224                     10000 ,     /* largest possible value (inactivated for now)*/
225                     0 ,         /* decimal shift (none in this case) */
226                     0 ,         /* default value */
227                     TRUE        /* allow user to edit value? */
228                   ) ;
229 
230 	PLUTO_add_number( plint ,
231                     "Maximum" , /* label next to chooser */
232                     -10000 ,    /* smallest possible value */
233                     10000 ,     /* largest possible value (inactivated for now)*/
234                     0 ,         /* decimal shift (none in this case) */
235                     1 ,         /* default value */
236                     TRUE        /* allow user to edit value? */
237                   ) ;
238 
239    /*---------- 5th line: output stuff ----------*/
240 
241    PLUTO_add_option( plint ,
242                      "Output" ,  /* label at left of input line */
243                      "Output" ,  /* tag to return to plugin */
244                      TRUE        /* is this mandatory? */
245                    ) ;
246 
247    PLUTO_add_string( plint ,
248                      "Filename" ,  /* label next to textfield */
249                      0,NULL ,    /* no fixed strings to choose among */
250                      19          /* 19 spaces for typing in value */
251                    ) ;
252 
253    return plint ;
254 }
255 
256 /***************************************************************************
257   Main routine for this plugin (will be called from AFNI).
258 ****************************************************************************/
259 
DUMP_main(PLUGIN_interface * plint)260 static char * DUMP_main( PLUGIN_interface * plint )
261 {
262    extract_data uda,*ud;
263    MCW_idcode * idc ;
264    THD_3dim_dataset * xset , * yset ;
265    char * tag ;
266    int demean ,ndmp,nprf;
267    char *str, *nprfxstr, *mssg;
268    float minx , maxx , minthr , maxthr ;
269 
270 	str = (char *) calloc (PLUGIN_MAX_STRING_RANGE+10,sizeof(char));
271 	nprfxstr	 = (char *) calloc (PLUGIN_MAX_STRING_RANGE+20,sizeof(char));
272 	/* Do not allocate more space for mssg, because AFNI would choke on it*/
273 	mssg = (char *) calloc (PLUGIN_MAX_STRING_RANGE,sizeof(char));
274 	memset(&uda, 0, sizeof(extract_data));
275 	if (str == NULL || nprfxstr == NULL || mssg == NULL )
276 									  return "********************\n"
277 												"Could not Allocate\n"
278 												"a teeni weeni bit of\n"
279 												"Memory ! \n"
280 												"********************\n";
281 
282 	ud = &uda;		/* ud now points to an allocated space */
283 
284    /*--------------------------------------------------------------------*/
285    /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/
286 	tag = PLUTO_get_optiontag(plint) ;
287 
288    if (tag == NULL)
289    	{
290    		return "************************\n"
291              "Bad 1st line option \n"
292              "************************"  ;
293    	}
294 
295 
296    idc  = PLUTO_get_idcode(plint) ; 	/* get 1st dataset item */
297    xset = PLUTO_find_dset(idc) ;                   /* get ptr to dataset */
298    if( xset == NULL )
299       return "**********************\n"
300              "Cannot find Dataset #1\n"
301              "**********************"  ;
302 
303 	ud->dsetname = DSET_FILECODE (xset);
304 	ud->Nsub = DSET_NVALS (xset);
305 
306 	/*--------- loop over ramining options ---------*/
307 	ud->DoInt = NOPE;
308 	ud->DoThres = NOPE;
309 	ud->DoInd = NOPE;
310 
311 	ud->intind = 1; /* The first subbrick is numbered 1 here, it makes more sense to the user.*/
312 	ud->thrind = 2;
313 
314 	do
315 		{
316 			tag = PLUTO_get_optiontag(plint) ;
317 			if (tag == NULL) break;
318 
319 			if (equal_strings (tag, "Index") == 1)
320 				{
321 					ud->DoInd = YUP;
322 					ud->intind = PLUTO_get_number(plint) ;
323 					ud->thrind = PLUTO_get_number(plint) ;
324 					continue;
325 				}
326 
327 			if (equal_strings (tag, "Intensity") == 1)
328 				{
329 					ud->DoInt = YUP;
330 					ud->mini = PLUTO_get_number(plint) ;
331 					ud->maxi = PLUTO_get_number(plint) ;
332 					continue;
333 				}
334 
335 			if (equal_strings (tag, "Threshold") == 1)
336 				{
337 					ud->DoThres = YUP;
338 					ud->minth = PLUTO_get_number(plint) ;
339 					ud->maxth = PLUTO_get_number(plint) ;
340 					continue;
341 				}
342 
343 			if (equal_strings (tag, "Output") == 1)
344 					{
345 						ud->strout = PLUTO_get_string(plint) ;
346 						continue;
347 					}
348 
349 
350 		} while (1);
351 
352 	if ( ISFUNC(xset) ) ud->isfunc = YUP;
353 		else ud->isfunc = NOPE;
354 
355 	if ( ISANAT(xset) ) ud->isanat = YUP;
356 		else ud->isanat = NOPE;
357 
358 	if (xset->func_type == FUNC_FIM_TYPE)
359 			ud->fimonly = 1;
360 		else
361 			ud->fimonly = 0;
362 
363 	if (ud->isanat && (ud->DoThres== YUP || ud->DoInd == YUP))
364 		{
365 			return "*************************************\n"
366                 "Can't use threshold or index options \n"
367                 "for fim or ANAT type bricks !\n"
368                 "*************************************"  ;
369 		}
370 
371 
372 	if (ud->DoInd == YUP && (ud->fimonly == YUP && ud->isfunc == YUP))
373 		{
374 			return "*******************************\n"
375                 "Can't specify Indices for fim\n"
376                 "type bricks, they only have one !\n"
377                 "*******************************"  ;
378 		}
379 
380 
381 	/* Check for plausibility of input parameters */
382 	if ((ud->DoInt && (ud->maxi < ud->mini)) || (ud->DoThres && (ud->maxth < ud->minth)))
383 		{
384 		return "**********************\n"
385              "Something's wrong with\n"
386              "min and max  values.\n"
387              "**********************"  ;
388 		}
389 	if (ud->DoInd && (ud->intind > ud->Nsub || ud->thrind > ud->Nsub))
390 		{
391 
392 		return "**********************\n"
393              "One or both of the indices\n"
394              "is larger than the maximum\n"
395 				 "number of sub-bricks\n"
396              "**********************"  ;
397 		}
398 
399 	/*------------------------------------------------------*/
400    /*----- Open the output file for writing operation -----*/
401 
402 	/*if strout is null or of length 0, use the a default name */
403 	if (ud->strout == NULL)
404    	nprf = 0;
405    else
406    	nprf = 1;
407 
408 
409    if (nprf == 1 && (int)strlen(ud->strout) == 0)
410    	nprf = 0;
411 
412 
413    if (nprf == 0)
414    	{
415 			sprintf (nprfxstr,"%s.3Ddump",DSET_PREFIX(xset));
416 			ud->strout = nprfxstr;
417    	}
418 
419 
420 	sprintf (str,"%s.log",ud->strout);
421 
422    if ((filexists(ud->strout) == 1) || (filexists(str) == 1))
423    	{
424    		return "**************************************\n"
425    		       "Output file(s) exists, can't overwrite\n"
426    		       "**************************************\n";
427    	}
428 
429 	ud->outfile = fopen (ud->strout,"w");
430 	ud->outlogfile = fopen (str,"w");
431 
432 	if ((ud->outfile == NULL) || (ud->outlogfile == NULL))
433 		{
434 			return "*****************************************\n"
435    		       "Could not open Output file(s) for writing\n"
436    		       "Check permissions.\n"
437    		       "*****************************************\n";
438 		}
439 
440    /*------------------------------------------------------*/
441    /*---------- At this point, the inputs are OK ----------*/
442 
443    /*-- do the actual work --*/
444    ndmp = Dumpit( ud ,  xset ) ;
445 
446    if( ndmp < -1.0 )
447       {
448 			switch (ndmp)
449 				{
450 					case -2:
451 						return 	"********************************************\n"
452              					"Fatal Error: Could not allocate memory\n"
453 									"(this is a message brought to you by Dumpit)\n"
454              					"********************************************\n"  ;
455 						break;
456 					default:
457 						return 	"*********************************\n"
458              					"Error while dumping data\n"
459              					"*********************************"  ;
460 
461 						break;
462 
463 				}
464 		}
465 
466    /*-- put the output to the screen --*/
467 
468    /* That output message was too long. AFNI was crashing, must ask Bob to allow more verbose messages */
469 
470    /*sprintf(mssg , "            Dataset %s was dumped.\n"
471                  "%d voxels (%5f %% of total) met the boundary conditions.\n"
472                   , DSET_FILECODE(xset) , ndmp , (float)ndmp/(float)(ud->nxx * ud->nyy * ud-> nzz)*100.0) ;*/
473 
474    /* That's shorter */
475 	sprintf(mssg , "%d voxels (%5f %% of total) were dumped.\n"
476 	                 , ndmp , (float)ndmp/(float)(ud->nxx * ud->nyy * ud-> nzz)*100.0) ;
477 
478 	PLUTO_popup_message( plint , mssg ) ;
479 
480 
481 
482 	fclose (ud->outfile);
483 	fclose (ud->outlogfile);
484 	free (nprfxstr);
485 	free (str);
486 	free (mssg);
487 
488    return NULL ;  /* null string returned means all was OK */
489 }
490 
491 
Dumpit(extract_data * ud,THD_3dim_dataset * xset)492 static int Dumpit( extract_data* ud, THD_3dim_dataset * xset)
493 {
494    void  *  xar  ;
495    void  * thar ;
496    float * fxar  ;
497 	float ** Storear;
498    int ii , jj, nxyz , fxar_new = 0  ,xpos,ypos,zpos , ndmp, pass;
499 
500 	ndmp = -1;
501 
502    /*-- get datasets sizes --*/
503 
504 	ud->nxx = xset->daxes->nxx;
505 	ud->nyy = xset->daxes->nyy;
506 	ud->nzz = xset->daxes->nzz;
507 
508    nxyz = xset->daxes->nxx * xset->daxes->nyy * xset->daxes->nzz ;
509 
510    /* Allocate space for data storage */
511 	fxar = (float *) malloc( sizeof(float) * nxyz ) ; fxar_new = 1 ;
512    Storear = (float **) allocate2D (ud->Nsub ,nxyz ,sizeof(float)); /* changed from :  allocate2D (nxyz  ,ud->Nsub,sizeof(float)) */
513 
514 	if (fxar == NULL || Storear == NULL)
515 		{
516 			return -2;
517 		}
518 
519 	/*-- load the first dataset into memory --*/
520 
521 		DSET_load( xset ) ;
522 
523 	/* Store Bricks in 2D array */
524    for (ii = 0;ii < ud->Nsub; ++ii)
525 		{
526    		xar   = DSET_ARRAY(xset,ii) ;        /* get the array */
527    		EDIT_coerce_scale_type (nxyz,DSET_BRICK_FACTOR(xset,ii),
528    							DSET_BRICK_TYPE(xset,ii), xar,	MRI_float,fxar ) ;
529 
530 			/* Store the iith sub-brick in Storear array */
531 			for (jj = 0; jj < nxyz; ++jj)
532 					Storear[ii][jj] = fxar[jj]; /* changed from : Storear[jj][ii] */
533 		}
534 
535    DSET_unload( xset ) ;  /* don't need this in memory anymore */
536 
537 	/* Dump the input info data to the log file */
538 	write_ud (ud);
539 
540 
541    /* Now dump the data that meets the threshold */
542 
543    if( 1 ){
544       for( ii=0 ; ii < nxyz ; ii++ ){
545       	pass = YUP;
546       	if (pass && ud->DoInt)
547       		{
548       			if (Storear[ud->intind-1][ii] < ud->mini || Storear[ud->intind-1][ii] > ud->maxi) /* changed both from : Storear[ii][ud->intind-1]*/
549       				pass = NOPE;
550       		}
551 
552       	if (pass && ud->DoThres)
553       		{
554       			if (Storear[ud->thrind-1][ii] < ud->minth || Storear[ud->thrind-1][ii] > ud->maxth)/* changed both from : Storear[ii][ud->intind-1]*/
555       				pass = NOPE;
556       		}
557 
558       	if (pass)
559       	{
560       		zpos = (int)ii / (int)(xset->daxes->nxx * xset->daxes->nyy);
561 				ypos = (int)(ii - zpos * xset->daxes->nxx * xset->daxes->nyy) / xset->daxes->nxx;
562 				xpos = ii - ( ypos * xset->daxes->nxx ) - ( zpos * xset->daxes->nxx * xset->daxes->nyy ) ;
563 
564          	fprintf (ud->outfile,"%d\t%d\t%d\t%d\t",ii,xpos,ypos,zpos);
565 
566 				for (jj = 0; jj < ud->Nsub; ++jj)
567 					fprintf (ud->outfile," %f\t",Storear[jj][ii]); /* changed from: Storear[ii][jj] */
568 
569 				fprintf (ud->outfile,"\n");
570 
571 				++ndmp;
572          }
573         }
574 
575 		/* increment by one because I want it to start at 0 */
576      	++ndmp;
577    }
578 
579 
580 	fprintf (ud->outlogfile,"\n%d voxel points met the threshold conditions\n",ndmp);
581 
582    /*-- free up arrays --*/
583 
584 
585    if( fxar_new )
586 		{
587 		free(fxar) ;
588 		}
589 	 else
590 	 	{
591 			DSET_unload(xset) ;
592 		}
593 
594 
595 	free2D ((char **)Storear,ud->Nsub);	/* changed from free2D ((char **)Storear,nxyz); */
596 
597 
598    return ndmp ;
599 }
600 
601 
602 /* ************************************************************ */
603 /* function to check for file existence       */
604 /* ************************************************************ */
605 
filexists(char * f_name)606 static int filexists (char *f_name)
607 {/*filexists*/
608         FILE *outfile;
609 
610         outfile = fopen (f_name,"r");
611         if (outfile == NULL)
612                 return (0);
613         else
614                 fclose (outfile);
615                 return (1);
616 
617 }/*filexists*/
618 
619 /* ************************************************************ */
620 /* function to create log file       */
621 /* ************************************************************ */
622 
write_ud(extract_data * ud)623 void write_ud (extract_data* ud)
624 	{
625 		fprintf (ud->outlogfile,"\n\nUser Data Values \n");
626 		fprintf (ud->outlogfile,"Input data set file name= %s\n",ud->dsetname);
627 		fprintf (ud->outlogfile,"Is the file fim only type ? = %d\n",ud->fimonly);
628 		fprintf (ud->outlogfile,"Number of Subbricks : %d\n",ud->Nsub);
629 		fprintf (ud->outlogfile,"output file name = %s\n",ud->strout);
630 		fprintf (ud->outlogfile,"Number of voxels in X direction = %d\n",ud->nxx);
631 		fprintf (ud->outlogfile,"Number of voxels in Y direction = %d\n",ud->nyy);
632 		fprintf (ud->outlogfile,"Number of voxels in Z direction = %d\n",ud->nzz);
633 		fprintf (ud->outlogfile,"Do intensity mask ? = %d\n",ud->DoInt);
634 		fprintf (ud->outlogfile,"Minimum intensity = %f\n",ud->mini);
635 		fprintf (ud->outlogfile,"Maximum intensity = %f\n",ud->maxi);
636 		fprintf (ud->outlogfile,"Do threshold mask ? = %d\n",ud->DoThres);
637 		fprintf (ud->outlogfile,"Minimum threshold = %f\n",ud->minth);
638 		fprintf (ud->outlogfile,"Maximum threshold = %f\n",ud->maxth);
639 		fprintf (ud->outlogfile,"Select Intensity and Threshold indices = %d\n",ud->DoInd);
640 		fprintf (ud->outlogfile,"Intensity index = %d\n",ud->intind);
641 		fprintf (ud->outlogfile,"Threshold index = %d\n",ud->thrind);
642 		fprintf (ud->outlogfile,"\nThe format for the output file is the following:\n");
643 	   fprintf (ud->outlogfile,"VI\tX\tY\tZ\tSb1\tSb2\t... Sbn\n\n");
644 
645 
646 		return;
647 	}
648 
649 /* ************************************************************ */
650 /* function to allocate 2D arrays       */
651 /* ************************************************************ */
652 
allocate2D(int rows,int cols,int element_size)653 static char **allocate2D (int rows,int cols,int element_size)
654 
655 {
656     int i, j;
657     char **A;
658 
659 /* try to allocate the request */
660     switch(element_size) {
661         case sizeof(short): {    /* integer matrix */
662             short **int_matrix;
663             int_matrix = (short **)calloc(rows,sizeof(short *));
664             if(!int_matrix) {
665                 printf("\nError making pointers in %dx%d int matrix\n"
666                             ,rows,cols);
667                 return(NULL);
668 		/*                exit(1);*/
669             }
670             for(i = 0 ; i < rows ; i++) {
671                 int_matrix[i] = (short *)calloc(cols,sizeof(short));
672                 if(!int_matrix[i]) {
673                     printf("\nError making row %d in %dx%d int matrix\n"
674                             ,i,rows,cols);
675                     for(j=0;j<=i;j++) {
676                       if(int_matrix[j])
677 			free(int_matrix[j]);
678                     }
679                     free(int_matrix);
680                     return(NULL);
681 		    /*                    exit(1);*/
682                 }
683             }
684             A = (char **)int_matrix;
685             break;
686         }
687         case sizeof(float): {    /* float matrix */
688             float **float_matrix;
689             float_matrix = (float **)calloc(rows,sizeof(float *));
690             if(!float_matrix) {
691                 printf("\nError making pointers in %dx%d float matrix\n"
692                             ,rows,cols);
693                 return(NULL);
694 		/*                exit(1);*/
695             }
696             for(i = 0 ; i < rows ; i++) {
697                 float_matrix[i] = (float *)calloc(cols,sizeof(float));
698                 if(!float_matrix[i]) {
699                     printf("\nError making row %d in %dx%d float matrix\n"
700                             ,i,rows,cols);
701                     for(j=0;j<=i;j++) {
702                       if(float_matrix[j])
703 			free(float_matrix[j]);
704                     }
705                     free(float_matrix);
706                     return(NULL);
707 		    /*                    exit(1);*/
708                 }
709             }
710             A = (char **)float_matrix;
711             break;
712         }
713         case sizeof(double): {   /* double matrix */
714             double **double_matrix;
715             double_matrix = (double **)calloc(rows,sizeof(double *));
716             if(!double_matrix) {
717                 printf("\nError making pointers in %dx%d double matrix\n"
718                             ,rows,cols);
719                 return(NULL);
720 		/*                exit(1);*/
721             }
722             for(i = 0 ; i < rows ; i++) {
723                 double_matrix[i] = (double *)calloc(cols,sizeof(double));
724                 if(!double_matrix[i]) {
725                     printf("\nError making row %d in %dx%d double matrix\n"
726                             ,i,rows,cols);
727                     for(j=0;j<=i;j++) {
728                       if(double_matrix[j])
729 			free(double_matrix[j]);
730                     }
731                     free(double_matrix);
732                     return(NULL);
733 
734 		    /*                    exit(1);*/
735                 }
736             }
737             A = (char **)double_matrix;
738             break;
739         }
740         default:
741             printf("\nERROR in matrix_allocate: unsupported type\n");
742             return(NULL);
743 	    /*            exit(1);*/
744     }
745     return(A);
746 }
747 
748 /* ************************************************************ */
749 /* function to free 2D arrays       */
750 /* ************************************************************ */
free2D(char ** a,int rows)751 static void free2D(char **a,int rows)
752 
753 {
754     int i;
755 
756 /* free each row of data */
757     for(i = 0 ; i < rows ; i++) free(a[i]);
758 
759 /* free each row pointer */
760     free((char *)a);
761     a = NULL;           /* set to null for error */
762 
763 	return;
764 }
765 
766 /* ************************************************************ */
767 /* function to Check if strings are equal       */
768 /* ************************************************************ */
769 
770 
equal_strings(char * s1,char * s2)771 int equal_strings (char *s1,char *s2)
772 
773  {
774    int i=0;
775 
776    if (s1 == NULL && s2 == NULL) return (-2);
777 
778    if ((s1 == NULL && s2 != NULL) || (s1 != NULL && s2 == NULL)) return (-1);
779 
780    while (s1[i] == s2[i]
781    			&& s1[i] != '\0' && s2[i] != '\0') ++i;
782 
783    	if (s1[i] == '\0' && s2[i] == '\0') return (1);
784    	 else return (0);
785 
786  }
787