Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

SUMA_DataSets.c

Go to the documentation of this file.
00001 /* This file should not contai functions that REQUIRE the compilation or the headers of SUMA.
00002 This file might be compiled and used by AFNI 
00003 */
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include <assert.h>
00007 #include <string.h>
00008 #include <sys/time.h>
00009 #include <math.h>
00010 #include "mrilib.h"
00011 #include "niml.h"
00012 #include "../niml/niml_private.h"
00013 #include "xutil.h"
00014 
00015 #if defined SUMA_TEST_DATA_SETS_STAND_ALONE
00016 #define STAND_ALONE
00017 #elif defined SUMA_Test_DSET_IO_STANDALONE
00018 #define STAND_ALONE
00019 #elif defined SUMA_ConvertDset_STANDALONE
00020 #define STAND_ALONE
00021 #else
00022 #endif
00023 
00024 #include "SUMA_suma.h"
00025 
00026 
00027 #ifdef STAND_ALONE
00028    #if defined SUMA_COMPILED
00029       /* need to define these global variables because function calls are made to functions in files that declare these variables as extern */
00030       SUMA_CommonFields *SUMAg_CF;
00031       SUMA_SurfaceViewer *SUMAg_cSV; /*!< Global pointer to current Surface Viewer structure*/
00032       SUMA_SurfaceViewer *SUMAg_SVv = NULL; /*!< Global pointer to the vector containing the various Surface Viewer Structures 
00033                                           SUMAg_SVv contains SUMA_MAX_SURF_VIEWERS structures */
00034       int SUMAg_N_SVv = 0; /*!< Number of SVs realized by X */
00035       SUMA_DO *SUMAg_DOv;   /*!< Global pointer to Displayable Object structure vector*/
00036       int SUMAg_N_DOv = 0; /*!< Number of DOs stored in DOv */
00037    #endif
00038 #else
00039   #if defined SUMA_COMPILED
00040       extern SUMA_CommonFields *SUMAg_CF;
00041       extern int SUMAg_N_DOv; 
00042       extern SUMA_DO *SUMAg_DOv;
00043   #endif 
00044 #endif
00045 
00046 static int verv[] = { SUMA_VERSION_VECTOR }; 
00047 float SUMA_LatestVersionNumber(void)
00048 {
00049    return((float)verv[0]/10000.0);
00050 }
00051 
00052 /*!
00053    Creates a NI group to store surface data 
00054    N_el is the number of data elements stored in each column
00055    N_el can be the number of nodes for example. 
00056 */
00057 SUMA_Boolean SUMA_NewDsetGrp (SUMA_DSET *dset, SUMA_DSET_TYPE dtp, 
00058                            char* MeshParent_idcode, 
00059                           char * GeomParent_idcode, int N_el, 
00060                           char *filename, char *thisidcode)
00061 {
00062    static char FuncName[]={"SUMA_NewDsetGrp"};
00063    char idcode[SUMA_IDCODE_LENGTH], *namecode, *dname;
00064    
00065    SUMA_ENTRY;
00066    
00067    if (!dset) { SUMA_SL_Err("NULL dset"); SUMA_RETURN(NOPE); }
00068    if (dset->N_links != 0) { SUMA_SL_Err("Not expected here, N_links != 0"); SUMA_RETURN(NOPE); }
00069    
00070    dset->ngr = NI_new_group_element();
00071    NI_rename_group(dset->ngr, SUMA_Dset_Type_Name(dtp));
00072    
00073    /* assign an idcode */
00074    if (!thisidcode) {
00075       if (!filename) {
00076          UNIQ_idcode_fill(idcode);
00077          NI_set_attribute (dset->ngr, "Object_ID", idcode); /* create one *//* changed from idcode March 31 */
00078       } else { 
00079          namecode = UNIQ_hashcode(filename);  /* from filename */
00080          NI_set_attribute (dset->ngr, "Object_ID", namecode); SUMA_free(namecode);
00081       }
00082    } else {
00083       NI_set_attribute (dset->ngr, "Object_ID", thisidcode);
00084    }
00085 
00086    /* set the idcodes of the parents */
00087    if (MeshParent_idcode) {
00088       NI_set_attribute (dset->ngr, "Parent_ID", MeshParent_idcode); 
00089    } else {
00090       NI_set_attribute (dset->ngr, "Parent_ID", NULL); /* don't use SUMA_EMPTY_ATTR unless you must NULL is nice*/
00091    }
00092    if (GeomParent_idcode) {
00093       NI_set_attribute (dset->ngr, "GeomParent_idcode", GeomParent_idcode);
00094    } else {
00095       NI_set_attribute (dset->ngr, "GeomParent_idcode", NULL);
00096    }
00097   
00098    if (filename) NI_set_attribute (dset->ngr, "filename", filename);
00099    
00100    /* Now add the data element */
00101    dname = SUMA_append_string(SUMA_Dset_Type_Name(dtp), "_data");
00102    dset->dnel = NI_new_data_element(dname, N_el); SUMA_free(dname); dname = NULL;
00103    NI_add_to_group(dset->ngr, dset->dnel);
00104    
00105    
00106    SUMA_RETURN(YUP);  
00107 }
00108                           
00109 static byte SUMA_ALLOW_NEL_USE;
00110 void SUMA_allow_nel_use(int al)
00111 {
00112    if (al) SUMA_ALLOW_NEL_USE = 1;
00113    else SUMA_ALLOW_NEL_USE = 0;
00114    
00115    return;
00116 } 
00117 
00118 /*!
00119    Creates a NI elem. to store surface data 
00120    N_el is the number of data elements stored in each column
00121    N_el can be the number of nodes for example
00122    Do not use this function to create dsets anymore, use
00123    SUMA_NewDsetGrp
00124 */
00125 NI_element * SUMA_NewNel (SUMA_DSET_TYPE dtp, char* MeshParent_idcode, 
00126                           char * GeomParent_idcode, int N_el, 
00127                           char *filename, char *thisidcode)
00128 {
00129    static char FuncName[]={"SUMA_NewNel"};
00130    NI_element *nel=NULL;
00131    char idcode[SUMA_IDCODE_LENGTH], *namecode;
00132    
00133    SUMA_ENTRY;
00134 
00135    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, perhaps. Check on caller.");
00136    
00137    nel = NI_new_data_element(SUMA_Dset_Type_Name(dtp), N_el);
00138    
00139    /* assign an idcode */
00140    if (!thisidcode) {
00141       if (!filename) {
00142          UNIQ_idcode_fill(idcode);
00143          NI_set_attribute (nel, "Object_ID", idcode); /* create one *//* changed from idcode March 31 */
00144       } else { 
00145          namecode = UNIQ_hashcode(filename);  /* from filename */
00146          NI_set_attribute (nel, "Object_ID", namecode); SUMA_free(namecode);
00147       }
00148    } else {
00149       NI_set_attribute (nel, "Object_ID", thisidcode);
00150    }
00151    
00152    
00153    /* set the idcodes of the parents */
00154    if (MeshParent_idcode) {
00155       NI_set_attribute (nel, "Parent_ID", MeshParent_idcode); /* changed from MeshParent_idcode March 31 */
00156    } else {
00157       NI_set_attribute (nel, "Parent_ID", SUMA_EMPTY_ATTR);
00158    }
00159    if (GeomParent_idcode) {
00160       NI_set_attribute (nel, "GeomParent_idcode", GeomParent_idcode);
00161    } else {
00162       NI_set_attribute (nel, "GeomParent_idcode", SUMA_EMPTY_ATTR);
00163    }
00164   
00165    if (filename) NI_set_attribute (nel, "filename", filename);
00166    
00167    SUMA_allow_nel_use(0); 
00168    SUMA_RETURN(nel);  
00169 }
00170 
00171 /*!
00172    \brief Returns A COPY of the label of a column in a NI_element
00173    NULL in case of error 
00174    YOU SHOULD FREE THIS POINTER when you're done with it
00175 */
00176 char *SUMA_DsetColLabelCopy(SUMA_DSET *dset, int i, int addcolnum)
00177 {
00178    static char FuncName[]={"SUMA_DsetColLabelCopy"};
00179    char Name[500], *lbl = NULL, **sc=NULL, *s=NULL;
00180    NI_element *nelb=NULL;
00181    
00182    SUMA_ENTRY;
00183    
00184    if (!dset || !dset->dnel) { SUMA_RETURN(NULL); }
00185    if (i < 0 || i >= dset->dnel->vec_num) { SUMA_RETURN(NULL); }
00186    
00187    nelb = SUMA_FindDsetAttributeElement(dset, "ColumnsLabels");
00188    SUMA_NEL_GET_STRING(nelb, 0, 0, lbl); /* sc is a pointer copy here, do not free */
00189    lbl = SUMA_Get_Sub_String(lbl, SUMA_NI_SS, i);
00190    sprintf(Name, "%d: ", i);
00191    if (lbl) { 
00192       if (addcolnum) s = SUMA_append_string(Name, lbl); 
00193       else s = SUMA_copy_string(lbl); 
00194       SUMA_free(lbl); lbl = NULL;
00195       SUMA_RETURN(s);
00196    }
00197    
00198    /* no label, try the name of the nel */
00199    lbl = NI_get_attribute(dset->ngr, "label");
00200    if (lbl) {
00201       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
00202       else SUMA_RETURN(SUMA_copy_string(lbl));
00203    }
00204    lbl = NI_get_attribute(dset->ngr, "filename");
00205    if (lbl) {
00206       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
00207       else SUMA_RETURN(SUMA_copy_string(lbl));
00208    }
00209    
00210    if (dset->ngr->name) {
00211       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, dset->ngr->name)); 
00212       else SUMA_RETURN(SUMA_copy_string(dset->ngr->name));
00213    }
00214    
00215    /* give me a bone */
00216    if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, "bone"));
00217    else  SUMA_RETURN(SUMA_copy_string("bone"));
00218 }
00219 /*!
00220    \brief Returns A COPY of the label of a column in a NI_element
00221    NULL in case of error 
00222    YOU SHOULD FREE THIS POINTER when you're done with it
00223    
00224 */
00225 char *SUMA_ColLabelCopy(NI_element *nel, int i, int addcolnum)
00226 {
00227    static char FuncName[]={"SUMA_ColLabelCopy"};
00228    char Name[500], *lbl;
00229    
00230    SUMA_ENTRY;
00231    
00232    /* SUMA_SL_Warn("Obsolete, use new version."); it is still used for converting old types to new one */
00233 
00234    if (i < 0) { SUMA_RETURN(NULL); }
00235    if (!nel) { SUMA_RETURN(NULL); }
00236    
00237    sprintf(Name, "LabelCol_%d", i);
00238    lbl = NI_get_attribute(nel, Name);
00239    sprintf(Name, "%d: ", i);
00240    if (lbl) {
00241       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
00242       else SUMA_RETURN(SUMA_copy_string(lbl));
00243    }
00244    /* no label, try the name of the nel */
00245    lbl = NI_get_attribute(nel, "label");
00246    if (lbl) {
00247       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
00248       else SUMA_RETURN(SUMA_copy_string(lbl));
00249    }
00250    lbl = NI_get_attribute(nel, "filename");
00251    if (lbl) {
00252       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, lbl));
00253       else SUMA_RETURN(SUMA_copy_string(lbl));
00254    }
00255    
00256    if (nel->name) {
00257       if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, nel->name)); 
00258       else SUMA_RETURN(SUMA_copy_string(nel->name));
00259    }
00260    
00261    /* give me a bone */
00262    if (addcolnum) SUMA_RETURN(SUMA_append_string(Name, "bone"));
00263    else  SUMA_RETURN(SUMA_copy_string("bone"));
00264 }
00265 
00266 NI_element *SUMA_FindDsetDataAttributeElement(SUMA_DSET *dset)
00267 {
00268    static char FuncName[]={"SUMA_FindDsetDataAttributeElement"};
00269    char *attname=NULL;
00270    
00271    SUMA_ENTRY;
00272    
00273    attname = SUMA_append_string(dset->ngr->name,"_data");
00274    
00275    SUMA_RETURN(SUMA_FindNgrAttributeElement(dset->ngr, attname));
00276 }
00277 
00278 NI_element *SUMA_FindDsetAttributeElement(SUMA_DSET *dset, char *attname)
00279 {
00280    static char FuncName[]={"SUMA_FindDsetAttributeElement"};
00281    int ip;
00282    SUMA_Boolean LocalHead = NOPE;
00283    
00284    SUMA_ENTRY;
00285    
00286    if (!dset || !attname) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
00287    if (!dset->ngr) { SUMA_SL_Err("NUll input "); SUMA_RETURN(NULL); }
00288 
00289 
00290    SUMA_RETURN(SUMA_FindNgrAttributeElement(dset->ngr, attname));
00291 }
00292 
00293 NI_element *SUMA_FindNgrAttributeElement(NI_group *ngr, char *attname)
00294 {
00295    static char FuncName[]={"SUMA_FindNgrAttributeElement"};
00296    NI_element *nel = NULL;
00297    int ip;
00298    SUMA_Boolean LocalHead = NOPE;
00299    
00300    SUMA_ENTRY;
00301    
00302    if (!ngr || !attname) { SUMA_SL_Err("NUll input "); SUMA_RETURN(nel); }
00303   /* now read the elements in this group */
00304    for( ip=0 ; ip < ngr->part_num ; ip++ ){ 
00305       switch( ngr->part_typ[ip] ){
00306          /*-- a sub-group ==> recursion! --*/
00307          case NI_GROUP_TYPE:
00308             break ;
00309          case NI_ELEMENT_TYPE:
00310             nel = (NI_element *)ngr->part[ip] ;
00311             if (LocalHead)  {
00312                fprintf(SUMA_STDERR,"%s:  Looking for %s   name=%s vec_len=%d vec_filled=%d, vec_num=%d\n", FuncName,\
00313                         attname, nel->name, nel->vec_len, nel->vec_filled, nel->vec_num );
00314             }
00315             if (!strcmp(attname, nel->name)) SUMA_RETURN(nel);
00316             else nel = NULL;
00317             break;
00318          default:
00319             SUMA_SL_Err("Don't know what to make of this group element, ignoring.");
00320             break;
00321       }
00322    }
00323 
00324 
00325    SUMA_RETURN(nel);
00326 }
00327 
00328 
00329 /*!
00330    Add an attribute element to a data set, to be called after adding a column to the data element
00331    The old version of this is SUMA_AddColAttr
00332 */
00333 int SUMA_AddDsetColAttr (SUMA_DSET *dset, char *col_label, SUMA_COL_TYPE ctp, void *col_attr, int col_index)
00334 {
00335    static char FuncName[]={"SUMA_AddDsetColAttr"};
00336    NI_element *nelb = NULL;
00337    char Name[500], Attr[500], *attrstr;
00338    
00339    SUMA_ENTRY;
00340    
00341    if (!dset) SUMA_RETURN(0);
00342    if (col_index < 0) col_index = dset->dnel->vec_num-1;
00343    if (col_index < 0 || !dset->dnel->vec_num ) { SUMA_SL_Err("No columns in data set's data element!"); SUMA_RETURN(0); }
00344    if (dset->dnel->vec_num <= col_index) { SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
00345    
00346    /* has the column label element been added yet ?*/
00347    nelb = SUMA_FindDsetAttributeElement(dset, "ColumnsLabels");
00348    if (!nelb) { /* need to form this element */
00349       nelb = NI_new_data_element("ColumnsLabels", dset->dnel->vec_num);
00350       NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
00351       NI_add_to_group(dset->ngr, nelb);
00352    } 
00353    SUMA_AddColAtt_CompString(nelb, col_index, col_label, SUMA_NI_SS);
00354 
00355    /* has the column type element been added yet ? */
00356    nelb = SUMA_FindDsetAttributeElement(dset, "ColumnsTypes");
00357    if (!nelb) { /* need to form this element */
00358       nelb = NI_new_data_element("ColumnsTypes", dset->dnel->vec_num);
00359       NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
00360       NI_add_to_group(dset->ngr, nelb);
00361    } 
00362    /* set the type */
00363    SUMA_AddColAtt_CompString(nelb, col_index, SUMA_Col_Type_Name(ctp), SUMA_NI_SS);
00364    
00365    /* set the attribute column */
00366    nelb = SUMA_FindDsetAttributeElement(dset, "ColumnsAttributes");
00367    if (!nelb) { /* need to form this element */
00368       nelb = NI_new_data_element("ColumnsAttributes", dset->dnel->vec_num);
00369       NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
00370       NI_add_to_group(dset->ngr, nelb);
00371    } 
00372    /* set the attribute string */   
00373    switch (ctp) {
00374       case SUMA_NODE_BYTE:
00375          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00376          break;
00377          
00378       case SUMA_NODE_DOUBLE:
00379          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00380          break;
00381          
00382       case SUMA_NODE_INDEX:
00383          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00384          break;
00385      
00386       case SUMA_NODE_INT:
00387          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00388          break;
00389       
00390       case SUMA_NODE_SHORT:
00391          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00392          break;
00393       
00394       case SUMA_NODE_ILABEL:
00395          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00396          break;   
00397       
00398       case SUMA_NODE_X:
00399          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00400          break;
00401       
00402       case SUMA_NODE_Y:
00403          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00404          break;
00405       
00406       case SUMA_NODE_Z:
00407          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00408          break; 
00409          
00410       case SUMA_NODE_R:
00411          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00412          break;
00413       
00414       case SUMA_NODE_G:
00415          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00416          break;
00417       
00418       case SUMA_NODE_B:
00419          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00420          break;    
00421        
00422       case SUMA_NODE_A:
00423          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00424          break;
00425          
00426       case SUMA_NODE_Rb:
00427          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00428          break;
00429       
00430       case SUMA_NODE_Gb:
00431          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00432          break;
00433       
00434       case SUMA_NODE_Bb:
00435          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00436          break;    
00437        
00438       case SUMA_NODE_Ab:
00439          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00440          break;
00441       
00442       case SUMA_NODE_FLOAT:
00443          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00444          break;     
00445       
00446       case SUMA_NODE_3C:
00447          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00448          break;  
00449          
00450       case SUMA_NODE_STRING:
00451          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00452          break;     
00453       
00454       case SUMA_NODE_CX:
00455          attrstr = SUMA_copy_string(SUMA_EMPTY_ATTR);
00456          break;  
00457       
00458       case SUMA_NODE_XCORR:
00459          { int *dofp = (int *)col_attr;
00460             sprintf(Attr,"dof: %d", *dofp);
00461             attrstr = SUMA_copy_string(Attr);
00462          }
00463          break;  
00464 
00465       default:
00466          attrstr = NULL;
00467          break;          
00468    }
00469    
00470    SUMA_AddColAtt_CompString(nelb, col_index, attrstr, SUMA_NI_SS);
00471    
00472    if (attrstr) SUMA_free(attrstr); attrstr = NULL;
00473 
00474    SUMA_RETURN(1);   
00475 }
00476 
00477 /*!
00478    
00479    Adds an attribute to nel for that explains the last added column's 
00480    contents. You should call this function after each SUMA_AddNelCol call 
00481    col_attr (void *) is a pointer to a structure containing special
00482    attributes of the data in the last column added. At the moment,
00483    this pointer is not being used, but you can imagine needing it if
00484    you have to store certain stats or parameters that go with each column.
00485        
00486 */
00487 int SUMA_AddColAttr (NI_element *nel, char *col_label, SUMA_COL_TYPE ctp, void *col_attr, int col_index)
00488 {
00489    static char FuncName[]={"SUMA_AddColAttr"};
00490    char Name[500], Attr[500];
00491    
00492    SUMA_ENTRY;
00493    
00494    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, use new version.");
00495 
00496    if (!nel) SUMA_RETURN(0);
00497    if (col_index < 0) col_index = nel->vec_num-1;
00498    if (col_index < 0 || !nel->vec_num ) { SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
00499    if (nel->vec_num <= col_index) { SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
00500    
00501    /* if a label is specified, set it */
00502    if (col_label) {
00503       sprintf(Name, "LabelCol_%d", col_index);
00504       NI_set_attribute ( nel, Name, col_label);
00505    }
00506    /* save the type of the column */
00507    sprintf(Name, "TypeCol_%d", col_index);
00508    NI_set_attribute ( nel, Name, SUMA_Col_Type_Name(ctp));
00509    
00510    sprintf(Attr, "AttrCol_%d", col_index);
00511    switch (ctp) {
00512       case SUMA_NODE_BYTE:
00513          NI_set_attribute ( nel, Attr, NULL);
00514          break;
00515          
00516       case SUMA_NODE_DOUBLE:
00517          NI_set_attribute ( nel, Attr, NULL);
00518          break;
00519          
00520       case SUMA_NODE_INDEX:
00521          /* form the string of attributes for this column */
00522          NI_set_attribute ( nel, Attr, NULL);
00523          break;
00524      
00525       case SUMA_NODE_INT:
00526          NI_set_attribute ( nel, Attr, NULL);
00527          break;
00528       
00529       case SUMA_NODE_SHORT:
00530          NI_set_attribute ( nel, Attr, NULL);
00531          break;
00532       
00533       case SUMA_NODE_ILABEL:
00534          NI_set_attribute ( nel, Attr, NULL);
00535          break;   
00536       
00537       case SUMA_NODE_X:
00538          NI_set_attribute ( nel, Attr, NULL);
00539          break;
00540       
00541       case SUMA_NODE_Y:
00542          NI_set_attribute ( nel, Attr, NULL);
00543          break;
00544       
00545       case SUMA_NODE_Z:
00546          NI_set_attribute ( nel, Attr, NULL);
00547          break; 
00548          
00549       case SUMA_NODE_R:
00550          NI_set_attribute ( nel, Attr, NULL);
00551          break;
00552       
00553       case SUMA_NODE_G:
00554          NI_set_attribute ( nel, Attr, NULL);
00555          break;
00556       
00557       case SUMA_NODE_B:
00558          NI_set_attribute ( nel, Attr, NULL);
00559          break;    
00560        
00561       case SUMA_NODE_A:
00562          NI_set_attribute ( nel, Attr, NULL);
00563          break;
00564          
00565       case SUMA_NODE_Rb:
00566          NI_set_attribute ( nel, Attr, NULL);
00567          break;
00568       
00569       case SUMA_NODE_Gb:
00570          NI_set_attribute ( nel, Attr, NULL);
00571          break;
00572       
00573       case SUMA_NODE_Bb:
00574          NI_set_attribute ( nel, Attr, NULL);
00575          break;    
00576        
00577       case SUMA_NODE_Ab:
00578          NI_set_attribute ( nel, Attr, NULL);
00579          break;
00580       
00581       case SUMA_NODE_FLOAT:
00582          NI_set_attribute ( nel, Attr, NULL);
00583          break;     
00584       
00585       case SUMA_NODE_3C:
00586          NI_set_attribute ( nel, Attr, NULL);
00587          break;  
00588          
00589       case SUMA_NODE_STRING:
00590          NI_set_attribute ( nel, Attr, NULL);
00591          break;     
00592       
00593       case SUMA_NODE_CX:
00594          NI_set_attribute ( nel, Attr, NULL);
00595          break;  
00596       
00597       default:
00598          NI_set_attribute ( nel, Attr, NULL);
00599          break;          
00600    }
00601    
00602    SUMA_allow_nel_use(0);
00603 
00604    SUMA_RETURN(1);   
00605 }
00606 
00607 /*!
00608    Adds some generic attributes.
00609    For the moment, the range is added for numeric columns 
00610    if col_index is -1, then it is assumed that the attributes are for the latest column added (vec_num -1)
00611 */
00612 int SUMA_AddGenDsetColAttr (SUMA_DSET *dset, SUMA_COL_TYPE ctp, void *col, int stride, int col_index) 
00613 {
00614    static char FuncName[]={"SUMA_AddGenDsetColAttr"};
00615    char Name[500], **junk, *stmp, *curstring = NULL;
00616    float amin = 0.0, amax = 0.0, *fv;
00617    int aminloc = -1, amaxloc = -1, *iv;
00618    byte *bv;
00619    NI_element *nelb = NULL;
00620    SUMA_Boolean LocalHead = NOPE;
00621    
00622    SUMA_ENTRY;
00623    
00624    if (!dset || !dset->dnel) { SUMA_SL_Err("Null input"); SUMA_RETURN(0); } 
00625    if (col_index < 0) col_index = dset->dnel->vec_num-1;
00626    if (col_index < 0 || !dset->dnel->vec_num ) { SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
00627    if (dset->dnel->vec_num <= col_index) { SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
00628    
00629    /* does the range attribute element exist ? */
00630    nelb = SUMA_FindDsetAttributeElement(dset, "ColumnsRanges");
00631    if (!nelb) { /* need to form this element */
00632       SUMA_LH("Need to create ranges element");
00633       nelb = NI_new_data_element("ColumnsRanges", 1); /* one long string */
00634       NI_add_to_group(dset->ngr, nelb);
00635       #if 0 /* trying to work with NI_insert */
00636       { int i ; junk = (char **)SUMA_malloc(sizeof(char*)*300); 
00637          for (i=0; i< 300; ++i) junk[i] = (char *)SUMA_malloc(300 * sizeof(char));
00638          for (i=0; i<50; ++i) sprintf(junk[i], "Hello Baby Joannne ro"); }
00639       NI_add_column_stride ( nelb, NI_STRING, junk, 1 );
00640       #else
00641          NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
00642       #endif
00643       if (LocalHead) SUMA_ShowNel(nelb);
00644       curstring = NULL;
00645    } else {
00646       SUMA_LH("Ranges element found, getting previous string");
00647       SUMA_NEL_GET_STRING(nelb, 0, 0, curstring);
00648    }
00649    if (!col) { 
00650       SUMA_LH("No data");
00651       /* Do not complain, that is not a bad thing.
00652       People can use this to allocate for a column
00653       without filling it up */
00654       stmp = SUMA_copy_string("0 0 -1 -1");
00655    } else { 
00656       SUMA_LH("Calculating range");
00657       switch (SUMA_ColType2TypeCast(ctp)) {
00658          case SUMA_int:
00659             iv = (int *)col;
00660             SUMA_MIN_MAX_VEC_STRIDE(iv ,dset->dnel->vec_filled, amin, amax, aminloc, amaxloc, stride);
00661             snprintf(Name, 500*sizeof(char),"%d %d %d %d", (int)amin, (int)amax, aminloc, amaxloc);
00662             break;
00663          case SUMA_float:
00664             fv = (float *)col;
00665             SUMA_MIN_MAX_VEC_STRIDE(fv ,dset->dnel->vec_filled, amin, amax, aminloc, amaxloc, stride);
00666             snprintf(Name, 500*sizeof(char),"%f %f %d %d", amin, amax, aminloc, amaxloc);
00667             break;
00668          case SUMA_byte:
00669             bv = (byte *)col;
00670             SUMA_MIN_MAX_VEC_STRIDE(bv ,dset->dnel->vec_filled, amin, amax, aminloc, amaxloc, stride);
00671             snprintf(Name, 500*sizeof(char),"%d %d %d %d", (int)amin, (int)amax, aminloc, amaxloc);
00672             break;
00673          case SUMA_string:
00674             Name[0] = '\0';
00675             break;
00676          default:
00677             fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
00678             SUMA_RETURN(0);
00679             break; 
00680       }
00681       stmp = SUMA_copy_string(Name);
00682    }
00683    
00684    
00685    SUMA_AddColAtt_CompString(nelb, col_index, stmp, SUMA_NI_SS);
00686    if (LocalHead) SUMA_ShowNel(nelb);
00687    SUMA_free(stmp); stmp = NULL;
00688    SUMA_RETURN(1);  
00689 }
00690 
00691 
00692 /*!
00693    Adds some generic attributes.
00694    For the moment, the range is added for numeric columns 
00695    if col_index is -1, then it is assumed that the attributes are for the latest column added (vec_num -1)
00696 */
00697 int SUMA_AddGenColAttr (NI_element *nel, SUMA_COL_TYPE ctp, void *col, int stride, int col_index) 
00698 {
00699    static char FuncName[]={"SUMA_AddGenColAttr"};
00700    static char stmp[500], Name[500];
00701    float amin = 0.0, amax = 0.0, *fv;
00702    int aminloc = -1, amaxloc = -1, *iv;
00703    byte *bv;
00704 
00705    SUMA_ENTRY;
00706    
00707    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, use new version.");
00708 
00709    if (!nel) { SUMA_SL_Err("Null Nel"); SUMA_RETURN(0); }
00710    if (col_index < 0) col_index = nel->vec_num-1;
00711    if (col_index < 0 || !nel->vec_num ) { SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
00712    if (nel->vec_num <= col_index) { SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
00713    
00714    sprintf(Name, "RangeCol_%d", col_index);
00715 
00716    if (!col) { 
00717       /* Do not complain, that is not a bad thing.
00718       People can use this to allocate for a column
00719       without filling it up */
00720       sprintf(stmp, "0 0 -1 -1");
00721    } else {
00722       switch (SUMA_ColType2TypeCast(ctp)) {
00723          case SUMA_int:
00724             iv = (int *)col;
00725             SUMA_MIN_MAX_VEC_STRIDE(iv ,nel->vec_filled, amin, amax, aminloc, amaxloc, stride);
00726             snprintf(stmp, 500*sizeof(char),"%d %d %d %d", (int)amin, (int)amax, aminloc, amaxloc);
00727             break;
00728          case SUMA_float:
00729             fv = (float *)col;
00730             SUMA_MIN_MAX_VEC_STRIDE(fv ,nel->vec_filled, amin, amax, aminloc, amaxloc, stride);
00731             snprintf(stmp, 500*sizeof(char),"%f %f %d %d", amin, amax, aminloc, amaxloc);
00732             break;
00733          case SUMA_byte:
00734             bv = (byte *)col;
00735             SUMA_MIN_MAX_VEC_STRIDE(bv ,nel->vec_filled, amin, amax, aminloc, amaxloc, stride);
00736             snprintf(stmp, 500*sizeof(char),"%d %d %d %d", (int)amin, (int)amax, aminloc, amaxloc);
00737             break;
00738          case SUMA_string:
00739             stmp[0] = '\0';
00740             break;
00741          default:
00742             fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
00743             SUMA_RETURN(0);
00744             break; 
00745       }
00746    }
00747    
00748    NI_set_attribute ( nel, Name, stmp);
00749    
00750    SUMA_allow_nel_use(0); 
00751    SUMA_RETURN(1);  
00752 }
00753 
00754 
00755 /*!
00756    \brief Gets the column range values
00757    col_index can be -1 if you want the attributes of the last column
00758 */
00759 int SUMA_GetDsetColRange(SUMA_DSET *dset, int col_index, float range[2], int loc[2])
00760 {
00761    static char FuncName[]={"SUMA_GetDsetColRange"};
00762    char *rs = NULL, **sc=NULL, Name[500];
00763    float nums[4];
00764    NI_element *nelb = NULL;
00765    
00766    SUMA_ENTRY;
00767    
00768    if (!dset || !dset->dnel) { SUMA_SL_Err("Null input"); SUMA_RETURN(0); }
00769    if (col_index < 0) col_index = dset->dnel->vec_num-1;
00770    if (col_index < 0 || !dset->dnel->vec_num ) { SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
00771    if (dset->dnel->vec_num <= col_index) { SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
00772    
00773    nelb = SUMA_FindDsetAttributeElement(dset, "ColumnsRanges");
00774    if (!nelb) { SUMA_SL_Err("Failed to find column range attribute"); SUMA_RETURN(0); }
00775    
00776    SUMA_NEL_GET_STRING(nelb, 0, 0, rs); /* rs is a pointer copy here, do not free */
00777    rs = SUMA_Get_Sub_String(rs, SUMA_NI_SS, col_index);
00778    if (!rs) { SUMA_SL_Err("No range field."); SUMA_RETURN(0); }
00779    if (SUMA_StringToNum(rs, nums, 4) != 4) { SUMA_SL_Err("Failed to read 4 nums from range."); SUMA_RETURN(0); }
00780    range[0] = nums[0]; range[1] = nums[1]; 
00781    loc[0] = (int)nums[2]; loc[1] = (int)nums[3];
00782    SUMA_free(rs); rs = NULL;   
00783    SUMA_RETURN(1);
00784 }
00785 
00786 
00787 /*!
00788    \brief Gets the column range values
00789    col_index can be -1 if you want the attributes of the last column
00790 */
00791 int SUMA_GetColRange(NI_element *nel, int col_index, float range[2], int loc[2])
00792 {
00793    static char FuncName[]={"SUMA_GetColRange"};
00794    char *rs = NULL, Name[500];
00795    float nums[4];
00796    
00797    SUMA_ENTRY;
00798    
00799    SUMA_SL_Warn("Obsolete, use new version.");
00800 
00801    if (!nel) { SUMA_SL_Err("Null Nel"); SUMA_RETURN(0); }
00802    if (col_index < 0) col_index = nel->vec_num-1;
00803    if (col_index < 0 || !nel->vec_num ) { SUMA_SL_Err("No columns in data set!"); SUMA_RETURN(0); }
00804    if (nel->vec_num <= col_index) { SUMA_SL_Err("col_index >= nel->vec_num!"); SUMA_RETURN(0); }
00805    
00806    
00807    sprintf(Name, "RangeCol_%d", col_index);
00808    rs = NI_get_attribute(nel, Name);
00809    
00810    if (!rs) { SUMA_SL_Err("No range field."); SUMA_RETURN(0); }
00811    if (SUMA_StringToNum(rs, nums, 4) != 4) { SUMA_SL_Err("Failed to read 4 nums from range."); SUMA_RETURN(0); }
00812    range[0] = nums[0]; range[1] = nums[1]; 
00813    loc[0] = (int)nums[2]; loc[1] = (int)nums[3];
00814       
00815    SUMA_RETURN(1);
00816 }
00817 /*!
00818    Adds a column to dset->dnel (new version of SUMA_AddNelCol)
00819    The vectors added are nel->vec_len long so col should contain at least
00820    nel->vec_len * stride elements.
00821    
00822    What to do when filling up to nel->vec_filled only ? Does one need to 
00823    write another version of NI_add_column_stride ? (see file niml/niml_element)
00824    Is the use of vec_filled what I think it is ?
00825    
00826    Mar 23 04: Made modifications to NI_add_column and _stride
00827    so that data are copied up to nel->vec_filled instead of 
00828    nel->vec_len if nel->vec_filled is > 0 and < vec_len
00829    
00830    If you wish to allocate space for a column (nel->vec_len long)
00831    then pass NULL for col
00832 */
00833 
00834 int SUMA_AddDsetNelCol ( SUMA_DSET *dset, char *col_label, SUMA_COL_TYPE ctp, void *col, 
00835                      void *col_attr, int stride)
00836 {
00837    static char FuncName[]={"SUMA_AddDsetNelCol"};
00838    NI_element *nelb=NULL;
00839    
00840    SUMA_ENTRY;
00841    
00842    if (!dset || !dset->dnel) { SUMA_SL_Err("Null input"); SUMA_RETURN(0); }
00843    if (!col) { 
00844       /* Do not complain, that is not a bad thing.
00845       People can use this to allocate for a column
00846       without filling it up */
00847       /* SUMA_SL_Err("Null Col"); SUMA_RETURN(0); */
00848    }
00849    
00850    switch (SUMA_ColType2TypeCast(ctp)) {
00851       case SUMA_int:
00852          NI_add_column_stride ( dset->dnel, NI_INT, (int *)col, stride);
00853          break;
00854       case SUMA_float:
00855          NI_add_column_stride ( dset->dnel, NI_FLOAT, (float *)col, stride );      
00856          break;
00857       case SUMA_byte:
00858          NI_add_column_stride ( dset->dnel, NI_BYTE, (byte *)col, stride );      
00859          break;
00860       case SUMA_double:
00861          NI_add_column_stride ( dset->dnel, NI_DOUBLE, (double *)col, stride );      
00862          break;
00863       case SUMA_string:
00864          NI_add_column_stride ( dset->dnel, NI_STRING, (char **)col, stride );
00865          break;
00866       default:
00867          fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
00868          SUMA_RETURN(0);
00869          break; 
00870    }
00871    
00872    /* set some generic attributes */
00873    SUMA_AddGenDsetColAttr (dset, ctp, col, stride, -1);
00874    /* add the attributes of that column */
00875    SUMA_AddDsetColAttr (dset, col_label, ctp, col_attr, -1);
00876    
00877    SUMA_RETURN(1);
00878 }
00879 /*!
00880    Adds a column to Nel
00881    The vectors added are nel->vec_len long so col should contain at least
00882    nel->vec_len * stride elements.
00883    
00884    What to do when filling up to nel->vec_filled only ? Does one need to 
00885    write another version of NI_add_column_stride ? (see file niml/niml_element)
00886    Is the use of vec_filled what I think it is ?
00887    
00888    Mar 23 04: Made modifications to NI_add_column and _stride
00889    so that data are copied up to nel->vec_filled instead of 
00890    nel->vec_len if nel->vec_filled is > 0 and < vec_len
00891    
00892    If you wish to allocate space for a column (nel->vec_len long)
00893    then pass NULL for col
00894 */
00895 
00896 int SUMA_AddNelCol ( NI_element *nel, char *col_label, SUMA_COL_TYPE ctp, void *col, 
00897                      void *col_attr, int stride)
00898 {
00899    static char FuncName[]={"SUMA_AddNelCol"};
00900    SUMA_ENTRY;
00901    
00902    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, use new version.");
00903    if (!nel) { SUMA_SL_Err("Null Nel"); SUMA_RETURN(0); }
00904    if (!col) { 
00905       /* Do not complain, that is not a bad thing.
00906       People can use this to allocate for a column
00907       without filling it up */
00908       /* SUMA_SL_Err("Null Col"); SUMA_RETURN(0); */
00909    }
00910    
00911    switch (SUMA_ColType2TypeCast(ctp)) {
00912       case SUMA_int:
00913          NI_add_column_stride ( nel, NI_INT, (int *)col, stride);
00914          break;
00915       case SUMA_float:
00916          NI_add_column_stride ( nel, NI_FLOAT, (float *)col, stride );      
00917          break;
00918       case SUMA_byte:
00919          NI_add_column_stride ( nel, NI_BYTE, (byte *)col, stride );      
00920          break;
00921       case SUMA_double:
00922          NI_add_column_stride ( nel, NI_DOUBLE, (double *)col, stride );      
00923          break;
00924       case SUMA_string:
00925          NI_add_column_stride ( nel, NI_STRING, (char **)col, stride );
00926          break;
00927       default:
00928          fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
00929          SUMA_RETURN(0);
00930          break; 
00931    }
00932    
00933    /* set some generic attributes */
00934    SUMA_allow_nel_use(1);
00935    SUMA_AddGenColAttr (nel, ctp, col, stride, -1);
00936    /* add the attributes of that column */
00937    SUMA_allow_nel_use(1);
00938    SUMA_AddColAttr (nel, col_label, ctp, col_attr, -1);
00939    
00940    SUMA_allow_nel_use(0);
00941    SUMA_RETURN(1);
00942 }
00943 
00944 /*! 
00945    \brief creates a new dataset that has a copy of each row in odset 
00946    wherever rowmask[irow] is not zero. 
00947    \param odset (SUMA_DSET *) input dataset
00948    \param rowmask (int *) [nel->vec_len x 1] vector specifying which rows to preserve
00949                                              If rowmask[irow] is 1 then this row is copied
00950                                              into ndset. 
00951                                              If rowmask[irow] = 0 then the row is either
00952                                              skipped (see masked_only) or set to 0 in its entirety 
00953                                              (see keep_node_index for exception).
00954                                              If rowmask == NULL then all rows are copied
00955    \param colmask (int *) [nel->vec_num x 1] vector specifying which volumns to operate on.
00956                                              If colmask[icol] is 1 then values in this column 
00957                                              are copied. 
00958                                              If colmask == NULL then all columns are copied
00959    \param masked_only (int)   If 1 then the output dataset is only to contain
00960                               those rows where rowmask[irow] = 1
00961                               If 0 then all rows are output but with column entries set to 0
00962                               for all rows where rowmask[irow] = 0. One column might be
00963                               exempt from nulling if it meets the requirements on Schedule B form suma654.233 
00964                               or if it is of the type SUMA_NODE_INDEX and keep_node_index is set to 1. 
00965                               
00966    \param keep_node_index (int) If 1, then preserves the node index column (SUMA_NODE_INDEX) from being masked.
00967                                 Makes sense to use it when masked_only == 0. 
00968    \param ndset (SUMA_DSET *) Copy of dataset with masking applied.
00969    
00970    - You might want to have a version that replaces columns in odset with the masked data
00971    as opposed to copying them. I think I do something like this with the drawn ROI dataset...
00972    
00973    \sa SUMA_Copy_Part_Column
00974 */  
00975 SUMA_DSET * SUMA_MaskedCopyofDset(SUMA_DSET *odset, byte *rowmask, byte *colmask, int masked_only, int keep_node_index)
00976 {
00977    static char FuncName[]={"SUMA_MaskedCopyofDset"};
00978    int n_incopy = -1, i;
00979    char *new_name=NULL, idcode[SUMA_IDCODE_LENGTH], *lblcp;
00980    SUMA_DSET *ndset=NULL;
00981    NI_rowtype *rt=NULL;
00982    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
00983    void *ncol=NULL;
00984    int DoThisCol=0;
00985    SUMA_Boolean LocalHead = NOPE;
00986    
00987    SUMA_ENTRY;
00988    
00989    if (!odset) { SUMA_SL_Err("Null input"); SUMA_RETURN(NULL); }
00990    if (!odset->dnel) { SUMA_SL_Err("Null dnel"); SUMA_RETURN(NULL); }
00991    if (!SUMA_is_AllNumeric_dset(odset)) {
00992       SUMA_SL_Err("Function does not deal withdata sets containing non-numeric columns");
00993       SUMA_RETURN(NULL);
00994    }
00995    if (0 && LocalHead) {
00996       SUMA_ShowNel(odset->dnel);
00997    }
00998    for (i=0; i < odset->dnel->vec_num; ++i) {
00999       if (!colmask) DoThisCol = 1;
01000       else DoThisCol = colmask[i];
01001       if (DoThisCol) {
01002          if (LocalHead) fprintf(SUMA_STDERR,"%s:\nProcessing column %d\n", FuncName, i);
01003          ctp = SUMA_TypeOfDsetColNumb(odset, i); 
01004          rt = NI_rowtype_find_code(SUMA_ColType2TypeCast(ctp)) ; 
01005          if( rt == NULL || ROWTYPE_is_varsize(rt)) {
01006             SUMA_SL_Err("Could not recognize rowtype, or rowtype is of variable size."); SUMA_RETURN(NULL);
01007          }
01008          if (ctp == SUMA_NODE_INDEX && keep_node_index && !masked_only) {
01009             SUMA_LH("Preserving");
01010             /* preserve all indices */
01011             ncol = SUMA_Copy_Part_Column(odset->dnel->vec[i], rt, odset->dnel->vec_len, NULL, masked_only, &n_incopy);
01012          } else {
01013             SUMA_LH("Not Preserving");
01014             ncol = SUMA_Copy_Part_Column(odset->dnel->vec[i], rt, odset->dnel->vec_len, rowmask, masked_only, &n_incopy);  
01015          }
01016          if (!ncol) {
01017             SUMA_SL_Err("No data got copied.");
01018             SUMA_RETURN(ndset);
01019          }
01020          if (!ndset) {
01021             new_name = SUMA_append_string(NI_get_attribute(odset->ngr,"filename"),"copy");
01022             UNIQ_idcode_fill(idcode); 
01023             ndset =  SUMA_CreateDsetPointer( new_name, SUMA_Dset_Type(odset->ngr->name), idcode, NI_get_attribute(odset->ngr,"Parent_ID"),  n_incopy ); 
01024             SUMA_free(new_name); new_name = NULL;
01025          }
01026          /* add the column */
01027          SUMA_LH("Getting the label");
01028          lblcp = SUMA_DsetColLabelCopy(odset, i, 0);
01029          SUMA_LH("Inserting the column");
01030          if (!SUMA_AddDsetNelCol (ndset, lblcp, ctp, ncol, NULL ,1)) {
01031             SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
01032             SUMA_FreeDset((void*)ndset); ndset = NULL;
01033             SUMA_RETURN(ndset);
01034          } 
01035          if (lblcp) SUMA_free(lblcp); lblcp = NULL;
01036       } else {
01037          if (LocalHead) fprintf(SUMA_STDERR,"%s:\nSkipping column %d\n", FuncName, i);
01038       }
01039    }
01040    
01041    SUMA_RETURN(ndset);
01042 }
01043 
01044 /*!
01045    see help for SUMA_MaskedCopyofDset
01046       
01047 */
01048 void *SUMA_Copy_Part_Column(void *col, NI_rowtype *rt, int N_col, byte *rowmask, int masked_only, int *n_incopy)
01049 {
01050    static char FuncName[]={"SUMA_Copy_Part_Column"};
01051    int n_alloc = -1, i, j, cnt;
01052    char *ndat = NULL;
01053    SUMA_Boolean LocalHead = NOPE;
01054    SUMA_ENTRY;
01055     
01056    *n_incopy = -1;
01057    n_alloc = 0;
01058    if (masked_only) {
01059       if (rowmask) {
01060          for (i=0; i<N_col; ++i) {
01061             if (rowmask[i]) ++n_alloc;
01062          }
01063       } else { /* copy entire column ... */
01064          n_alloc = N_col;
01065       }
01066    } else {
01067       n_alloc = N_col;
01068    }  
01069    
01070    if (!n_alloc) {
01071       SUMA_SL_Err("No values to go in column...");
01072       SUMA_RETURN(NULL);
01073    }
01074    
01075    /* allocate for result */
01076          ndat = (char *)SUMA_malloc(sizeof(char) *  rt->size * n_alloc ) ;
01077          if (!ndat) { SUMA_SL_Crit("Failed to allocate for ndat"); SUMA_RETURN(NULL); }
01078          /* Now to copy the proper values */
01079          if (!masked_only) {
01080             SUMA_LH("All copy");
01081             memcpy( ndat , (char *)col , rt->size * n_alloc ) ;
01082             /* reset values that are not in mask */
01083             if (rowmask) {
01084                switch(rt->code) {
01085                   case NI_BYTE:
01086                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, byte, 0);}
01087                      break;
01088                   case NI_SHORT:
01089                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, short, 0);}
01090                      break;
01091                   case NI_INT:
01092                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, int, 0);}
01093                      break;
01094                   case NI_FLOAT:
01095                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, float, 0);}
01096                      break;
01097                   case NI_DOUBLE:
01098                      for (j=0; j<N_col; ++j) if (!rowmask[j]) {SUMA_ASSIGN_VALUE_IN_VEC (ndat, j, double, 0);}
01099                      break;
01100                   default:
01101                      SUMA_SL_Warn("Type not allowed for masking operation, skipping.");
01102                      break;
01103                }
01104             } 
01105          } else {
01106             if (rowmask) {
01107                /* copy good values, one at a time */
01108                SUMA_LH("Masked only copy");
01109                cnt = 0;
01110                switch(rt->code) {
01111                   case NI_BYTE:
01112                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, byte, byte); ++cnt;}
01113                      break;
01114                   case NI_SHORT:
01115                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, short, short); ++cnt;}
01116                      break;
01117                   case NI_INT:
01118                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, int, int); ++cnt;}
01119                      break;
01120                   case NI_FLOAT:
01121                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, float, float); ++cnt;}
01122                      break;
01123                   case NI_DOUBLE:
01124                      for (j=0; j<N_col; ++j) if (rowmask[j]) {SUMA_COPY_VALUE_IN_VEC(col, ndat, j, cnt, double, double); ++cnt;}
01125                      break;
01126                   default:
01127                      SUMA_SL_Warn("Type not allowed for masking operation, skipping.");
01128                      break;
01129                }
01130             } else {
01131                /* wants a copy of everything */
01132                memcpy( ndat , (char *)col , rt->size * n_alloc ) ;
01133             } 
01134             
01135          }
01136    *n_incopy = n_alloc;
01137    SUMA_LH("Returning");
01138    SUMA_RETURN((void *)ndat);
01139 }
01140 /*!
01141    \brief Function to fill the contents of a pre-existing column 
01142    created with SUMA_AddDsetNelCol.  
01143    if vec_filled > 0 && vec_filled <= vec_len, filling is done
01144    up to vec_filled.
01145    vec_filled must be set BEFORE YOU CALL THIS FUNCTION
01146    New version of SUMA_FillNelCol
01147 */
01148 int SUMA_FillDsetNelCol (SUMA_DSET *dset, char *col_label, SUMA_COL_TYPE ctp, void *col, 
01149                      void *col_attr, int stride) 
01150 {  
01151    static char FuncName[]={"SUMA_FillDsetNelCol"};
01152    int icol = -1;
01153    int *iv, N_i;
01154    
01155    SUMA_ENTRY;
01156    
01157    /* find the index into vec of the column of type ctp,
01158       complain if you find more than 1 */
01159    iv = SUMA_GetDsetColIndex (dset, ctp, &N_i);
01160    if (N_i != 1) {
01161       SUMA_SL_Err("Found more than one column.\n");
01162       SUMA_RETURN(-1);
01163    }
01164    icol = iv[0];
01165    SUMA_free(iv); iv = NULL;
01166    
01167    /* Now use the function NI_fill_column_stride
01168    that I have yet to write in nim_element.c
01169    (a modification of NI_add_column_stride) and
01170    you're all set */ 
01171    switch (SUMA_ColType2TypeCast(ctp)) {
01172       case SUMA_int:
01173          NI_fill_column_stride ( dset->dnel, NI_INT, (int *)col, icol, stride);
01174          break;
01175       case SUMA_float:
01176          NI_fill_column_stride ( dset->dnel, NI_FLOAT, (float *)col, icol, stride );      
01177          break;
01178       case SUMA_byte:
01179          NI_fill_column_stride ( dset->dnel, NI_BYTE, (byte *)col, icol, stride );      
01180          break;
01181       case SUMA_string:
01182          NI_fill_column_stride ( dset->dnel, NI_STRING, (char **)col, icol, stride );
01183          break;
01184       case SUMA_double:
01185          NI_fill_column_stride ( dset->dnel, NI_DOUBLE, (double **)col, icol, stride );
01186          break;
01187       default:
01188          fprintf  (stderr,"Error %s: Bad column type.\n", FuncName);
01189          SUMA_RETURN(0);
01190          break; 
01191    }
01192    /* set some generic attributes */
01193    SUMA_AddGenDsetColAttr (dset, ctp, col, stride, icol);
01194    /* add the attributes of that column */
01195    SUMA_AddDsetColAttr (dset, col_label, ctp, col_attr, icol);
01196    
01197    SUMA_RETURN(1);
01198 }
01199 /*!
01200    \brief Function to fill the contents of a pre-existing column 
01201    created with SUMA_AddNelCol.  
01202    if vec_filled > 0 && vec_filled <= vec_len, filling is done
01203    up to vec_filled.
01204    vec_filled must be set BEFORE YOU CALL THIS FUNCTION
01205 */
01206 int SUMA_FillNelCol (NI_element *nel, char *col_label, SUMA_COL_TYPE ctp, void *col, 
01207                      void *col_attr, int stride) 
01208 {  
01209    static char FuncName[]={"SUMA_FillNelCol"};
01210    int icol = -1;
01211    int *iv, N_i;
01212 
01213    SUMA_ENTRY;
01214 
01215    if (!SUMA_ALLOW_NEL_USE) SUMA_SL_Warn("Obsolete, use new version.");
01216    
01217    /* find the index into vec of the column of type ctp,
01218       complain if you find more than 1 */
01219    iv = SUMA_GetColIndex (nel, ctp, &N_i);
01220    if (N_i != 1) {
01221       SUMA_SL_Err("Found more than one column.\n");
01222       SUMA_RETURN(-1);
01223    }
01224    icol = iv[0];
01225    SUMA_free(iv); iv = NULL;
01226    
01227    /* Now use the function NI_fill_column_stride
01228    that I have yet to write in nim_element.c
01229    (a modification of NI_add_column_stride) and
01230    you're all set */ 
01231    switch (SUMA_ColType2TypeCast(ctp)) {
01232       case SUMA_int:
01233          NI_fill_column_stride ( nel, NI_INT, (int *)col, icol, stride);
01234          break;
01235       case SUMA_float:
01236          NI_fill_column_stride ( nel, NI_FLOAT, (float *)col, icol, stride );      
01237          break;
01238       case SUMA_byte:
01239          NI_fill_column_stride ( nel, NI_BYTE, (byte *)col, icol, stride );      
01240          break;
01241       case SUMA_string:
01242          NI_fill_column_stride ( nel, NI_STRING, (char **)col, icol, stride );
01243          break;
01244       case SUMA_double:
01245          NI_fill_column_stride ( nel, NI_DOUBLE, (double **)col, icol, stride );
01246          break;
01247       default:
01248          fprintf  (stderr,"Error %s: Bad column type.\n", FuncName);
01249          SUMA_RETURN(0);
01250          break; 
01251    }
01252    /* set some generic attributes */
01253    SUMA_AddGenColAttr (nel, ctp, col, stride, icol);
01254    /* add the attributes of that column */
01255    SUMA_AddColAttr (nel, col_label, ctp, col_attr, icol);
01256    
01257    SUMA_allow_nel_use(0); 
01258    SUMA_RETURN(1);
01259 }
01260 
01261 SUMA_VARTYPE SUMA_VarType2TypeCast (char *vt)
01262 {
01263    static char FuncName[]={"SUMA_VarType2TypeCast"};
01264    
01265    SUMA_ENTRY;
01266    
01267    if (!vt) SUMA_RETURN(SUMA_notypeset);
01268    
01269    if (strstr(vt,"int")) SUMA_RETURN(SUMA_int);
01270    if (strstr(vt,"float")) SUMA_RETURN(SUMA_float);
01271    if (strstr(vt,"byte")) SUMA_RETURN(SUMA_byte);
01272    if (strstr(vt,"double")) SUMA_RETURN(SUMA_double);
01273    if (strstr(vt,"short")) SUMA_RETURN(SUMA_short);
01274    
01275    SUMA_RETURN(SUMA_notypeset);
01276 }
01277 
01278 int SUMA_SizeOf(SUMA_VARTYPE vt)
01279 {
01280    static char FuncName[]={"SUMA_SizeOf"};
01281    
01282    SUMA_ENTRY;
01283    
01284    switch (vt) {
01285       case SUMA_int:
01286          SUMA_RETURN(sizeof(int));
01287          break;
01288       case SUMA_float:
01289          SUMA_RETURN(sizeof(float));
01290          break;
01291       case SUMA_byte:
01292          SUMA_RETURN(sizeof(byte));
01293          break;
01294       case SUMA_double:
01295          SUMA_RETURN(sizeof(double));
01296          break;
01297       case SUMA_short:
01298          SUMA_RETURN(sizeof(short));
01299          break;
01300       default:
01301          SUMA_RETURN(-1);
01302    }
01303    
01304 }
01305 
01306 SUMA_COL_TYPE SUMA_VarType2ColType (char *vt)
01307 {
01308    static char FuncName[]={"SUMA_VarType2ColType"};
01309    
01310    SUMA_ENTRY;
01311    
01312    if (!vt) SUMA_RETURN(SUMA_notypeset);
01313    
01314    if (strstr(vt,"int")) SUMA_RETURN(SUMA_NODE_INT);
01315    if (strstr(vt,"float")) SUMA_RETURN(SUMA_NODE_FLOAT);
01316    if (strstr(vt,"byte")) SUMA_RETURN(SUMA_NODE_BYTE);
01317    if (strstr(vt,"double")) SUMA_RETURN(SUMA_NODE_DOUBLE);
01318    if (strstr(vt,"short")) SUMA_RETURN(SUMA_NODE_SHORT);
01319    
01320    SUMA_RETURN(SUMA_ERROR_COL_TYPE);
01321 }
01322  
01323 SUMA_VARTYPE SUMA_ColType2TypeCast (SUMA_COL_TYPE ctp) 
01324 {
01325    static char FuncName[]={"SUMA_ColType2TypeCast"};
01326    
01327    SUMA_ENTRY;
01328    
01329    switch (ctp) {
01330       case SUMA_NODE_INT:
01331       case SUMA_NODE_ILABEL:
01332       case SUMA_NODE_INDEX:
01333          SUMA_RETURN(SUMA_int);
01334          break;
01335       case SUMA_NODE_FLOAT:
01336       case SUMA_NODE_CX:
01337       case SUMA_NODE_X:
01338       case SUMA_NODE_Y:
01339       case SUMA_NODE_Z:
01340       case SUMA_NODE_R:
01341       case SUMA_NODE_G:
01342       case SUMA_NODE_B:
01343       case SUMA_NODE_A:
01344       case SUMA_NODE_XCORR:
01345       case SUMA_NODE_3C:
01346          SUMA_RETURN(SUMA_float);      
01347          break;
01348       case SUMA_NODE_BYTE:
01349       case SUMA_NODE_Rb:
01350       case SUMA_NODE_Gb:
01351       case SUMA_NODE_Bb:
01352       case SUMA_NODE_Ab:
01353          SUMA_RETURN(SUMA_byte);          
01354          break;
01355       case SUMA_NODE_STRING:
01356          SUMA_RETURN(SUMA_string);
01357          break;
01358       default:
01359          fprintf  (stderr,"Error %s: Bad column type.\n", FuncName);
01360          SUMA_RETURN(SUMA_notypeset);
01361          break; 
01362    }
01363    
01364    SUMA_RETURN(SUMA_notypeset);
01365 }
01366 char * SUMA_Dset_Format_Name (SUMA_DSET_FORMAT fr)
01367 {
01368    static char FuncName[]={"SUMA_Dset_Format_Name"};
01369    
01370    SUMA_ENTRY;
01371    
01372    switch(fr) {
01373       case SUMA_ERROR_DSET_FORMAT:
01374          SUMA_RETURN ("Error_Dset_Format");
01375          break;
01376       case SUMA_NO_DSET_FORMAT:
01377          SUMA_RETURN ("Dset_Format_Undefined");
01378          break;
01379       case SUMA_ASCII_NIML:
01380          SUMA_RETURN ("Ascii_Niml");
01381          break;
01382       case SUMA_BINARY_NIML:
01383          SUMA_RETURN ("Binary_Niml");
01384          break;
01385       case SUMA_NIML:
01386          SUMA_RETURN ("Niml");
01387          break;
01388       case SUMA_1D:
01389          SUMA_RETURN ("Afni_1D");
01390          break;
01391       case SUMA_ASCII_OPEN_DX_DSET:
01392          SUMA_RETURN ("Ascii_OpenDX_dset");
01393          break;
01394       default:
01395          SUMA_RETURN("Cowabonga-gimlauron");
01396          break;
01397    }   
01398    
01399 }
01400 
01401 SUMA_DSET_FORMAT SUMA_Dset_Format (char *Name)
01402 {
01403    static char FuncName[]={"SUMA_Dset_Format"};
01404 
01405    SUMA_ENTRY;
01406    
01407    if (!strcmp(Name,"Error_Dset_Format")) SUMA_RETURN (SUMA_ERROR_DSET_FORMAT);
01408    if (!strcmp(Name,"Dset_Format_Undefined")) SUMA_RETURN (SUMA_NO_DSET_FORMAT);
01409    if (!strcmp(Name,"Ascii_Niml")) SUMA_RETURN (SUMA_ASCII_NIML);
01410    if (!strcmp(Name,"Binary_Niml")) SUMA_RETURN (SUMA_BINARY_NIML);
01411    if (!strcmp(Name,"Niml")) SUMA_RETURN (SUMA_NIML);
01412    if (!strcmp(Name,"Afni_1D")) SUMA_RETURN (SUMA_1D);
01413    if (!strcmp(Name,"Ascii_OpenDX_dset")) SUMA_RETURN (SUMA_ASCII_OPEN_DX_DSET);
01414    SUMA_RETURN(SUMA_ERROR_DSET_FORMAT);
01415 }
01416 
01417 char * SUMA_Dset_Type_Name (SUMA_DSET_TYPE tp)
01418 {
01419    static char FuncName[]={"SUMA_Dset_Type_Name"};
01420    
01421    SUMA_ENTRY;
01422    
01423    switch (tp) {
01424       case SUMA_NO_DSET_TYPE:
01425          SUMA_RETURN("Dset_Type_Undefined");
01426          break;
01427       case SUMA_ERROR_DSET_TYPE:
01428          SUMA_RETURN("Error_Dset_Type");
01429          break;
01430       case SUMA_NODE_BUCKET:
01431          SUMA_RETURN("Node_Bucket");
01432          break;
01433       case SUMA_AFNI_NODE_BUCKET:
01434          SUMA_RETURN("AFNI_3D_dataset");
01435          break;
01436       case SUMA_NODE_ROI:
01437          SUMA_RETURN("Node_ROI");
01438          break;
01439       case SUMA_NODE_RGB:
01440          SUMA_RETURN("Node_RGB");
01441          break;
01442       case SUMA_NODE_RGBA:
01443          SUMA_RETURN("Node_RGBA");
01444          break;
01445       case SUMA_NODE_RGBb:
01446          SUMA_RETURN("Node_RGBb");
01447          break;
01448       case SUMA_NODE_RGBAb:
01449          SUMA_RETURN("Node_RGBAb");
01450          break;
01451       case SUMA_NODE_XYZ:
01452          SUMA_RETURN("Node_XYZ");
01453          break;
01454       case SUMA_NEW_NODE_XYZ:
01455          SUMA_RETURN("NewNode_XYZ");
01456          break;
01457       case SUMA_VIEWER_SETTING:
01458          SUMA_RETURN("Viewer_Visual_Setting");
01459          break;
01460       case SUMA_NODE_CONVEXITY:
01461          SUMA_RETURN("Node_Convexity");
01462          break;
01463       case SUMA_NEW_MESH_IJK:
01464          SUMA_RETURN("NewMesh_IJK");
01465          break;
01466       case SUMA_MESH_IJK:
01467          SUMA_RETURN("Mesh_IJK");
01468          break;
01469       case SUMA_PREP_NEW_SURFACE:
01470          SUMA_RETURN("PrepNewSurface");
01471          break;
01472       case SUMA_SURFACE_VOLUME_PARENT:
01473          SUMA_RETURN("SurfaceVolumeParent");
01474          break;
01475       case SUMA_SURFACE_OBJECT:
01476          SUMA_RETURN("SurfaceObject");
01477          break;
01478       default:
01479          SUMA_RETURN("Cowabonga-gothdo");
01480          break;
01481    }
01482 }
01483 
01484 SUMA_DSET_TYPE SUMA_Dset_Type (char *Name)
01485 {
01486    static char FuncName[]={"SUMA_Dset_Type"};
01487    
01488    SUMA_ENTRY;
01489    if (!Name) { SUMA_S_Err("Null Name"); SUMA_RETURN(SUMA_NO_DSET_TYPE); }
01490    if (!strcmp(Name,"Dset_Type_Undefined")) SUMA_RETURN (SUMA_NO_DSET_TYPE);
01491    if (!strcmp(Name,"Error_Dset_Type")) SUMA_RETURN (SUMA_ERROR_DSET_TYPE);
01492    if (!strcmp(Name,"Node_Bucket")) SUMA_RETURN (SUMA_NODE_BUCKET);
01493    if (!strcmp(Name,"Node_ROI")) SUMA_RETURN (SUMA_NODE_ROI);
01494    if (!strcmp(Name,"Node_RGB")) SUMA_RETURN (SUMA_NODE_RGB);
01495    if (!strcmp(Name,"Node_RGBA")) SUMA_RETURN (SUMA_NODE_RGBA);
01496    if (!strcmp(Name,"Node_RGBb")) SUMA_RETURN (SUMA_NODE_RGBb);
01497    if (!strcmp(Name,"Node_RGBAb")) SUMA_RETURN (SUMA_NODE_RGBAb);
01498    if (!strcmp(Name,"Node_XYZ")) SUMA_RETURN (SUMA_NODE_XYZ);
01499    if (!strcmp(Name,"NewNode_XYZ")) SUMA_RETURN (SUMA_NEW_NODE_XYZ);
01500    if (!strcmp(Name,"Viewer_Visual_Setting")) SUMA_RETURN (SUMA_VIEWER_SETTING);
01501    if (!strcmp(Name,"Cowabonga")) SUMA_RETURN (SUMA_ERROR_DSET_TYPE);
01502    if (!strcmp(Name,"Node_Convexity")) SUMA_RETURN (SUMA_NODE_CONVEXITY);
01503    if (!strcmp(Name,"AFNI_3D_dataset")) SUMA_RETURN (SUMA_AFNI_NODE_BUCKET);
01504    if (!strcmp(Name,"NewMesh_IJK")) SUMA_RETURN (SUMA_NEW_MESH_IJK);
01505    if (!strcmp(Name,"Mesh_IJK")) SUMA_RETURN (SUMA_MESH_IJK);
01506    if (!strcmp(Name,"PrepNewSurface")) SUMA_RETURN (SUMA_PREP_NEW_SURFACE);
01507    if (!strcmp(Name,"SurfaceVolumeParent")) SUMA_RETURN (SUMA_SURFACE_VOLUME_PARENT);
01508    if (!strcmp(Name,"SurfaceObject")) SUMA_RETURN (SUMA_SURFACE_OBJECT);
01509    SUMA_RETURN (SUMA_ERROR_DSET_TYPE);
01510 }
01511 
01512 char * SUMA_Col_Type_Name (SUMA_COL_TYPE tp)
01513 {
01514    static char FuncName[]={"SUMA_Col_Type_Name"};
01515    
01516    SUMA_ENTRY;
01517    
01518    switch (tp) {
01519       case SUMA_NO_COL_TYPE:
01520          SUMA_RETURN("Col_Type_Undefined");
01521          break;
01522       case SUMA_ERROR_COL_TYPE:
01523          SUMA_RETURN ("Error_Col_Type");
01524          break;
01525       case SUMA_NODE_INT:
01526          SUMA_RETURN("Generic_Int");
01527          break;
01528       case SUMA_NODE_INDEX:
01529          SUMA_RETURN("Node_Index");
01530          break;
01531       case SUMA_NODE_ILABEL:
01532          SUMA_RETURN("Node_Index_Label");
01533          break;
01534       case SUMA_NODE_FLOAT:
01535          SUMA_RETURN("Generic_Float");
01536          break;
01537       case SUMA_NODE_SHORT:
01538          SUMA_RETURN("Generic_Short");
01539          break;
01540       case SUMA_NODE_3C:
01541          SUMA_RETURN("XYZ_triplets");
01542          break;
01543       case SUMA_NODE_X:
01544          SUMA_RETURN("X_coord");
01545          break;
01546       case SUMA_NODE_Y:
01547          SUMA_RETURN("Y_coord");
01548          break;
01549       case SUMA_NODE_Z:
01550          SUMA_RETURN("Z_coord");
01551          break;
01552       case SUMA_NODE_R:
01553          SUMA_RETURN("R_col");
01554          break;
01555       case SUMA_NODE_G:
01556          SUMA_RETURN("G_col");
01557          break;
01558       case SUMA_NODE_B:
01559          SUMA_RETURN("B_col");
01560          break;
01561       case SUMA_NODE_STRING:
01562          SUMA_RETURN("Generic_String");
01563          break;
01564       case SUMA_NODE_CX:
01565          SUMA_RETURN("Convexity");
01566          break;
01567       case SUMA_NODE_BYTE:
01568          SUMA_RETURN("Generic_Byte");
01569          break;
01570       case SUMA_NODE_DOUBLE:
01571          SUMA_RETURN("Generic_Double");
01572          break;
01573       case SUMA_NODE_XCORR:
01574          SUMA_RETURN("Cross_Corr_Coeff");
01575          break;
01576       default:
01577          SUMA_RETURN("Cowabonga-Jo");
01578          break;
01579    }
01580    
01581 }
01582 
01583 /*!
01584    For daily use, call       ctp = SUMA_TypeOfColNumb(nel, i); 
01585 
01586 */
01587 SUMA_COL_TYPE SUMA_Col_Type (char *Name)
01588 {
01589    static char FuncName[]={"SUMA_Col_Type"};
01590    
01591    SUMA_ENTRY;
01592    if (!Name)  { SUMA_SL_Err("NULL Name");  SUMA_RETURN (SUMA_ERROR_COL_TYPE); }
01593    if (!strcmp(Name,"Col_Type_Undefined")) SUMA_RETURN (SUMA_NO_COL_TYPE);
01594    if (!strcmp(Name,"Error_Col_Type")) SUMA_RETURN (SUMA_ERROR_COL_TYPE);
01595    if (!strcmp(Name,"Generic_Int")) SUMA_RETURN (SUMA_NODE_INT);
01596    if (!strcmp(Name,"Generic_Short")) SUMA_RETURN (SUMA_NODE_SHORT);
01597    if (!strcmp(Name,"Node_Index")) SUMA_RETURN (SUMA_NODE_INDEX);
01598    if (!strcmp(Name,"Node_Index_Label")) SUMA_RETURN (SUMA_NODE_ILABEL);
01599    if (!strcmp(Name,"Generic_Float")) SUMA_RETURN (SUMA_NODE_FLOAT);
01600    if (!strcmp(Name,"XYZ_triplets")) SUMA_RETURN (SUMA_NODE_3C);
01601    if (!strcmp(Name,"X_coord")) SUMA_RETURN (SUMA_NODE_X);
01602    if (!strcmp(Name,"Y_coord")) SUMA_RETURN (SUMA_NODE_Y);
01603    if (!strcmp(Name,"Z_coord")) SUMA_RETURN (SUMA_NODE_Z);
01604    if (!strcmp(Name,"R_col")) SUMA_RETURN (SUMA_NODE_R);
01605    if (!strcmp(Name,"G_col")) SUMA_RETURN (SUMA_NODE_G);
01606    if (!strcmp(Name,"B_col")) SUMA_RETURN (SUMA_NODE_B);
01607    if (!strcmp(Name,"Generic_String")) SUMA_RETURN (SUMA_NODE_STRING);
01608    if (!strcmp(Name,"Generic_Byte")) SUMA_RETURN (SUMA_NODE_BYTE);
01609    if (!strcmp(Name,"Generic_Double")) SUMA_RETURN (SUMA_NODE_DOUBLE);
01610    if (!strcmp(Name,"Convexity")) SUMA_RETURN (SUMA_NODE_CX);
01611    if (!strcmp(Name,"Cross_Corr_Coeff")) SUMA_RETURN (SUMA_NODE_XCORR);
01612    /* if (!strcmp(Name,"")) SUMA_RETURN (); */
01613    SUMA_RETURN (SUMA_ERROR_COL_TYPE);
01614 
01615 }
01616 
01617 
01618 int SUMA_ShowNel (NI_element *nel)
01619 {
01620    static char FuncName[]={"SUMA_ShowNel"};
01621    NI_stream nstdout;
01622    
01623    SUMA_ENTRY;
01624    
01625    nstdout = NI_stream_open( "fd:1","w");
01626    if( nstdout == NULL ){ 
01627       fprintf(stderr,"%s: Can't open fd:1\n", FuncName); 
01628       SUMA_RETURN(0); 
01629    }
01630    fprintf (stdout, "\n-----------nel stdout begin-----------\n");
01631    NI_write_element( nstdout , nel , NI_TEXT_MODE ) ;
01632    fprintf (stdout, "\n-----------nel stdout end  -----------\n");
01633    NI_stream_close(nstdout);
01634    
01635    SUMA_RETURN(1);
01636 }
01637 
01638 
01639 int *SUMA_GetDsetColIndex (SUMA_DSET *dset, SUMA_COL_TYPE tp, int *N_i)
01640 {
01641    static char FuncName[]={"SUMA_GetDsetColIndex"};
01642    int *iv=NULL, i=0;
01643    char stmp[500], *atr;
01644    int ctp;
01645    SUMA_Boolean LocalHead = NOPE;
01646    
01647    SUMA_ENTRY;
01648    
01649    if (!dset || !dset->dnel) { SUMA_SL_Err ("NULL input"); SUMA_RETURN(NULL); }
01650    *N_i = -1;
01651    iv = (int *)SUMA_calloc(dset->dnel->vec_num, sizeof(int));
01652    if (!iv) {
01653       SUMA_RETURN(NULL);
01654    }   
01655    
01656    *N_i = 0;
01657    for (i=0; i < dset->dnel->vec_num; ++i) {
01658       ctp = SUMA_TypeOfDsetColNumb(dset, i);
01659       if (ctp == tp) {
01660          iv[*N_i] = i;
01661          *N_i = *N_i + 1;
01662       }
01663    }
01664    
01665    if (!*N_i) { SUMA_free(iv); iv = NULL; }
01666    SUMA_RETURN(iv);
01667 }
01668 
01669 int *SUMA_GetColIndex (NI_element *nel, SUMA_COL_TYPE tp, int *N_i)
01670 {
01671    static char FuncName[]={"SUMA_GetColIndex"};
01672    int *iv=NULL, i=0;
01673    char stmp[500], *atr;
01674    int ctp;
01675    SUMA_Boolean LocalHead = NOPE;
01676    
01677    SUMA_ENTRY;
01678    
01679    SUMA_SL_Warn("Obsolete, use new version.");
01680 
01681    if (!nel) { SUMA_SL_Err ("NULL nel"); SUMA_RETURN(NULL); }
01682    *N_i = -1;
01683    iv = (int *)SUMA_calloc(nel->vec_num, sizeof(int));
01684    if (!iv) {
01685       SUMA_RETURN(NULL);
01686    }   
01687    
01688    *N_i = 0;
01689    for (i=0; i < nel->vec_num; ++i) {
01690       ctp = SUMA_TypeOfColNumb(nel, i);
01691       if (ctp == tp) {
01692          iv[*N_i] = i;
01693          *N_i = *N_i + 1;
01694       }
01695    }
01696    
01697    if (!*N_i) { SUMA_free(iv); iv = NULL; }
01698    SUMA_RETURN(iv);
01699 }
01700 
01701 /*!
01702    \brief returns a string with a history note
01703    \param CallingFunc (char *) name of function / program calling
01704    \param N_arg (int) number of arguments in arg
01705    \param arg (char **) vector of strings 
01706    \param sold (char *) old history note
01707    \return histoire (char *) 
01708 */
01709 
01710 char *SUMA_HistString (char *CallingFunc, int N_arg, char **arg, char *sold)
01711 {
01712    static char FuncName[]={"SUMA_HistString"}; 
01713    char *stmp=NULL;
01714    int N_tot, i;
01715    
01716    SUMA_ENTRY;
01717    
01718    if (!arg) SUMA_RETURN(NULL);
01719    if (!arg[0]) SUMA_RETURN(NULL);
01720    if (!N_arg) SUMA_RETURN(NULL);
01721    
01722    if (sold) stmp = SUMA_append_string (sold, "\n");
01723 
01724    if (CallingFunc) {
01725       stmp = SUMA_append_replace_string (stmp, CallingFunc, "",1);
01726       stmp = SUMA_append_replace_string (stmp, ":", " ", 1);
01727    }
01728    
01729    for (i=0; i < N_arg; ++i) 
01730       stmp = SUMA_append_replace_string (stmp, arg[i], " ", 1);
01731       
01732    SUMA_RETURN(stmp);
01733 }   
01734 
01735 /*! 
01736    \brief returns pointer to history string.
01737    DO NOT FREE THIS POINTER, it is a copy
01738    of the pointer in one of ngr's elements.
01739    NULL if no history or no history elements 
01740    were found
01741 */
01742 char * SUMA_GetNgrHist(NI_group *ngr)
01743 {
01744    static char FuncName[]={"SUMA_GetNgrHist"};
01745    char **sv, *shist = NULL;
01746    NI_element *nelb = NULL;
01747    SUMA_Boolean LocalHead = NOPE;
01748    
01749    SUMA_ENTRY; 
01750    
01751    nelb = SUMA_FindNgrAttributeElement(ngr, "History");
01752    if (nelb) {
01753       sv = (char **)nelb->vec[0];   
01754       shist = (char *)sv[0];   
01755    } else {
01756       shist = NULL;
01757    }
01758    SUMA_RETURN(shist);
01759 }
01760 
01761 /*!
01762    \brief adds a history element note to the ni-group
01763    
01764    \param dset (NI_group *)
01765    \param CallingFunc (char *) name of function / program calling
01766    \param N_arg (int) number of arguments in arg
01767    \param arg (char **) vector of strings 
01768    \return ans (int) 0 Failed
01769                      1 OK 
01770 */
01771 int SUMA_AddNgrHist(NI_group *ngr, char *CallingFunc, int N_arg, char **arg)
01772 {
01773    static char FuncName[]={"SUMA_AddNgrHist"}; 
01774    char *stmp=NULL, *sold=NULL, **sv=NULL;
01775    int N_tot, i;
01776    NI_element *nelb = NULL;
01777    SUMA_Boolean LocalHead = NOPE;
01778    
01779    SUMA_ENTRY;
01780    
01781    if (!arg) SUMA_RETURN(0);
01782    if (!arg[0]) SUMA_RETURN(0);
01783    if (!ngr) SUMA_RETURN(0);
01784    if (!N_arg) SUMA_RETURN(0);
01785    
01786    /* get former history element, if any and old string */
01787    nelb = SUMA_FindNgrAttributeElement(ngr, "History");
01788    if (nelb) {
01789       sv = (char **)nelb->vec[0];   
01790       sold = (char *)sv[0];   
01791    } else {
01792       sold = NULL;
01793    }
01794   
01795    /* form the new string */
01796    stmp = SUMA_HistString (CallingFunc, N_arg, arg, sold);
01797    
01798    
01799    if (stmp) {
01800       if (nelb) { /* element existed */
01801          /* now need to replace the old string with the new one */
01802          if (sold) { /* clean the old pos */
01803             NI_free(sold); sold = sv[0] = NULL;
01804          }
01805       } else { /* element never existed */
01806          nelb = NI_new_data_element("History", 1);
01807          NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
01808          NI_add_to_group(ngr, nelb);
01809       }
01810       /* now add the new string */
01811       SUMA_NEL_REPLACE_STRING(nelb, 0, 0, (void*)stmp);
01812       SUMA_free(stmp); stmp = NULL;
01813    } else {
01814       SUMA_SL_Err("Failed to create string!");
01815       SUMA_RETURN(0);
01816    }
01817    
01818    SUMA_RETURN(1);
01819 }
01820 
01821 /*!
01822    \brief adds a history note to the ni-element
01823    
01824    \param nel (NI_element *)
01825    \param CallingFunc (char *) name of function / program calling
01826    \param N_arg (int) number of arguments in arg
01827    \param arg (char **) vector of strings 
01828    \return ans (int) 0 Failed
01829                      1 OK 
01830 */
01831 int SUMA_AddNelHist(NI_element *nel, char *CallingFunc, int N_arg, char **arg)
01832 {
01833    static char FuncName[]={"SUMA_AddNelHist"}; 
01834    char *stmp=NULL, *sold=NULL;
01835    int N_tot, i;
01836    
01837    SUMA_ENTRY;
01838    
01839    SUMA_SL_Warn("Obsolete, use new version.");
01840 
01841    if (!arg) SUMA_RETURN(0);
01842    if (!arg[0]) SUMA_RETURN(0);
01843    if (!nel) SUMA_RETURN(0);
01844    if (!N_arg) SUMA_RETURN(0);
01845    
01846    sold = NI_get_attribute(nel, "History");
01847    stmp = SUMA_HistString (CallingFunc, N_arg, arg, sold);
01848    
01849   if (stmp) {
01850       NI_set_attribute ( nel, "History", stmp);
01851       SUMA_free(stmp);
01852    }
01853    
01854    SUMA_RETURN(1);
01855 }
01856 
01857 
01858       
01859 
01860 /*** 
01861    Functions to deal with SUMA's datasets
01862    They don't quite belong in SUMA_DataSets.c because
01863    they are specific to SUMA
01864 ***/
01865 
01866 /*!
01867    \brief look for a dataset with a particular idcode
01868 */
01869 SUMA_DSET * SUMA_FindDset (char *idcode, DList *DsetList)
01870 {
01871    static char FuncName[]={"SUMA_FindDset"};
01872    SUMA_DSET *dset = NULL, *dsetf = NULL;
01873    char *dsetid;
01874    DListElmt *el=NULL;
01875    SUMA_Boolean LocalHead = NOPE;
01876    
01877    SUMA_ENTRY;
01878    
01879     
01880    dsetf = NULL;
01881    if (!DsetList) { SUMA_SL_Err("NULL DsetList"); SUMA_RETURN(dsetf); }
01882    if (!DsetList->size) { SUMA_RETURN(dsetf); }
01883    if (!idcode) { SUMA_SL_Err("NULL idcode"); SUMA_RETURN(dsetf); }
01884    el = NULL;
01885    do { 
01886       if (!el) el = dlist_head(DsetList);
01887       else el = dlist_next(el);
01888       dset = (SUMA_DSET *)el->data;
01889       if (!dset) {
01890          SUMA_SLP_Err("Unexpected NULL dset element in list!\nPlease report this occurrence to ziad@nih.gov."); 
01891       } else {   
01892          #ifdef OLD_DSET      /* before dsets were NI_groups */
01893          if (dset->nel) {
01894             dsetid = NI_get_attribute(dset->nel, "idcode"); /* obsolete */
01895             if (!dsetid) dsetid = NI_get_attribute(dset->nel, "Object_ID");
01896             if (dsetid) {
01897                if (!strcmp(dsetid, idcode))  dsetf = dset; /* match */
01898             } 
01899          }
01900          #else 
01901          if (dset->ngr) {
01902             dsetid = NI_get_attribute(dset->ngr, "idcode"); /* obsolete */
01903             if (!dsetid) dsetid = NI_get_attribute(dset->ngr, "Object_ID");
01904             if (dsetid) {
01905                if (!strcmp(dsetid, idcode))  dsetf = dset; /* match */
01906             } 
01907          }
01908          #endif
01909       } 
01910    } while ( (el != dlist_tail(DsetList)) && !dsetf ); 
01911    SUMA_RETURN(dsetf);
01912 }
01913 
01914 /*!
01915    \brief Function to free a Dset 
01916    
01917    - YOU SHOULD NOT FREE individual dsets yourself
01918    That is done by the dlist_destroy function
01919 */
01920 void SUMA_FreeDset(void *vp)
01921 {
01922    static char FuncName[]={"SUMA_FreeDset"};
01923    int i;
01924    SUMA_DSET *dset;
01925    SUMA_Boolean LocalHead = NOPE;
01926    
01927    SUMA_ENTRY;
01928    
01929    dset = (SUMA_DSET *)vp;
01930    
01931    if (!dset) SUMA_RETURNe;
01932    if (dset->N_links) {
01933       SUMA_SL_Err("dset structure has links to it.\n"
01934                   "structure not freed.\n"
01935                   "That is a now a memory leak.\n");
01936       SUMA_ShowDset (dset, 0, NULL);            
01937       SUMA_RETURNe;
01938    }
01939    
01940    #ifdef OLD_DSET /* before ngr was used */
01941    if (dset->nel) NI_free_element(dset->nel); dset->nel = NULL; /* you can keep ni_free from freeing a nel->vec[i] 
01942                                                           vector by copying nel->vec[i] to a pointer then
01943                                                           setting nel->vec[i] = NULL */ 
01944    #else
01945    dset->dnel = NULL; /* this one was a pointer copy to an element inside ngr */
01946    if (dset->ngr) NI_free_element(dset->ngr); dset->ngr = NULL; /* you can keep ni_free from freeing a nel->vec[i] 
01947                                                           vector by copying nel->vec[i] to a pointer then
01948                                                           setting nel->vec[i] = NULL */ 
01949    #endif
01950    #if 0
01951    if (dset->filename) SUMA_free(dset->filename);
01952    if (dset->Label) SUMA_free(dset->Label);
01953    if (dset->idcode) SUMA_free(dset->idcode);
01954    if (dset->domain_idcode) SUMA_free(dset->domain_idcode);
01955    if (dset->NodeDef) SUMA_free(dset->NodeDef);
01956    if (dset->N_mx) SUMA_free(dset->N_mx);
01957    if (dset->data) {
01958       for (i=0; i<dset->N_sub; ++i) {
01959          if (dset->data[i]) SUMA_free(dset->data[i]);
01960       }
01961    }
01962    if (dset->tp) SUMA_free(dset->tp);
01963    #endif
01964    
01965    SUMA_free(dset); dset = NULL;
01966    
01967    SUMA_RETURNe;
01968 }
01969 
01970 /*!
01971    \brief Pointer linking and unliking functions.
01972    They are to be used for all pointer linking
01973    in SUMA. For now they are just used for the datasets
01974    but I plan to move all "inode" stuff in here.
01975    
01976    These functions are generalized versions of SUMA_LinkToDset
01977    and SUMA_UnlinkFromDset
01978 */
01979 void *SUMA_LinkToPointer(void *ptr)
01980 {
01981    static char FuncName[]={"SUMA_LinkToPointer"};
01982    SUMA_LinkedPtr *dset=NULL;
01983    SUMA_Boolean LocalHead = NOPE;
01984    
01985    SUMA_ENTRY;
01986    
01987    if (!ptr) {
01988       SUMA_SL_Err("NULL pointer");
01989       SUMA_RETURN(NULL);
01990    }
01991    dset = (SUMA_LinkedPtr *)ptr;
01992    if (LocalHead) fprintf(SUMA_STDERR,"%s:\n Link Requested to pointer %p. \n"
01993                                       "LinkedPtrType = %d, owner_id = %s\n"
01994                                       "N_links was %d\n", 
01995                                       FuncName, dset, dset->LinkedPtrType, dset->owner_id, dset->N_links);
01996    dset->N_links = dset->N_links + 1;
01997    
01998    SUMA_RETURN((void *)dset);
01999 }
02000 void *SUMA_UnlinkFromPointer(void *ptr)
02001 {
02002    static char FuncName[]={"SUMA_UnlinkFromPointer"};
02003    SUMA_LinkedPtr *dset=NULL;
02004    SUMA_Boolean LocalHead = NOPE;
02005    
02006    SUMA_ENTRY;
02007 
02008    if (!ptr) {
02009       SUMA_SL_Err("NULL pointer");
02010       SUMA_RETURN(NULL);
02011    }
02012    dset = (SUMA_LinkedPtr *)ptr;
02013    if (LocalHead) fprintf(SUMA_STDERR, "%s:\n Unlink Requested from pointer %p.\n"
02014                                        "LinkedPtrType = %d, owner_id = %s\n"
02015                                        "N_links was %d\n", 
02016                                        FuncName, dset, dset->LinkedPtrType, dset->owner_id, dset->N_links);
02017    if (dset->N_links > 0) dset->N_links = dset->N_links - 1;
02018    else if (dset->N_links == 0) { SUMA_SL_Err("N_links ==0\nThis should not happen here.\n");   SUMA_RETURN(NULL); }
02019    
02020    SUMA_RETURN(NULL);
02021 }
02022 #if 0
02023 SUMA_DSET *SUMA_LinkToDset(SUMA_DSET *dset)
02024 {
02025    static char FuncName[]={"SUMA_LinkToDset"};
02026    SUMA_Boolean LocalHead = NOPE;
02027    
02028    SUMA_ENTRY;
02029    
02030    if (LocalHead) fprintf(SUMA_STDERR,"%s:\n Link Requested to dset %p. N_links was %d\n", FuncName, dset, dset->N_links);
02031    dset->N_links = dset->N_links + 1;
02032    
02033    SUMA_RETURN(dset);
02034 }
02035 SUMA_DSET *SUMA_UnlinkFromDset(SUMA_DSET *dset)
02036 {
02037    static char FuncName[]={"SUMA_UnlinkFromDset"};
02038    SUMA_Boolean LocalHead = NOPE;
02039    
02040    SUMA_ENTRY;
02041    
02042    if (LocalHead) fprintf(SUMA_STDERR,"%s:\n Unink Requested from dset %p. N_links was %d\n", FuncName, dset, dset->N_links);
02043    if (dset->N_links > 0) dset->N_links = dset->N_links - 1;
02044    else if (dset->N_links == 0) { SUMA_SL_Err("N_links ==0\nThis should not happen here.\n");   SUMA_RETURN(NULL); }
02045    
02046    SUMA_RETURN(NULL);
02047 }
02048 #endif
02049 SUMA_DSET * SUMA_NewDsetPointer(void)
02050 {
02051    static char FuncName[]={"SUMA_NewDsetPointer"};
02052    SUMA_DSET *dset = NULL;
02053    SUMA_Boolean LocalHead = NOPE;
02054    SUMA_ENTRY;
02055 
02056    dset = (SUMA_DSET *)SUMA_malloc(sizeof(SUMA_DSET));
02057    if (!dset) {
02058       SUMA_SL_Err("Failed to allocate for dset");
02059       SUMA_RETURN(dset);
02060    }
02061    if (LocalHead) fprintf(SUMA_STDERR,"%s:\n dset %p allocated.\n", FuncName, dset);
02062    /* initialize */
02063    #ifdef OLD_DSET
02064    dset->nel = NULL;
02065    #else
02066    dset->dnel = NULL;
02067    dset->ngr = NULL;
02068    #endif
02069    dset->N_links = 0;
02070    dset->owner_id[0] = '\0';
02071    dset->LinkedPtrType = SUMA_LINKED_DSET_TYPE;
02072    SUMA_RETURN(dset);
02073 }
02074 /*!
02075    \brief Function to allocate and initialize a dataset and add 
02076    it to the list of data sets .
02077    
02078    dset = SUMA_CreateDsetPointer (
02079                               char *filename, char *idcode,
02080                               char *domain_idcode, int N_Alloc
02081                               ) ;    
02082    \param filename (char *): Name of dset, typically, filename with path
02083    \param idcode (char *): identifier to use for dset.
02084                                If idcode is NULL then a new one is
02085                                generated from filename.
02086    \param domain_idcode(char *): idcode of domain. (used for both MeshDomain 
02087                               and geometry domain)
02088    \return dset (SUMA_DSET *): Element of DsetList containing dataset that 
02089                               was created by the function.
02090 
02091    -  This function does the following:
02092       xxxxxxx
02093       
02094    \sa SUMA_AddNelCol
02095    \sa SUMA_InsertDsetPointer
02096 */
02097 SUMA_DSET * SUMA_CreateDsetPointer (  
02098                               char *filename, SUMA_DSET_TYPE tp,
02099                               char *idcode,
02100                               char *domain_idcode,
02101                               int N_Alloc 
02102                               ) 
02103 {
02104    static char FuncName[]={"SUMA_CreateDsetPointer"};
02105    int ilist = -1, i = -1;
02106    char *Label=NULL, *locid=NULL;
02107    SUMA_DSET *dset=NULL;
02108    DListElmt *Elm = NULL;
02109    SUMA_Boolean LocalHead = NOPE;
02110    
02111    SUMA_ENTRY;
02112    
02113    #if 0  /* not required anymore */
02114       if (!filename) { SUMA_SL_Err("Need Dset filename"); SUMA_RETURN(dset); }
02115    #endif
02116    #if 0
02117    if (N_Alloc != N_NodeDef) {
02118       SUMA_SL_Err("Not ready to deal with N_Alloc != N_NodeDef");
02119       SUMA_RETURN(dset);
02120    }
02121    #endif
02122    
02123    if (!idcode) { /* No id is given yet */
02124       if (filename) {
02125          if (LocalHead) fprintf(SUMA_STDERR,"%s: Using filename %s to create IDcode.\n", FuncName, filename); 
02126          SUMA_NEW_ID(locid, filename);   /* form one from the filename */
02127       } else {
02128          SUMA_NEW_ID(locid, NULL); 
02129       } 
02130    }else {
02131       locid = SUMA_copy_string(idcode);
02132    }
02133    
02134    dset = SUMA_NewDsetPointer();
02135    if (!SUMA_NewDsetGrp (dset, tp, domain_idcode, domain_idcode, N_Alloc, filename, locid)) {
02136       SUMA_SL_Crit("Failed to create dset.\n");
02137       SUMA_RETURN(0);
02138    }
02139 
02140    Label = SUMA_truncate_string(filename, 20); 
02141    NI_set_attribute(dset->ngr, "label", Label); SUMA_free(Label); Label = NULL;
02142    
02143    NI_set_attribute(dset->ngr, "sorted_node_def", "No");
02144    
02145    if (locid) SUMA_free(locid); locid = NULL;
02146    SUMA_RETURN(dset);
02147 }    
02148 
02149 /*!
02150    \brief inserts a dataset pointer into the DsetList
02151    \param dset (SUMA_DSET *)
02152    \param DsetList (DList *): List of dset objects.
02153 */   
02154 int SUMA_InsertDsetPointer (SUMA_DSET *dset, DList *DsetList)
02155 {
02156    static char FuncName[]={"SUMA_InsertDsetPointer"};
02157    char *s=NULL, stmp[200];
02158    SUMA_Boolean LocalHead = NOPE;
02159 
02160    SUMA_ENTRY;
02161    
02162    if (!DsetList)  { SUMA_SL_Err("Need Dset List"); SUMA_RETURN(0); }
02163    if (!dset) { SUMA_SL_Err("dset is NULL"); SUMA_RETURN(0); }
02164    if (!dset->dnel) { SUMA_SL_Err("dset->nel is NULL\nNothing to do"); SUMA_RETURN(0); }
02165 
02166    s= SDSET_ID(dset); if (!s) { SUMA_SL_Err("dset has no idcode.\n"); SUMA_RETURN(0); }
02167    if (SUMA_FindDset (s,  DsetList)) {
02168       sprintf(stmp, "Dset with similar idcode \n"
02169                      "(%s)found in list.\n", s);
02170       SUMA_SL_Err(stmp);
02171       SUMA_RETURN(0);
02172    }
02173    
02174    /* insert into list */
02175    if (dlist_ins_next(DsetList, dlist_tail(DsetList), (void *)dset) < 0) {
02176       SUMA_SL_Err("Failed to insert dset into list");
02177       SUMA_FreeDset(dset); dset = NULL;
02178       SUMA_RETURN(0);
02179    }
02180    
02181    SUMA_RETURN(1);
02182 }
02183 
02184 char *SUMA_ShowMeSome (void *dt, SUMA_VARTYPE tp, int N_dt, int mxshow)
02185 {
02186    static char FuncName[]={"SUMA_ShowMeSome"};
02187    int i, imx, firsthalf, secondhalf;
02188    double *dtd;
02189    int *dti;
02190    byte *dtb;
02191    char **dts;
02192    float *dtf;
02193    char *s=NULL;
02194    SUMA_STRING *SS=NULL;
02195    SUMA_Boolean LocalHead = NOPE;
02196    
02197    SUMA_ENTRY;
02198    
02199    if (mxshow > N_dt) mxshow = N_dt;
02200    
02201    if (mxshow < 0) SUMA_RETURN(s);
02202    
02203    firsthalf = mxshow / 2;
02204    secondhalf = mxshow - firsthalf;
02205    
02206    SS = SUMA_StringAppend(NULL, NULL);
02207    
02208    if (LocalHead) fprintf(SUMA_STDERR,"%s: tp=%d, SUMA_double=%d, SUMA_float=%d, SUMA_int=%d, SUMA_byte=%d, SUMA_short=%d\n", 
02209                            FuncName, tp, SUMA_double, SUMA_float, SUMA_int, SUMA_byte, SUMA_short);
02210    if (mxshow) {
02211       switch (tp) {
02212          case SUMA_double:
02213             dtd = (double*)dt;
02214             for (i=0; i < firsthalf; ++i) SS = SUMA_StringAppend_va(SS, "%f, ", dtd[i]);
02215             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
02216             if (secondhalf > 1) { for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i) SS = SUMA_StringAppend_va(SS, "%f, ", dtd[i]); }
02217             SS = SUMA_StringAppend_va(SS, "%f", dtd[N_dt-1]);
02218             break;
02219          case SUMA_float:
02220             dtf = (float*)dt;
02221             for (i=0; i < firsthalf; ++i) SS = SUMA_StringAppend_va(SS, "%f, ", dtf[i]);
02222             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
02223             if (secondhalf > 1) { for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i) SS = SUMA_StringAppend_va(SS, "%f, ", dtf[i]); }
02224             SS = SUMA_StringAppend_va(SS, "%f", dtf[N_dt-1]);
02225             break;
02226          case SUMA_int:
02227             dti = (int*)dt;
02228             for (i=0; i < firsthalf; ++i) SS = SUMA_StringAppend_va(SS, "%d, ", dti[i]);
02229             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
02230             if (secondhalf > 1) { for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i) SS = SUMA_StringAppend_va(SS, "%d, ", dti[i]); }
02231             SS = SUMA_StringAppend_va(SS, "%d", dti[N_dt-1]);
02232             break;
02233          case SUMA_byte:
02234             dtb = (byte*)dt;
02235             for (i=0; i < firsthalf; ++i) SS = SUMA_StringAppend_va(SS, "%d, ", dtb[i]);
02236             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
02237             if (secondhalf > 1) { for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i) SS = SUMA_StringAppend_va(SS, "%d, ", dtb[i]); }
02238             SS = SUMA_StringAppend_va(SS, "%d", dtb[N_dt-1]);
02239             break;
02240          case SUMA_string:
02241             dts = (char **)dt;
02242             for (i=0; i < firsthalf; ++i) SS = SUMA_StringAppend_va(SS, "%s, ", dts[i]);
02243             if (mxshow < N_dt) SS = SUMA_StringAppend_va(SS, "..., ");
02244             if (secondhalf > 1) { for (i=SUMA_MAX_PAIR(N_dt-secondhalf, firsthalf); i<N_dt-1; ++i) SS = SUMA_StringAppend_va(SS, "%s, ", dts[i]); }
02245             SS = SUMA_StringAppend_va(SS, "%s", dts[N_dt-1]);
02246             break;
02247          default:
02248             SS = SUMA_StringAppend_va(SS, "Type not supported.");
02249       }
02250    } else {
02251       SS = SUMA_StringAppend_va(SS, "Empty vector.");
02252    }  
02253 
02254    SUMA_SS2S(SS,s);
02255    
02256    SUMA_RETURN(s);
02257 }
02258 
02259 void SUMA_ShowDset (SUMA_DSET *dset, int detail, FILE *out)
02260 {
02261    static char FuncName[]={"SUMA_ShowDset"};
02262    char *si = NULL;
02263    
02264    SUMA_ENTRY;
02265    
02266    if (!out) out = SUMA_STDERR;
02267    
02268    si = SUMA_DsetInfo(dset, detail);
02269    
02270    fprintf(out,"%s\n", si);
02271    
02272    if (si) SUMA_free(si); si = NULL;
02273    
02274    SUMA_RETURNe;
02275    
02276 }
02277 /*!
02278    \brief Function to return info on SUMA_DSET
02279    
02280    - You must free the returned string on your own
02281    \sa SUMA_ShowDset
02282 */
02283 char *SUMA_DsetInfo (SUMA_DSET *dset, int detail)
02284 {
02285    static char FuncName[]={"SUMA_DsetInfo"};
02286    int i;
02287    SUMA_COL_TYPE ctp;
02288    char *s=NULL, stmp[200];
02289    SUMA_STRING *SS=NULL;
02290    
02291    SUMA_ENTRY;
02292    
02293    SS = SUMA_StringAppend(NULL, NULL);
02294    
02295    if (dset) {
02296       SS = SUMA_StringAppend_va(SS, "Dset %p\n", dset);
02297       SS = SUMA_StringAppend_va(SS, "Number of Links: %d\n", dset->N_links);
02298       if (dset->dnel) {
02299          SS = SUMA_StringAppend_va(SS, "Dset Name: %s (%d)\n", 
02300             dset->dnel->name, SUMA_Dset_Type(dset->dnel->name));
02301          if (SDSET_FILENAME(dset)) 
02302             SS = SUMA_StringAppend_va(SS, "filename: %s\n", SDSET_FILENAME(dset));
02303          else SS = SUMA_StringAppend_va(SS, "filename: NULL\n");
02304          if (SDSET_LABEL(dset)) 
02305             SS = SUMA_StringAppend_va(SS, "label: %s\n", SDSET_LABEL(dset));
02306          else SS = SUMA_StringAppend_va(SS, "label: NULL\n");
02307          if (SDSET_ID(dset)) 
02308             SS = SUMA_StringAppend_va(SS, "Object_ID (idcode): %s\n", SDSET_ID(dset));
02309          else SS = SUMA_StringAppend_va(SS, "Object_ID (idcode): NULL\n");
02310          if (SDSET_IDGDOM(dset)) 
02311             SS = SUMA_StringAppend_va(SS, "GeomParent_idcode: %s\n", SDSET_IDGDOM(dset));
02312          else SS = SUMA_StringAppend_va(SS, "GeomParent_idcode: NULL\n");
02313          if (SDSET_IDMDOM(dset)) 
02314             SS = SUMA_StringAppend_va(SS, "Parent_ID (MeshParent_idcode): %s\n", SDSET_IDMDOM(dset));
02315          else SS = SUMA_StringAppend_va(SS, "Parent_ID ( MeshParent_idcode): NULL\n");
02316          
02317          SS = SUMA_StringAppend_va(SS, "vec_num (N_subsets): %d\n", dset->dnel->vec_num);
02318          SS = SUMA_StringAppend_va(SS, "vec_filled (N_NodeDef): %d\n", dset->dnel->vec_filled);
02319          SS = SUMA_StringAppend_va(SS, "vec_len (N_Alloc): %d\n", dset->dnel->vec_len);
02320          if (SDSET_SORTED(dset)) 
02321             SS = SUMA_StringAppend_va(SS, "sorted_node_def: %s\n", SDSET_SORTED(dset));
02322          else SS = SUMA_StringAppend_va(SS, "sorted_node_def: NULL\n");
02323 
02324          /* where is the node index (NodeDef) column ? */
02325          SS = SUMA_StringAppend_va(SS, "Looking for Node Index (NodeDef) column:\n");
02326          {   
02327             int *iv, N_i;
02328             iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_INDEX, &N_i);
02329             if (!iv) {
02330                SS = SUMA_StringAppend_va(SS, "\tFailed to find a Node Index column.\n");
02331             } else {
02332                SS = SUMA_StringAppend_va(SS, "\t%d Node Index columns found.\n",
02333                                           N_i);
02334                SUMA_free(iv); iv = NULL;
02335             }
02336          }
02337          for (i=0; i < dset->dnel->vec_num; ++i) {
02338             SS = SUMA_StringAppend_va(SS, "vec[%d]:\n", i);
02339             sprintf (stmp,"TypeCol_%d", i);
02340             ctp = SUMA_TypeOfDsetColNumb(dset, i); 
02341             SS = SUMA_StringAppend_va(SS, "\tColumn %d's type: %s\n",
02342                                        i, SUMA_Col_Type_Name(ctp));
02343             #if 1
02344             sprintf(stmp,"attrCol_%d", i);
02345             s = SUMA_AttrOfDsetColNumb(dset, i);
02346             if (s && s[0] != '\0') {
02347                SS = SUMA_StringAppend_va(SS, "\tColumn %d's attribute: %s\n", 
02348                                        i, s ); 
02349             } else {
02350                SS = SUMA_StringAppend_va(SS, "\tColumn %d's attribute does not exist.\n", 
02351                                        i );
02352             }
02353             if (s) SUMA_free(s); s = NULL;
02354             if (dset->dnel->vec[i]) {
02355                s = SUMA_ShowMeSome((void*)(  dset->dnel->vec[i]), 
02356                                              SUMA_ColType2TypeCast (ctp) 
02357                                              , dset->dnel->vec_len, 5);
02358                SS = SUMA_StringAppend_va(SS, "         %s\n", s); SUMA_free(s); s = NULL;
02359             } else SS = SUMA_StringAppend_va(SS, "         NULL\n");
02360             #endif
02361          }
02362          if (detail) { /* write the entire element to SS */
02363             NI_stream ns = NI_stream_open("str:", "w");
02364             NI_write_element(ns, dset->ngr, NI_TEXT_MODE);
02365             SS = SUMA_StringAppend(SS, "\n Full NI group in text mode:\n"); 
02366             SS = SUMA_StringAppend(SS, NI_stream_getbuf(ns)); /* don't use StringAppend_va because it does not all 
02367                                                                 the concatenation of very long strings. */
02368             SS = SUMA_StringAppend(SS, "\n");
02369             NI_stream_close(ns);
02370          }
02371       } else {
02372          SS = SUMA_StringAppend(SS, "NULL dset->dnel.");
02373       }
02374    } else {
02375       SS = SUMA_StringAppend(SS, "NULL dset.");
02376    }
02377    
02378    SUMA_SS2S(SS, s);
02379    
02380    SUMA_RETURN(s);
02381 }
02382 
02383 /*!
02384    \brief Returns a pointer to the column containing NodeDef
02385    (if it exists, in dset). Do not free this pointer!
02386 */
02387 int * SUMA_GetNodeDef(SUMA_DSET *dset)
02388 {
02389    static char FuncName[]={"SUMA_GetNodeDef"};
02390    int *iv, N_i, *NodeDef = NULL;
02391    SUMA_Boolean LocalHead=NOPE;
02392    
02393    SUMA_ENTRY;
02394    
02395    iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_INDEX, &N_i);
02396    if (!iv) {
02397       SUMA_LH("No such column found.");
02398       SUMA_RETURN(NULL);
02399    } else {
02400       SUMA_LH("Column found.");
02401       NodeDef = (int*)(dset->dnel->vec[iv[0]]);
02402       if (N_i > 1) {
02403          SUMA_SL_Warn("Found more than one node index vector.\nReturning first one found.\n");
02404       }
02405       SUMA_free(iv); iv = NULL;
02406    }
02407    
02408    SUMA_RETURN(NodeDef); 
02409 }
02410 
02411 /*!
02412    \brief Look for datasets statifying the following:
02413       type SUMA_NODE_CONVEXITY 
02414       idcode_str for a geometry domain and a mesh domain
02415    \param ReturnDsetPointer if 1 then return pointer is to dset element (SUMA_DSET *)
02416                             if 0 then return pointer is to Cx (float *)
02417    \return A POINTER copy to Cx (float *)
02418 */    
02419 void * SUMA_GetCx(char *idcode_str, DList *DsetList, int ReturnDsetPointer) 
02420 {
02421    static char FuncName[]={"SUMA_GetCx"};
02422    float *Cx = NULL;
02423    char *tp_name, *idg, *idm;
02424    int *iv = NULL, N_i=-1, N_found = -1;
02425    DListElmt *el;
02426    SUMA_DSET *dset=NULL;
02427 
02428    SUMA_ENTRY;
02429 
02430    if (!dlist_size(DsetList)) SUMA_RETURN(Cx);
02431    if (!idcode_str)  SUMA_RETURN(Cx);
02432    tp_name = SUMA_Dset_Type_Name(SUMA_NODE_CONVEXITY);
02433 
02434    el = NULL;
02435    Cx = NULL;
02436    N_found = 0;
02437    do {
02438       if (!el) el = dlist_head(DsetList);
02439       else el = el->next;
02440       dset = (SUMA_DSET *)el->data;
02441       if (dset->dnel) {
02442          if (strcmp(SDSET_TYPE_NAME(dset), tp_name) == 0) {
02443             /* matched type, now look for matching domain */
02444             idg = SDSET_IDGDOM(dset); idm = SDSET_IDMDOM(dset);
02445             if (idg && idm) {
02446                if (!strcmp(SDSET_IDGDOM(dset), idcode_str)) {
02447                   if (!N_found) {
02448                      /* find the column of type SUMA_NODE_CX */
02449                      iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_CX, &N_i);
02450                      if (!iv) { SUMA_SL_Err("SUMA_NODE_CX not found."); SUMA_RETURN(NULL); }
02451                      if (N_i != 1) { SUMA_SL_Err("more than 1 SUMA_NODE_CX found."); SUMA_RETURN(NULL); }
02452                      Cx = (float *)dset->dnel->vec[iv[0]];
02453                      SUMA_free(iv); iv = NULL;
02454                   }
02455                   ++ N_found;
02456                }
02457             }
02458          } 
02459       }
02460 
02461    }  while (el != dlist_tail(DsetList));
02462 
02463    if (N_found > 1) {
02464       SUMA_SL_Warn ("More than one convexity dataset found.\nReturning first one encountered.");
02465    }
02466 
02467    if (ReturnDsetPointer) {SUMA_RETURN((void*)dset);}
02468    else {SUMA_RETURN((void *)Cx);}
02469 }
02470 
02471 /*!
02472    \brief Returns the index of the node for which 
02473    data exists in row row of  Dset.
02474    Set N_Node to SO->N_Node in the function call whenever
02475    appropriate, it helps the function go faster 
02476    in certain instances. You can't get SO inside this
02477    function from MeshParent_idcode of nel because this file 
02478    is not to know about surface objects.
02479    Set N_Node to -1 if you don't want to use it 
02480 */
02481 int SUMA_GetNodeIndex_FromNodeRow(SUMA_DSET *dset, int row, int N_Node)
02482 {
02483    static char FuncName[]={"SUMA_GetNodeIndex_FromNodeRow"};
02484    static int WarnCount;
02485    int Found = -1, i, *NodeDef=NULL;
02486    double dval=0.0;
02487    char *str=NULL;
02488    NI_element *nel = dset->dnel;
02489    SUMA_Boolean LocalHead = NOPE;
02490    
02491    SUMA_ENTRY;
02492    
02493    if (row < 0) SUMA_RETURN(-1);
02494    
02495    if (N_Node >= 0  && row >= N_Node) {
02496       SUMA_SL_Err("row index >= N_Node\n"
02497                   "Will somebody please think of the children!");
02498       SUMA_RETURN(-1);
02499    } 
02500    if (row >= nel->vec_len) {
02501       SUMA_SL_Err("row index >= nel->vec_len\n"
02502                   "Bad logic!");
02503       SUMA_RETURN(-1);
02504    } 
02505    
02506    #if 0 
02507    /*(DO NOT DELETE)*/
02508    /* This would fail if data are not ordered such that row(i) is the data for node i */
02509    /* try the fast one */
02510    SUMA_LH("Trying the fast one");
02511    if (nel->vec_len == nel->vec_filled && nel->vec_len == N_Node) {
02512       SUMA_RETURN(row);
02513    }
02514    #endif
02515    
02516    SUMA_LH("Trying the slow mo");
02517    /* does this dset have a column index ? */
02518    NodeDef = SUMA_GetNodeDef (dset);
02519    
02520    if (NodeDef) {
02521       SUMA_LH("Col. Index found");
02522       if (row >= nel->vec_filled) {
02523          SUMA_SL_Err("row >= nel->vec_filled.\n");
02524          SUMA_RETURN(-1);
02525       } else {
02526          SUMA_RETURN(NodeDef[row]);
02527       }
02528    } 
02529    
02530    /* last resort, assume that data are ordered properly (see commented out section above)*/
02531    if (nel->vec_len == nel->vec_filled && nel->vec_len == N_Node) {
02532       if (0 && !(WarnCount % 25 - 1)) {
02533          SUMA_SLP_Warn( "Assuming ith row of data\n"
02534                      "corresponds to node i.\n"
02535                      "You'll get trash if this is not true.\n"
02536                      "This warning is shown intermittently.");
02537       } ++ WarnCount; 
02538       SUMA_RETURN(row);
02539    }
02540       
02541    SUMA_SL_Err("No way to get column index.");
02542       
02543    /* bad news lews, this node is not in this Dset */ 
02544    SUMA_RETURN(-1);
02545 }
02546 
02547 
02548 /*!
02549    \brief j = SUMA_GetNodeRow_FromNodeIndex( dset, i);
02550    Returns the row index of a node in the columns
02551    of a data set. In other terms, node i's data are in 
02552    row j of the columns in nel 
02553    for N_Node, see comments in  SUMA_GetNodeIndex_FromNodeRow
02554    \sa SUMA_GetNodeIndex_FromNodeRow
02555 */
02556 int SUMA_GetNodeRow_FromNodeIndex(SUMA_DSET *dset, int node, int N_Node)
02557 {
02558    static char FuncName[]={"SUMA_GetNodeRow_FromNodeIndex"};
02559    static int WarnCount;
02560    int Found = -1, i, *NodeDef=NULL;
02561    double dval=0.0;
02562    char *str=NULL;
02563    NI_element *nel = NULL;
02564    SUMA_Boolean LocalHead = NOPE;
02565    
02566    SUMA_ENTRY;
02567       
02568    
02569    if (!dset || node < 0 || (N_Node >=0 && node >= N_Node)) {
02570       /* turn this warning off once you confirm that Shane's bug is gone */
02571       if (LocalHead) SUMA_S_Warn("Strange input, returning -1.");
02572       SUMA_RETURN(-1);
02573    }
02574    
02575    nel = dset->dnel;
02576    if (!nel) {
02577       SUMA_SL_Err("Nasty dset");
02578       SUMA_RETURN(-1);
02579    }
02580    #if 0
02581    /* DO NOT DELETE, SEE BELOW */
02582    /* try the fast one */
02583    /* This would fail if data are not ordered such that row(i) is the data for node i */
02584    SUMA_LH("Trying the fast one");
02585    if (nel->vec_len == nel->vec_filled && nel->vec_len == N_Node) {
02586       SUMA_RETURN(node);
02587    }
02588    #endif
02589    
02590    SUMA_LH("Trying the slow mo");
02591    /* does this dset have a column index ? */
02592    NodeDef = SUMA_GetNodeDef (dset);
02593    
02594    if (NodeDef) {
02595       SUMA_LH("Col. Index found");
02596       if (nel->vec_filled > node) { /* bug here (used to be < !) discovered thanks to Rosanna and Shane */
02597          if (node == NodeDef[node]) {
02598             SUMA_LH("Got lucky");
02599             SUMA_RETURN(node);
02600          }
02601       }
02602       /* explicit search */
02603       SUMA_LH("Explicit");
02604       if (nel->vec_filled > N_Node) {
02605          SUMA_SL_Err("Unexpected error nel->vec_filled > N_Node");
02606          SUMA_RETURN(-1);
02607       }
02608       for (i=0; i<nel->vec_filled; ++i) {
02609          if (NodeDef[i] == node) SUMA_RETURN(i);
02610       }
02611    } else {
02612       SUMA_LH("No Col. Index found");
02613    }
02614    
02615    /* last resort, assume that data are ordered properly (see commented out section above)*/
02616    if (nel->vec_len == nel->vec_filled && nel->vec_len == N_Node) {
02617       if (0 && !(WarnCount % 25 - 1)) {
02618          SUMA_SLP_Warn( "Assuming ith row of data\n"
02619                      "corresponds to node i.\n"
02620                      "You'll get trash if this is not true.\n"
02621                      "This warning is shown intermittently.");
02622       } ++ WarnCount;       
02623       SUMA_RETURN(node);
02624    }
02625       
02626    /* bad news lews, this node is not in this Dset */ 
02627    SUMA_RETURN(-1);
02628 }
02629 /*!
02630    \brief Returns the value from column ind, row ival
02631    The value is stored in a double variable 0.0  in case of error. 
02632    \sa SUMA_GetValInCol
02633 */
02634 double SUMA_GetValInCol2(NI_element *nel, int ind, int ival) 
02635 {
02636    static char FuncName[]={"SUMA_GetValInCol2"};
02637    SUMA_COL_TYPE ctp;
02638    SUMA_VARTYPE vtp;
02639    byte *bv = NULL;
02640    double *dv = NULL, dval = 0.0;
02641    float *fv=NULL;
02642    int *iv = NULL;
02643    char **cv = NULL;
02644    SUMA_Boolean LocalHead = NOPE;
02645 
02646    SUMA_ENTRY;
02647 
02648    SUMA_SL_Warn("Obsolete, check caller");
02649    if (!nel) { SUMA_SL_Err("NULL input"); SUMA_RETURN(0.0); }
02650 
02651    if (ind < 0 || ind > nel->vec_num - 1) {
02652       SUMA_SL_Err("Bad index");
02653       SUMA_RETURN(0.0);
02654    }
02655 
02656    if (ival >= nel->vec_len) {
02657       SUMA_SL_Err("ival too large");
02658       SUMA_RETURN(0.0);
02659    }
02660 
02661    ctp = SUMA_TypeOfColNumb(nel, ind); 
02662 
02663    vtp = SUMA_ColType2TypeCast (ctp) ;
02664    switch (vtp) {
02665       case SUMA_byte:
02666          bv = (byte *)nel->vec[ind];
02667          dval = (double)bv[ival];
02668          break;
02669       case SUMA_int:
02670          iv = (int *)nel->vec[ind];
02671          dval = (double)iv[ival];
02672          break;
02673       case SUMA_float:
02674          fv = (float *)nel->vec[ind];
02675          dval = (double)fv[ival];
02676          break;
02677       case SUMA_double:
02678          dv = (double *)nel->vec[ind];
02679          dval = (double)dv[ival];
02680          break;
02681       default:
02682          SUMA_SL_Err("This type is not supported.\n");
02683          SUMA_RETURN(0.0);
02684          break;
02685    }
02686 
02687    SUMA_RETURN(dval);
02688 }
02689 
02690 /*!
02691    \brief Returns the value from column ind, row ival
02692    The value is stored in a double variable and a string
02693    version is returned. NULL in case of error. You are to free
02694    the returned string.
02695    \sa SUMA_GetValInCol2
02696 */
02697 char * SUMA_GetValInCol(NI_element *nel, int ind, int ival, double *dval) 
02698 {
02699    static char FuncName[]={"SUMA_GetValInCol"};
02700    SUMA_COL_TYPE ctp;
02701    SUMA_VARTYPE vtp;
02702    byte *bv = NULL;
02703    double *dv = NULL;
02704    float *fv=NULL;
02705    int *iv = NULL;
02706    char  *str=NULL, **cv = NULL;
02707    SUMA_Boolean LocalHead = NOPE;
02708 
02709    SUMA_ENTRY;
02710 
02711    SUMA_SL_Warn("Obsolete, check caller");
02712    if (!nel || !dval) { SUMA_SL_Err("NULL input"); SUMA_RETURN(NULL); }
02713 
02714    if (ind < 0 || ind > nel->vec_num - 1) {
02715       SUMA_SL_Err("Bad index");
02716       SUMA_RETURN(NULL);
02717    }
02718 
02719    if (ival >= nel->vec_len) {
02720       SUMA_SL_Err("ival too large");
02721       SUMA_RETURN(NULL);
02722    }
02723 
02724    ctp = SUMA_TypeOfColNumb(nel, ind); 
02725 
02726    vtp = SUMA_ColType2TypeCast (ctp) ;
02727    switch (vtp) {
02728       case SUMA_byte:
02729          str = (char *)SUMA_malloc(50*sizeof(char));
02730          bv = (byte *)nel->vec[ind];
02731          sprintf(str,"%d",bv[ival]);
02732          *dval = (double)bv[ival];
02733          break;
02734       case SUMA_int:
02735          str = (char *)SUMA_malloc(50*sizeof(char));
02736          iv = (int *)nel->vec[ind];
02737          sprintf(str,"%d",iv[ival]);
02738          *dval = (double)iv[ival];
02739          break;
02740       case SUMA_float:
02741          str = (char *)SUMA_malloc(50*sizeof(char));
02742          fv = (float *)nel->vec[ind];
02743          sprintf(str,"%f",fv[ival]);
02744          *dval = (double)fv[ival];
02745          break;
02746       case SUMA_double:
02747          str = (char *)SUMA_malloc(50*sizeof(char));
02748          dv = (double *)nel->vec[ind];
02749          sprintf(str,"%f",dv[ival]);
02750          *dval = (double)dv[ival];
02751          break;
02752       case SUMA_string:
02753          cv = (char **)nel->vec[ind];
02754          *dval = 0.0;
02755          str = SUMA_copy_string((char*)cv[ival]);
02756          break;
02757       default:
02758          SUMA_SL_Err("This type is not supported yet.\n");
02759          SUMA_RETURN(NULL);
02760          break;
02761    }
02762 
02763    SUMA_LH(str);
02764    SUMA_RETURN(str);
02765 }
02766 
02767 /*!
02768    \brief Returns the value from column ind, row ival
02769    The value is stored in a double variable 0.0  in case of error. 
02770    \sa SUMA_GetDsetValInCol
02771 */
02772 double SUMA_GetDsetValInCol2(SUMA_DSET *dset, int ind, int ival) 
02773 {
02774    static char FuncName[]={"SUMA_GetDsetValInCol2"};
02775    SUMA_COL_TYPE ctp;
02776    SUMA_VARTYPE vtp;
02777    byte *bv = NULL;
02778    double *dv = NULL, dval = 0.0;
02779    float *fv=NULL;
02780    int *iv = NULL;
02781    char **cv = NULL;
02782    SUMA_Boolean LocalHead = NOPE;
02783 
02784    SUMA_ENTRY;
02785 
02786    if (!dset->dnel) { SUMA_SL_Err("NULL input"); SUMA_RETURN(0.0); }
02787 
02788    if (ind < 0 || ind > dset->dnel->vec_num - 1) {
02789       SUMA_SL_Err("Bad index");
02790       SUMA_RETURN(0.0);
02791    }
02792 
02793    if (ival >= dset->dnel->vec_len) {
02794       SUMA_SL_Err("ival too large");
02795       SUMA_RETURN(0.0);
02796    }
02797 
02798    ctp = SUMA_TypeOfDsetColNumb(dset, ind); 
02799 
02800    vtp = SUMA_ColType2TypeCast (ctp) ;
02801    switch (vtp) {
02802       case SUMA_byte:
02803          bv = (byte *)dset->dnel->vec[ind];
02804          dval = (double)bv[ival];
02805          break;
02806       case SUMA_int:
02807          iv = (int *)dset->dnel->vec[ind];
02808          dval = (double)iv[ival];
02809          break;
02810       case SUMA_float:
02811          fv = (float *)dset->dnel->vec[ind];
02812          dval = (double)fv[ival];
02813          break;
02814       case SUMA_double:
02815          dv = (double *)dset->dnel->vec[ind];
02816          dval = (double)dv[ival];
02817          break;
02818       default:
02819          SUMA_SL_Err("This type is not supported.\n");
02820          SUMA_RETURN(0.0);
02821          break;
02822    }
02823 
02824    SUMA_RETURN(dval);
02825 }
02826 
02827 /*!
02828    \brief Returns the value from column ind, row ival
02829    The value is stored in a double variable and a string
02830    version is returned. NULL in case of error. You are to free
02831    the returned string.
02832    \sa SUMA_GetDsetValInCol2
02833 */
02834 char * SUMA_GetDsetValInCol(SUMA_DSET *dset, int ind, int ival, double *dval) 
02835 {
02836    static char FuncName[]={"SUMA_GetDsetValInCol"};
02837    SUMA_COL_TYPE ctp;
02838    SUMA_VARTYPE vtp;
02839    byte *bv = NULL;
02840    double *dv = NULL;
02841    float *fv=NULL;
02842    int *iv = NULL;
02843    char  *str=NULL, **cv = NULL;
02844    SUMA_Boolean LocalHead = NOPE;
02845 
02846    SUMA_ENTRY;
02847 
02848    if (!dset->dnel || !dval) { SUMA_SL_Err("NULL input"); SUMA_RETURN(NULL); }
02849 
02850    if (ind < 0 || ind > dset->dnel->vec_num - 1) {
02851       SUMA_SL_Err("Bad index");
02852       SUMA_RETURN(NULL);
02853    }
02854 
02855    if (ival >= dset->dnel->vec_len) {
02856       SUMA_SL_Err("ival too large");
02857       SUMA_RETURN(NULL);
02858    }
02859 
02860    ctp = SUMA_TypeOfDsetColNumb(dset, ind); 
02861 
02862    vtp = SUMA_ColType2TypeCast (ctp) ;
02863    switch (vtp) {
02864       case SUMA_byte:
02865          str = (char *)SUMA_malloc(50*sizeof(char));
02866          bv = (byte *)dset->dnel->vec[ind];
02867          sprintf(str,"%d",bv[ival]);
02868          *dval = (double)bv[ival];
02869          break;
02870       case SUMA_int:
02871          str = (char *)SUMA_malloc(50*sizeof(char));
02872          iv = (int *)dset->dnel->vec[ind];
02873          sprintf(str,"%d",iv[ival]);
02874          *dval = (double)iv[ival];
02875          break;
02876       case SUMA_float:
02877          str = (char *)SUMA_malloc(50*sizeof(char));
02878          fv = (float *)dset->dnel->vec[ind];
02879          sprintf(str,"%f",fv[ival]);
02880          *dval = (double)fv[ival];
02881          break;
02882       case SUMA_double:
02883          str = (char *)SUMA_malloc(50*sizeof(char));
02884          dv = (double *)dset->dnel->vec[ind];
02885          sprintf(str,"%f",dv[ival]);
02886          *dval = (double)dv[ival];
02887          break;
02888       case SUMA_string:
02889          cv = (char **)dset->dnel->vec[ind];
02890          *dval = 0.0;
02891          str = SUMA_copy_string((char*)cv[ival]);
02892          break;
02893       default:
02894          SUMA_SL_Err("This type is not supported yet.\n");
02895          SUMA_RETURN(NULL);
02896          break;
02897    }
02898 
02899    SUMA_LH(str);
02900    SUMA_RETURN(str);
02901 }
02902 
02903 /*!
02904    \brief Copies the contents of a NI_element column into
02905    a new float vector
02906    V = SUMA_Col2Float (nel,  ind,  FilledOnly);
02907    
02908    \param nel (NI_element *)
02909    \param ind (int) index of column to be copied
02910    \param FilledOnly (int) 0 = allocate for and read all of the column 
02911                               (up to nel->vec_len)
02912                            1 = allocate for and read the filled portion 
02913                                of the column (up to nel->vec_filled)
02914    \return V (float *) vector (allocated by the function) containing
02915                      the column's contents.
02916  */
02917 float * SUMA_Col2Float (NI_element *nel, int ind, int FilledOnly)
02918 {
02919    static char FuncName[]={"SUMA_Col2Float"};
02920    int i = -1, N_read = -1, *iv = NULL;
02921    float *V=NULL, *fv = NULL;
02922    SUMA_COL_TYPE ctp;
02923    SUMA_VARTYPE vtp;
02924    
02925    SUMA_ENTRY;
02926    
02927    SUMA_SL_Err("Obsolete, check caller");
02928    SUMA_RETURN(NULL);
02929    
02930    if (!nel) { SUMA_RETURN(NULL); }
02931    
02932    if (ind < 0 || ind > nel->vec_num - 1) {
02933       SUMA_SL_Err("Bad index");
02934       SUMA_RETURN(NULL);
02935    }
02936    
02937    if (FilledOnly) {
02938       N_read = nel->vec_filled;
02939    } else {
02940       N_read = nel->vec_len;
02941    }
02942    
02943    ctp = SUMA_TypeOfColNumb(nel, ind); 
02944 
02945    V = (float *)SUMA_malloc(sizeof(float)*N_read);
02946    if (!V) { SUMA_SL_Crit("Failed to allocate for V."); SUMA_RETURN(NULL); }
02947    vtp = SUMA_ColType2TypeCast (ctp) ;
02948    switch (vtp) {
02949       case SUMA_int:
02950          iv = (int *)nel->vec[ind];
02951          for (i=0; i<N_read; ++i) V[i] = (float)iv[i];
02952          break;
02953       case SUMA_float:
02954          fv = (float *)nel->vec[ind];
02955          for (i=0; i<N_read; ++i) V[i] = fv[i];
02956          break;
02957       default:
02958          SUMA_SL_Err("This type is not supported.\n");
02959          SUMA_free(V);
02960          SUMA_RETURN(NULL);
02961          break;
02962    }
02963    
02964    SUMA_RETURN(V);
02965 }
02966 /*!
02967    \brief Copies the contents of a NI_element column into
02968    a new float vector
02969    V = SUMA_DsetCol2Float (nel,  ind,  FilledOnly);
02970    
02971    \param nel (NI_element *)
02972    \param ind (int) index of column to be copied
02973    \param FilledOnly (int) 0 = allocate for and read all of the column 
02974                               (up to nel->vec_len)
02975                            1 = allocate for and read the filled portion 
02976                                of the column (up to nel->vec_filled)
02977    \return V (float *) vector (allocated by the function) containing
02978                      the column's contents.
02979  */
02980 float * SUMA_DsetCol2Float (SUMA_DSET *dset, int ind, int FilledOnly)
02981 {
02982    static char FuncName[]={"SUMA_DsetCol2Float"};
02983    int i = -1, N_read = -1, *iv = NULL;
02984    float *V=NULL, *fv = NULL;
02985    SUMA_COL_TYPE ctp;
02986    SUMA_VARTYPE vtp;
02987    
02988    SUMA_ENTRY;
02989       
02990    if (!dset) { SUMA_RETURN(NULL); }
02991    
02992    if (ind < 0 || ind > dset->dnel->vec_num - 1) {
02993       SUMA_SL_Err("Bad index");
02994       SUMA_RETURN(NULL);
02995    }
02996    
02997    if (FilledOnly) {
02998       N_read = dset->dnel->vec_filled;
02999    } else {
03000       N_read = dset->dnel->vec_len;
03001    }
03002    
03003    ctp = SUMA_TypeOfDsetColNumb(dset, ind); 
03004 
03005    V = (float *)SUMA_malloc(sizeof(float)*N_read);
03006    if (!V) { SUMA_SL_Crit("Failed to allocate for V."); SUMA_RETURN(NULL); }
03007    vtp = SUMA_ColType2TypeCast (ctp) ;
03008    switch (vtp) {
03009       case SUMA_int:
03010          iv = (int *)dset->dnel->vec[ind];
03011          for (i=0; i<N_read; ++i) V[i] = (float)iv[i];
03012          break;
03013       case SUMA_float:
03014          fv = (float *)dset->dnel->vec[ind];
03015          for (i=0; i<N_read; ++i) V[i] = fv[i];
03016          break;
03017       default:
03018          SUMA_SL_Err("This type is not supported.\n");
03019          SUMA_free(V);
03020          SUMA_RETURN(NULL);
03021          break;
03022    }
03023    
03024    SUMA_RETURN(V);
03025 }
03026 
03027 /*!
03028    a function to return the string attribute of a column
03029    Free with SUMA_free
03030 */
03031 char * SUMA_AttrOfDsetColNumb(SUMA_DSET *dset, int ind)
03032 {
03033    static char FuncName[]={"SUMA_AttrOfDsetColNumb"};
03034    char *cnm = NULL;
03035    NI_element *nelb=NULL;
03036    SUMA_Boolean LocalHead = NOPE;
03037    
03038    if (!dset) {  
03039       SUMA_SL_Err("NULL NI element");
03040       SUMA_RETURN(cnm);
03041    }
03042    if (ind < 0 || ind > (dset->dnel->vec_num - 1)) {
03043       SUMA_SL_Err("Bad index");
03044       SUMA_RETURN(cnm);
03045    }
03046    
03047    /* try SUMA's */
03048    nelb = SUMA_FindDsetAttributeElement(dset, "ColumnsAttributes");
03049    if (nelb) {
03050       SUMA_NEL_GET_STRING(nelb, 0, 0, cnm); /* cnm is a pointer copy here, do not free */
03051       cnm = SUMA_Get_Sub_String(cnm, SUMA_NI_SS, ind);
03052       SUMA_RETURN(cnm);
03053    }
03054 
03055    
03056    
03057    SUMA_SL_Err("Failed to find attribute");
03058    SUMA_RETURN(NULL);
03059 }
03060 
03061 /*!
03062    a wrapper to faciliate getting column types from 
03063    both SUMA and AFNI formatted niml elements
03064    \sa SUMA_Col_Type
03065    NOTE, this function will repeatedly parse the entire string
03066    for column types. That's both stupid and inefficient.
03067    Write an efficient version called  SUMA_TypesOfDsetColNumb next ...
03068 */
03069 SUMA_COL_TYPE SUMA_TypeOfDsetColNumb(SUMA_DSET *dset, int ind) 
03070 {
03071    static char FuncName[]={"SUMA_TypeOfDsetColNumb"};
03072    int *ctpv = NULL;
03073    char *cnm = NULL, **sc = NULL;
03074    int_array *iar = NULL;
03075    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
03076    char stmp[100];
03077    NI_element *nelb=NULL;
03078    SUMA_Boolean LocalHead = NOPE;
03079    
03080    SUMA_ENTRY;
03081    
03082    if (!dset) {  
03083       SUMA_SL_Err("NULL NI element");
03084       SUMA_RETURN(ctp);
03085    }
03086    if (ind < 0 || ind > (dset->dnel->vec_num - 1)) {
03087       SUMA_SL_Err("Bad index");
03088       SUMA_RETURN(ctp);
03089    }
03090    
03091    /* try SUMA's */
03092    nelb = SUMA_FindDsetAttributeElement(dset, "ColumnsTypes");
03093    if (nelb) {
03094       SUMA_LH("Fetching Type a la suma");
03095       SUMA_NEL_GET_STRING(nelb, 0, 0, cnm); /* cnm is a pointer copy here, do not free */
03096       cnm = SUMA_Get_Sub_String(cnm, SUMA_NI_SS, ind);
03097    }
03098    if (cnm) {
03099       ctp = SUMA_Col_Type(cnm); SUMA_free(cnm); cnm = NULL;
03100       SUMA_RETURN(ctp);
03101    }
03102    
03103    /* try AFNI's */
03104    SUMA_LH("Fetching Type a la afni");
03105    cnm = NI_get_attribute(dset->dnel, "ni_type");
03106    if (cnm) {
03107       SUMA_LH(cnm);
03108       iar = decode_type_string( cnm ); 
03109       if (iar) {
03110          ctp = iar->ar[ind];   /* this is not the same as SUMA's column type, it is just data type */
03111          NI_free(iar->ar); NI_free(iar); iar = NULL;
03112          switch(ctp) {
03113             case SUMA_int:
03114                ctp = SUMA_NODE_INT;
03115                break;
03116             case SUMA_float:
03117                ctp = SUMA_NODE_FLOAT;
03118                break;
03119             case SUMA_byte:
03120                ctp = SUMA_NODE_BYTE;
03121                break;
03122             case SUMA_short:
03123                ctp = SUMA_NODE_SHORT;
03124                break;
03125             default:
03126                SUMA_SL_Err("AFNI column type not supported at the moment.\n");
03127                ctp = SUMA_ERROR_COL_TYPE;
03128                break;
03129          }
03130          SUMA_RETURN(ctp);
03131       }
03132    }
03133    
03134    SUMA_SL_Err("Failed to determine type");
03135    SUMA_RETURN(ctp);
03136 }
03137 
03138 
03139 
03140 /*!
03141    a wrapper to faciliate getting column types from 
03142    both SUMA and AFNI formatted niml elements
03143    \sa SUMA_Col_Type
03144 */
03145 SUMA_COL_TYPE SUMA_TypeOfColNumb(NI_element *nel, int ind) 
03146 {
03147    static char FuncName[]={"SUMA_TypeOfColNumb"};
03148    int *ctpv = NULL;
03149    char *cnm = NULL;
03150    int_array *iar = NULL;
03151    SUMA_COL_TYPE ctp = SUMA_ERROR_COL_TYPE;
03152    char stmp[100];
03153    SUMA_Boolean LocalHead = NOPE;
03154    
03155    /* SUMA_SL_Warn("Obsolete, use new version."); still needed to convert old format to new one */
03156    
03157    if (!nel) {  
03158       SUMA_SL_Err("NULL NI element");
03159       SUMA_RETURN(ctp);
03160    }
03161    if (ind < 0 || ind > (nel->vec_num - 1)) {
03162       SUMA_SL_Err("Bad index");
03163       SUMA_RETURN(ctp);
03164    }
03165    
03166    /* try SUMA's */
03167    snprintf (stmp,50*sizeof(char),"TypeCol_%d", ind);
03168    cnm = NI_get_attribute(nel, stmp);
03169    if (cnm) {
03170       SUMA_RETURN(SUMA_Col_Type(cnm));
03171    }
03172    
03173    /* try AFNI's */
03174    cnm = NI_get_attribute(nel, "ni_type");
03175    if (cnm) {
03176       SUMA_LH(cnm);
03177       iar = decode_type_string( cnm ); 
03178       if (iar) {
03179          ctp = iar->ar[ind];   /* this is not the same as SUMA's column type, it is just data type */
03180          NI_free(iar->ar); NI_free(iar); iar = NULL;
03181          switch(ctp) {
03182             case SUMA_int:
03183                ctp = SUMA_NODE_INT;
03184                break;
03185             case SUMA_float:
03186                ctp = SUMA_NODE_FLOAT;
03187                break;
03188             case SUMA_byte:
03189                ctp = SUMA_NODE_BYTE;
03190                break;
03191             case SUMA_short:
03192                ctp = SUMA_NODE_SHORT;
03193                break;
03194             default:
03195                SUMA_SL_Err("AFNI column type not supported at the moment.\n");
03196                ctp = SUMA_ERROR_COL_TYPE;
03197                break;
03198          }
03199          SUMA_RETURN(ctp);
03200       }
03201    }
03202    
03203    SUMA_SL_Err("Failed to determine type");
03204    SUMA_RETURN(ctp);
03205 }
03206 
03207 /*!
03208    \brief Load a surface-based dataset from disk
03209    
03210    \param Name (char *) THe name of the file
03211    \param form (SUMA_DSET_FORMAT *) The format of the file
03212                                   can choose SUMA_NO_DSET_FORMAT
03213                                   and have the function attempt 
03214                                   to guess. In that case the function
03215                                   will set the value of form
03216    \return (SUMA_DSET *) dset 
03217    The datset does not get associated with a surface (owner_id[0] = '\0')
03218    You'll have to do this manually later on if you wish
03219    You typically want to insert that dataset into SUMA's DsetList list...
03220 */
03221 SUMA_DSET *SUMA_LoadDset (char *Name, SUMA_DSET_FORMAT *form, int verb)
03222 {  
03223    static char FuncName[]={"SUMA_LoadDset"};
03224    SUMA_DSET *dset = NULL;
03225    SUMA_Boolean LocalHead = NOPE;
03226    
03227    SUMA_ENTRY;
03228    
03229    if (!Name) { SUMA_SL_Err("NULL Name"); SUMA_RETURN(dset); }
03230    
03231    switch (*form) {
03232       case SUMA_NIML:
03233       case SUMA_ASCII_NIML:
03234       case SUMA_BINARY_NIML:
03235          SUMA_LH("Loading NIML Dset");
03236          dset = SUMA_LoadNimlDset(Name, verb);
03237          break;
03238       case SUMA_1D:
03239          SUMA_LH("Loading 1D Dset");
03240          dset = SUMA_Load1DDset(Name, verb);
03241          break;
03242       case SUMA_ASCII_OPEN_DX_DSET:
03243          SUMA_LH("Loading DX Dset");
03244          dset = SUMA_LoadDXDset(Name, verb);
03245          break;
03246       case SUMA_NO_DSET_FORMAT:
03247          if (!dset) { SUMA_LH("Trying NIML Dset"); dset = SUMA_LoadNimlDset(Name, 0); *form = SUMA_NIML; }
03248          if (!dset) { SUMA_LH("Trying 1D Dset"); dset = SUMA_Load1DDset(Name, 0); *form = SUMA_1D; }
03249          if (!dset) { SUMA_LH("Trying DX Dset"); dset = SUMA_Load1DDset(Name, 0); *form = SUMA_ASCII_OPEN_DX_DSET; }
03250          break;
03251       default:
03252          if (verb) SUMA_SLP_Err("Bad format specification");
03253          SUMA_RETURN(dset);   
03254    }
03255    
03256    if (!dset) {
03257       if (verb) SUMA_SL_Err("Failed to read dset");
03258       SUMA_RETURN(dset);   
03259    }
03260    if (LocalHead) {
03261       SUMA_ShowDset(dset, 0, NULL);
03262    } 
03263    SUMA_RETURN(dset);
03264 }
03265 
03266 
03267 /*!
03268    \brief writes a dataset to disk
03269    \param Name (char *) Name of output file. 
03270    \param dset (SUMA_DSET *) Le dataset
03271    \param form (SUMA_DSET_FORMAT ) Le format
03272    \return OutName (char *)The name used for the output file 
03273                            (you have to free that one yourself)
03274                            NULL if things went bad.
03275    - Be careful, this function will not change the idcode of the
03276    dataset being written. You'll have to do that manually.
03277 */
03278 char * SUMA_WriteDset (char *Name, SUMA_DSET *dset, SUMA_DSET_FORMAT form, int overwrite, int verb) 
03279 {
03280    static char FuncName[]={"SUMA_WriteDset"};
03281    char *PrefOut = NULL, *NameOut = NULL, *strmname=NULL, stmp[500];
03282    int flg = 0, exists = 0;
03283    SUMA_Boolean LocalHead = NOPE;
03284    
03285    SUMA_ENTRY;
03286    
03287    if (!dset) { SUMA_SL_Err("NULL dset"); SUMA_RETURN(NameOut); }
03288    if (!dset->ngr) { SUMA_SL_Err("NULL dset->ngr"); SUMA_RETURN(NameOut); }
03289    if (!Name) { SUMA_SL_Err("NULL Name"); SUMA_RETURN(NameOut); }
03290    PrefOut = SUMA_RemoveDsetExtension(Name, form);
03291    if (!PrefOut) { SUMA_SL_Err("Failed to write dset"); SUMA_RETURN(NameOut); }
03292    exists = 0;
03293    switch (form) {
03294       case SUMA_NIML:
03295       case SUMA_ASCII_NIML:
03296       case SUMA_BINARY_NIML:
03297          NameOut = SUMA_Extension(PrefOut, ".niml.dset", NOPE);
03298          if (!overwrite &&  SUMA_filexists(NameOut)) {
03299             exists = 1;
03300          } else {
03301             strmname = SUMA_append_string("file:",NameOut);
03302             NI_set_attribute(dset->ngr,"filename", NameOut);
03303             if (form == SUMA_ASCII_NIML) { 
03304               SUMA_LH("Writing NIML, ASCII..."); SUMA_LH(strmname);  NEL_WRITE_TX (dset->ngr, strmname, flg);  SUMA_LH("DONE.");
03305             } else { 
03306               SUMA_LH("Writing NIML, BINARY..."); SUMA_LH(strmname); NEL_WRITE_BI (dset->ngr, strmname, flg); SUMA_LH("DONE.");
03307             }
03308          }
03309          break;
03310       case SUMA_1D:
03311          NameOut = SUMA_Extension(PrefOut, ".1D.dset", NOPE);
03312          if (!overwrite &&  SUMA_filexists(NameOut)) {
03313             exists = 1;
03314          } else {
03315             NI_set_attribute(dset->ngr,"filename", NameOut);
03316             strmname = SUMA_append_string("file:",NameOut);
03317                  SUMA_LH("Writing 1D..."); SUMA_LH(strmname); 
03318             DSET_WRITE_1D (dset, strmname, flg);
03319             if (!flg) {
03320                SUMA_SL_Err("Output file not written");
03321             } else {
03322                SUMA_LH("DONE.");
03323             }
03324          } 
03325          break;
03326       case SUMA_1D_PURE:
03327          NameOut = SUMA_Extension(PrefOut, ".1D.dset", NOPE);
03328          if (!overwrite &&  SUMA_filexists(NameOut)) {
03329             exists = 1;
03330          } else {
03331             NI_set_attribute(dset->ngr,"filename", NameOut);
03332             strmname = SUMA_copy_string(NameOut);
03333                  SUMA_LH("Writing 1D pure..."); SUMA_LH(strmname); 
03334             DSET_WRITE_1D_PURE (dset, strmname, flg);
03335             if (!flg) {
03336                SUMA_SL_Err("Output file not written");
03337             } else {
03338                SUMA_LH("DONE.");
03339             }
03340          } 
03341          break;
03342       case SUMA_NO_DSET_FORMAT:
03343          SUMA_SLP_Err("Must specify output format");
03344          break;
03345       default:
03346          SUMA_SLP_Err("Bad format specification");
03347          break;
03348    }
03349    
03350    if (exists) {
03351       snprintf(stmp, 500*sizeof(char), "Output file %s exists.\n Will not overwrite.", NameOut);
03352       SUMA_SLP_Err(stmp);
03353       if (NameOut) SUMA_free(NameOut); NameOut = NULL;
03354    } else if (!NameOut || !flg) {
03355       if (verb) SUMA_SLP_Err("Failed writing dataset.");
03356       if (NameOut) SUMA_free(NameOut); NameOut = NULL;
03357    }
03358    
03359    if (PrefOut) SUMA_free(PrefOut); PrefOut = NULL;
03360    if (strmname) SUMA_free(strmname); strmname = NULL;
03361    SUMA_RETURN(NameOut);
03362 }
03363 
03364 /*!
03365    \brief Guess file format from extension
03366    \param Name (char *) name 
03367    \return form SUMA_DSET_FORMAT
03368 */
03369 SUMA_DSET_FORMAT SUMA_GuessFormatFromExtension(char *Name)
03370 {
03371    static char FuncName[]={"SUMA_GuessFormatFromExtension"};
03372    SUMA_DSET_FORMAT form = SUMA_NO_DSET_FORMAT;
03373      
03374    SUMA_ENTRY;
03375    
03376    if (!Name) { SUMA_SL_Err("NULL Name"); SUMA_RETURN(form); }
03377    if (SUMA_isExtension(Name, ".niml.dset")) form = SUMA_NIML;
03378    if (SUMA_isExtension(Name, ".1D.dset")) form = SUMA_1D;
03379    if (SUMA_isExtension(Name, ".niml.cmap")) form = SUMA_NIML;
03380    if (SUMA_isExtension(Name, ".1D.cmap")) form = SUMA_1D; 
03381    if (SUMA_isExtension(Name, ".dx")) form = SUMA_ASCII_OPEN_DX_DSET; 
03382    if (SUMA_isExtension(Name, ".dx.dset")) form = SUMA_ASCII_OPEN_DX_DSET; 
03383    SUMA_RETURN(form);
03384 }
03385 /*!
03386    \brief Removes the standard extension from a dataset filename
03387    \param Name (char *) name 
03388    \param form SUMA_DSET_FORMAT
03389    \return (char *) no_extension (you have to free that one with SUMA_free)
03390 */
03391 
03392 char *SUMA_RemoveDsetExtension (char*Name, SUMA_DSET_FORMAT form)
03393 {
03394    static char FuncName[]={"SUMA_RemoveDsetExtension"};
03395    char *noex = NULL, *tmp = NULL;
03396    
03397    SUMA_ENTRY;
03398    
03399    if (!Name) { SUMA_SL_Err("NULL Name"); SUMA_RETURN(NULL); }
03400   
03401    switch (form) {
03402       case SUMA_NIML:
03403       case SUMA_ASCII_NIML:
03404       case SUMA_BINARY_NIML:
03405          noex  =  SUMA_Extension(Name, ".niml.dset", YUP);
03406          break;
03407       case SUMA_1D:
03408       case SUMA_1D_PURE:
03409          tmp  =  SUMA_Extension(Name, ".1D", YUP);
03410          noex  =  SUMA_Extension(tmp, ".1D.dset", YUP); SUMA_free(tmp); tmp = NULL;
03411          break;
03412       case SUMA_ASCII_OPEN_DX_DSET:
03413          tmp  =  SUMA_Extension(Name, ".dx", YUP);
03414          noex  =  SUMA_Extension(tmp, ".dx.dset", YUP); SUMA_free(tmp); tmp = NULL;
03415          break;
03416       case SUMA_NO_DSET_FORMAT:
03417          tmp  =  SUMA_Extension(Name, ".1D", YUP);
03418          noex = SUMA_Extension(tmp, ".1D.dset", YUP); SUMA_free(tmp); tmp = NULL; tmp = noex;
03419          noex = SUMA_Extension(tmp, ".niml.dset", YUP); SUMA_free(tmp); tmp = NULL;
03420          break;
03421       default:
03422          SUMA_SLP_Err("Bad format specification");
03423          break;
03424    }
03425    
03426    SUMA_RETURN(noex);
03427 }
03428 
03429 /*!
03430    \brief a function to turn the old dataset NI_element to the new
03431    dataset NI_group structure. Only essentials are preserved. Some
03432    of the attributes will remain empty in the data element, no simple
03433    way at the moment to remove attributes from a nel
03434 */
03435 NI_group *SUMA_oDsetNel2nDsetNgr(NI_element *nel) 
03436 {
03437    static char FuncName[]={"SUMA_oDsetNel2nDsetNgr"};
03438    NI_group *ngr = NULL;
03439    NI_element *nelb = NULL;
03440    char *idcode=NULL, *dname=NULL, *col_label = NULL, *stmp=NULL;
03441    int ctp, i;
03442    NI_element *dnel = NULL;
03443    SUMA_DSET dset; /* dummy */
03444    SUMA_ENTRY;
03445 
03446    ngr = NI_new_group_element();
03447    NI_rename_group(ngr, nel->name);
03448 
03449    /* copy the ID */
03450    idcode = NI_get_attribute(nel,"idcode");
03451    if (!idcode) idcode = NI_get_attribute(nel,"ni_idcode");
03452    if (idcode) {
03453       NI_set_attribute(ngr, "Object_ID", idcode);
03454    } else {
03455       SUMA_NEW_ID(idcode, NULL);
03456       NI_set_attribute(ngr, "Object_ID", idcode); SUMA_free(idcode); idcode = NULL;
03457    }
03458    /* the domain parent */
03459    idcode = NI_get_attribute(nel,"DomParent_idcode");
03460    if (idcode) {
03461       NI_set_attribute(ngr, "Parent_ID", idcode);
03462    } else {
03463       NI_set_attribute(ngr, "Parent_ID", NULL); 
03464    }
03465    
03466    /* the geometry domain parent */
03467    idcode = NI_get_attribute(nel,"GeomParent_idcode");
03468    if (idcode) {
03469       NI_set_attribute(ngr, "GeomParent_idcode", idcode);
03470    } else {
03471       NI_set_attribute(ngr, "GeomParent_idcode", NULL); 
03472    }
03473    
03474    /* form the data nel */
03475    dname = SUMA_append_string(ngr->name, "_data");
03476    dnel = NI_new_data_element(dname, nel->vec_len); SUMA_free(dname); dname = NULL;
03477    NI_add_to_group(ngr, dnel);
03478 
03479    /* now, manually add the columns' spots */
03480    for (i=0; i<nel->vec_num; ++ i) {
03481       ctp = SUMA_TypeOfColNumb(nel, i);
03482       switch (SUMA_ColType2TypeCast(ctp)) {  /* MUST use the old function SUMA_TypeOfColNumb here ! */
03483          case SUMA_int:
03484             NI_add_column_stride ( dnel, NI_INT, NULL, 1);
03485             break;
03486          case SUMA_float:
03487             NI_add_column_stride ( dnel, NI_FLOAT, NULL, 1 );      
03488             break;
03489          case SUMA_byte:
03490             NI_add_column_stride ( dnel, NI_BYTE, NULL, 1 );      
03491             break;
03492          case SUMA_double:
03493             NI_add_column_stride ( dnel, NI_DOUBLE, NULL, 1 );      
03494             break;
03495          case SUMA_string:
03496             NI_add_column_stride ( dnel, NI_STRING, NULL, 1 );
03497             break;
03498          default:
03499             fprintf (stderr,"Error %s: Bad column type.\n", FuncName);
03500             NI_free_element(ngr);
03501             SUMA_RETURN(NULL);
03502             break;
03503       } 
03504       /* copy the vector's pointer */
03505       dnel->vec[i] = nel->vec[i]; nel->vec[i] = NULL;
03506       /* set some generic attributes */
03507       dset.dnel = dnel; dset.ngr = ngr;
03508       SUMA_AddGenDsetColAttr (&dset, ctp, dnel->vec[i], 1, -1);
03509       /* add the attributes of that column */
03510       col_label = SUMA_ColLabelCopy(nel, i, 0);
03511       SUMA_AddDsetColAttr (&dset, col_label, ctp, NULL, -1);
03512       if (col_label) SUMA_free(col_label); col_label = NULL;
03513       
03514    }   
03515    
03516    /* add the history note */
03517    stmp = NI_get_attribute(nel, "History");
03518    if (stmp) {
03519       nelb = NI_new_data_element("History", 1);
03520       NI_add_column_stride ( nelb, NI_STRING, NULL, 1 );
03521       NI_add_to_group(ngr, nelb);
03522       /* now add the new string */
03523       SUMA_NEL_REPLACE_STRING(nelb, 0, 0, (void*)stmp);
03524    }
03525    
03526    
03527    SUMA_RETURN(ngr);
03528 }
03529 
03530 /*!
03531 
03532    \brief Load a surface-based data set of the niml format
03533    \param Name (char *) name or prefix of dataset
03534    \param verb (int) level of verbosity. 0 mute, 1 normal, 2 dramatic perhaps
03535    \return dset (SUMA_DSET *)
03536    
03537    - Reads one ni element only
03538 */
03539 SUMA_DSET *SUMA_LoadNimlDset (char *Name, int verb)
03540 {
03541    static char FuncName[]={"SUMA_LoadNimlDset"};
03542    char *FullName = NULL, *niname = NULL;
03543    NI_stream ns = NULL;
03544    void *nini=NULL;
03545    SUMA_DSET *dset=NULL;
03546    int tt;
03547    SUMA_Boolean iselement = NOPE;
03548    SUMA_Boolean LocalHead = NOPE;
03549 
03550    SUMA_ENTRY;
03551    
03552    if (!Name) { SUMA_SL_Err("Null Name"); SUMA_RETURN(dset); }
03553    
03554    /* work the name */
03555    if (!SUMA_filexists(Name)) {
03556       /* try the extension game */
03557       FullName = SUMA_Extension(Name, ".niml.dset", NOPE);
03558       if (!SUMA_filexists(FullName)) {
03559          if (verb)  { SUMA_SL_Err("Failed to find dset file."); }
03560          if (FullName) SUMA_free(FullName); FullName = NULL;
03561          SUMA_RETURN(dset);
03562       }
03563    }else {
03564       FullName = SUMA_copy_string(Name);
03565    }
03566    
03567    /* got the name, now load it */
03568    niname = SUMA_append_string("file:", FullName);
03569    
03570    ns = NI_stream_open(niname, "r");
03571    if (!ns) {
03572       SUMA_SL_Crit("Failed to open NI stream for reading.");
03573       if (FullName) SUMA_free(FullName); FullName = NULL;
03574       SUMA_RETURN(dset);
03575    }
03576    
03577    nini = NI_read_element(ns, 1) ; 
03578    NI_stream_close( ns ) ; ns = NULL;
03579    tt = NI_element_type(nini);
03580     
03581    SUMA_LH("Checking on nini type");
03582    /* check if group or element */
03583    if(tt == NI_GROUP_TYPE) {
03584       iselement = NOPE; 
03585       SUMA_LH("Dealing with group");
03586    } else if (tt == NI_ELEMENT_TYPE) { 
03587       iselement = YUP; 
03588       SUMA_LH("Dealing with element");
03589    } else {
03590       fprintf(SUMA_STDERR,"Error %s: Not an element, nor a group. What is this?\n", FuncName);
03591       SUMA_RETURN(NOPE);
03592    }
03593    
03594    
03595    if (iselement) {
03596       dset = SUMA_NewDsetPointer();
03597       dset->ngr = SUMA_oDsetNel2nDsetNgr((NI_element *)nini);
03598       dset->dnel = SUMA_FindDsetDataAttributeElement(dset);
03599       if (!dset->dnel) {
03600          SUMA_SL_Warn("Failed to find dset data element");
03601       }
03602       NI_free_element((NI_element *)nini);
03603       #ifdef OLD_DSET
03604       if (!nel) {
03605          if (verb) { SUMA_SL_Err("Failed to read dset."); }
03606       } else {
03607          /* Now store that baby in Dset */
03608          dset = SUMA_NewDsetPointer();
03609          dset->nel = (NI_element *)nel; nini = NULL;
03610       }
03611       #endif
03612    } else {
03613       dset = SUMA_NewDsetPointer();
03614       dset->ngr = (NI_group *)nini; nini = NULL;
03615       dset->dnel = SUMA_FindDsetDataAttributeElement(dset);
03616       if (!dset->dnel) {
03617          SUMA_SL_Warn("Failed to find dset data element");
03618       }
03619    }   
03620    /* done, clean up and out you go */
03621    if (niname) SUMA_free(niname); niname = NULL;      
03622    if (FullName) SUMA_free(FullName); FullName = NULL;
03623    SUMA_RETURN(dset);
03624 }
03625 
03626 /*!
03627    \brief A function to create a dataset out of an OpenDX object
03628    \param FullName (char *) the filename
03629    \param dset_id (char *) if null, SUMA_CreateDsetPointer will create one
03630    \param dom_id (char *) domain idcode null if you have none
03631    \param dx (SUMA_OPEN_DX_STRUCT *) pointer to OpenDX object
03632    \return dset (SUMA_DSET *) NULL if trouble, of course. 
03633 */
03634 SUMA_DSET *SUMA_OpenDX2dset( char *FullName, char *dset_id, char *dom_id, 
03635                                 SUMA_OPEN_DX_STRUCT *dx ) 
03636 {
03637    static char FuncName[]={"SUMA_OpenDX2dset"};
03638    SUMA_DSET *dset = NULL;
03639    int i = 0;
03640 
03641    SUMA_ENTRY;
03642    
03643    if (!FullName) { SUMA_SL_Err("Need a FullName"); SUMA_RETURN(dset); }
03644    if (!dx) { SUMA_SL_Err("NULL dx"); SUMA_RETURN(dset); }
03645    
03646    dset = SUMA_CreateDsetPointer( FullName, SUMA_NODE_BUCKET, dset_id, dom_id,  dx->items); 
03647    
03648    /* now add the columns */
03649    
03650    for (i=0; i<SUMA_NCOL_OPENDX(dx); ++i) {
03651       if (!SUMA_AddDsetNelCol (dset, "dx_col", SUMA_VarType2ColType (dx->type), dx->datap+i, NULL , SUMA_NCOL_OPENDX(dx))) {
03652          SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
03653          SUMA_FreeDset((void*)dset); dset = NULL;
03654          SUMA_RETURN(dset);
03655       }
03656    }
03657 
03658    SUMA_RETURN(dset);
03659 }
03660 
03661 /*!
03662    \brief A function to create a dataset out of MRI_FLOAT_PTR(im)
03663          that is typically used to read in a 1D file   
03664    \param FullName (char *) the filename
03665    \param dset_id (char *) if null, SUMA_CreateDsetPointer will create one
03666    \param dom_id (char *) domain idcode null if you have none
03667    \param farp (float **) pointer to float vector. If far = MRI_FLOAT_PTR(im);
03668                            then pass farp is &far . I want the pointer
03669                            so that I can set it to NULL if the pointer
03670                            is copied instead of the data (i.e. ptr_cpy ! = 0)
03671    \param vec_len (int) That would be im->nx
03672    \param vec_num (int) That would be im->ny
03673    \param ptr_cpy (int) 0 if you want to copy the values in *farp, 
03674                         1 if you want to make a pointer copy. In that case
03675                         (not supported yet, *farp is set to NULL)
03676    \return dset (SUMA_DSET *) NULL if trouble, of course. 
03677 */
03678 SUMA_DSET *SUMA_far2dset( char *FullName, char *dset_id, char *dom_id, 
03679                                  float **farp, int vec_len, int vec_num, 
03680                                  int ptr_cpy) 
03681 {
03682    static char FuncName[]={"SUMA_far2dset"};
03683    SUMA_DSET *dset = NULL;
03684    int i = 0;
03685    float *far = NULL;
03686 
03687    SUMA_ENTRY;
03688    
03689    if (!FullName) { SUMA_SL_Err("Need a FullName"); SUMA_RETURN(dset); }
03690    if (!farp) { SUMA_SL_Err("NULL farp"); SUMA_RETURN(dset); }
03691    far = *farp;
03692    if (!far) { SUMA_SL_Err("NULL *farp"); SUMA_RETURN(dset); }
03693    if (vec_len < 0 || vec_num < 0) { SUMA_SL_Err("Negative vec_len or vec_num"); SUMA_RETURN(dset); }
03694    if (ptr_cpy) { SUMA_SL_Err("Pointer copy not supported yet"); SUMA_RETURN(dset); }
03695    
03696    if (vec_num > 200 * vec_len || vec_num > 50000) { /* a warning for MSB's mishap */
03697       char *eee = getenv("SUMA_1D_Transponse_Warn");
03698       int Warn = 1;
03699       static int nwarn = 0;
03700       Warn = 1;
03701       if (eee) {
03702          if (strcmp(eee,"NO") == 0) Warn = 0; /* stay out of this */
03703       }  
03704       if (Warn) {
03705          if (!nwarn) {
03706             SUMA_SLP_Warn( "Unusual 1D file dimensions.\n"
03707                         "Number of rows (nodes) much less\n"
03708                         "than number of columns (sub-bricks).\n"
03709                         "This warning is put up in case\n"
03710                         "you have the dataset incorrectly \n"
03711                         "transposed for some reason. Should\n"
03712                         "you need to transpose it again, use \n"
03713                         "the program 1dtranspose .\n"
03714                         "1D files where the number of columns\n"
03715                         "is much larger than the number of \n"
03716                         "rows will take a long time to load \n"
03717                         "and a longer time to have the X interface\n"
03718                         "initialized.\n"
03719                         "The read operation was cancelled this\n"
03720                         "time, read the file again if you think\n"
03721                         "the file you are reading is properly \n"
03722                         "formatted. This warning will\n"
03723                         "no be shown again in this session.\n"
03724                         "Set the environment variable \n"
03725                         "SUMA_1D_Transponse_Warn = NO\n"
03726                         "in .sumarc if you do not want to see\n"
03727                         "this warning ever again.\n"
03728                         );
03729             /* return the first time with NULL */
03730             ++nwarn; SUMA_RETURN(NULL);
03731          } 
03732       }
03733    }
03734    dset = SUMA_CreateDsetPointer( FullName, SUMA_NODE_BUCKET, dset_id, dom_id,  vec_len  ); 
03735    
03736    /* now add the columns */
03737    for (i=0; i<vec_num; ++i) {
03738       if (!SUMA_AddDsetNelCol (dset, "numeric", SUMA_NODE_FLOAT, (void *)(&(far[i*vec_len])), NULL ,1)) {
03739          SUMA_SL_Crit("Failed in SUMA_AddDsetNelCol");
03740          SUMA_FreeDset((void*)dset); dset = NULL;
03741          SUMA_RETURN(dset);
03742       }
03743    }
03744 
03745    if (ptr_cpy) *farp = NULL;
03746 
03747    SUMA_RETURN(dset);
03748 }
03749 
03750 int SUMA_is_AllNumeric_dset(SUMA_DSET *dset) 
03751 {
03752    static char FuncName[]={"SUMA_is_AllNumeric_dset"};
03753    int ctp, vtp, i;
03754    
03755    SUMA_ENTRY;
03756    
03757    if (!dset) SUMA_RETURN(0);
03758    
03759    for (i=0; i<dset->dnel->vec_num; ++i) {
03760       ctp = SUMA_TypeOfDsetColNumb(dset, i); 
03761       vtp = SUMA_ColType2TypeCast(ctp) ;
03762       if (vtp < SUMA_byte || vtp > SUMA_double) SUMA_RETURN(0);
03763    }
03764    
03765    SUMA_RETURN(1);
03766 }
03767 int SUMA_is_AllNumeric_ngr(NI_group *ngr) 
03768 {
03769    static char FuncName[]={"SUMA_is_AllNumeric_ngr"};
03770    int ctp, vtp, i;
03771    NI_element *nelb;
03772    char *sname=NULL;
03773    SUMA_DSET dset;
03774    
03775    SUMA_ENTRY;
03776    
03777    if (!ngr) SUMA_RETURN(0);
03778    
03779    sname = SUMA_append_string(ngr->name,"_data");
03780    nelb = SUMA_FindNgrAttributeElement(ngr, sname);
03781    SUMA_free(sname); sname = NULL;
03782    /* bundle it up */
03783    dset.ngr = ngr;
03784    dset.dnel = nelb;
03785    for (i=0; i<dset.dnel->vec_num; ++i) {
03786       ctp = SUMA_TypeOfDsetColNumb(&dset, i); 
03787       vtp = SUMA_ColType2TypeCast(ctp) ;
03788       if (vtp < SUMA_byte || vtp > SUMA_double) SUMA_RETURN(0);
03789    }
03790    
03791    SUMA_RETURN(1);
03792 }
03793 
03794 int SUMA_is_AllNumeric_nel(NI_element *nel) 
03795 {
03796    static char FuncName[]={"SUMA_is_AllNumeric_nel"};
03797    int ctp, vtp, i;
03798    
03799    SUMA_ENTRY;
03800    
03801    SUMA_SL_Warn("Obsolete, perhaps. Check on caller.");
03802 
03803    if (!nel) SUMA_RETURN(0);
03804    
03805    for (i=0; i<nel->vec_num; ++i) {
03806       ctp = SUMA_TypeOfColNumb(nel, i); 
03807       vtp = SUMA_ColType2TypeCast(ctp) ;
03808       if (vtp < SUMA_byte || vtp > SUMA_double) SUMA_RETURN(0);
03809    }
03810    
03811    SUMA_RETURN(1);
03812 }
03813 
03814 static char *ParentOfDsetToLoad = NULL;
03815 
03816 /*! Used to provide an identifier for the surface on which a dset will
03817 be attached. Remember to reset this pointer to NULL after loading the dset */
03818 void SUMA_SetParent_DsetToLoad(char *parent)
03819 {
03820    ParentOfDsetToLoad = parent;
03821    return;
03822 }
03823 
03824 /*!
03825 
03826    \brief Load a surface-based data set of the DX format
03827    \param Name (char *) name or prefix of dataset
03828    \param verb (int) level of verbosity. 0 mute, 1 normal, 2 dramatic perhaps
03829    \return dset (SUMA_DSET *)
03830    
03831 */
03832 SUMA_DSET *SUMA_LoadDXDset (char *Name, int verb)
03833 {
03834    static char FuncName[]={"SUMA_LoadDXDset"};
03835    char *FullName = NULL;
03836    MRI_IMAGE *im = NULL;
03837    float *far=NULL;
03838    int i, ndxv=0;
03839    char *idcode = NULL, *name=NULL;
03840    SUMA_DSET *dset=NULL;
03841    SUMA_OPEN_DX_STRUCT **dxv=NULL, *dx=NULL;
03842    SUMA_ENTRY;
03843    
03844    if (!Name) { SUMA_SL_Err("Null Name"); SUMA_RETURN(dset); }
03845    
03846    /* work the name */
03847    if (!SUMA_filexists(Name)) {
03848       /* try the extension game */
03849       FullName = SUMA_Extension(Name, ".dx.dset", NOPE);
03850       if (!SUMA_filexists(FullName)) {
03851          SUMA_free(FullName); FullName = NULL;
03852          FullName = SUMA_Extension(Name, ".dx", NOPE);
03853          if (!SUMA_filexists(FullName)) {
03854             if (verb)  { SUMA_SL_Err("Failed to find dset file."); }
03855             goto CLEAN_EXIT;
03856          }
03857       }
03858    }else {
03859       FullName = SUMA_copy_string(Name);
03860    }
03861    
03862    /* load the objects */
03863    if (!(dxv = SUMA_OpenDX_Read(FullName, &ndxv))) {
03864       if (verb) SUMA_SL_Err("Failed to read OpenDx File");
03865       goto CLEAN_EXIT;
03866    }
03867 
03868    /* if more than one, warn that only one is to be used */
03869    if (ndxv < 1) {
03870       SUMA_SL_Err("no objects in file");
03871       goto CLEAN_EXIT;
03872    }else if (ndxv > 1) {
03873       SUMA_SL_Warn("More than one object found in file.\nUsing first applicable one.");
03874    }
03875    /* find the object that is appropriate */
03876    i=0; dx = NULL;
03877    while (i<ndxv && !dx) {
03878       if (dxv[i]->datap && dxv[i]->items) {
03879          dx = dxv[i];
03880       }
03881       ++i;
03882    }
03883    if (!dx) {
03884       SUMA_SL_Err("No appropriate objects found");
03885       SUMA_Show_OpenDX_Struct(dxv, ndxv, NULL); fflush(stdout);
03886       goto CLEAN_EXIT;
03887    }
03888    /* transfer contents to dset */
03889    if (ParentOfDsetToLoad) name = SUMA_append_string(ParentOfDsetToLoad, FullName);
03890    else if (FullName) name = SUMA_copy_string(FullName);
03891    else name = SUMA_copy_string("wow");
03892    SUMA_NEW_ID(idcode, name);
03893    SUMA_free(name); name = NULL;
03894    dset = SUMA_OpenDX2dset(FullName, idcode, NULL, dx);
03895    if (idcode) SUMA_free(idcode); idcode = NULL;
03896    if (!dset) {
03897       SUMA_SLP_Err("Failed in SUMA_OpenDX2dset\n");
03898       goto CLEAN_EXIT;
03899    }
03900    
03901    
03902    CLEAN_EXIT:
03903    if (FullName) SUMA_free(FullName); FullName = NULL;
03904    for (i=0; i<ndxv; ++i) {
03905       dxv[i] = SUMA_Free_OpenDX_Struct(dxv[i]);
03906    }
03907    if (dxv) SUMA_free(dxv); dxv = NULL;
03908    SUMA_RETURN(dset);
03909 } 
03910 /*!
03911 
03912    \brief Load a surface-based data set of the 1D format
03913    \param Name (char *) name or prefix of dataset
03914    \param verb (int) level of verbosity. 0 mute, 1 normal, 2 dramatic perhaps
03915    \return dset (SUMA_DSET *)
03916    
03917 */
03918 SUMA_DSET *SUMA_Load1DDset (char *oName, int verb)
03919 {
03920    static char FuncName[]={"SUMA_Load1DDset"};
03921    char *FullName = NULL;
03922    MRI_IMAGE *im = NULL;
03923    float *far=NULL;
03924    int i;
03925    char *idcode = NULL, *name=NULL, *nstrip = NULL;
03926    SUMA_DSET *dset=NULL;
03927    
03928    SUMA_ENTRY;
03929    
03930    if (!oName) { SUMA_SL_Err("Null Name"); SUMA_RETURN(dset); }
03931    
03932    SUMA_S_Note(oName);
03933    /* remove [] if existing */
03934    nstrip = SUMA_copy_string(oName);
03935    for (i=0; i<strlen(nstrip); ++i) if (nstrip[i] == '[') { nstrip[i] = '\0'; break; }
03936    
03937    /* work the name */
03938    if (!SUMA_filexists(nstrip)) {
03939       /* try the extension game */
03940       FullName = SUMA_Extension(nstrip, ".1D.dset", NOPE);
03941       if (!SUMA_filexists(FullName)) {
03942          if (verb)  { SUMA_SL_Err("Failed to find dset file."); }
03943          if (FullName) SUMA_free(FullName); FullName = NULL;
03944          SUMA_RETURN(dset);
03945       }
03946    }else {
03947       FullName = SUMA_copy_string(nstrip);
03948    }
03949    /* got the name, now read it */
03950    im = mri_read_1D (oName);
03951    if (!im) {
03952       if (verb) SUMA_SLP_Err("Failed to read file");
03953       if (FullName) SUMA_free(FullName); FullName = NULL;
03954       SUMA_RETURN(NULL);
03955    }   
03956    
03957    /* form a good id */
03958    if (ParentOfDsetToLoad) name = SUMA_append_string(ParentOfDsetToLoad, FullName);
03959    else if (FullName) name = SUMA_copy_string(FullName);
03960    else name = SUMA_copy_string("wow");
03961    SUMA_NEW_ID(idcode, name);
03962    SUMA_free(name); name = NULL;
03963    far = MRI_FLOAT_PTR(im);
03964    dset = SUMA_far2dset(FullName, idcode, NULL, &far, im->nx, im->ny, 0);
03965    if (idcode) SUMA_free(idcode); idcode = NULL;
03966    if (!dset) {
03967       SUMA_SLP_Err("Failed in SUMA_far2dset\n");
03968       if (im) mri_free(im); im = NULL;
03969       if (FullName) SUMA_free(FullName); FullName = NULL; 
03970       SUMA_RETURN(NULL);
03971    }
03972    
03973    /* done, clean up and out you go */
03974    if (im) mri_free(im); im = NULL; 
03975    if (FullName) SUMA_free(FullName); FullName = NULL;
03976    if (nstrip) SUMA_free(nstrip); nstrip = NULL;
03977    SUMA_RETURN(dset);
03978 }
03979 
03980 /*!
03981    \brief Replaces a dataset's idcode with a new one
03982 */
03983 SUMA_Boolean SUMA_NewDsetID (SUMA_DSET *dset)
03984 {
03985    static char FuncName[]={"SUMA_NewDsetID"};
03986    char stmp[SUMA_IDCODE_LENGTH];
03987    
03988    SUMA_ENTRY;
03989    
03990    UNIQ_idcode_fill(stmp);
03991    
03992    if (!dset) SUMA_RETURN(NOPE);
03993    if (!dset->dnel) SUMA_RETURN(NOPE);
03994    
03995    NI_set_attribute(dset->dnel, "Object_ID", stmp);
03996    
03997    SUMA_RETURN(YUP);
03998 }
03999 
04000 /*!
04001    \brief return a niml dset's ID,
04002     substitute for macro  SDSET_ID
04003 */
04004 char* SUMA_sdset_id(SUMA_DSET *dset)
04005 {
04006    static char FuncName[]={"SUMA_sdset_id"};
04007    char *id=NULL;
04008    
04009    SUMA_ENTRY;
04010    
04011    if (!dset) SUMA_RETURN(id);
04012    #ifdef OLD_DSET
04013    if (!dset->nel) SUMA_RETURN(id);
04014    
04015    id = NI_get_attribute(dset->nel,"Object_ID"); 
04016    if (!id) id = NI_get_attribute(dset->nel,"idcode"); /* the olde way */ 
04017    #else
04018    if (!dset->ngr) SUMA_RETURN(id);
04019    
04020    id = NI_get_attribute(dset->ngr,"Object_ID"); 
04021    if (!id) id = NI_get_attribute(dset->ngr,"idcode"); /* the olde way */ 
04022    #endif
04023    SUMA_RETURN(id);
04024 }
04025 
04026 
04027 /*!
04028    \brief return a niml dset's mesh parent ID , substitute for macro 
04029    SDSET_IDMDOM
04030 */
04031 char* SUMA_sdset_idmdom(SUMA_DSET *dset)
04032 {
04033    static char FuncName[]={"SUMA_sdset_idmdom"};
04034    char *id=NULL;
04035    
04036    SUMA_ENTRY;
04037    
04038    if (!dset) SUMA_RETURN(id);
04039    #ifdef OLD_DSET
04040    if (!dset->nel) SUMA_RETURN(id);
04041    
04042    id = NI_get_attribute(dset->nel,"Parent_ID"); 
04043    if (SUMA_IS_EMPTY_STR_ATTR(id)) id = NI_get_attribute(dset->nel,"MeshParent_idcode"); /* the olde way */ 
04044    #else
04045    if (!dset->ngr) SUMA_RETURN(SUMA_EMPTY_ATTR);
04046    
04047    id = NI_get_attribute(dset->ngr,"Parent_ID"); 
04048    #endif
04049    SUMA_RETURN(id);
04050 }
04051 
04052 #ifdef SUMA_ConvertDset_STANDALONE
04053 void usage_ConverDset()
04054 {
04055    static char FuncName[]={"usage_ConverDset"};
04056    char *s = NULL;
04057    s = SUMA_help_basics();
04058    printf ( "Usage: \n"
04059             "  ConvertDset -o_TYPE -input DSET [-i_TYPE] [-prefix OUT_PREF]\n"
04060             "  Converts a surface dataset from one format to another.\n"
04061             "  Mandatory parameters:\n"
04062             "     -o_TYPE: TYPE of output datasets\n"
04063             "              where TYPE is one of:\n"
04064             "           niml_asc (or niml): for ASCII niml format.\n"
04065             "           niml_bi:            for BINARY niml format.\n"
04066             "           1D:                 for AFNI's 1D ascii format.\n"
04067             "     -input DSET: Input dataset to be converted.\n"
04068             "  Optional parameters:\n"
04069             "     -i_TYPE: TYPE of input datasets\n"
04070             "              where TYPE is one of:\n"
04071             "           niml: for niml data sets.\n"
04072             "           1D:   for AFNI's 1D ascii format.\n"
04073             "           1Dp:  like 1D but with no comments\n"
04074             "                 or other 1D formatting gimmicks.\n"
04075             "           dx: OpenDX format, expects to work on 1st\n"
04076             "               object only.\n"
04077             "           If no format is specified, the program will \n"
04078             "           guess however that might slow \n"
04079             "           operations down considerably.\n"
04080             "     -prefix OUT_PREF: Output prefix for data set.\n"
04081             "                       Default is something based\n"
04082             "                       on the input prefix.\n"
04083             "  Notes:\n"
04084             "     -This program will not overwrite pre-existing files.\n"  
04085             "     -The new data set is given a new idcode.\n"
04086             "%s"
04087             "\n", s);
04088    SUMA_free(s); s = NULL;
04089    #ifdef SUMA_COMPILED
04090    s = SUMA_New_Additions(0, 1); printf("%s\n", s);SUMA_free(s); s = NULL;
04091    #endif
04092    fprintf (SUMA_STDOUT, "    Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov    Thu Apr  8 16:15:02 EDT 2004\n\n");
04093    exit(0); 
04094 }
04095 int main (int argc,char *argv[])
04096 {/* Main */
04097    static char FuncName[]={"ConvertDset"};
04098    int kar, brk, i_input, i;
04099    SUMA_DSET_FORMAT iform, oform;
04100    SUMA_DSET *dset = NULL;
04101    char *NameOut, *prfx = NULL, *prefix = NULL;
04102    SUMA_Boolean LocalHead = NOPE;
04103    
04104    SUMA_mainENTRY;
04105    
04106    SUMA_STANDALONE_INIT;
04107 
04108    if (argc < 3) {
04109       usage_ConverDset  ();
04110       exit (1);
04111    }
04112 
04113    iform = SUMA_NO_DSET_FORMAT;
04114    oform = SUMA_NO_DSET_FORMAT;
04115    i_input = -1;
04116    prfx = NULL;
04117    kar = 1;
04118    brk = NOPE;
04119    while (kar < argc) { /* loop accross command ine options */
04120       if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
04121          usage_ConverDset  ();
04122          exit (1);
04123       }
04124       
04125       SUMA_SKIP_COMMON_OPTIONS(brk, kar);
04126       
04127       SUMA_TO_LOWER(argv[kar]);
04128       if (!brk && (strcmp(argv[kar], "-i_1d") == 0))
04129       {
04130          if (iform != SUMA_NO_DSET_FORMAT) {
04131             SUMA_SL_Err("input type already specified.");
04132             exit(1);
04133          }
04134          iform = SUMA_1D;
04135          brk = YUP;
04136       }
04137       
04138       if (!brk && (strcmp(argv[kar], "-i_niml") == 0))
04139       {
04140          if (iform != SUMA_NO_DSET_FORMAT) {
04141             SUMA_SL_Err("input type already specified.");
04142             exit(1);
04143          }
04144          iform = SUMA_NIML;
04145          brk = YUP;
04146       }
04147       
04148       if (!brk && (strcmp(argv[kar], "-i_dx") == 0))
04149       {
04150          if (iform != SUMA_NO_DSET_FORMAT) {
04151             SUMA_SL_Err("input type already specified.");
04152             exit(1);
04153          }
04154          iform = SUMA_ASCII_OPEN_DX_DSET;
04155          brk = YUP;
04156       }
04157       
04158       if (!brk && (strcmp(argv[kar], "-o_1d") == 0))
04159       {
04160          if (oform != SUMA_NO_DSET_FORMAT) {
04161             SUMA_SL_Err("output type already specified.");
04162             exit(1);
04163          }
04164          oform = SUMA_1D;
04165          brk = YUP;
04166       }
04167       
04168       if (!brk && (strcmp(argv[kar], "-o_1dp") == 0))
04169       {
04170          if (oform != SUMA_NO_DSET_FORMAT) {
04171             SUMA_SL_Err("output type already specified.");
04172             exit(1);
04173          }
04174          oform = SUMA_1D_PURE;
04175          brk = YUP;
04176       }
04177       
04178       if (!brk && (strcmp(argv[kar], "-o_niml") == 0))
04179       {
04180          if (oform != SUMA_NO_DSET_FORMAT) {
04181             SUMA_SL_Err("output type already specified.");
04182             exit(1);
04183          }
04184          
04185          oform = SUMA_ASCII_NIML;
04186          brk = YUP;
04187       }
04188       
04189       if (!brk && (strcmp(argv[kar], "-o_niml_asc") == 0))
04190       {
04191          if (oform != SUMA_NO_DSET_FORMAT) {
04192             SUMA_SL_Err("output type already specified.");
04193             exit(1);
04194          }
04195          
04196          oform = SUMA_ASCII_NIML;
04197          brk = YUP;
04198       }
04199       
04200       if (!brk && (strcmp(argv[kar], "-o_niml_bi") == 0))
04201       {
04202          if (oform != SUMA_NO_DSET_FORMAT) {
04203             SUMA_SL_Err("output type already specified.");
04204             exit(1);
04205          }
04206          
04207          oform = SUMA_BINARY_NIML;
04208          brk = YUP;
04209       }
04210       
04211       if (!brk && (strcmp(argv[kar], "-input") == 0))
04212       {
04213          if (kar+1 >= argc) {
04214             SUMA_SL_Err("Need argument after -input");
04215             exit(1);
04216          }
04217          if (i_input >= 0) {
04218             SUMA_SL_Err("-input already specified.");
04219             exit(1);
04220          }
04221          i_input = kar+1;
04222          ++kar;
04223          brk = YUP;
04224       }
04225       
04226       if (!brk && (strcmp(argv[kar], "-prefix") == 0))
04227       {
04228          if (kar+1 >= argc) {
04229             SUMA_SL_Err("Need argument after -prefix");
04230             exit(1);
04231          }
04232          ++kar;
04233          prfx = argv[kar];
04234          brk = YUP;
04235       }
04236       
04237       if (!brk) {
04238          fprintf (SUMA_STDERR,"Error %s: Option %s not understood. Try -help for usage\n", FuncName, argv[kar]);
04239          exit (1);
04240       } else {   
04241          brk = NOPE;
04242          kar ++;
04243       }
04244       
04245    }/* loop accross command ine options */
04246     
04247    if (oform == SUMA_NO_DSET_FORMAT) {
04248       SUMA_SL_Err("Output format MUST be specified");
04249       exit(1);
04250    }
04251 
04252    for (i=i_input; i<i_input + 1; ++i) {
04253       if (LocalHead) fprintf(SUMA_STDERR,"%s:\n Reading %s...\n", FuncName, argv[i]); 
04254       dset = SUMA_LoadDset (argv[i], &iform, 0); 
04255       if (!dset) { SUMA_SL_Err(  "Failed to load dataset.\n"
04256                                  "Make sure file exists\n"
04257                                  "and is of the specified\n"
04258                                  "format."); exit(1); }
04259       if (!prfx) {
04260          /* don't use iform because some 1Ds are NIML compatible and they get
04261          read-in as such unless you specifically order otherwise. */
04262          prefix = SUMA_RemoveDsetExtension(argv[i], SUMA_NO_DSET_FORMAT);
04263       } else { 
04264          prefix = SUMA_copy_string(prfx); 
04265       }
04266       
04267       /* set a new ID for the dset */
04268       SUMA_NewDsetID (dset); 
04269       
04270       NameOut = SUMA_WriteDset (prefix, dset, oform, 0, 0);
04271       if (!NameOut) { SUMA_SL_Err("Failed to write dataset."); exit(1); } 
04272       if (prefix) SUMA_free(prefix); prefix = NULL;    
04273       if (dset) SUMA_FreeDset((void *)dset); dset = NULL;
04274       if (NameOut) SUMA_free(NameOut); NameOut = NULL;
04275    }
04276    
04277         SUMA_RETURN(0);
04278 }    
04279 #endif
04280 
04281 #ifdef SUMA_Test_DSET_IO_STANDALONE
04282 void usage_Test_DSET_IO ()
04283    
04284   {/*Usage*/
04285           char *sb=NULL;
04286           sb = SUMA_help_basics();
04287           printf ("\n"
04288                   "Usage:  \n"
04289                   "%s"
04290                   "\n", sb);
04291           SUMA_free(sb);
04292           exit (0);
04293   }/*Usage*/
04294    
04295 int main (int argc,char *argv[])
04296 {/* Main */
04297    static char FuncName[]={"SUMA_TestDsetIO"}; 
04298    int *NodeDef=NULL;
04299    byte *maskrow, *maskcol;
04300    int i, i3, N_NodeDef, N_Alloc, flg;
04301    float *r=NULL, *g=NULL, *b=NULL, *rgb=NULL;
04302    char stmp[500], idcode[50], **s, *si, *OutName = NULL;
04303    NI_element *nel=NULL;
04304    NI_stream ns;
04305    int found = 0, NoStride = 0;
04306    byte *bt=NULL;
04307    SUMA_DSET * dset = NULL, *ndset=NULL;
04308    SUMA_Boolean LocalHead = YUP;
04309    
04310    SUMA_mainENTRY;
04311    
04312    SUMA_STANDALONE_INIT;
04313         
04314    LocalHead = YUP; /* turn on debugging */
04315    SUMA_LH("Creating Data ...");
04316    /* Create some sample data*/
04317       /* let us create some colors to go on each node */
04318       N_Alloc = 50;
04319       NodeDef = (int *)SUMA_malloc(N_Alloc * sizeof(int));
04320       r = (float *)SUMA_malloc(N_Alloc * sizeof(float));
04321       g = (float *)SUMA_malloc(N_Alloc * sizeof(float));
04322       b = (float *)SUMA_malloc(N_Alloc * sizeof(float));
04323       bt = (byte *)SUMA_malloc(N_Alloc * sizeof(byte));
04324       s = (char **)SUMA_malloc(N_Alloc * sizeof(char *));
04325       maskrow = (byte *)SUMA_malloc(N_Alloc * sizeof(byte));
04326       maskcol = (byte *)SUMA_malloc(10*sizeof(byte)); for (i=0; i<10; ++i) { if (i==1 || i == 3) maskcol[i]=0; else maskcol[i] = 1; }
04327       N_NodeDef = N_Alloc;
04328       for (i=0; i<N_NodeDef; ++i) {
04329          NodeDef[i] = i;
04330          r[i] = sin((float)i/N_NodeDef*5);
04331          g[i] = sin((float)i/N_NodeDef*10);
04332          b[i] = cos((float)i/N_NodeDef*7);
04333          bt[i] = (byte)(4*b[i]);
04334          sprintf(stmp,"teststr_%d", i);
04335          s[i] = SUMA_copy_string(stmp);
04336          if (i==3 || i== 7 || i==33) maskrow[i] = 1; else maskrow[i]=0;
04337       }
04338       /* what if you had a vector of say, triplets */
04339       rgb = (float *)SUMA_malloc(3 * N_Alloc * sizeof(float));
04340       for (i=0; i<N_NodeDef; ++i) {
04341          i3 = 3*i;
04342          rgb[i3] = r[i];
04343          rgb[i3+1] = g[i];
04344          rgb[i3+2] = b[i];
04345       }
04346       
04347   {
04348       float *xc, *de, *amp;
04349       int dof;
04350       /* store some statistics */
04351       xc = (float *)SUMA_malloc(N_Alloc * sizeof(float));
04352       de = (float *)SUMA_malloc(N_Alloc * sizeof(float));
04353       amp = (float *)SUMA_malloc(N_Alloc * sizeof(float));
04354       for (i=0; i<N_NodeDef; ++i) {
04355          xc[i] = rand()%1000/1000.0 * 1.0;
04356          de[i] = rand()%1000/1000.0 * 30;
04357          amp[i] = rand()%1000/1000.0 * 5.0;
04358       }
04359      
04360       SUMA_LH("Creating dset pointer");
04361       dset = SUMA_CreateDsetPointer(
04362                                     "ExpandingRing_ResponseDelay",         /* some label */
04363                                     SUMA_NODE_BUCKET,                /* mix and match */
04364                                     NULL,    /* no idcode, let the function create one from the filename*/
04365                                     NULL,       /* no domain str specified */
04366                                     N_Alloc    /* Number of nodes allocated for */
04367                                     ); /* DO NOT free dset, it is store in DsetList */
04368       #ifdef SUMA_COMPILED
04369       SUMA_LH("inserting dset pointer into list");
04370       if (!SUMA_InsertDsetPointer(dset, SUMAg_CF->DsetList)) {
04371          SUMA_SL_Err("Failed to insert dset into list");
04372          exit(1);
04373       }  
04374       #endif
04375         /* form the dataset */
04376    SUMA_LH("Adding stat NodeDef column ...");
04377    if (!SUMA_AddDsetNelCol (   dset, /* the famed nel */ 
04378                            "Node Indices", 
04379                            SUMA_NODE_INDEX, /* the column's type (description),
04380                                                one of SUMA_COL_TYPE */
04381                            (void *)NodeDef, /* column pointer p, here it is
04382                                              the list of node indices */
04383                            NULL  /* that's an optional structure containing 
04384                                     attributes of the added column. 
04385                                     Not used at the moment */
04386                            ,1 /* stride, useful when you need to copy a column
04387                                  from a multiplexed vector. Say you have in p 
04388                                  [rgb rgb rgb rgb], to set the g column you 
04389                                  send in p+1 for the column pointer and a stride
04390                                  of 3 */
04391                            )) {
04392          fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04393          exit(1);                    
04394       }
04395       
04396       SUMA_LH("Adding stat other columns...");
04397          dof = 120;
04398          if (!SUMA_AddDsetNelCol (dset, "XcorrCoef", SUMA_NODE_XCORR, (void *)xc, (void *)&dof ,1)) {
04399             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddDsetNelCol", FuncName);
04400             exit(1);
04401          }
04402 
04403          if (!SUMA_AddDsetNelCol (dset, "Delay", SUMA_NODE_FLOAT, (void *)de, NULL ,1)) {
04404             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddDsetNelCol", FuncName);
04405             exit(1);
04406          }
04407 
04408          if (!SUMA_AddDsetNelCol (dset, "Amplitude", SUMA_NODE_FLOAT, (void *)amp, NULL ,1)) {
04409             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddDsetNelCol", FuncName);
04410             exit(1);
04411          }
04412       SUMA_LH("History note");
04413       if (!SUMA_AddNgrHist(dset->ngr, FuncName, argc, argv)) {
04414          SUMA_SL_Err("History addition failed.");
04415          exit(1);
04416       }
04417       OutName = SUMA_WriteDset ("SampleDset", dset, SUMA_ASCII_NIML, 1, 1); 
04418       if (!OutName) {
04419          SUMA_SL_Err("Write Failed.");
04420       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName); 
04421          SUMA_free(OutName); OutName = NULL;
04422       }
04423       
04424       #ifdef SUMA_COMPILED
04425       /* Now create a new dataset nel 
04426       no need to worry about loosing previous dset because it is in 
04427       SUMAg_CF->DsetList*/
04428       #else
04429       /* free dset by hand */
04430       SUMA_LH("Freeing datasets ...");
04431       if (dset) SUMA_FreeDset((void *)dset);
04432       dset = NULL;
04433       #endif
04434       
04435    }
04436    SUMA_LH("Creating dset pointer");
04437    dset = SUMA_CreateDsetPointer(
04438                                  "SomethingLikeFileName",         /* usually the filename */
04439                                  SUMA_NODE_BUCKET,                /* mix and match */
04440                                  NULL,    /* no idcode, let the function create one from the filename*/
04441                                  NULL,       /* no domain str specified */
04442                                  N_Alloc    /* Number of nodes allocated for */
04443                                  ); /* DO NOT free dset, it is store in DsetList */
04444    #ifdef SUMA_COMPILED
04445    SUMA_LH("inserting dset pointer into list");
04446    if (!SUMA_InsertDsetPointer(dset, SUMAg_CF->DsetList)) {
04447       SUMA_SL_Err("Failed to insert dset into list");
04448       exit(1);
04449    }  
04450    #endif
04451                            
04452         /* form the dataset */
04453    SUMA_LH("Adding NodeDef column ...");
04454    if (!SUMA_AddDsetNelCol (   dset, /* the famed nel */ 
04455                            "le Node Def", 
04456                            SUMA_NODE_INDEX, /* the column's type (description),
04457                                                one of SUMA_COL_TYPE */
04458                            (void *)NodeDef, /* column pointer p, here it is
04459                                              the list of node indices */
04460                            NULL  /* that's an optional structure containing 
04461                                     attributes of the added column. 
04462                                     Not used at the moment */
04463                            ,1 /* stride, useful when you need to copy a column
04464                                  from a multiplexed vector. Say you have in p 
04465                                  [rgb rgb rgb rgb], to set the g column you 
04466                                  send in p+1 for the column pointer and a stride
04467                                  of 3 */
04468                            )) {
04469          fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04470          exit(1);                    
04471       }
04472       
04473       SUMA_LH("Adding other columns...");
04474       NoStride = 0;
04475       if (NoStride) {
04476          /* insert separate r, g and b column */
04477          if (!SUMA_AddDsetNelCol (dset, "Le R", SUMA_NODE_R, (void *)r, NULL ,1)) {
04478             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04479             exit(1);
04480          }
04481 
04482          if (!SUMA_AddDsetNelCol (dset, "Le G", SUMA_NODE_G, (void *)g, NULL ,1)) {
04483             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04484             exit(1);
04485          }
04486 
04487          if (!SUMA_AddDsetNelCol (dset, "Le B", SUMA_NODE_B, (void *)b, NULL ,1)) {
04488             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04489             exit(1);
04490          }
04491       } else {
04492          /* insert from multiplexed rgb vector */
04493          if (!SUMA_AddDsetNelCol (dset, "le R", SUMA_NODE_R, (void *)rgb, NULL ,3 )) {
04494             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04495             exit(1);
04496          }
04497 
04498          if (!SUMA_AddDsetNelCol (dset, "Le G", SUMA_NODE_G, (void *)(rgb+1), NULL ,3)) {
04499             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04500             exit(1);
04501          }
04502 
04503          if (!SUMA_AddDsetNelCol (dset, "Le B", SUMA_NODE_B, (void *)(rgb+2), NULL ,3)) {
04504             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04505             exit(1);
04506          }
04507       }
04508       { int suc; SUMA_LH("Where are the attributes?"); NEL_WRITE_TX(dset->ngr,"fd:1",suc); }
04509       /* add the byte column, just to check multi type nightmares */
04510       if (!SUMA_AddDsetNelCol (dset, "Le byte moi", SUMA_NODE_BYTE, (void *)bt, NULL ,1)) {
04511             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04512             exit(1);
04513       }
04514       
04515       SUMA_LH("Testing write ops before adding string columns ...");
04516       /* before adding a string column ... */
04517       OutName = SUMA_WriteDset ("Test_write_all_num", dset, SUMA_1D, 1, 1); 
04518       if (!OutName) {
04519          SUMA_SL_Err("Write Failed.");
04520       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName); 
04521          SUMA_free(OutName); OutName = NULL;
04522       }
04523       
04524       OutName = SUMA_WriteDset ("Test_writebi_all_num", dset, SUMA_BINARY_NIML, 1, 1); 
04525       if (!OutName) {
04526          SUMA_SL_Err("Write Failed.");
04527       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName); 
04528          SUMA_free(OutName); OutName = NULL; 
04529       }
04530            
04531       OutName = SUMA_WriteDset ("Test_writeas_all_num", dset, SUMA_ASCII_NIML, 1, 1); 
04532       if (!OutName) {
04533          SUMA_SL_Err("Write Failed.");
04534       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName); 
04535          SUMA_free(OutName); OutName = NULL;
04536       }
04537       
04538       /* zero out some columns and test operations */
04539       SUMA_LH("Trying masking operations");
04540       ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 1, 0); 
04541       SUMA_LH("Done");
04542       /* try also:
04543          ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 0, 1);
04544          ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 0, 0);
04545          ndset = SUMA_MaskedCopyofDset(dset, maskrow, NULL, 1, 0); 
04546          ndset = SUMA_MaskedCopyofDset(dset, NULL, NULL, 1, 0); 
04547          ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 1, 0); 
04548       */
04549       if (!ndset) {
04550          SUMA_SL_Err("Failed in SUMA_MaskedCopyofDset");
04551       } else {
04552          OutName = SUMA_WriteDset ("Test_writeas_MaskedCopy_num", ndset, SUMA_ASCII_NIML, 1, 1); 
04553          if (!OutName) {
04554             SUMA_SL_Err("Write Failed.");
04555          } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName); 
04556             SUMA_free(OutName); OutName = NULL;
04557          }
04558          SUMA_free(ndset); ndset = NULL;
04559       }
04560       
04561       SUMA_LH("Adding a string column");
04562       /* add a string column, just for kicks ..*/
04563       if (!SUMA_AddDsetNelCol (dset, "la string", SUMA_NODE_STRING, (void *)s, NULL, 1)) {
04564          fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04565          exit(1);  
04566       }
04567       
04568       /* now try to create a masked copy, this should fail */
04569       fprintf (stderr,"%s: Attempting to mask a not all numeric dset, this should fail\n", FuncName);
04570       ndset = SUMA_MaskedCopyofDset(dset, maskrow, maskcol, 1, 0); 
04571       if (ndset) {
04572          fprintf (stderr,"Error  %s:\nWhat the hell? This should not be supported.", FuncName);
04573          exit(1);
04574       }else{
04575          fprintf (stderr,"%s: Good, failed.\n", FuncName);
04576       }  
04577       /* after adding a string column ... */
04578       SUMA_LH("Writing datasets ...");
04579       OutName = SUMA_WriteDset ("Test_writeas", dset, SUMA_ASCII_NIML, 1, 1); 
04580       if (!OutName) {
04581          SUMA_SL_Err("Write Failed.");
04582       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName); 
04583          SUMA_free(OutName); OutName = NULL;
04584       }
04585       
04586       OutName = SUMA_WriteDset ("Test_writebi", dset, SUMA_BINARY_NIML, 1, 1); 
04587       if (!OutName) {
04588          SUMA_SL_Err("Write Failed.");
04589       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName); 
04590          SUMA_free(OutName); OutName = NULL;
04591       }
04592            
04593       SUMA_LH("Writing to 1D a dataset that is not all numbers.\nThis should fail.\n");
04594       OutName = SUMA_WriteDset ("Test_write", dset, SUMA_1D, 1, 1); 
04595       if (!OutName) {
04596          SUMA_SL_Err("Write Failed.");
04597       } else { fprintf (stderr,"%s:\nDset written to %s\n", FuncName, OutName); 
04598          SUMA_free(OutName); OutName = NULL;
04599       }
04600       
04601      
04602       
04603         
04604       /* How about loading some data */
04605       #ifdef SUMA_COMPILED
04606       /* Now create a new dataset nel 
04607       no need to worry about loosing previous dset because it is in 
04608       SUMAg_CF->DsetList*/
04609       #else
04610       /* free dset by hand */
04611       SUMA_LH("Freeing datasets ...");
04612       if (dset) SUMA_FreeDset((void *)dset);
04613       dset = NULL;
04614       #endif
04615       
04616       SUMA_LH("Fresh dataset ...");
04617       dset = SUMA_NewDsetPointer();
04618       SUMA_LH("Reading dataset ...");
04619       DSET_READ(dset, "file:Test_writebi.niml.dset"); if (!dset->ngr) exit(1);
04620       /* insert the baby into the list */
04621       
04622       #ifdef SUMA_COMPILED
04623       SUMA_LH("Inserting newly read element into list\n");
04624       if (!SUMA_InsertDsetPointer(dset, SUMAg_CF->DsetList)) {
04625          char *newid = NULL;
04626          SUMA_SL_Err("Failed to insert dset into list");
04627          /* Now change the idcode of that baby */
04628          newid = UNIQ_hashcode(SDSET_ID(dset));
04629          NI_set_attribute(dset->dnel, "Object_ID", newid); SUMA_free(newid);
04630          SUMA_LH("Trying to insert dset with a new id ");
04631          if (!SUMA_InsertDsetPointer(dset, SUMAg_CF->DsetList)) {
04632             SUMA_SL_Err("Failed to insert dset into list\nI failed to succeed, snif.");
04633             exit(1);
04634          }
04635          SUMA_LH("Lovely, that worked...");
04636       }
04637       #endif
04638            
04639       /* show me the whole thing. Don't do this for an enormous nel */
04640          /* SUMA_ShowNel(dset->nel); */
04641          
04642       
04643       /* I want the pointer to the green column but do not know its index */
04644          {   
04645             int j, *iv, N_i;
04646             float *fp;
04647             fprintf (stderr,"---Looking for green column ---\n");
04648             iv = SUMA_GetDsetColIndex (dset, SUMA_NODE_G, &N_i);
04649             if (!iv) {
04650                fprintf (stderr,"Error %s: Failed to find column.\n"
04651                            , FuncName);
04652             } else {
04653                fprintf (stderr,"\t%d columns of type SUMA_NODE_G found.\n",
04654                            N_i);
04655                if (N_i) {
04656                   fprintf (stderr,"\tReporting values at index %d\n", iv[0]);
04657                   fp = (float *)dset->dnel->vec[iv[0]]; /* I know we only have one 
04658                                                    such col. here */
04659                   for (j=0; j < dset->dnel->vec_len; ++j) {
04660                      fprintf (stderr,"%f, ", fp[j]);
04661                   }
04662                   SUMA_free(iv); iv = NULL;
04663                }
04664             }
04665             
04666                   
04667          }
04668           
04669    
04670    /* Now show me that baby,*/
04671    SUMA_LH("I wanna Show You Some Info");
04672    si = SUMA_DsetInfo (dset, 0);
04673    fprintf (SUMA_STDERR,"Output of DsetInfo:\n%s\n", si); SUMA_free(si); si=NULL; 
04674    
04675    if (LocalHead) fprintf(stderr," %s:-\nFrenching ...\n", FuncName);
04676 
04677    /* free other stuff */
04678    if (r) SUMA_free(r); r = NULL;
04679    if (g) SUMA_free(g); g = NULL;
04680    if (b) SUMA_free(b); b = NULL;
04681    if (rgb) SUMA_free(rgb); rgb = NULL;
04682    if (maskrow) SUMA_free(maskrow); maskrow = NULL;
04683    if (maskcol) SUMA_free(maskcol); maskcol = NULL;
04684    if (NodeDef) SUMA_free(NodeDef); NodeDef = NULL;  
04685    if (s) {
04686       for (i=0; i<N_NodeDef; ++i) {
04687          if (s[i]) SUMA_free(s[i]);
04688       }
04689       SUMA_free(s);
04690    }
04691 
04692    #ifdef SUMA_COMPILED
04693    /* dset and its contents are freed in SUMA_Free_CommonFields */
04694    if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
04695    #else
04696    /* free dset by hand */
04697    if (dset) SUMA_FreeDset((void *)dset);
04698    #endif
04699    
04700         SUMA_RETURN (0);
04701 }/* Main */
04702 #endif
04703    
04704 
04705 
04706 
04707 
04708 
04709 
04710 #ifdef SUMA_TEST_DATA_SETS_STAND_ALONE
04711 void  SUMA_TestDataSets_Usage()
04712    
04713   {/*Usage*/
04714           printf ("\nUsage:   \n");
04715           printf ("\t ..... \n\n");
04716           printf ("\t\t\t Ziad S. Saad SSCC/NIMH/NIH ziad@nih.gov \t"
04717                   "Thu May 29 14:42:58 EDT 2003 \n");
04718           exit (0);
04719   }/*Usage*/
04720    
04721 int main (int argc,char *argv[])
04722 {/* Main */
04723    static char FuncName[]={"SUMA_TestDataSets-Main-"}; 
04724         char *VolParName, *specfilename = NULL;
04725    int kar, *Node = NULL, N_Node=-1;
04726    int SurfIn, brk, LocalHead = 1;
04727     
04728    /* Example 1: 5 nodes, 3 floats per node */
04729    
04730    SUMA_mainENTRY;
04731    
04732    SUMA_STANDALONE_INIT;
04733    
04734         /* Work the options */
04735         kar = 1;
04736         brk = 0;
04737         while (kar < argc) { /* loop accross command line options */
04738                 /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/
04739                 
04740       if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
04741                          SUMA_TestDataSets_Usage ();
04742           exit (1);
04743                 }
04744       
04745       SUMA_SKIP_COMMON_OPTIONS(brk, kar);
04746       
04747                 if (!brk) {
04748                         fprintf (stderr,
04749                "Error %s: Option %s not understood. Try -help for usage\n",
04750                 FuncName, argv[kar]);
04751                         exit (1);
04752                 } else {        
04753                         brk = 0;
04754                         kar ++;
04755                 }
04756                 
04757         }/* loop accross command ine options */
04758 
04759    /* Say you want to save a bunch of node values */
04760    { /* BEGIN: Test to save a data set with a bunch of node values */
04761       int i, i3, *node = NULL, N_Node;
04762       float *r=NULL, *g=NULL, *b=NULL, *rgb=NULL;
04763       char stmp[500], idcode[50], **s;
04764       NI_element *nel=NULL;
04765       NI_stream ns;
04766       int found = 0, NoStride = 0;
04767       
04768       UNIQ_idcode_fill (idcode);
04769       
04770       /* let us create some colors to go on each node */
04771       N_Node = 50;
04772       node = (int *)SUMA_malloc(N_Node * sizeof(int));
04773       r = (float *)SUMA_malloc(N_Node * sizeof(float));
04774       g = (float *)SUMA_malloc(N_Node * sizeof(float));
04775       b = (float *)SUMA_malloc(N_Node * sizeof(float));
04776       s = (char **)SUMA_malloc(N_Node * sizeof(char *));
04777       for (i=0; i<N_Node; ++i) {
04778          node[i] = i;
04779          r[i] = sin((float)i/N_Node*5);
04780          g[i] = sin((float)i/N_Node*10);
04781          b[i] = cos((float)i/N_Node*7);
04782          sprintf(stmp,"teststr_%d", i);
04783          s[i] = SUMA_copy_string(stmp);
04784       }
04785       /* what if you had a vector of say, triplets */
04786       rgb = (float *)SUMA_malloc(3 * N_Node * sizeof(float));
04787       for (i=0; i<N_Node; ++i) {
04788          i3 = 3*i;
04789          rgb[i3] = r[i];
04790          rgb[i3+1] = g[i];
04791          rgb[i3+2] = b[i];
04792       }
04793    
04794       /* Now create that data element and write it out */
04795       nel = SUMA_NewNel (  SUMA_NODE_RGB, /* one of SUMA_DSET_TYPE */
04796                            idcode, /* idcode of Domain Parent */
04797                            NULL, /* idcode of geometry parent, not useful here*/
04798                            N_Node,/* Number of elements */
04799                            "Test",
04800                            NULL); 
04801       if (!nel) {
04802          fprintf (stderr,"Error  %s:\nFailed in SUMA_NewNel", FuncName);
04803          exit(1);
04804       }
04805       
04806       /* Add the columns */
04807       if (!SUMA_AddNelCol (nel, /* the famed nel */ 
04808                            "le index", 
04809                            SUMA_NODE_INDEX, /* the column's type (description),
04810                                                one of SUMA_COL_TYPE */
04811                            (void *)node, /* the list of node indices */
04812                            NULL  /* that's an optional structure containing 
04813                                     attributes of the added column. 
04814                                     Not used at the moment */
04815                            ,1 /* stride, useful when you need to copy a column
04816                                  from a multiplexed vector. Say you have in p 
04817                                  [rgb rgb rgb rgb], to get the g column you 
04818                                  send in p+1 for the column pointer and a stride
04819                                  of 3 */
04820                            )) {
04821          fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04822          exit(1);                    
04823       }
04824       
04825       NoStride = 0;
04826       if (NoStride) {
04827          /* insert separate r, g and b column */
04828          if (!SUMA_AddNelCol (nel, "le R", SUMA_NODE_R, (void *)r, NULL ,1)) {
04829             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04830             exit(1);
04831          }
04832 
04833          if (!SUMA_AddNelCol (nel, "le G", SUMA_NODE_G, (void *)g, NULL ,1)) {
04834             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04835             exit(1);
04836          }
04837 
04838          if (!SUMA_AddNelCol (nel, "le B", SUMA_NODE_B, (void *)b, NULL ,1)) {
04839             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04840             exit(1);
04841          }
04842       } else {
04843          /* insert from multiplexed rgb vector */
04844          if (!SUMA_AddNelCol (nel, "le R", SUMA_NODE_R, (void *)rgb, NULL ,3 )) {
04845             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04846             exit(1);
04847          }
04848 
04849          if (!SUMA_AddNelCol (nel, "le G", SUMA_NODE_G, (void *)(rgb+1), NULL ,3)) {
04850             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04851             exit(1);
04852          }
04853 
04854          if (!SUMA_AddNelCol (nel, "le B", SUMA_NODE_B, (void *)(rgb+2), NULL ,3)) {
04855             fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04856             exit(1);
04857          }
04858       }
04859       
04860       /* add a string column, just for kicks ..*/
04861       if (!SUMA_AddNelCol (nel, "la string", SUMA_NODE_STRING, (void *)s, NULL, 1)) {
04862          fprintf (stderr,"Error  %s:\nFailed in SUMA_AddNelCol", FuncName);
04863          exit(1);  
04864       }
04865       
04866       /* Test writing results in asc, 1D format */ 
04867          if (LocalHead) fprintf(stderr," %s:-\nWriting ascii 1D ...\n"
04868                         , FuncName);
04869          /* open the stream */
04870          ns = NI_stream_open( "file:Test_write_asc_1D" , "w" ) ;
04871          if( ns == NULL ){
04872            fprintf (stderr,"Error  %s:\nCan't open Test_write_asc_1D!"
04873                         , FuncName); exit(1);
04874          }
04875 
04876          /* write out the element */
04877          if (NI_write_element( ns , nel ,
04878                                NI_TEXT_MODE | NI_HEADERSHARP_FLAG ) < 0) {
04879             fprintf (stderr,"Error  %s:\nFailed in NI_write_element"
04880                            , FuncName);
04881             exit(1);
04882          }
04883 
04884          /* close the stream */
04885          NI_stream_close( ns ) ; 
04886       
04887       /* Test writing results in asc niml format */
04888          if (LocalHead) fprintf(stderr," %s:-\nWriting ascii ...\n"
04889                                        , FuncName);
04890          /* open the stream */
04891          ns = NI_stream_open( "file:Test_write_asc" , "w" ) ;
04892          if( ns == NULL ){
04893            fprintf (stderr,"Error  %s:\nCan't open Test_write_asc!", FuncName);
04894            exit(1);
04895          }
04896 
04897          /* write out the element */
04898          if (NI_write_element( ns , nel , NI_TEXT_MODE ) < 0) {
04899             fprintf (stderr,"Error  %s:\nFailed in NI_write_element", FuncName);
04900             exit(1);
04901          }
04902 
04903          /* close the stream */
04904          NI_stream_close( ns ) ;
04905       
04906       /* Test writing results in binary niml format */
04907          if (LocalHead) fprintf(stderr," %s:-\nWriting binary ...\n"
04908                                        , FuncName);
04909          /* open the stream */
04910          ns = NI_stream_open( "file:Test_write_bin" , "w" ) ;
04911          if( ns == NULL ){
04912             fprintf (stderr,"Error %s:\nCan't open Test_write_bin!"
04913                            , FuncName); exit(1);
04914          }
04915 
04916          /* write out the element */
04917          if (NI_write_element( ns , nel , NI_BINARY_MODE ) < 0) {
04918             fprintf (stderr,"Error %s:\nFailed in NI_write_element"
04919                            , FuncName);
04920             exit(1);
04921          }
04922 
04923          /* close the stream */
04924          NI_stream_close( ns ) ;
04925 
04926          /* free nel */
04927          NI_free_element(nel) ; nel = NULL;
04928        
04929       /* How about loading some data */
04930          ns = NI_stream_open( "file:Test_write_bin" , "r");
04931          nel = NI_read_element(ns,1) ;
04932          /* close the stream */
04933          NI_stream_close( ns ) ;
04934          
04935       /* show me the whole thing. Don't do this for an enormous nel */
04936          SUMA_ShowNel(nel);
04937          
04938       /* What type is it ? */
04939          fprintf (stderr,"\tNel type: %s (%d)\n",  
04940                         nel->name, SUMA_Dset_Type(nel->name));
04941          
04942       /* What are the columns's types and attributes ? */
04943          for (i=0; i < nel->vec_num; ++i) {
04944             sprintf(stmp,"TypeCol_%d", i);
04945             fprintf (stderr,"\tColumn %d's name: %s\n",
04946                      i, NI_get_attribute(nel, stmp));
04947             sprintf(stmp,"attrCol_%d", i);
04948             fprintf (stderr,"\tColumn %d's attribute: %s\n", 
04949                      i, NI_get_attribute(nel, stmp));
04950          }
04951       
04952       /* I want the pointer to the green column but do not know its index */
04953          {   
04954             int j, *iv, N_i;
04955             float *fp;
04956             fprintf (stderr,"---Looking for green column ---\n");
04957             iv = SUMA_GetColIndex (nel, SUMA_NODE_G, &N_i);
04958             if (!iv) {
04959                fprintf (stderr,"Error %s: Failed to find column.\n"
04960                            , FuncName);
04961             } else {
04962                fprintf (stderr,"\t%d columns of type SUMA_NODE_G found.\n",
04963                            N_i);
04964                if (N_i) {
04965                   fprintf (stderr,"\tReporting values at index %d\n", iv[0]);
04966                   fp = (float *)nel->vec[iv[0]]; /* I know we only have one 
04967                                                    such col. here */
04968                   for (j=0; j < nel->vec_len; ++j) {
04969                      fprintf (stderr,"%f, ", fp[j]);
04970                   }
04971                   SUMA_free(iv); iv = NULL;
04972                }
04973             }
04974             
04975                   
04976          }
04977           
04978       /* free nel */
04979       NI_free_element(nel) ; nel = NULL;
04980       
04981       if (LocalHead) fprintf(stderr," %s:-\nFrenching ...\n", FuncName);
04982       
04983       /* free other stuff */
04984       if (r) SUMA_free(r); r = NULL;
04985       if (g) SUMA_free(g); g = NULL;
04986       if (b) SUMA_free(b); b = NULL;
04987       if (rgb) SUMA_free(rgb); rgb = NULL;
04988       if (node) SUMA_free(node); node = NULL;  
04989       if (s) {
04990          for (i=0; i<N_Node; ++i) {
04991             if (s[i]) SUMA_free(s[i]);
04992          }
04993          SUMA_free(s);
04994       } 
04995    } /* END: Test to save a data set with a bunch of node values */
04996         
04997    #ifdef SUMA_COMPILED
04998    if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
04999    #endif
05000      
05001    SUMA_RETURN(0);
05002 }/* Main */
05003 
05004 #endif
05005 
05006 
05007 /*********************** BEGIN Miscellaneous support functions **************************** */
05008 /* A few functions that are useful without having to link and include all of SUMA's structures */
05009  
05010 /*!
05011    \brief load the environment varaibles first from 
05012    $HOME/.sumarc and $HOME/.afnirc
05013    if HOME is not defined then try .afnirc and .sumarc
05014    Shameless wrapper for AFNI_process_environ
05015 
05016    No fanices here, this function is called before CommonFields
05017 */
05018 void SUMA_process_environ(void)
05019 {
05020    static char FuncName[]={"SUMA_process_environ"};
05021    struct stat stbuf;
05022    char *sumarc = NULL, *homeenv=NULL;
05023    SUMA_Boolean LocalHead = NOPE;
05024 
05025    sumarc = (char *)malloc(sizeof(char)*(SUMA_MAX_NAME_LENGTH+SUMA_MAX_DIR_LENGTH+1));
05026 
05027    /* load the environment variables from .sumarc and .afnirc*/
05028    homeenv = getenv("HOME");
05029 
05030    if (!homeenv) sprintf(sumarc, ".sumarc");
05031    else sprintf(sumarc,"%s/.sumarc", homeenv);
05032    if (stat(sumarc, &stbuf) != -1) {
05033       if (LocalHead) fprintf (SUMA_STDERR,"%s: Loading %s ...\n", FuncName, sumarc);
05034       AFNI_process_environ(sumarc); 
05035    } else {
05036       if (LocalHead) fprintf (SUMA_STDERR,"%s: No rc files found.\n", FuncName);
05037    }
05038 
05039    if (!homeenv) sprintf(sumarc, ".afnirc");
05040    else sprintf(sumarc,"%s/.afnirc", homeenv);
05041    if (stat(sumarc, &stbuf) != -1) {
05042       if (LocalHead) fprintf (SUMA_STDERR,"%s: Loading %s ...\n", FuncName, sumarc);
05043       AFNI_process_environ(sumarc); 
05044    } else {
05045       if (LocalHead) fprintf (SUMA_STDERR,"%s: No rc files found.\n", FuncName);
05046    }   
05047 
05048    if (sumarc) free(sumarc); sumarc = NULL; /* allocated before CommonFields */
05049    return;
05050 }
05051 
05052 char *SUMA_help_basics()
05053 {
05054    SUMA_STRING *SS = NULL;
05055    char *s=NULL;
05056    static char FuncName[]={"SUMA_help_basics"};
05057    
05058    SUMA_ENTRY;
05059    
05060    SS = SUMA_StringAppend(NULL, NULL);
05061    SS = SUMA_StringAppend(SS,
05062                   "  Common Debugging Options:\n"
05063                   "   [-trace]: Turns on In/Out debug and Memory tracing.\n"
05064                   "             For speeding up the tracing log, I recommend \n"
05065                   "             you redirect stdout to a file when using this option.\n"
05066                   "             For example, if you were running suma you would use:\n"
05067                   "             suma -spec lh.spec -sv ... > TraceFile\n"
05068                   "             This option replaces the old -iodbg and -memdbg.\n"
05069                   "   [-TRACE]: Turns on extreme tracing.\n"
05070                   "   [-nomall]: Turn off memory tracing.\n"
05071                   "   [-yesmall]: Turn on memory tracing (default).\n"
05072                   "   [-novolreg]: Ignore any Volreg or Tagalign transformations\n"
05073                   "                present in the Surface Volume.\n"
05074                   "  NOTE: For programs that output results to stdout\n"
05075                   "    (that is to your shell/screen), the debugging info\n"
05076                   "    might get mixed up with your results.\n" 
05077                   " \n");
05078    SUMA_SS2S(SS,s);               
05079    SUMA_RETURN(s);
05080 }
05081 
05082 char *SUMA_help_talk()
05083 {
05084    SUMA_STRING *SS = NULL;
05085    char *s=NULL;
05086    static char FuncName[]={"SUMA_help_talk"};
05087    
05088    SUMA_ENTRY;
05089    
05090    SS = SUMA_StringAppend(NULL, NULL);
05091    SS = SUMA_StringAppend(SS,
05092                   "  SUMA communication options:\n"
05093                   "      -talk_suma: Send progress with each iteration to SUMA.\n"
05094                   "      -refresh_rate rps: Maximum number of updates to SUMA per second.\n"
05095                   "                         The default is the maximum speed.\n"
05096                   "      -send_kth kth: Send the kth element to SUMA (default is 1).\n"
05097                   "                     This allows you to cut down on the number of elements\n"
05098                   "                     being sent to SUMA.\n" 
05099                   "      -sh <SumaHost>: Name (or IP address) of the computer running SUMA.\n"
05100                   "                      This parameter is optional, the default is 127.0.0.1 \n"
05101                   "      -ni_text: Use NI_TEXT_MODE for data transmission.\n"
05102                   "      -ni_binary: Use NI_BINARY_MODE for data transmission.\n"
05103                   "                  (default is ni_binary).\n"
05104                   "      -feed_afni: Send updates to AFNI via SUMA's talk.\n"
05105                   "\n");
05106    SUMA_SS2S(SS,s);               
05107    SUMA_RETURN(s);
05108 }
05109 
05110 /*!
05111    \brief parse command line arguments for input/output debugging and
05112    memory debugging. Use no fancies in this function!
05113    
05114    This function is to be called after SUMAg_CF has been created,
05115    if #ifdef SUMA_COMPILED 
05116    
05117    Default for iotrace = 0
05118                memtrace = 1 
05119    Those defaults are common to all apps 
05120    
05121 */
05122 void SUMA_ParseInput_basics (char *argv[], int argc) 
05123 {
05124 
05125    static char FuncName[]={"SUMA_ParseInput_basics"};
05126    int brk = 0;
05127    int kar, Domemtrace, Doiotrace;
05128 
05129    if (!argv) return;
05130    if (argc < 2) return;
05131 
05132    kar = 1;
05133    brk = 0;
05134    Domemtrace = 1;
05135    Doiotrace = 0;
05136    while (kar < argc) { /* loop accross tracing and debugging command line options */
05137                 if ((strcmp(argv[kar], "-memdbg") == 0) ||
05138           (strcmp(argv[kar], "-yesmall") == 0) ) {
05139                         fprintf(SUMA_STDOUT,"Warning %s:  running in memory trace mode.\n", FuncName);
05140                         Domemtrace = 1;
05141          brk = 1;
05142                 }
05143       
05144       if (!brk && (strcmp(argv[kar], "-nomall") == 0)) {
05145                         fprintf(SUMA_STDOUT,"Warning %s:  turning off memory trace mode.\n", FuncName);
05146                         Domemtrace = 0;
05147                         brk = 1;
05148                 }
05149 
05150       if (!brk && ( (strcmp(argv[kar], "-trace") == 0) ||
05151                    (strcmp(argv[kar], "-iodbg") == 0)) ){
05152                         fprintf(SUMA_STDERR,"Warning %s: SUMA running in I/O trace mode.\n", FuncName);
05153                         Doiotrace = 1;
05154          brk = 1;
05155                 }
05156       
05157       if (!brk && (strcmp(argv[kar], "-TRACE") == 0)) {
05158                         fprintf(SUMA_STDERR,"Warning %s: SUMA running in detailed I/O trace mode.\n", FuncName);
05159                         Doiotrace = 2;
05160          brk = 1;
05161                 }
05162       
05163       if (!brk && (strcmp(argv[kar], "-novolreg") == 0)) {
05164                         SUMA_IGNORE_VOLREG;
05165          brk = 1;
05166                 }
05167       
05168       brk = 0;
05169       kar ++;
05170    }
05171     
05172    if (Doiotrace) { SUMA_INOUT_NOTIFY_ON; } 
05173    if (Domemtrace) { SUMA_MEMTRACE_ON; }
05174 
05175    /* some more special ones */
05176    #ifdef USE_TRACING
05177       if (Doiotrace == 2) { DBG_trace = 2; } 
05178    #endif
05179    
05180    return;
05181 }
05182 
05183 
05184 /*!**
05185    
05186 Purpose : 
05187    
05188    splits a path/filename into its path and filename components
05189    
05190 Usage : 
05191                 Ans = SUMA_StripPath (Name)
05192    
05193    
05194 Input paramters : 
05195 \param   Name (char *) something like /hello/something
05196    
05197 Returns : 
05198 \return   ans (SUMA_FileName) .Path (char *) and .FileName (char *)
05199    
05200 Support : 
05201 \sa  SUMA_define.h 
05202 
05203 NOTE: SUMA_ParseFname() is better than this function    
05204    
05205 To Compile as stand alone:
05206 gcc -DSUMA_StripPath_STAND_ALONE -Wall -o $1 $1.c -SUMA_lib.a -I/usr/X11R6/include -I./
05207 ***/
05208 SUMA_FileName SUMA_StripPath (char *FileName)
05209 {/*SUMA_StripPath*/
05210    static char FuncName[] = {"SUMA_StripPath"},  PathDelimiter[]={"/"}; 
05211    int i, j, NotFound=1, N_FileName;
05212         SUMA_FileName NewName;
05213         
05214         N_FileName = strlen(FileName);
05215         if (N_FileName ){
05216                 i = N_FileName -1;
05217                 while (i > -1 && NotFound) {
05218                         if (FileName[i] == PathDelimiter[0]) NotFound = 0;
05219                         --i;
05220                 }
05221                 if (!NotFound && i > -1) {
05222                         NewName.Path = (char *)SUMA_malloc(sizeof(char)*(N_FileName+1));
05223                         NewName.FileName = (char *)SUMA_malloc(sizeof(char)*(N_FileName+1));
05224                         if (NewName.Path == NULL || NewName.FileName == NULL) {
05225                                 SUMA_SL_Err("Failed to allocate");
05226             return (NewName);
05227                         }
05228                         for (j=0; j<=i+1; ++j) {
05229                                 NewName.Path[j] = FileName[j];
05230                         }
05231          NewName.Path[j] = '\0';
05232          
05233                         /*fprintf(stdout,"jbegin=%d/%d\n", i+2, N_FileName);*/
05234                         for (j=i+2; j < N_FileName; ++j) NewName.FileName[j-i-2] = FileName[j];
05235          NewName.FileName[j-i-2] = '\0';
05236          
05237                         /* fprintf(stdout,"All Path (%d chars)/%d: %s\n", (i+2),  strlen(NewName.Path), NewName.Path);
05238                         fprintf(stdout,"All FileName (%d chars)/%d: %s\n", (N_FileName-i-2), strlen(NewName.FileName), NewName.FileName); */
05239                 }
05240                 else {
05241                         NewName.Path = (char *)SUMA_malloc(sizeof(char)*(N_FileName+1));
05242                         NewName.FileName = (char *)SUMA_malloc(sizeof(char)*(N_FileName+1));
05243                         if (NewName.Path == NULL || NewName.FileName == NULL) {
05244                                 SUMA_SL_Err("Failed to allocate");
05245             return (NewName);
05246                         }
05247                         sprintf(NewName.Path,"./");             
05248                         sprintf(NewName.FileName,"%s", FileName);
05249                 }
05250         }
05251         else {
05252                 NewName.Path = NULL;
05253                 NewName.FileName = NULL;
05254         }
05255         return (NewName);
05256 }/*SUMA_StripPath*/
05257 
05258 /*!
05259    \brief ans = SUMA_ParseFname (FileName);
05260    parses a file name into its elements
05261    \param FileName (char *) obvious ...
05262    \return ans (SUMA_PARSED_NAME *) pointer to structure with following fields:
05263       .FileName (char *) containing filename without path. 
05264                         if empty .FileName[0] = '\0'
05265       .Path (char *) containing path including last slash.
05266                      If no path exists, Path is "./" 
05267       .Ext (char *) containing extension including the dot.
05268                     If no extension exists, Ext[0] = '\0'
05269       .FileName_NoExt (char *) filename without extension.
05270       
05271       \sa SUMA_Free_Parsed_Name
05272 */
05273 SUMA_PARSED_NAME * SUMA_ParseFname (char *FileName)
05274 {/*SUMA_ParseFname*/
05275    static char FuncName[]={"SUMA_ParseFname"};
05276    char PathDelimiter='/'; 
05277    int i, j, iExt , iFile, iPath, N_FileName;
05278         SUMA_PARSED_NAME *NewName = NULL;
05279    SUMA_Boolean FoundPath = NOPE, FoundExt, FoundFile;
05280         
05281    SUMA_ENTRY;
05282 
05283 
05284         N_FileName = strlen(FileName);
05285    iExt = N_FileName;
05286    iPath = -1;
05287    iFile = 0;
05288    FoundPath = NOPE;
05289    FoundExt = NOPE;
05290         if (N_FileName ){
05291                 NewName = (SUMA_PARSED_NAME *) SUMA_malloc(sizeof(SUMA_PARSED_NAME));
05292       
05293       i = N_FileName -1;
05294                 while (i > -1 && !FoundPath) {
05295                         if (FileName[i] == '.' && !FoundExt) {
05296             iExt = i;
05297             FoundExt = YUP;
05298          } else if (FileName[i] == PathDelimiter) {
05299             FoundPath = YUP;
05300             iPath = i;
05301             iFile = i+1;
05302          }
05303                         --i;
05304                 }
05305       
05306       if (iFile == iExt) {
05307          /* .file, not an extension */
05308          FoundExt = NOPE;
05309       }
05310       
05311       if (iFile ==  N_FileName) FoundFile = NOPE;
05312       else FoundFile = YUP;
05313       
05314       if (FoundPath) {
05315          NewName->Path = (char *)SUMA_malloc(sizeof(char)*(iPath+2));
05316          for (i=0; i<= iPath; ++i) NewName->Path[i] = FileName[i];
05317          NewName->Path[i] = '\0';
05318       }else {
05319          NewName->Path = (char *)SUMA_malloc(sizeof(char)*(3));
05320          sprintf(NewName->Path, "./");
05321       }
05322       
05323       if (FoundFile) {
05324          NewName->FileName = (char *)SUMA_malloc(sizeof(char)*(N_FileName - iFile + 2));
05325          for (i=iFile; i< N_FileName; ++i) NewName->FileName[i-iFile] = FileName[i];
05326          NewName->FileName[i-iFile] = '\0';
05327       }else {
05328          NewName->FileName = (char *)SUMA_malloc(sizeof(char));
05329          NewName->FileName[0] = '\0';
05330       }      
05331                 
05332       if (FoundExt) {
05333                    NewName->FileName_NoExt = (char *)SUMA_malloc(sizeof(char)*(N_FileName - iFile +2));
05334          NewName->Ext = (char *)SUMA_malloc(sizeof(char)*(N_FileName - iExt+2));
05335          for (i=iFile; i< iExt; ++i) NewName->FileName_NoExt[i-iFile] = FileName[i];
05336          NewName->FileName_NoExt[i-iFile] = '\0';
05337          for (i=iExt; i < N_FileName; ++i) NewName->Ext[i-iExt] = FileName[i];
05338          NewName->Ext[i-iExt] = '\0';
05339       } else {
05340          NewName->FileName_NoExt = (char *)SUMA_malloc(sizeof(char));
05341          NewName->Ext = (char *)SUMA_malloc(sizeof(char));
05342          NewName->FileName_NoExt[0] = '\0';
05343          NewName->Ext[0] = '\0';
05344       }
05345       
05346         }
05347    
05348         SUMA_RETURN (NewName);
05349 }/*SUMA_ParseFname*/
05350 
05351 /*!
05352    \brief ans = SUMA_isExtension(filename, ext);
05353       YUP if filename has the extension ext
05354 */
05355 SUMA_Boolean SUMA_isExtension(char *filename, char *ext)
05356 {
05357    static char FuncName[]={"SUMA_isExtension"}; 
05358    int cnt, N_ext, N_filename;
05359       
05360    SUMA_ENTRY;
05361 
05362    if (!filename) SUMA_RETURN(NOPE);
05363    if (!ext) SUMA_RETURN(NOPE);
05364    N_ext = strlen(ext);
05365    N_filename = strlen(filename);
05366    if (N_ext > N_filename) SUMA_RETURN(NOPE);
05367 
05368    cnt = 1;
05369    while (cnt <= N_ext) {
05370       if (filename[N_filename-cnt] != ext[N_ext-cnt]) SUMA_RETURN(NOPE);
05371       ++cnt; 
05372    } 
05373    
05374    SUMA_RETURN(YUP);
05375 }
05376 
05377 /*!
05378    \brief ans = SUMA_Extension(filename, ext, Remove);
05379       removes or enforces an arbitrary extension from/to a filename
05380    
05381    \param filename(char *) input filename
05382    \param ext (char *) extension
05383    \param Remove (SUMA_Boolean) YUP = Remove extension if found
05384                                       Do nothing if it is not there already 
05385                                 NOPE = Add extension if not there
05386                                        Do nothing if it is there already    
05387    \returns ans (char*) containing modified filename 
05388   
05389    - You must free ans on your own
05390    Examples:
05391       {
05392       char *ans=NULL;
05393       ans = SUMA_Extension("Junk.niml.roi", ".niml.roi", YUP);
05394       SUMA_LH(ans); SUMA_free(ans);
05395       
05396       ans = SUMA_Extension("Junk.niml.roi", ".niml.roi", NOPE);
05397       SUMA_LH(ans); SUMA_free(ans);
05398       
05399       ans = SUMA_Extension("Junk.niml.roi", ".niml.roxi", NOPE);
05400       SUMA_LH(ans); SUMA_free(ans);
05401       
05402       ans = SUMA_Extension("Junk.niml.roi", ".niml.roxi", YUP);
05403       SUMA_LH(ans); SUMA_free(ans);
05404       
05405       ans = SUMA_Extension("Junk.niml.roi", "", YUP);
05406       SUMA_LH(ans); SUMA_free(ans);
05407       
05408       ans = SUMA_Extension(".roi", "Junk.niml.roi", NOPE);
05409       SUMA_LH(ans); SUMA_free(ans);
05410       
05411       ans = SUMA_Extension("", "", NOPE);
05412       SUMA_LH(ans); SUMA_free(ans);
05413       
05414       exit(1);
05415     }
05416 
05417 */
05418 
05419 char *SUMA_Extension(char *filename, char *ext, SUMA_Boolean Remove)
05420 {
05421    static char FuncName[]={"SUMA_Extension"}; 
05422    char *ans = NULL;
05423    int i, next, nfilename, ifile;
05424    SUMA_Boolean NoMatch = NOPE, LocalHead = NOPE;
05425    
05426    SUMA_ENTRY;
05427 
05428    if (!filename) SUMA_RETURN(NULL);
05429    nfilename = strlen(filename);
05430    
05431    if (!ext) {
05432       ans = (char *)SUMA_malloc((nfilename+1)*sizeof(char));
05433       ans = strcpy(ans,filename);
05434       SUMA_RETURN(ans);
05435    }
05436    next = strlen(ext);
05437    
05438    #if 0
05439    if (nfilename < next || next < 1 || nfilename < 1) {
05440       ans = (char *)SUMA_malloc((nfilename+1)*sizeof(char));
05441       ans = strcpy(ans,filename);
05442       SUMA_RETURN(ans);
05443    }
05444    #endif
05445    
05446    ifile = nfilename - next;
05447    NoMatch = NOPE;
05448    i = 0;
05449    do {
05450       if (LocalHead) fprintf (SUMA_STDERR,"%s: Comparing %c %c\n", FuncName, filename[ifile+i], ext[i]);
05451       if (filename[ifile+i] != ext[i]) NoMatch = YUP;
05452       ++i;
05453    }  while (ifile < nfilename && i < next && !NoMatch);
05454 
05455    if (NoMatch) {
05456       if (Remove) { /* nothing to do */
05457          SUMA_LH("NoMatch, nothing to do");
05458          ans = (char *)SUMA_malloc((nfilename+1)*sizeof(char));
05459          ans = strcpy(ans,filename);
05460          SUMA_RETURN(ans);
05461       } else { /* add extension */
05462          SUMA_LH("NoMatch, adding extensio");
05463          ans = (char *)SUMA_malloc((nfilename+next+1)*sizeof(char));
05464          sprintf(ans,"%s%s", filename, ext);
05465          SUMA_RETURN(ans);
05466       }
05467    }else {
05468       if (Remove) { /* remove it */
05469          SUMA_LH("Match, removing extension");
05470          ans = (char *)SUMA_malloc((nfilename - next+2)*sizeof(char));
05471          for (i=0; i< nfilename - next; ++i)  ans[i] = filename[i];
05472          ans[nfilename - next] = '\0'; /* for good measure */
05473       } else { /* nothing to do */
05474          SUMA_LH("Match, nothing to do");
05475          ans = (char *)SUMA_malloc((nfilename+1)*sizeof(char));
05476          ans = strcpy(ans,filename);
05477          SUMA_RETURN(ans);
05478       }
05479    }
05480    
05481    SUMA_RETURN (ans);
05482 
05483 }   
05484 void *SUMA_Free_Parsed_Name(SUMA_PARSED_NAME *Test) 
05485 {
05486    static char FuncName[]={"SUMA_Free_Parsed_Name"}; 
05487 
05488    SUMA_ENTRY;
05489 
05490    if (!Test) SUMA_RETURN (NULL);
05491    if (Test->Path) SUMA_free(Test->Path);
05492    if (Test->FileName) SUMA_free(Test->FileName);
05493    if (Test->Ext) SUMA_free(Test->Ext);
05494    if (Test->FileName_NoExt) SUMA_free(Test->FileName_NoExt);
05495    SUMA_free(Test);
05496    
05497    SUMA_RETURN (NULL);
05498 }
05499 
05500 
05501 /*! Taken from filexists 
05502 returns 1 if file can be read/found
05503 */
05504 int SUMA_filexists (char *f_name)
05505 {/*SUMA_filexists*/
05506     FILE *outfile;
05507     static char FuncName[]={"SUMA_filexists"};
05508    
05509    SUMA_ENTRY;
05510 
05511     outfile = fopen (f_name,"r");
05512     if (outfile == NULL) {
05513        SUMA_RETURN(0); 
05514    }
05515     else {
05516        fclose (outfile); 
05517    }
05518     
05519    SUMA_RETURN(1);
05520        
05521 }/*SUMA_filexists*/
05522 
05523 
05524 /*!
05525    \brief function that tests whether a string contains N numbers
05526    
05527    \param str (char *) null terminated string
05528    \param N (void *) This is an integer in disguise
05529    \return 1: If str is NULL or N numbers were found in str
05530 */
05531 int SUMA_isNumString (char *s, void *p)
05532 {
05533    static char FuncName[]={"SUMA_isNumString"};
05534    char *endp, *strtp;
05535    int nd, N;
05536    int eos, FoundTip;
05537    double d;
05538    int LocalHead = 0;
05539    
05540    SUMA_ENTRY;
05541    
05542    if (!s) SUMA_RETURN(1); 
05543    
05544    N = (int)p;
05545    
05546    /* clean s by removing trailing junk then replacing non characters by space*/
05547    FoundTip = 0;
05548    for (nd=strlen(s)-1; nd >=0; --nd) {
05549       if (!isdigit(s[nd]) && s[nd] != '.'  && s[nd] != '-' && s[nd] != '+') {
05550          if (!FoundTip) {
05551             s[nd]= '\0'; /* remove */
05552          } else {
05553             s[nd] = ' '; /* blank */
05554          }
05555       }else {
05556          FoundTip = 1;
05557       }
05558    }
05559    
05560    if (LocalHead) fprintf (stderr, "%s: string now:%s:\n", FuncName, s);
05561    
05562    /* parse s */
05563    strtp = s;
05564    endp = NULL;
05565    nd = 0;
05566    eos = 0;
05567    while (!eos) {
05568       d = strtod(strtp, &endp);
05569       if (LocalHead) fprintf (stderr, "%s: value %f, ERANGE: %d, EDOM %d, errno %d\n", FuncName, d, ERANGE, EDOM, errno); 
05570       
05571 
05572       if (endp == strtp && *endp=='\0') { 
05573          eos = 1;
05574       } else {
05575          strtp = endp;
05576          ++nd;
05577          if (nd > N && nd > 1000) {
05578             SUMA_SL_Err("Fishy fish");
05579             fprintf (stderr, "%s: >>>%s<<<", FuncName, s);
05580             SUMA_RETURN(0);
05581          }
05582       }
05583    }
05584    
05585    if (LocalHead) fprintf (stderr,"%s: Read %d/%d values.\n", FuncName, nd,N);
05586    if (N != nd) {
05587       SUMA_RETURN(0);
05588    } else {
05589       SUMA_RETURN(1);
05590    }
05591    
05592 }   
05593 
05594 /*!
05595    \brief function that parses a string of numbers into a float vector
05596    
05597    \param str (char *) null terminated string
05598    \param fv (float*) vector where values will be stored
05599    \param N (int) This is the number of values desired
05600    \return int: This is the number of values read. 
05601       The function will not register in fv more than N values 
05602       (to keep from running over preallocated space), but it
05603       will return the full number of values found.
05604       
05605       -1 in case of error
05606    \sa SUMA_isNumString
05607    \sa SUMA_strtol_vec
05608    \sa SUMA_AdvancePastNumbers
05609 */
05610 int SUMA_StringToNum (char *s, float *fv, int N)
05611 {
05612    static char FuncName[]={"SUMA_StringToNum"};
05613    char *endp, *strtp;
05614    int nd;
05615    int eos, FoundTip;
05616    double d;
05617    int LocalHead = 0;
05618    
05619    SUMA_ENTRY;
05620    
05621    if (!s) SUMA_RETURN(0); 
05622      
05623    /* clean s by removing trailing junk then replacing non characters by space*/
05624    FoundTip = 0;
05625    for (nd=strlen(s)-1; nd >=0; --nd) {
05626       if (!isdigit(s[nd]) && s[nd] != '.' && s[nd] != '-' && s[nd] != '+') {
05627          if (!FoundTip) {
05628             s[nd]= '\0'; /* remove */
05629          } else {
05630             s[nd] = ' '; /* blank */
05631          }
05632       }else {
05633          FoundTip = 1;
05634       }
05635    }
05636    
05637    if (LocalHead) fprintf (stderr, "%s: string now:%s:\n", FuncName, s);
05638    
05639    /* parse s */
05640    strtp = s;
05641    endp = NULL;
05642    nd = 0;
05643    eos = 0;
05644    while (!eos) {
05645       d = strtod(strtp, &endp);
05646       if (LocalHead) fprintf (stderr, "%s: value %f, ERANGE: %d, EDOM %d, errno %d\n", FuncName, d, ERANGE, EDOM, errno); 
05647       
05648       if (endp == strtp && *endp=='\0') { 
05649          eos = 1;
05650       } else {
05651          if (nd < N) fv[nd] = (float)d;
05652          strtp = endp;
05653          ++nd;
05654          if (nd > N && nd >1000) {
05655             SUMA_SL_Err("Something's fishy");
05656             fprintf (stderr, "s = >>>%s<<<\nnd = %d\n", s, nd);
05657             SUMA_RETURN(-1);
05658          }
05659       }
05660    }
05661    
05662    if (LocalHead) fprintf (stderr,"%s: Read %d/%d values.\n", FuncName, nd, N);
05663    
05664    SUMA_RETURN(nd);
05665    
05666 }   
05667 
05668 /*!
05669    \brief forces a string to be of a certain length.
05670    If truncation is necessary, ... are inserted at 
05671    the end of the string.
05672    
05673    You need to free the returned pointer
05674 */
05675 char *SUMA_set_string_length(char *buf, char cp, int n)
05676 {
05677    static char FuncName[]={"SUMA_set_string_length"};
05678    char *lbl=NULL, *lbl30=NULL;
05679    
05680    SUMA_ENTRY;
05681    
05682    if (!buf) SUMA_RETURN(NULL);
05683    
05684    lbl = SUMA_truncate_string (buf, n);
05685    if (!lbl) {
05686       SUMA_SL_Err("Failed to truncate");
05687       SUMA_RETURN(NULL);
05688    }
05689          
05690    if (strlen(lbl) != n) {
05691       lbl30 = SUMA_pad_string(lbl, ' ', n, 1); 
05692       SUMA_free(lbl); lbl = NULL;
05693    } else {
05694       lbl30 = lbl; lbl = NULL;
05695    }
05696    
05697    SUMA_RETURN(lbl30);
05698 }
05699 
05700 /*!
05701    \brief padds a string to a certain length.
05702    You can use this function to crop a string to 
05703    the specified number of characters n
05704    Padding is done with character cp
05705    The original string is not modified.
05706     
05707    s_tr = SUMA_pad_string(s1, cp, n, add2end);
05708    
05709    \sa SUMA_pad_str
05710    \sa SUMA_truncate_string
05711    - free returned pointer with: if(s_tr) SUMA_free(s_tr);
05712 */
05713 char *SUMA_pad_string(char *buf, char cp, int n, int add2end)
05714 {
05715    static char FuncName[]={"SUMA_pad_string"};
05716    char *atr = NULL;
05717    int i, ib, nb;
05718    SUMA_Boolean LocalHead = NOPE;
05719    
05720    SUMA_ENTRY;
05721    
05722    if (!buf) SUMA_RETURN(NULL);
05723    
05724    atr = (char *) SUMA_calloc(n+2, sizeof(char));
05725    nb = strlen(buf);
05726    
05727    if (add2end) { /* add to end */
05728       i=0;
05729       while (i < n) {
05730          if (i<nb) atr[i] = buf[i];
05731          else atr[i] = cp;
05732          ++i;
05733       }
05734       atr[i] = '\0';
05735    } else {
05736       atr[n] = '\0';
05737       i = n -1; 
05738       ib = nb - 1;
05739       while (i >= 0) {
05740          if (ib >=0) atr[i] = buf[ib];
05741          else atr[i] = cp;
05742          --i; --ib;
05743       }
05744       
05745    }
05746    
05747    if (LocalHead) {
05748       fprintf(SUMA_STDERR,"%s:\nin\t:%s:\nout\t:%s:\n", FuncName, buf, atr);
05749    }
05750    SUMA_RETURN(atr);  
05751 }
05752 
05753 /*!
05754    \brief truncates a string to a certain length.
05755    Adds ... as the last characters of the string
05756    The original string is not modified.
05757     
05758    s_tr = SUMA_truncate_string(s1, n);
05759    
05760    - free returned pointer with: if(s_tr) SUMA_free(s_tr);
05761 */
05762 char *SUMA_truncate_string(char *buf, int n)
05763 {
05764    static char FuncName[]={"SUMA_truncate_string"};
05765    char *atr = NULL;
05766    int i;
05767 
05768    SUMA_ENTRY;
05769    
05770    if (!buf) SUMA_RETURN(NULL);
05771    
05772    if (n < 5) {
05773       fprintf(stderr,"Error %s:\nNot worth the effort. N < 5.", FuncName);
05774       SUMA_RETURN(NULL);
05775    }
05776    
05777    if (strlen(buf) <= n) {
05778       atr = (char *) SUMA_calloc(strlen(buf)+2, sizeof(char));
05779       sprintf(atr, "%s", buf);
05780       SUMA_RETURN (atr);
05781    }else {
05782       atr = (char *) SUMA_calloc(n+3, sizeof(char));
05783       i=0;
05784       while (i < n - 3) {
05785          atr[i] = buf[i];
05786          ++i;
05787       }
05788       atr[i] = atr[i+1] = atr[i+2] = '.';
05789       atr[i+3] = '\0';
05790    }
05791    
05792    SUMA_RETURN(atr);  
05793 }
05794 
05795 /*!
05796    \brief returns a copy of a null terminated string . 
05797    s_cp = SUMA_copy_string(s1);
05798    
05799    - free returned pointer with: if(s_cp) SUMA_free(s_cp);
05800 */
05801 char *SUMA_copy_string(char *buf)
05802 {
05803    static char FuncName[]={"SUMA_copy_string"};
05804    char *atr = NULL;
05805    int i;
05806    
05807    SUMA_ENTRY;
05808    
05809    if (!buf) SUMA_RETURN(NULL);
05810    
05811    atr = (char *) SUMA_calloc(strlen(buf)+2, sizeof(char));
05812    
05813    i=0;
05814    while (buf[i]) {
05815       atr[i] = buf[i];
05816       ++i;
05817    }
05818    atr[i] = '\0';
05819    
05820    SUMA_RETURN(atr);  
05821 }
05822 
05823 /*!
05824    \brief appends two null terminated strings.
05825    
05826    s_ap = SUMA_append_string(s1, s2);
05827   
05828    - s1 and s2 are copied into a new string
05829    -free returned pointer with:  if(s_ap) SUMA_free(s_ap);
05830    - None of the strings passed to the function
05831    are freed.
05832    
05833    \sa SUMA_append_replace_string
05834 */
05835 char * SUMA_append_string(char *s1, char *s2)
05836 {
05837    static char FuncName[]={"SUMA_append_string"};
05838    char *atr = NULL;
05839    int i,cnt, N_s2, N_s1;
05840 
05841    
05842    SUMA_ENTRY;
05843    
05844    if (!s1 && !s2) SUMA_RETURN(NULL);
05845    if (!s1) N_s1 = 0;
05846    else N_s1 = strlen(s1);
05847    
05848    if (!s2) N_s2 = 0;
05849    else N_s2 = strlen(s2);
05850    
05851    atr = (char *) SUMA_calloc(N_s1+N_s2+2, sizeof(char));
05852    
05853    /* copy first string */
05854    cnt = 0;
05855    if (N_s1){
05856       i=0;
05857       while (s1[i]) {
05858          atr[cnt] = s1[i];
05859          ++i;
05860          ++cnt;
05861       }
05862    }   
05863    if (N_s2) {
05864       i=0;
05865       while (s2[i]) {   
05866          atr[cnt] = s2[i];
05867          ++i;
05868          ++cnt;
05869       }
05870    }
05871    atr[cnt] = '\0';
05872    
05873    SUMA_RETURN(atr);  
05874 }    
05875 
05876 
05877 /*!
05878    \brief appends two null terminated strings.
05879    
05880    s_ap = SUMA_append_replace_string(s1, s2, spc, whichTofree);
05881   
05882   \param s1 (char *) string 1
05883   \param s2 (char *) string 2
05884   \param spc (char *) spacing string
05885   \param whichTofree (int) 0 free none, 
05886                            1 free s1
05887                            2 free s2
05888                            3 free s1 and s2
05889    \return s_ap (char *) a string formed by "%s%s%s", s1, spc, s2
05890    
05891    - s1 and s2 are copied into a new string with spc in between
05892    - s1 (but not s2 or spc ) IS FREED inside this function
05893    -free returned pointer with:  if(s_ap) SUMA_free(s_ap);
05894    
05895    \sa SUMA_append_string
05896 */
05897 char * SUMA_append_replace_string(char *s1, char *s2, char *Spc, int whichTofree)
05898 {
05899    static char FuncName[]={"SUMA_append_replace_string"};
05900    char *atr = NULL;
05901    int i,cnt, N_s2, N_s1, N_Spc=0;
05902 
05903    
05904    SUMA_ENTRY;
05905    
05906    if (!s1 && !s2) SUMA_RETURN(NULL);
05907    
05908    if (!s1) N_s1 = 0;
05909    else N_s1 = strlen(s1);
05910    
05911    if (!s2) N_s2 = 0;
05912    else N_s2 = strlen(s2);
05913    
05914    if (!Spc) N_Spc = 0;
05915    else N_Spc = strlen(Spc);
05916    
05917    atr = (char *) SUMA_calloc(N_s1+N_s2+N_Spc+2, sizeof(char));
05918    
05919    /* copy first string */
05920    i=0;
05921    cnt = 0;
05922    if (s1) {
05923       while (s1[i]) {
05924          atr[cnt] = s1[i];
05925          ++i;
05926          ++cnt;
05927       }
05928    }
05929      
05930    i=0;
05931    if (Spc) {
05932       while (Spc[i]) {
05933          atr[cnt] = Spc[i];
05934          ++i;
05935          ++cnt;
05936       }
05937    }
05938    
05939    i=0;
05940    if (s2) {
05941       while (s2[i]) {   
05942          atr[cnt] = s2[i];
05943          ++i;
05944          ++cnt;
05945       }
05946    }
05947    atr[cnt] = '\0';
05948    
05949    switch (whichTofree) {
05950       case 0:
05951          break;
05952       case 1:
05953          if (s1) free(s1);
05954          break;
05955       case 2:
05956          if (s2) free(s2);
05957          break;
05958       case 3:
05959          if (s1) free(s1);
05960          if (s2) free(s2);
05961          break;
05962       default: 
05963          fprintf(stderr, "Error %s:\nBad freeing parameter\n"
05964                          "No variables were freed.\n",
05965                          FuncName);
05966          break;
05967    }  
05968 
05969    SUMA_RETURN(atr);  
05970 }    
05971 
05972 /*!
05973    \brief Appends newstring to string in SS->s while taking care of resizing space allocated for s
05974    
05975    \param SS (SUMA_STRING *) pointer to string structure
05976    \param newstring (char *) pointer to string to add to SS
05977    \return SS (SUMA_STRING *) pointer to string structure with SS->s now containing newstring
05978    - When SS is null, 1000 characters are allocated for s (initialization) and s[0] = '\0';
05979    - When newstring is NULL, space allocated for SS->s is resized to the correct dimension and 
05980    a null character is placed at the end.
05981    \sa SUMA_SS2S
05982 */
05983 SUMA_STRING * SUMA_StringAppend (SUMA_STRING *SS, char *newstring)
05984 {
05985    static char FuncName[]={"SUMA_StringAppend"};
05986    int N_inc = 0, N_cur = 0;
05987    int N_chunk = 1000;
05988    SUMA_Boolean LocalHead = NOPE;
05989    
05990    SUMA_ENTRY;
05991    
05992    if (!SS) {
05993       if (LocalHead) fprintf (SUMA_STDERR, "%s: Allocating for SS.\n", FuncName);
05994       SS = (SUMA_STRING *) SUMA_malloc (sizeof(SUMA_STRING));
05995       SS->s = (char *) SUMA_calloc (N_chunk, sizeof(char));
05996       SS->s[0] = '\0';
05997       SS->N_alloc = N_chunk;
05998       SUMA_RETURN (SS);
05999    }
06000    
06001    if (newstring) {
06002       if (LocalHead) fprintf (SUMA_STDERR, "%s: Appending to SS->s.\n", FuncName);
06003       N_inc = strlen (newstring);
06004       N_cur = strlen (SS->s);
06005       if (SS->N_alloc < N_cur+N_inc+1) { /* must reallocate */
06006          if (LocalHead) fprintf (SUMA_STDERR, "%s: Must reallocate for SS->s.\n", FuncName);
06007          SS->N_alloc = N_cur+N_inc+N_chunk+1;
06008          SS->s = (char *)SUMA_realloc (SS->s, sizeof(char)*SS->N_alloc);
06009          if (!SS->s) {
06010             fprintf (SUMA_STDERR, "Error %s: Failed to reallocate for s.\n", FuncName);
06011             SUMA_RETURN (NULL);
06012          }
06013       }
06014       /* append */
06015       sprintf (SS->s, "%s%s", SS->s, newstring);
06016    }else {
06017       /* shrink SS->s to small size */
06018       N_cur = strlen (SS->s);
06019       if (SS->N_alloc > N_cur+1) {
06020          if (LocalHead) fprintf (SUMA_STDERR, "%s: Shrink realloc for SS->s.\n", FuncName);
06021          SS->N_alloc = N_cur+1;
06022          SS->s = (char *)SUMA_realloc (SS->s, sizeof(char)*SS->N_alloc);
06023          if (!SS->s) {
06024             fprintf (SUMA_STDERR, "Error %s: Failed to reallocate for s.\n", FuncName);
06025             SUMA_RETURN (NULL);
06026          }
06027          /*put a null at the end */
06028          SS->s[SS->N_alloc-1] = '\0';
06029       }
06030    }
06031    
06032    SUMA_RETURN (SS);
06033 
06034 }
06035 
06036 /*!
06037    \brief Appends newstring to string in SS->s while taking care of resizing space allocated for s
06038    A variable argument version of SUMA_StringAppend
06039    
06040    \param SS (SUMA_STRING *) pointer to string structure
06041    \param newstring (char *) pointer to string to add to SS
06042    \param ..... the remaining parameters a la printf manner
06043    \return SS (SUMA_STRING *) pointer to string structure with SS->s now containing newstring
06044    - When SS is null, 1000 characters are allocated for s (initialization) and s[0] = '\0';
06045    - When newstring is NULL, space allocated for SS->s is resized to the correct dimension and 
06046    a null character is placed at the end.
06047    
06048    - For this function, the formatted length of newstring should not be > than MAX_APPEND-1 
06049    If that occurs, the string will be trunctated and no one should get hurt
06050    
06051    NOTE: DO NOT SEND NULL pointers in the variable argument parts or crashes will occur on SUN
06052    Such NULL pointers do not result in null vararg_ptr and cause a seg fault in vsnprintf
06053    
06054    \sa SUMA_StringAppend
06055    \sa SUMA_SS2S
06056 */
06057 
06058 #define MAX_APPEND 3000
06059 
06060 SUMA_STRING * SUMA_StringAppend_va (SUMA_STRING *SS, char *newstring, ... )
06061 {
06062    static char FuncName[]={"SUMA_StringAppend_va"};
06063    char sbuf[MAX_APPEND];
06064    int nout;
06065    va_list vararg_ptr ;
06066    SUMA_Boolean LocalHead = NOPE;
06067    
06068    SUMA_ENTRY;
06069    
06070    if (!SS) {
06071       SUMA_LH("NULL SS");
06072       /* let the other one handle this */
06073       SUMA_RETURN (SUMA_StringAppend(SS,newstring));
06074    }
06075    
06076    if (newstring) {
06077       SUMA_LH("newstring ...");
06078       /* form the newstring and send it to the olde SUMA_StringAppend */
06079       va_start( vararg_ptr ,  newstring) ;
06080       if (strlen(newstring) >= MAX_APPEND -1 ) {
06081          SUMA_SL_Err("newstring too long.\nCannot use SUMA_StringAppend_va");
06082          SUMA_RETURN(SUMA_StringAppend(SS,"Error SUMA_StringAppend_va: ***string too long to add ***"));
06083       }
06084       if (LocalHead) {
06085          SUMA_LH("Calling vsnprintf");
06086          if (vararg_ptr) {
06087             SUMA_LH("Non NULL vararg_ptr");
06088          } else {
06089             SUMA_LH("NULL vararg_ptr");
06090          }
06091       }
06092       nout = vsnprintf (sbuf, MAX_APPEND * sizeof(char), newstring, vararg_ptr); 
06093       if (LocalHead) fprintf(SUMA_STDERR,"%s:\n Calling va_end, nout = %d\n", FuncName, nout);
06094       va_end(vararg_ptr);  /* cleanup */
06095       
06096       if (nout < 0) {
06097          SUMA_SL_Err("Error reported by  vsnprintf");
06098          SUMA_RETURN(SUMA_StringAppend(SS,"Error SUMA_StringAppend_va: ***Error reported by  vsnprintf"));
06099       }
06100       if (nout >= MAX_APPEND) {
06101          SUMA_SL_Warn("String trunctated by vsnprintf");
06102          SUMA_StringAppend(SS,sbuf);
06103          SUMA_RETURN(SUMA_StringAppend(SS,"WARNING: ***Previous string trunctated because of its length. ***"));
06104       }
06105       SUMA_LH("Calling StringAppend");
06106       SUMA_RETURN (SUMA_StringAppend(SS,sbuf));
06107    }else {
06108       SUMA_LH("NULL newstring");
06109       /* let the other one handle this */
06110       SUMA_RETURN (SUMA_StringAppend(SS,newstring));
06111    }
06112    
06113    /* should not be here */
06114    SUMA_RETURN (NULL);
06115 
06116 }
06117 
06118 
06119 void SUMA_sigfunc(int sig)   /** signal handler for fatal errors **/
06120 {
06121    char * sname ;
06122    static volatile int fff=0 ;
06123    if( fff ) _exit(1) ; else fff = 1 ;
06124    switch(sig){
06125       default:      sname = "unknown" ; break ;
06126       case SIGINT:  sname = "SIGINT(ctrl+c)"  ; break ;
06127       case SIGPIPE: sname = "SIGPIPE(broken pipe)" ; break ;
06128       case SIGSEGV: sname = "SIGSEGV(access outside limits)" ; break ;
06129       case SIGBUS:  sname = "SIGBUS(access violation)"  ; break ;
06130       case SIGTERM: sname = "SIGTERM(termination requested)" ; break ;
06131    }
06132    fprintf(stderr,"\nFatal Signal %d (%s) received\n",sig,sname); fflush(stderr);
06133    TRACEBACK ;
06134    fprintf(stderr,"*** Program Abort ***\nSUMA Version %.2f\nCompile Date: %s\n", SUMA_LatestVersionNumber(), __DATE__) ; fflush(stderr) ;
06135    exit(1) ;
06136 }
06137 
06138 /*--------------------------------------------------------------------*/
06139 /*! My version of Bob's Decode a single string into a bunch of strings, separated
06140     by characters from the list in sep.
06141     - Passing sep in as NULL means to use "," as the separator.
06142     - In each sub-string, leading and trailing blanks will be excised.
06143     - This can result in 0 length strings (e.g., "1,,2," will result
06144       in the second and fourth output strings having 0 length).
06145    \sa SUMA_NI_get_ith_string
06146 ----------------------------------------------------------------------*/
06147 
06148 NI_str_array * SUMA_NI_decode_string_list( char *ss , char *sep )
06149 {
06150    static char FuncName[]={"SUMA_NI_decode_string_list"};
06151    NI_str_array *sar ;
06152    int num , nn,id,jd , lss ;
06153 
06154    if( ss == NULL || ss[0] == '\0' ) return NULL ; /* bad input */
06155 
06156    if( sep == NULL || sep[0] == '\0' ) sep = "," ;  /* default sep */
06157 
06158    sar = NI_malloc(NI_str_array, sizeof(NI_str_array)) ;  /* create output */
06159    sar->num = 0 ; sar->str = NULL ;
06160 
06161    /* scan for sub-strings */
06162 
06163    lss = NI_strlen(ss) ;
06164    num = id = 0 ;
06165    while( id < lss ){
06166 
06167       /* skip current position ahead over whitespace */
06168 
06169       while( id < lss && isspace(ss[id]) ) id++ ;
06170       if( id == lss ) break ;                           /* ran out of string */
06171 
06172       jd = id ;               /* save current position (start of new string) */
06173 
06174       /* skip ahead until ss[id] is a separator [or a space - 10 Dec 2002 ZSS I don't like that one, 
06175                               gives me funny looking results with legitimate spaces ,
06176                               line below was: while( id < lss && strchr(sep,ss[id]) == NULL  && !isspace(ss[id])) id++; ] */
06177 
06178       while( id < lss && strchr(sep,ss[id]) == NULL ) id++;
06179       if( id == jd ){ id++; continue; }    /* is only a separator? */
06180 
06181       /* new sub-string runs from ss[jd] to ss[id-1] */
06182 
06183       sar->str = NI_realloc( sar->str , char*, sizeof(char *)*(num+1) ) ;
06184 
06185       nn = id-jd ;                                   /* length of sub-string */
06186 #if 0
06187       while( nn > 0 && isspace(ss[jd+nn-1]) ) nn-- ; /* clip trailing blanks */
06188 #endif
06189       sar->str[num] = NI_malloc(char, (nn+1)*sizeof(char)) ;              /* make output string  */
06190       if( nn > 0 ) memcpy(sar->str[num],ss+jd,nn) ;  /* copy sub-string    */
06191       sar->str[num++][nn] = '\0' ;                   /* terminate output  */
06192 
06193       id++ ;                                         /* skip separator  */
06194    }
06195 
06196    sar->num = num ; return sar ;
06197 }
06198 
06199 /*--------------------------------------------------------------------*/
06200 /*! \brief Returns a copy of the ith string in a string list. 
06201 \sa SUMA_NI_decode_string_list ( on which this function is based)
06202 ----------------------------------------------------------------------*/
06203 
06204 char  * SUMA_NI_get_ith_string( char *ss , char *sep, int i )
06205 {
06206    static char FuncName[]={"SUMA_NI_get_ith_string"};
06207    char *str =NULL;
06208    int num , nn,id,jd , lss ;
06209    
06210    SUMA_ENTRY;
06211    
06212    if( ss == NULL || ss[0] == '\0' || i<0) SUMA_RETURN( NULL ) ; /* bad input */
06213 
06214    if( sep == NULL || sep[0] == '\0' ) sep = "," ;  /* default sep */
06215 
06216 
06217    /* scan for sub-strings */
06218 
06219    lss = NI_strlen(ss) ;
06220    num = id = 0 ;
06221    while( id < lss ){
06222 
06223       /* skip current position ahead over whitespace */
06224 
06225       while( id < lss && isspace(ss[id]) ) id++ ;
06226       if( id == lss ) break ;                           /* ran out of string */
06227 
06228       jd = id ;               /* save current position (start of new string) */
06229 
06230       /* skip ahead until ss[id] is a separator [or a space - 10 Dec 2002 ZSS I don't like that one, 
06231                               gives me funny looking results with legitimate spaces ,
06232                               line below was: while( id < lss && strchr(sep,ss[id]) == NULL  && !isspace(ss[id])) id++; ] */
06233 
06234       while( id < lss && strchr(sep,ss[id]) == NULL ) id++;
06235       if( id == jd ){ id++; continue; }    /* is only a separator? */
06236 
06237 
06238 
06239       nn = id-jd ;                                   /* length of sub-string */
06240       
06241       if (i==num) { /* that is the one I want */
06242          /* new sub-string runs from ss[jd] to ss[id-1] */
06243          str = (char *) SUMA_malloc( sizeof(char )*(nn+1) ) ;
06244          if( nn > 0 ) memcpy(str,ss+jd,nn) ;  /* copy sub-string    */
06245          str[nn] = '\0' ;                   /* terminate output  */
06246          SUMA_RETURN(str);
06247       } 
06248       ++num;   
06249       id++ ;                                         /* skip separator  */
06250    }
06251 
06252    /* not found, return with NULL */
06253    SUMA_RETURN( str );
06254 }
06255 void SUMA_Show_NI_str_ar(NI_str_array *nisa, FILE *out)
06256 {
06257    static char FuncName[]={"SUMA_Show_NI_str_ar"};
06258    int i;
06259    char *s=NULL;
06260    SUMA_STRING *SS = NULL;
06261    
06262    if (!out) out = SUMA_STDOUT;
06263    
06264    SS = SUMA_StringAppend(NULL, NULL);
06265    
06266    if (!nisa) SS = SUMA_StringAppend_va(SS, "NULL struct");
06267    else {
06268       SS = SUMA_StringAppend_va(SS, "%d strings:\n", nisa->num);
06269       for (i=0; i<nisa->num; ++i) {
06270          SS = SUMA_StringAppend_va(SS, "\t%d->>>%s<<<\n", i, nisa->str[i]);
06271       }
06272    }
06273    
06274    SUMA_SS2S(SS,s);
06275    
06276    fprintf(out, "%s", s); SUMA_free(s); s= NULL;
06277    fflush(out);
06278    SUMA_RETURNe;
06279 }
06280 
06281 /*!
06282    \brief take a bunch of strings stored in NI_str_array
06283    and turn them into a composite string
06284    Free result with SUMA_free
06285    \sa SUMA_NI_str_ar_2_comp_str
06286 */
06287 char *SUMA_NI_str_ar_2_comp_str (NI_str_array *nisa, char *sep)
06288 {
06289    static char FuncName[]={"SUMA_NI_str_array_2_string"};
06290    char *ar = NULL, *s=NULL;
06291    int i, nsep, k, ns, cnt, Nchars = 0;
06292    SUMA_Boolean LocalHead = NOPE;
06293    
06294    SUMA_ENTRY;
06295    
06296    if (LocalHead) SUMA_Show_NI_str_ar(nisa, NULL);
06297    
06298    if (!nisa) SUMA_RETURN(NULL);
06299    
06300    if (sep) nsep = strlen(sep);
06301    else nsep = 0;
06302    
06303    /* what's the total number of chars ? */
06304    for (i=0; i<nisa->num; ++i) {
06305       if (nisa->str[i]) { Nchars += strlen(nisa->str[i])+nsep ; } /* be safe allocate a bit more ...*/
06306       else Nchars += nsep; /* for separator */
06307    }
06308    
06309    ar = (char *)SUMA_malloc(sizeof(char)*Nchars);
06310    
06311    cnt = 0;
06312    for (i=0; i<nisa->num; ++i) { 
06313       s = nisa->str[i];
06314       if (s) {
06315          ns = strlen(s); 
06316       } else {
06317          ns = 0;
06318       }
06319       k = 0;
06320       while (k < ns) { ar[cnt] = s[k]; ++k; ++cnt; }
06321       k = 0;
06322       while (k < nsep) { ar[cnt] = sep[k]; ++k; ++cnt; }
06323    }
06324    ar[cnt] = '\0'; /* le bouchon */
06325    
06326    SUMA_RETURN(ar);
06327 }
06328 
06329 /*!
06330    \brief Inverse of SUMA_NI_str_ar_2_comp_str
06331    free output with SUMA_free_NI_str_array
06332 */
06333 NI_str_array *SUMA_comp_str_2_NI_str_ar(char *s, char *sep)
06334 {
06335    static char FuncName[]={"SUMA_comp_str_2_NI_str_ar"};
06336    NI_str_array *nisa = NULL;
06337    
06338    SUMA_ENTRY;
06339    
06340    if (!s) SUMA_RETURN(nisa);
06341    
06342    nisa = SUMA_NI_decode_string_list(s, sep);
06343    
06344    SUMA_RETURN(nisa);
06345 }
06346 
06347 NI_str_array *SUMA_free_NI_str_array(NI_str_array *nisa)
06348 {
06349    static char FuncName[]={"SUMA_free_NI_str_array"}; 
06350    int i;
06351    
06352    SUMA_ENTRY;
06353    
06354    if (nisa) {
06355       for (i=0; i<nisa->num; ++i) {
06356          if (nisa->str[i]) NI_free(nisa->str[i]); nisa->str[i] = NULL;
06357       }
06358       NI_free(nisa); nisa = NULL;
06359    }
06360    
06361    SUMA_RETURN(nisa);
06362 }
06363 
06364 /*!
06365    \brief returns the iith string in a sep separated composite string cs 
06366    free result with SUMA_free
06367 */
06368 char *SUMA_Get_Sub_String(char *cs, char *sep, int ii)
06369 {
06370    static char FuncName[]={"SUMA_Get_Sub_String"};
06371    NI_str_array *nisa=NULL;
06372    char *s = NULL;
06373    SUMA_Boolean LocalHead = NOPE;
06374    
06375    SUMA_ENTRY;
06376    
06377    if (ii < 0) { SUMA_SL_Err("Bad index"); SUMA_RETURN(s); }
06378    if (!cs) { SUMA_SL_Err("NULL input"); SUMA_RETURN(s); }
06379    #if 0 /* old slow way */
06380       nisa = SUMA_comp_str_2_NI_str_ar(cs, sep);
06381       if (LocalHead) SUMA_Show_NI_str_ar(nisa, NULL);
06382       if (!nisa) { SUMA_SL_Err("Failed in SUMA_comp_str_2_NI_str_ar"); SUMA_RETURN(s); }
06383       if (ii >= nisa->num) { /* SUMA_SL_Warn("not enough strings"); */ SUMA_RETURN(s); }
06384       s = SUMA_copy_string(nisa->str[ii]);
06385       SUMA_free_NI_str_array(nisa); nisa = NULL;
06386    #else 
06387       s = SUMA_NI_get_ith_string( cs , sep, ii );
06388 
06389    #endif
06390    SUMA_RETURN(s);
06391 }
06392 
06393 /*!
06394    \brief replace the col th string attribute in a one-string nel
06395 */
06396 int SUMA_AddColAtt_CompString(NI_element *nel, int col, char *lbl, char *sep)
06397 {
06398    static char FuncName[]={"SUMA_AddColAtt_CompString"};
06399    NI_str_array *nisa = NULL;
06400    char *cs=NULL, *ns=NULL;
06401    SUMA_Boolean LocalHead = NOPE;
06402    
06403    SUMA_ENTRY;
06404    
06405    if (!nel) { SUMA_SL_Err("NULL element"); SUMA_RETURN(NOPE); }
06406    if (col < 0) { SUMA_SL_Err("Negative column index"); SUMA_RETURN(NOPE); }
06407    
06408    SUMA_NEL_GET_STRING(nel, 0, 0, cs); /* composite string */
06409    
06410    if (!cs) { /* first baby, put it in */
06411       if (LocalHead) fprintf(SUMA_STDERR,"%s: 1st string: %s\n", FuncName, lbl);
06412       SUMA_NEL_REPLACE_STRING(nel, 0, 0, lbl); 
06413       SUMA_RETURN(YUP);
06414    }
06415    
06416 
06417    nisa = SUMA_comp_str_2_NI_str_ar(cs, sep);
06418    if (!nisa) { SUMA_SL_Err("Failed in SUMA_comp_str_2_NI_str_ar"); SUMA_RETURN(NOPE); }
06419    
06420    if (col > nisa->num) { SUMA_SL_Err("col > nisa->num"); SUMA_RETURN(NOPE); }
06421    
06422    if (col == nisa->num) { /* add at the end */
06423       if (LocalHead) fprintf(SUMA_STDERR,"%s: append %s to end of %s\n", FuncName, lbl, cs); 
06424       ns = SUMA_append_replace_string(cs, lbl, sep, 0);
06425       SUMA_NEL_REPLACE_STRING(nel, 0, 0, ns);   
06426    } else { /* add in middle */
06427       if (nisa->str[col]) NI_free(nisa->str[col]); nisa->str[col] = NULL;
06428       if (lbl) {
06429          nisa->str[col] = (char*)NI_malloc(char, (strlen(lbl)+1)*sizeof(char));
06430          strcpy( nisa->str[col],  lbl ); 
06431          if (LocalHead) fprintf(SUMA_STDERR,"%s: inserted %s at location %d\n", FuncName, lbl, col);
06432          ns = SUMA_NI_str_ar_2_comp_str(nisa, sep);
06433          if (LocalHead) fprintf(SUMA_STDERR,"%s: final string is %s\n", FuncName, ns);
06434          SUMA_NEL_REPLACE_STRING(nel, 0, 0, ns); 
06435       }
06436    }
06437    if (ns) SUMA_free(ns); ns = NULL;
06438    if (nisa) SUMA_free_NI_str_array(nisa); nisa = NULL;
06439    
06440    SUMA_RETURN(YUP);
06441 }
06442 
06443 
06444 /*! Swap the 4 bytes pointed to by ppp: abcd -> dcba. */
06445 
06446 void SUMA_swap_4(void *ppp)
06447 {
06448    unsigned char *pntr = (unsigned char *) ppp ;
06449    unsigned char b0, b1, b2, b3;
06450 
06451    b0 = *pntr; b1 = *(pntr+1); b2 = *(pntr+2); b3 = *(pntr+3);
06452    *pntr = b3; *(pntr+1) = b2; *(pntr+2) = b1; *(pntr+3) = b0;
06453 }
06454 
06455 /*---------------------------------------------------------------*/
06456 
06457 /*! Swap the 8 bytes pointed to by ppp: abcdefgh -> hgfedcba. */
06458 
06459 void SUMA_swap_8(void *ppp)
06460 {
06461    unsigned char *pntr = (unsigned char *) ppp ;
06462    unsigned char b0, b1, b2, b3;
06463    unsigned char b4, b5, b6, b7;
06464 
06465    b0 = *pntr    ; b1 = *(pntr+1); b2 = *(pntr+2); b3 = *(pntr+3);
06466    b4 = *(pntr+4); b5 = *(pntr+5); b6 = *(pntr+6); b7 = *(pntr+7);
06467 
06468    *pntr     = b7; *(pntr+1) = b6; *(pntr+2) = b5; *(pntr+3) = b4;
06469    *(pntr+4) = b3; *(pntr+5) = b2; *(pntr+6) = b1; *(pntr+7) = b0;
06470 }
06471 
06472 /*---------------------------------------------------------------*/
06473 
06474 /*! Swap the 2 bytes pointed to by ppp: ab -> ba. */
06475 
06476 void SUMA_swap_2(void *ppp)
06477 {
06478    unsigned char *pntr = (unsigned char *) ppp ;
06479    unsigned char b0, b1;
06480 
06481    b0 = *pntr; b1 = *(pntr+1);
06482    *pntr = b1; *(pntr+1) = b0;
06483 }
06484 
06485 /*!
06486    \brief 
06487    \param endian (int)  0 : Don't know, do nothing
06488                         MSB_FIRST
06489                         LSB_FIRST
06490 */
06491 void *SUMA_BinarySuck(char *fname, SUMA_VARTYPE data_type, int endian, int start, int end, int *nvals_read)
06492 {
06493    static char FuncName[]={"SUMA_BinarySuck"};
06494    int bs, End, chnk, read_n, N_alloc, ex;
06495    FILE *fp=NULL;
06496    void *ans = NULL;
06497    SUMA_Boolean LocalHead = NOPE;
06498 
06499    SUMA_ENTRY;
06500 
06501    *nvals_read = 0;
06502    ans = NULL;
06503 
06504    if (!SUMA_filexists(fname)) { SUMA_SL_Err("File not found or could not be read"); goto CLEAN_EXIT; }
06505    if (start < 0) { SUMA_SL_Err("Neg start val!"); goto CLEAN_EXIT; }
06506 
06507    /* byte swapping? */
06508    bs = 0;
06509    SUMA_WHAT_ENDIAN(End);
06510    if (endian && endian != End) bs = 1;         
06511 
06512    /* open file */
06513    fp = fopen(fname,"r");
06514    if (!fp) { SUMA_SL_Err("Failed to open file for read op."); goto CLEAN_EXIT; }
06515 
06516    /* skip top, if need be */
06517    if (start) fseek(fp, start, SEEK_SET);
06518 
06519    /* size of each value */
06520    chnk = SUMA_SizeOf(data_type);
06521    if (chnk <= 0) {  SUMA_SL_Err("Bad data type"); goto CLEAN_EXIT; }
06522 
06523    /* how many values to read ? */
06524    read_n = -1;
06525    if (end > 0) {
06526       read_n = (end-start)/chnk;
06527       if (read_n < 0) { SUMA_SL_Err("Bad end, start values"); goto CLEAN_EXIT;  }
06528    }
06529 
06530    /* now start reading until you reach eof or end byte */
06531    if (read_n >= 0)  N_alloc = read_n;
06532    else N_alloc = ( THD_filesize( fname ) - start) / (unsigned long)chnk;
06533    if (LocalHead) fprintf(SUMA_STDERR,"%s: Expecting to read %d values\n", FuncName, N_alloc);
06534    
06535    ex = 0;
06536    switch (data_type) {
06537       case SUMA_float:
06538          {
06539             float *vec = (float *)SUMA_malloc(N_alloc * sizeof(float));
06540             if (!vec) { SUMA_SL_Err("Failed to allocate"); goto CLEAN_EXIT;  }
06541             SUMA_LH("Reading floats");
06542             ex = fread((void*)vec, chnk, N_alloc, fp);
06543             if (ex != N_alloc) { SUMA_SL_Err("Failed to read all data!"); SUMA_free(vec); goto CLEAN_EXIT; }
06544             if (bs) { SUMA_LH("swapping");  SUMA_SWAP_VEC(vec,N_alloc,chnk); }
06545             ans = (void*)vec;
06546          }
06547          break;
06548       case SUMA_int:
06549          {
06550             int *vec = (int *)SUMA_malloc(N_alloc * sizeof(int));
06551             if (!vec) { SUMA_SL_Err("Failed to allocate"); goto CLEAN_EXIT;  }
06552             SUMA_LH("Reading ints");
06553             ex = fread((void*)vec, chnk, N_alloc, fp);
06554             if (ex != N_alloc) { SUMA_SL_Err("Failed to read all data!"); SUMA_free(vec); goto CLEAN_EXIT; }
06555             if (bs) { SUMA_LH("swapping");  SUMA_SWAP_VEC(vec,N_alloc,chnk); }
06556             ans = (void*)vec;
06557          }
06558          break;
06559       case SUMA_byte:
06560          {
06561             byte *vec = (byte *)SUMA_malloc(N_alloc * sizeof(byte));
06562             if (!vec) { SUMA_SL_Err("Failed to allocate"); goto CLEAN_EXIT;  }
06563             SUMA_LH("Reading bytes");
06564             ex = fread((void*)vec, chnk, N_alloc, fp);
06565             if (ex != N_alloc) { SUMA_SL_Err("Failed to read all data!"); SUMA_free(vec); goto CLEAN_EXIT; }
06566             if (bs) { SUMA_LH("swapping");  SUMA_SWAP_VEC(vec,N_alloc,chnk); }
06567             ans = (void*)vec;
06568          }
06569          break;
06570       case SUMA_short:
06571          {
06572             short *vec = (short *)SUMA_malloc(N_alloc * sizeof(short));
06573             if (!vec) { SUMA_SL_Err("Failed to allocate"); goto CLEAN_EXIT;  }
06574             SUMA_LH("Reading shorts");
06575             ex = fread((void*)vec, chnk, N_alloc, fp);
06576             if (ex != N_alloc) { SUMA_SL_Err("Failed to read all data!"); SUMA_free(vec); goto CLEAN_EXIT; }
06577             if (bs) { SUMA_LH("swapping");  SUMA_SWAP_VEC(vec,N_alloc,chnk); }
06578             ans = (void*)vec;
06579          }
06580          break;
06581       default:
06582          SUMA_SL_Err("data type not supported");
06583          break;
06584    }
06585    
06586    *nvals_read = ex;
06587 
06588    CLEAN_EXIT:
06589    if (fp) fclose(fp);
06590    
06591    SUMA_RETURN(ans);
06592 }
06593 
06594 /*********************** END Miscellaneous support functions **************************** */
 

Powered by Plone

This site conforms to the following standards: