00001 
00002 
00003 
00004 
00005 
00006    
00007 #include "afni.h"
00008 #include "afni_plugin.h"
00009 
00010 #ifndef ALLOW_PLUGINS
00011 #  error "Plugins not properly set up -- see machdep.h"
00012 #endif
00013 
00014 
00015 
00016 
00017 typedef struct 
00018         {
00019                   int nxx;                      
00020                   int nyy;                      
00021                   int nzz;                      
00022                   char *dsetname; 
00023                   int errcode;          
00024                   int out;                      
00025                   int format;
00026                   int iloc;
00027                   int xloc;
00028                   int yloc;
00029                   int zloc;
00030                   int fimonly;          
00031                   int DoInt;
00032                   int DoThres;
00033                   int DoInd;
00034                   int intind; 
00035                   int   thrind;
00036                   int Nsub;
00037                   int isanat;
00038                   int isfunc;
00039                   float mini, maxi, minth, maxth;
00040                   char * strout;
00041                   FILE * outfile;
00042                   FILE * outlogfile;
00043                   char outname[PLUGIN_MAX_STRING_RANGE]; 
00044         }extract_data;
00045 
00046 
00047 static char helpstring[] =
00048   "                   3Ddump98 Plugin\n"
00049   "This plugin is used to write to an ascii file the data present in AFNI bricks.\n"
00050   "You can apply intenstity or threshold masks to the voxel data that is being extracted.\n\n" 
00051   "Plugin Inputs:\n\n"
00052   "   1- Dataset :\n"
00053   "      3D brick  -> 3D AFNI brick of the type :\n"
00054   "                    fim, fith, fico, fbuc, etc...\n"
00055   "                    spgr, epan.\n\n"
00056   "   2- SubBrick info : (Optional) \n"
00057   "      Intensity -> Index of the subbrick to be used\n"
00058   "                   as an intensity subbrick.\n"
00059   "      Threshold -> Index of the subbrick to be used \n"
00060   "                   as a threshold subbrick.\n" 
00061   "   While the subbrick indices are obvious when dealing with most bricks\n"
00062   "   You might need to specified them for bricks of the type bucket\n\n"
00063   "   3- Intensity Mask : (optional) \n"
00064   "      Minimum   -> Minimum boundary for intensity value (inclusive)\n"
00065   "      Maximum   -> Maximum boundary for intensity value (inclusive)\n"
00066   "   Data from voxels with intensity between Minimum and Maximum \n"
00067   "   are written to 'Filename'.\n\n"
00068   "   4- Threshold Mask : (optional) \n"
00069   "      Minimum   -> Minimum boundary for threshold value (inclusive)\n"
00070   "      Maximum   -> Maximum boundary for threshold value (inclusive)\n"
00071   "   Data from voxels with threshold value between Minimum and Maximum \n"
00072   "   are written to 'Filename'.\n\n"
00073   "   5- Output : \n"
00074   "      Filename  -> Name of ascii output file. \n"
00075   "                   If no name is specified, the default is\n"
00076   "                   the prefix of the inbut brick with the \n"
00077   "                   extension '.3Ddump' appended at the end.\n"
00078   "                   A LOG file, 'Filename.log' is also written to disk.\n"
00079   "                   The log file contains all the parameters settings used\n"
00080   "                   for generating 'Filename'.\n"
00081   "                   The format of 'Filename' is as follows :\n"
00082   "                   1- Voxel Index (VI) : Each voxel in an AFNI brick has a unique index.\n"
00083   "                                         Indices map directly to XYZ coordinates.\n"
00084   "                                         See AFNI plugin documentations for more info.\n"
00085   "                   2..4- Voxel coordinates (X Y Z) : Those are the voxel slice coordinates.\n"
00086   "                                                     You can see these coordinates in the upper left side\n"
00087   "                                                     of the AFNI window. To do so, you must first switch the\n"
00088   "                                                     voxel coordinate units from mm to slice coordinates.\n"
00089   "                                                     Define Datamode -> Misc -> Voxel Coords ?\n"
00090   "                                                     PS: The coords that show up in the graph window\n"
00091   "                                                     could be different from those in the upper left side \n"
00092   "                                                     of AFNI's main window.\n"
00093   "                   5..n- Subbrick values (Sb1 Sb2 ... Sbn) : Voxel values at each subbrick.\n\n"
00094   "If you have/find questions/comments/bugs about the plugin, \n"
00095   "send me an E-mail: ziad@image.bien.mu.edu\n\n"
00096   "                    Ziad Saad   Nov. 9 97, latest update Aug. 26 99.\n\n"
00097 ;
00098 
00099  
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 static char * yn_strings[] = { "n" , "y" }; 
00108 
00109 #define NUM_YN_STRINGS (sizeof(yn_strings)/sizeof(char *))
00110 
00111 #define YUP  1
00112 #define NOPE 0
00113 
00114 #define ERROR_FILEWRITE         2
00115 #define ERROR_OPTIONS           3
00116 
00117 
00118 static int filexists (char *);
00119 
00120 static char * DUMP_main( PLUGIN_interface * ) ;
00121 
00122 static int Dumpit( extract_data* , THD_3dim_dataset * ) ;
00123 
00124 static void write_ud (extract_data*);
00125 
00126 static char **allocate2D (int rows,int cols,int element_size);
00127 
00128 static void free2D(char **a,int rows);
00129 
00130 static int equal_strings (char *s1,char *s2);
00131 
00132 
00133 
00134 
00135 
00136 
00137 DEFINE_PLUGIN_PROTOTYPE
00138 
00139 PLUGIN_interface * PLUGIN_init( int ncall )
00140 {
00141    PLUGIN_interface * plint ;
00142 
00143    if( ncall > 0 ) return NULL ;  
00144 
00145    
00146 
00147    plint = PLUTO_new_interface( "3D Dump98" , "Ascii dump of 3D Dataset" , helpstring ,
00148                                  PLUGIN_CALL_VIA_MENU , DUMP_main  ) ;
00149 
00150    PLUTO_set_runlabels( plint , "Dump+Keep" , "Dump+Close" ) ;  
00151 
00152    
00153 
00154    PLUTO_add_option( plint , "Dataset" , "Dataset" , TRUE ) ;
00155    PLUTO_add_dataset(plint , "3D brick" ,
00156                                     ANAT_ALL_MASK  ,  FUNC_ALL_MASK ,
00157                                     SESSION_ALL_MASK |
00158                                     DIMEN_3D_MASK    | BRICK_ALLREAL_MASK ) ;
00159    
00160         
00161    
00162    
00163         PLUTO_add_option( plint ,
00164                      "SubBrik info" ,  
00165                      "Index" ,  
00166                      FALSE       
00167                    ) ;
00168         PLUTO_add_number( plint ,
00169                     "Intensity" ,  
00170                     1 ,         
00171                     10000 ,        
00172                     0 ,         
00173                     0 ,         
00174                     FALSE       
00175                   ) ;
00176                                 
00177         PLUTO_add_number( plint ,
00178                     "Threshold" ,  
00179                     1 ,         
00180                     10000 ,        
00181                     0 ,         
00182                     2 ,         
00183                     FALSE       
00184                   ) ;   
00185         
00186    
00187    PLUTO_add_option( plint ,
00188                      "Intensity Mask" ,  
00189                      "Intensity" ,  
00190                      FALSE       
00191                    ) ;
00192    
00193    PLUTO_add_number( plint ,
00194                     "Minimum" ,  
00195                     -100000 ,         
00196                     100000 ,        
00197                     0 ,         
00198                     0 ,         
00199                     TRUE       
00200                   ) ;
00201                   
00202         PLUTO_add_number( plint ,
00203                     "Maximum" ,  
00204                     -10000 ,         
00205                     10000 ,        
00206                     0 ,         
00207                     0 ,         
00208                     TRUE       
00209                   ) ;
00210    
00211    
00212    
00213    PLUTO_add_option( plint ,
00214                      "Threshold Mask" ,  
00215                      "Threshold" ,  
00216                      FALSE       
00217                    ) ;
00218    
00219    PLUTO_add_number( plint ,
00220                     "Minimum" ,  
00221                     -10000 ,         
00222                     10000 ,        
00223                     0 ,         
00224                     0.5 ,         
00225                     TRUE       
00226                   ) ;
00227                   
00228         PLUTO_add_number( plint ,
00229                     "Maximum" ,  
00230                     -10000 ,         
00231                     10000 ,        
00232                     0 ,         
00233                     1 ,         
00234                     TRUE       
00235                   ) ;
00236    
00237    
00238 
00239    PLUTO_add_option( plint ,
00240                      "Output" ,  
00241                      "Output" ,  
00242                      TRUE        
00243                    ) ;
00244 
00245    PLUTO_add_string( plint ,
00246                      "Filename" ,  
00247                      0,NULL ,    
00248                      19          
00249                    ) ;
00250                   
00251    return plint ;
00252 }
00253 
00254 
00255 
00256 
00257 
00258 static char * DUMP_main( PLUGIN_interface * plint )
00259 {
00260    extract_data uda,*ud;
00261    MCW_idcode * idc ;
00262    THD_3dim_dataset * xset , * yset ;
00263    char * tag ;
00264    int demean ,ndmp,nprf;
00265    char *str, *nprfxstr, *mssg;
00266    float minx , maxx , minthr , maxthr ;
00267         
00268         str = (char *) calloc (PLUGIN_MAX_STRING_RANGE+10,sizeof(char));
00269         nprfxstr         = (char *) calloc (PLUGIN_MAX_STRING_RANGE+20,sizeof(char));
00270         
00271         mssg = (char *) calloc (PLUGIN_MAX_STRING_RANGE,sizeof(char));
00272         
00273         if (str == NULL || nprfxstr == NULL || mssg == NULL ) 
00274                                                                           return "********************\n"
00275                                                                                                 "Could not Allocate\n"
00276                                                                                                 "a teeni weeni bit of\n"
00277                                                                                                 "Memory ! \n"
00278                                                                                                 "********************\n";
00279 
00280         ud = &uda;              
00281    
00282    
00283    
00284         tag = PLUTO_get_optiontag(plint) ;
00285    
00286    if (tag == NULL)
00287         {
00288                 return "************************\n"
00289              "Bad 1st line option \n"
00290              "************************"  ;
00291         }       
00292         
00293    
00294    idc  = PLUTO_get_idcode(plint) ;     
00295    xset = PLUTO_find_dset(idc) ;                   
00296    if( xset == NULL )
00297       return "**********************\n"
00298              "Cannot find Dataset #1\n"
00299              "**********************"  ;
00300         
00301         ud->dsetname = DSET_FILECODE (xset);
00302         ud->Nsub = DSET_NVALS (xset);
00303         
00304         
00305         ud->DoInt = NOPE;
00306         ud->DoThres = NOPE;
00307         ud->DoInd = NOPE;
00308         
00309         ud->intind = 1; 
00310         ud->thrind = 2; 
00311         
00312         do
00313                 {
00314                         tag = PLUTO_get_optiontag(plint) ;
00315                         if (tag == NULL) break;
00316                         
00317                         if (equal_strings (tag, "Index") == 1)
00318                                 {
00319                                         ud->DoInd = YUP;
00320                                         ud->intind = PLUTO_get_number(plint) ; 
00321                                         ud->thrind = PLUTO_get_number(plint) ;
00322                                         continue; 
00323                                 }
00324                         
00325                         if (equal_strings (tag, "Intensity") == 1)
00326                                 {
00327                                         ud->DoInt = YUP;
00328                                         ud->mini = PLUTO_get_number(plint) ; 
00329                                         ud->maxi = PLUTO_get_number(plint) ;
00330                                         continue;
00331                                 }
00332                         
00333                         if (equal_strings (tag, "Threshold") == 1)
00334                                 {
00335                                         ud->DoThres = YUP;
00336                                         ud->minth = PLUTO_get_number(plint) ; 
00337                                         ud->maxth = PLUTO_get_number(plint) ;
00338                                         continue;
00339                                 }
00340                         
00341                         if (equal_strings (tag, "Output") == 1)
00342                                         {
00343                                                 ud->strout = PLUTO_get_string(plint) ; 
00344                                                 continue;
00345                                         }
00346                         
00347                         
00348                 } while (1);
00349                 
00350         if ( ISFUNC(xset) ) ud->isfunc = YUP;
00351                 else ud->isfunc = NOPE;
00352         
00353         if ( ISANAT(xset) ) ud->isanat = YUP;
00354                 else ud->isanat = NOPE;
00355         
00356         if (xset->func_type == FUNC_FIM_TYPE)
00357                         ud->fimonly = 1;
00358                 else
00359                         ud->fimonly = 0;
00360         
00361         if (ud->isanat && (ud->DoThres== YUP || ud->DoInd == YUP))
00362                 {
00363                         return "*************************************\n"
00364                 "Can't use threshold or index options \n" 
00365                 "for fim or ANAT type bricks !\n"
00366                 "*************************************"  ;
00367                 }
00368         
00369 
00370         if (ud->DoInd == YUP && (ud->fimonly == YUP && ud->isfunc == YUP))
00371                 {
00372                         return "*******************************\n"
00373                 "Can't specify Indices for fim\n" 
00374                 "type bricks, they only have one !\n"
00375                 "*******************************"  ;
00376                 }
00377                         
00378 
00379         
00380         if ((ud->DoInt && (ud->maxi < ud->mini)) || (ud->DoThres && (ud->maxth < ud->minth)))
00381                 {
00382                 return "**********************\n"
00383              "Something's wrong with\n" 
00384              "min and max  values.\n"
00385              "**********************"  ;
00386                 }
00387         if (ud->DoInd && (ud->intind > ud->Nsub || ud->thrind > ud->Nsub))
00388                 {
00389                 
00390                 return "**********************\n"
00391              "One or both of the indices\n" 
00392              "is larger than the maximum\n"
00393                                  "number of sub-bricks\n"
00394              "**********************"  ;
00395                 }
00396 
00397         
00398    
00399    
00400         
00401         if (ud->strout == NULL)
00402         nprf = 0;
00403    else
00404         nprf = 1;
00405         
00406         
00407    if (nprf == 1 && (int)strlen(ud->strout) == 0)
00408         nprf = 0;
00409                 
00410         
00411    if (nprf == 0)
00412         {
00413                         sprintf (nprfxstr,"%s.3Ddump",DSET_PREFIX(xset));
00414                         ud->strout = nprfxstr;
00415         }
00416 
00417    
00418         sprintf (str,"%s.log",ud->strout);      
00419                 
00420    if ((filexists(ud->strout) == 1) || (filexists(str) == 1))
00421         {
00422                 return "**************************************\n"
00423                        "Output file(s) exists, can't overwrite\n"
00424                        "**************************************\n";
00425         }
00426         
00427         ud->outfile = fopen (ud->strout,"w");
00428         ud->outlogfile = fopen (str,"w");
00429         
00430         if ((ud->outfile == NULL) || (ud->outlogfile == NULL))
00431                 {
00432                         return "*****************************************\n"
00433                        "Could not open Output file(s) for writing\n"
00434                        "Check permissions.\n"
00435                        "*****************************************\n";
00436                 }
00437         
00438    
00439    
00440 
00441    
00442    ndmp = Dumpit( ud ,  xset ) ;
00443 
00444    if( ndmp < -1.0 )
00445       {
00446                         switch (ndmp)
00447                                 {
00448                                         case -2:
00449                                                 return  "********************************************\n"
00450                                                 "Fatal Error: Could not allocate memory\n"
00451                                                                         "(this is a message brought to you by Dumpit)\n"
00452                                                 "********************************************\n"  ;
00453                                                 break;
00454                                         default:
00455                                                 return  "*********************************\n"
00456                                                 "Error while dumping data\n"
00457                                                 "*********************************"  ;
00458 
00459                                                 break;
00460                         
00461                                 }
00462                 }
00463 
00464    
00465 
00466     
00467          
00468    
00469 
00470 
00471                                                 
00472    
00473         sprintf(mssg , "%d voxels (%5f %% of total) were dumped.\n" 
00474                          , ndmp , (float)ndmp/(float)(ud->nxx * ud->nyy * ud-> nzz)*100.0) ;
00475 
00476         PLUTO_popup_message( plint , mssg ) ;
00477         
00478         
00479         
00480         fclose (ud->outfile);
00481         fclose (ud->outlogfile);
00482         free (nprfxstr);        
00483         free (str);
00484         free (mssg); 
00485          
00486    return NULL ;  
00487 }
00488 
00489 
00490 static int Dumpit( extract_data* ud, THD_3dim_dataset * xset)
00491 {
00492    void  *  xar  ;
00493    void  * thar ;
00494    float * fxar  ;
00495         float ** Storear;
00496    int ii , jj, nxyz , fxar_new = 0  ,xpos,ypos,zpos , ndmp, pass;
00497 
00498         ndmp = -1;
00499         
00500    
00501 
00502         ud->nxx = xset->daxes->nxx;
00503         ud->nyy = xset->daxes->nyy;
00504         ud->nzz = xset->daxes->nzz;
00505         
00506    nxyz = xset->daxes->nxx * xset->daxes->nyy * xset->daxes->nzz ;
00507 
00508    
00509         fxar = (float *) malloc( sizeof(float) * nxyz ) ; fxar_new = 1 ;
00510    Storear = (float **) allocate2D (ud->Nsub ,nxyz ,sizeof(float)); 
00511         
00512         if (fxar == NULL || Storear == NULL)
00513                 {
00514                         return -2;
00515                 }
00516         
00517         
00518 
00519                 DSET_load( xset ) ;
00520                 
00521           
00522    for (ii = 0;ii < ud->Nsub; ++ii)
00523                 {
00524                 xar   = DSET_ARRAY(xset,ii) ;        
00525                 EDIT_coerce_scale_type (nxyz,DSET_BRICK_FACTOR(xset,ii),
00526                                                         DSET_BRICK_TYPE(xset,ii), xar,  MRI_float,fxar ) ;   
00527                         
00528                         
00529                         for (jj = 0; jj < nxyz; ++jj)
00530                                         Storear[ii][jj] = fxar[jj]; 
00531                 }
00532                 
00533    DSET_unload( xset ) ;  
00534         
00535         
00536         write_ud (ud);
00537         
00538 
00539    
00540 
00541    if( 1 ){
00542       for( ii=0 ; ii < nxyz ; ii++ ){
00543         pass = YUP;
00544         if (pass && ud->DoInt)
00545                 {
00546                         if (Storear[ud->intind-1][ii] < ud->mini || Storear[ud->intind-1][ii] > ud->maxi) 
00547                                 pass = NOPE;
00548                 }
00549         
00550         if (pass && ud->DoThres)   
00551                 {
00552                         if (Storear[ud->thrind-1][ii] < ud->minth || Storear[ud->thrind-1][ii] > ud->maxth)
00553                                 pass = NOPE;
00554                 }
00555         
00556         if (pass)
00557         {
00558                 zpos = (int)ii / (int)(xset->daxes->nxx * xset->daxes->nyy);
00559                                 ypos = (int)(ii - zpos * xset->daxes->nxx * xset->daxes->nyy) / xset->daxes->nxx;
00560                                 xpos = ii - ( ypos * xset->daxes->nxx ) - ( zpos * xset->daxes->nxx * xset->daxes->nyy ) ;
00561                 
00562                 fprintf (ud->outfile,"%d\t%d\t%d\t%d\t",ii,xpos,ypos,zpos);
00563                         
00564                                 for (jj = 0; jj < ud->Nsub; ++jj)
00565                                         fprintf (ud->outfile," %f\t",Storear[jj][ii]); 
00566                                         
00567                                 fprintf (ud->outfile,"\n");
00568                                                 
00569                                 ++ndmp;
00570          }
00571         }
00572                 
00573                 
00574         ++ndmp;
00575    }
00576         
00577         
00578         fprintf (ud->outlogfile,"\n%d voxel points met the threshold conditions\n",ndmp);
00579         
00580    
00581 
00582         
00583    if( fxar_new ) 
00584                 {
00585                 free(fxar) ;
00586                 }
00587          else 
00588                 {
00589                         DSET_unload(xset) ;
00590                 }
00591         
00592         
00593         free2D ((char **)Storear,ud->Nsub);     
00594 
00595         
00596    return ndmp ;
00597 }
00598 
00599 
00600  
00601 
00602  
00603         
00604 static int filexists (char *f_name)
00605 {
00606         FILE *outfile;
00607         
00608         outfile = fopen (f_name,"r");
00609         if (outfile == NULL)
00610                 return (0);
00611         else 
00612                 fclose (outfile);
00613                 return (1);
00614                 
00615 }
00616 
00617  
00618 
00619  
00620 
00621 void write_ud (extract_data* ud)
00622         {
00623                 fprintf (ud->outlogfile,"\n\nUser Data Values \n");
00624                 fprintf (ud->outlogfile,"Input data set file name= %s\n",ud->dsetname);
00625                 fprintf (ud->outlogfile,"Is the file fim only type ? = %d\n",ud->fimonly);
00626                 fprintf (ud->outlogfile,"Number of Subbricks : %d\n",ud->Nsub);
00627                 fprintf (ud->outlogfile,"output file name = %s\n",ud->strout);
00628                 fprintf (ud->outlogfile,"Number of voxels in X direction = %d\n",ud->nxx);
00629                 fprintf (ud->outlogfile,"Number of voxels in Y direction = %d\n",ud->nyy);
00630                 fprintf (ud->outlogfile,"Number of voxels in Z direction = %d\n",ud->nzz);
00631                 fprintf (ud->outlogfile,"Do intensity mask ? = %d\n",ud->DoInt);
00632                 fprintf (ud->outlogfile,"Minimum intensity = %f\n",ud->mini);
00633                 fprintf (ud->outlogfile,"Maximum intensity = %f\n",ud->maxi);
00634                 fprintf (ud->outlogfile,"Do threshold mask ? = %d\n",ud->DoThres);
00635                 fprintf (ud->outlogfile,"Minimum threshold = %f\n",ud->minth);
00636                 fprintf (ud->outlogfile,"Maximum threshold = %f\n",ud->maxth);
00637                 fprintf (ud->outlogfile,"Select Intensity and Threshold indices = %d\n",ud->DoInd);
00638                 fprintf (ud->outlogfile,"Intensity index = %d\n",ud->intind);
00639                 fprintf (ud->outlogfile,"Threshold index = %d\n",ud->thrind);
00640                 fprintf (ud->outlogfile,"\nThe format for the output file is the following:\n");
00641            fprintf (ud->outlogfile,"VI\tX\tY\tZ\tSb1\tSb2\t... Sbn\n\n");
00642                 
00643                 
00644                 return;
00645         }
00646 
00647  
00648 
00649  
00650 
00651 static char **allocate2D (int rows,int cols,int element_size)
00652 
00653 {
00654     int i, j;
00655     char **A;
00656 
00657 
00658     switch(element_size) {
00659         case sizeof(short): {    
00660             short **int_matrix;
00661             int_matrix = (short **)calloc(rows,sizeof(short *));
00662             if(!int_matrix) {
00663                 printf("\nError making pointers in %dx%d int matrix\n"
00664                             ,rows,cols);
00665                 return(NULL);
00666                 
00667             }
00668             for(i = 0 ; i < rows ; i++) {
00669                 int_matrix[i] = (short *)calloc(cols,sizeof(short));
00670                 if(!int_matrix[i]) {
00671                     printf("\nError making row %d in %dx%d int matrix\n"
00672                             ,i,rows,cols);
00673                     for(j=0;j<=i;j++) {
00674                       if(int_matrix[j])
00675                         free(int_matrix[j]);
00676                     }
00677                     free(int_matrix);
00678                     return(NULL);
00679                     
00680                 }
00681             }
00682             A = (char **)int_matrix;
00683             break;
00684         }
00685         case sizeof(float): {    
00686             float **float_matrix;
00687             float_matrix = (float **)calloc(rows,sizeof(float *));
00688             if(!float_matrix) {
00689                 printf("\nError making pointers in %dx%d float matrix\n"
00690                             ,rows,cols);
00691                 return(NULL);
00692                 
00693             }
00694             for(i = 0 ; i < rows ; i++) {
00695                 float_matrix[i] = (float *)calloc(cols,sizeof(float));
00696                 if(!float_matrix[i]) {
00697                     printf("\nError making row %d in %dx%d float matrix\n"
00698                             ,i,rows,cols);
00699                     for(j=0;j<=i;j++) {
00700                       if(float_matrix[j])
00701                         free(float_matrix[j]);
00702                     }
00703                     free(float_matrix);
00704                     return(NULL);
00705                     
00706                 }
00707             }
00708             A = (char **)float_matrix;
00709             break;
00710         }
00711         case sizeof(double): {   
00712             double **double_matrix;
00713             double_matrix = (double **)calloc(rows,sizeof(double *));
00714             if(!double_matrix) {
00715                 printf("\nError making pointers in %dx%d double matrix\n"
00716                             ,rows,cols);
00717                 return(NULL);
00718                 
00719             }
00720             for(i = 0 ; i < rows ; i++) {
00721                 double_matrix[i] = (double *)calloc(cols,sizeof(double));
00722                 if(!double_matrix[i]) {
00723                     printf("\nError making row %d in %dx%d double matrix\n"
00724                             ,i,rows,cols);
00725                     for(j=0;j<=i;j++) {
00726                       if(double_matrix[j])
00727                         free(double_matrix[j]);
00728                     }
00729                     free(double_matrix);
00730                     return(NULL);
00731 
00732                     
00733                 }
00734             }
00735             A = (char **)double_matrix;
00736             break;
00737         }
00738         default:
00739             printf("\nERROR in matrix_allocate: unsupported type\n");
00740             return(NULL);
00741             
00742     }
00743     return(A);
00744 }
00745 
00746  
00747 
00748  
00749 static void free2D(char **a,int rows)
00750     
00751 {
00752     int i;
00753     
00754 
00755     for(i = 0 ; i < rows ; i++) free(a[i]);
00756 
00757 
00758     free((char *)a);
00759     a = NULL;           
00760     
00761         return;
00762 }
00763 
00764  
00765 
00766  
00767 
00768 
00769 int equal_strings (char *s1,char *s2)
00770 
00771  {
00772    int i=0;
00773    
00774    if (s1 == NULL && s2 == NULL) return (-2);
00775    
00776    if ((s1 == NULL && s2 != NULL) || (s1 != NULL && s2 == NULL)) return (-1);
00777    
00778    while (s1[i] == s2[i] 
00779                         && s1[i] != '\0' && s2[i] != '\0') ++i;
00780                         
00781         if (s1[i] == '\0' && s2[i] == '\0') return (1);
00782          else return (0);
00783  
00784  }