1 #include "mrilib.h"
2 
3 #define NFMAX 26
4 
main(int argc,char * argv[])5 int main( int argc , char *argv[] )
6 {
7    int iarg=1 ;
8    int do_divorce=0 ;
9    char *sep = "*," ; int nsep=2 ;
10    char *filex[NFMAX] ; int nfilex , vv ;
11    float filler=3.e+33 ;
12 
13    /*------------------------------------------------------------------------*/
14 
15    if( argc < 3 || strcmp(argv[1],"-help") == 0 ){
16      printf(
17       "Usage: 1dMarry [options] file1 file2 ...\n"
18       "\n"
19       "  Joins together 2 (or more) ragged-right .1D files, for use with\n"
20       "    3dDeconvolve -stim_times_AM2.\n"
21       " **_OR_**\n"
22       "  Breaks up 1 married file into 2 (or more) single-valued files.\n"
23       "\n"
24       "OPTIONS:\n"
25       "=======\n"
26       " -sep abc  == Use the first character (e.g., 'a') as the separator\n"
27       "              between values 1 and 2, the second character (e.g., 'b')\n"
28       "              as the separator between values 2 and 3, etc.\n"
29       "            * These characters CANNOT be a blank, a tab, a digit,\n"
30       "              or a non-printable control character!\n"
31       "            * Default separator string is '*,' which will result\n"
32       "              in output similar to '3*4,5,6'\n"
33       "\n"
34       " -divorce  == Instead of marrying the files, assume that file1\n"
35       "              is already a married file: split time*value*value... tuples\n"
36       "              into separate files, and name them in the pattern\n"
37       "              'file2_A.1D' 'file2_B.1D' et cetera.\n"
38       "\n"
39       "If not divorcing, the 'married' file is written to stdout, and\n"
40       "probably should be captured using a redirection such as '>'.\n"
41       "\n"
42       "NOTES:\n"
43       "=====\n"
44       "* You cannot use column [...] or row {...} selectors on\n"
45       "    ragged-right .1D files, so don't even think about trying!\n"
46       "* The maximum number of values that can be married is %d.\n"
47       "    (No polygamy or polyandry jokes here, please.)\n"
48       "* For debugging purposes, with '-divorce', if 'file2' is '-',\n"
49       "    then all the divorcees are written directly to stdout.\n"
50       "\n"
51       "-- RWCox -- written hastily in March 2007 -- hope I don't repent\n"
52       "         -- modified to deal with multiple marriages -- December 2008\n"
53 
54       , NFMAX
55      ) ;
56      PRINT_COMPILE_DATE ; exit(0) ;
57    }
58 
59    /*------------------------------------------------------------------------*/
60 
61    while( iarg < argc && argv[iarg][0] == '-' ){
62 
63      if( strcmp(argv[iarg],"-divorce") == 0 ){
64        do_divorce = 1 ; iarg++ ; continue ;
65      }
66 
67      if( strcmp(argv[iarg],"-sep") == 0 ){
68        int jj ;
69        iarg++ ;
70        if( iarg >= argc )
71          ERROR_exit("1dMarry: need argument after '-sep'") ;
72        sep = argv[iarg] ; nsep = strlen(sep) ;
73        if( nsep < 1 ){
74          WARNING_message("Replacing empty '-sep' option with default") ;
75          sep = "*," ; nsep = 2 ;
76        }
77        for( jj=0 ; jj < nsep ; jj++ ){
78          if( isspace(sep[jj]) || iscntrl(sep[jj]) || isdigit(sep[jj]) )
79            ERROR_exit("1dMarry: Illegal character after '-sep'") ;
80        }
81        iarg++ ; continue ;
82      }
83 
84      ERROR_exit("1dMarry: Unknown option '%s'",argv[iarg]) ;
85    }
86 
87    /*------------------------------------------------------------------------*/
88 
89    /** copy filenames to something more convenient **/
90 
91    for( nfilex=0 ; iarg < argc && nfilex < NFMAX ; iarg++,nfilex++ )
92      filex[nfilex] = argv[iarg] ;
93 
94    /** check for various stoopidities **/
95 
96    if( nfilex == 0 )
97      ERROR_exit("1dMarry: need filenames at end of command line!") ;
98 
99    if( !do_divorce && nfilex == NFMAX && iarg < argc )
100      WARNING_message("Maximum number of marriages (%d) exceeded!",NFMAX) ;
101    else if( do_divorce && nfilex > 2 )
102      WARNING_message("Divorcing ==> filenames after #2 are ignored!") ;
103 
104    if( !THD_is_file(filex[0]) )
105      ERROR_exit("1dMarry: file '%s' does not exist!",filex[0]) ;
106 
107    if( !do_divorce ){  /* check all input files to see if */
108      int nbad ;        /* they are willing to be married */
109      if( nfilex < 2 )
110        ERROR_exit("Need at least 2 input filenames to perform the marriage!") ;
111      for( nbad=0,vv=1 ; vv < nfilex ; vv++ ){
112        if( !THD_is_file(filex[vv]) ){
113          ERROR_message("1Dmarry: file '%s' does not exist!",filex[vv]) ;
114          nbad++ ;
115        }
116      }
117      if( nbad > 0 )
118        ERROR_exit("The desired nuptials cannot take place!") ;
119 
120    } else if( nfilex == 1 ){  /* must create name of divorce file */
121                               /* since user didn't give us one   */
122      filex[1] = filex[0] ;
123      INFO_message(
124        "No filename given to get divorce results ==> using '%s'",filex[1]) ;
125    }
126 
127    /******----------- divorce first, it's easier -----------******/
128 
129    if( do_divorce ){
130 
131      MRI_IMAGE *vim ; MRI_IMARR *vimar ;
132      MRI_IMAGE *aim ; float *aar ; FILE *afp ; char *aname ;
133      int ii,jj , nx,ny , itop , needmult , vdim ;
134 
135      vim = mri_read_ascii_ragged_fvect( filex[0] , filler , 0 ) ;
136      if( vim == NULL )
137        ERROR_exit("1dMarry: can't read file '%s' for divorce",filex[0]) ;
138      vimar = mri_fvect_to_imarr(vim) ; mri_free(vim) ;
139      if( vimar == NULL )
140        ERROR_exit("1dMarry: can't process file '%s' for divorce!?!",filex[0]);
141 
142      vdim = IMARR_COUNT(vimar) ;
143      if( vdim < 2 )
144        ERROR_exit("1dMarry: file '%s' doesn't have 2+ values to divorce!",filex[0]) ;
145      else if( vdim > NFMAX )
146        ERROR_exit("1dMarry: file '%s' has more than %s values to divorce!",
147                   filex[0],NFMAX) ;
148      else
149        INFO_message("1dMarry: divorcing %d values from file '%s'",vdim,filex[0]) ;
150 
151      aim = IMARR_SUBIM(vimar,0) ; nx = aim->nx ; ny = aim->ny ;
152      aname = malloc(strlen(filex[1])+20) ;
153 
154      for( vv=0 ; vv < vdim ; vv++ ){            /* loop over images */
155        aim = IMARR_SUBIM(vimar,vv) ; aar = MRI_FLOAT_PTR(aim) ;
156        if( strcmp(filex[1],"-") == 0 ){
157          afp = stdout ; strcpy(aname,"stdout") ;
158        } else {
159          sprintf(aname,"%s_%c.1D",filex[1],'A'+vv) ; afp = fopen(aname,"w") ;
160        }
161        if( afp == NULL )
162          ERROR_exit("1dMarry: can't open file '%s' for output!",aname) ;
163 
164        needmult = (nx > 1) ;
165        for( jj=0 ; jj < ny ; jj++ ){            /* loop over rows */
166          for( itop=nx-1 ; itop >= 0 ; itop-- )  /* find last good value */
167            if( aar[itop+jj*nx] < filler ) break ;
168          if( itop < 0 ){
169            fprintf(afp," *\n") ;  /* indicates no data on this line */
170          } else {
171            needmult = needmult && (itop == 0) ;
172            for( ii=0 ; ii <= itop ; ii++ ){
173              if( aar[ii+jj*nx] < filler ) fprintf(afp," %g",aar[ii+jj*nx]) ;
174              else                         fprintf(afp," *") ;
175            }
176          }
177          if( itop == 0 && ny > 1 && needmult ){
178            fprintf(afp," *") ; needmult = 0 ;
179          }
180          fprintf(afp,"\n") ;
181        }
182        if( afp != stdout ) fclose(afp) ; else fflush(stdout) ;
183        INFO_message("1dMarry: wrote out file '%s'",aname) ;
184      }
185      DESTROY_IMARR(vimar) ;
186    }
187 
188    /******---------------------- Wedding Bells! ----------------------******/
189 
190    else {
191 
192      MRI_IMAGE *aim ; MRI_IMARR *vimar ;
193      float vval ;
194      int ii,jj , nx=0,ny=0 , itop , needmult , ngood,vdim=nfilex ;
195      FILE *fp=stdout ;
196 
197      INIT_IMARR(vimar) ;
198      for( vv=0 ; vv < nfilex ; vv++ ){
199        aim = mri_read_ascii_ragged( filex[vv] , filler ) ;
200        if( aim == NULL )
201          ERROR_exit("1dMarry: can't read file '%s'",filex[vv]) ;
202        if( vv == 0 ){ nx = aim->nx ; ny = aim->ny ; }
203        else if( aim->ny != ny )
204          ERROR_exit("files '%s' and '%s' don't have same number of rows!",
205                     filex[0] , filex[vv] ) ;
206        else if( aim->nx != nx )
207          ERROR_exit("files '%s' and '%s' don't have same length of rows!",
208                     filex[0] , filex[vv] ) ;
209        ADDTO_IMARR(vimar,aim) ;
210      }
211 
212      needmult = (nx > 1) ;
213 
214 #define VAL(v,i,j) (MRI_FLOAT_PTR(IMARR_SUBIM(vimar,(v))))[(i)+(j)*nx]
215 #define SEP(i) sep[ ((i)<nsep) ? (i) : nsep-1 ]
216 
217      for( jj=0 ; jj < ny ; jj++ ){              /* loop over rows */
218 
219        for( itop=nx-1 ; itop >= 0 ; itop-- ){   /* find last good value */
220          for( ngood=vv=0 ; vv < vdim ; vv++ )
221            if( VAL(vv,itop,jj) < filler ) ngood++ ;
222          if( ngood == vdim ) break ;  /* at least one good value found at itop */
223        }
224        if( itop < 0 ){
225          fprintf(fp," *\n") ;     /* signal that no values are in this row */
226        } else {
227          needmult = needmult && (itop == 0) ;
228          for( ii=0 ; ii <= itop ; ii++ ){
229            fprintf(fp," ") ;
230            for( ngood=vv=0 ; vv < vdim ; vv++ )
231              if( VAL(vv,itop,jj) < filler ) ngood++ ;
232            if( ngood == vdim ){
233              for( vv=0 ; vv < vdim ; vv++ ){
234                vval = VAL(vv,ii,jj) ;
235                if( vval < filler ) fprintf(fp,"%g",vval) ;
236                else                fprintf(fp,"*") ;
237                if( vv < vdim-1 )   fprintf(fp,"%c",SEP(vv)) ;
238              }
239            } else {
240              fprintf(fp," *") ;
241            }
242          }
243          if( itop == 0 && ny > 1 && needmult ){ fprintf(fp," *"); needmult = 0; }
244          fprintf(fp,"\n") ; fflush(fp) ;
245        }
246      }
247      if( fp != stdout ) fclose(fp) ;
248      DESTROY_IMARR(vimar) ;
249    }
250 
251    exit(0) ;
252 }
253