TPCCLIB
Loading...
Searching...
No Matches
paradd.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <math.h>
14/*****************************************************************************/
15#include "tpcextensions.h"
16#include "tpcift.h"
17#include "tpcpar.h"
18/*****************************************************************************/
19
20/*****************************************************************************/
21static char *info[] = {
22 "Insert parameter values from parameter file 2 into another, optionally new,",
23 "parameter file 1. If file1 does not exist, it will be created.",
24 " ",
25 "Usage: @P [options] file1 file2",
26 " ",
27 "Options:",
28 " -par=<list>",
29 " List of parameter numbers or names to be copied; all by default.",
30 " -tac=<list>",
31 " List of TAC numbers or names to be copied; all by default.",
32 " -ovr",
33 " Existing file1 is overwritten.",
34 " --dry",
35 " Nothing is actually copied, application only lists what it would do.",
36 " -stdoptions", // List standard options like --help, -v, etc
37 " ",
38 "Example 1:",
39 "Create a new parameter file which contains only parameters 1-3",
40 " @P -ovr -par=1-3 ab123new.res ab123fitk3.res",
41 " ",
42 "Example 2:",
43 "Create a new parameter file which contains only regions 'caud' and 'putam'",
44 " @P -ovr -tac=caud,putam ab234new.csv ab234srtm.csv",
45 " ",
46 "Example 3:",
47 "Combine parameter BPnd in region 'putam' from given studies into one file",
48 "in MS Windows command prompt window, and then convert it to XML format",
49 "supported by MS Excel",
50 " del combined.res",
51 " for %g in (s6789*.res) do @P -par=BPnd -tac=putam combined.res %g",
52 " parformat -f=xml combined.res",
53 " ",
54 "See also: parformat, parget, parsort, pardiff, parmean, tacadd, rescoll",
55 " ",
56 "Keywords: parameter, tool, reporting, software testing",
57 0};
58/*****************************************************************************/
59
60/*****************************************************************************/
61/* Turn on the globbing of the command line, since it is disabled by default in
62 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
63 In Unix&Linux wildcard command line processing is enabled by default. */
64/*
65#undef _CRT_glob
66#define _CRT_glob -1
67*/
68int _dowildcard = -1;
69/*****************************************************************************/
70
71/*****************************************************************************/
75int main(int argc, char **argv)
76{
77 int ai, help=0, version=0, verbose=1;
78 int ret, n;
79 int drymode=0; // 1=no files are actually edited or created
80 int newfile=0; // 0=TAC(s) are added; 1=new file is created
81 int overwrite=0; // 0=TAC(s) are added; 1=existing file is overwritten
82 char *cptr, parfile1[FILENAME_MAX], parfile2[FILENAME_MAX];
83 char *pars=NULL, *tacs=NULL; // remember to free allocated memory before exit
84 PAR par1, par2;
85 FILE *fp;
86
87
88 /*
89 * Get arguments
90 */
91 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
92 parInit(&par1); parInit(&par2);
93 parfile1[0]=parfile2[0]=(char)0;
94 /* Options */
95 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
96 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
97 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
98 if(strncasecmp(cptr, "OVR", 2)==0) {
99 overwrite=1; continue;
100 } else if(strncasecmp(cptr, "DRY", 2)==0) {
101 drymode=1; continue;
102 } else if(strncasecmp(cptr, "PAR=", 4)==0 && strnlen(cptr, 5)>4) {
103 pars=strdup(cptr+4); continue;
104 } else if(strncasecmp(cptr, "TAC=", 4)==0 && strnlen(cptr, 5)>4) {
105 tacs=strdup(cptr+4); continue;
106 }
107 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
108 return(1);
109 } else break; // tac name argument may start with '-'
110
111 TPCSTATUS status; statusInit(&status);
112 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
113 status.verbose=verbose-1;
114
115 /* Print help or version? */
116 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
117 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
118 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
119
120 /* Process other arguments, starting from the first non-option */
121 for(; ai<argc; ai++) {
122 if(!parfile1[0]) {
123 strlcpy(parfile1, argv[ai], FILENAME_MAX); continue;
124 } else if(!parfile2[0]) {
125 strlcpy(parfile2, argv[ai], FILENAME_MAX); continue;
126 }
127 fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]);
128 return(1);
129 }
130
131 /* Check that we got what we need */
132 if(!parfile2[0]) {
133 tpcPrintUsage(argv[0], info, stderr);
134 free(pars); free(tacs); return(1);
135 }
136
137 /* In verbose mode print arguments and options */
138 if(verbose>1) {
139 printf("parfile1 := %s\n", parfile1);
140 printf("parfile2 := %s\n", parfile2);
141 printf("overwrite := %d\n", overwrite);
142 printf("drymode := %d\n", drymode);
143 if(pars!=NULL) printf("pars := '%s'\n", pars);
144 if(tacs!=NULL) printf("tacs := '%s'\n", tacs);
145 }
146
147 /*
148 * Try to read the file in which data should be added
149 */
150 if(verbose>1) printf("trying to read %s\n", parfile1);
151 ret=parRead(&par1, parfile1, &status);
152 if(ret==TPCERROR_OK) {
153 /* File 1 could be read */
154 if(overwrite!=0) {
155 if(drymode) printf("File %s would be overwritten.\n", parfile1);
156 else if(verbose>=0) printf("File %s is overwritten.\n", parfile1);
157 newfile=1;
158 } else if(verbose>1) {
159 printf("fileformat1 := %s\n", parFormattxt(par1.format));
160 printf("parNr1 := %d\n", par1.tacNr);
161 printf("tacNr1 := %d\n", par1.tacNr);
162 }
163 parFree(&par1);
164 } else if(ret==TPCERROR_CANNOT_OPEN) {
165 /* File 1 does not exist */
166 if(drymode) printf("File %s would be created.\n", parfile1);
167 else if(verbose>=0) printf("File %s did not exist and was created.\n", parfile1);
168 newfile=1; parFree(&par1);
169 } else {
170 /* File 1 exists but cannot be read */
171 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
172 parFree(&par1); free(pars); free(tacs); return(2);
173 }
174
175
176 /*
177 * Read the file from where parameters are imported
178 */
179 if(verbose>1) printf("reading %s\n", parfile2);
180 ret=parRead(&par2, parfile2, &status);
181 if(ret!=TPCERROR_OK) {
182 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
183 parFree(&par2); free(pars); free(tacs); return(3);
184 }
185 if(verbose>1) {
186 printf("fileformat2 := %s\n", parFormattxt(par2.format));
187 printf("parNr2 := %d\n", par2.parNr);
188 printf("tacNr2 := %d\n", par2.tacNr);
189 }
190 if(verbose>6) {
191 printf("file contents:\n");
192 parWrite(&par2, stdout, PAR_FORMAT_CSV_UK, 1, NULL);
193 printf("----------------\n");
194 }
195
196 /*
197 * Select the data in file 2 to be copied
198 */
199 int parNr=0, tacNr=0;
200 if(pars==NULL) {
201 /* No parameters specified: select all */
202 parSelectParameters(&par2, NULL, 0, &status);
203 } else {
204 char buf[512];
205 for(int i=0; i<strTokenNr(pars, ",;"); i++) {
206 if(strTokenNCpy(pars, ",;", i+1, buf, 512)<1) continue;
207 n=parSelectParameters(&par2, buf, 0, &status);
208 if(n==0) fprintf(stderr, "Warning: %d parameter(s) match '%s'\n", n, buf);
209 else if(verbose>2) printf("%d parameter(s) match '%s'\n", n, buf);
210 }
211 }
212 parNr=parSelectedParameters(&par2);
213 if(parNr==0) {
214 fprintf(stderr, "Error: no parameter(s) to add.\n");
215 parFree(&par2); free(pars); free(tacs); return(4);
216 }
217 if(verbose>2 || drymode) {
218 for(int i=0; i<par2.parNr; i++)
219 if(par2.n[i].sw) printf("selected_parameter: %s\n", par2.n[i].name);
220 }
221 if(tacs==NULL) {
222 /* No TACs specified: select all */
223 parSelectTACs(&par2, NULL, 0, &status);
224 } else {
225 char buf[512];
226 for(int i=0; i<strTokenNr(tacs, ",;"); i++) {
227 if(strTokenNCpy(tacs, ",;", i+1, buf, 512)<1) continue;
228 n=parSelectTACs(&par2, buf, 0, &status);
229 if(n==0) fprintf(stderr, "Warning: %d TAC(s) match '%s'\n", n, buf);
230 else if(verbose>2) printf("%d TAC(s) match '%s'\n", n, buf);
231 }
232 }
233 tacNr=parSelectedTACs(&par2);
234 if(tacNr==0) {
235 fprintf(stderr, "Error: no TAC(s) to add.\n");
236 parFree(&par2); free(pars); free(tacs); return(5);
237 }
238 if(verbose>2 || drymode) {
239 for(int i=0; i<par2.tacNr; i++)
240 if(par2.r[i].sw) printf("selected_tac: %s\n", par2.r[i].name);
241 }
242 /* par and tac strings are not needed later */
243 free(pars); free(tacs);
244
245 /*
246 * Delete parameters and TACs that were not selected.
247 */
248 if(parNr!=par2.parNr) {
249 int i=par2.parNr-1;
250 while(i>=0) {
251 if(par2.n[i].sw==0) parDeletePar(&par2, i);
252 i--;
253 }
254 }
255 if(tacNr!=par2.tacNr) {
256 int i=par2.tacNr-1;
257 while(i>=0) {
258 if(par2.r[i].sw==0) parDeleteTAC(&par2, i);
259 i--;
260 }
261 }
262
263 /*
264 * If target file does not exist, then save the selected contents in file, and quit.
265 */
266 if(newfile) {
267
268 if(drymode) {
269 printf("%d parameter(s) and %d TAC(s) would be written in %s\n", par2.parNr, par2.tacNr, parfile1);
270 parFree(&par2);
271 return(0);
272 }
273
274 /* Write new parameter file */
275 if(verbose>1) printf(" saving\n");
276 fp=fopen(parfile1, "w");
277 if(fp==NULL) {
278 fprintf(stderr, "Error: cannot open file for writing.\n");
279 parFree(&par2); return(11);
280 }
281 ret=parWrite(&par2, fp, PAR_FORMAT_UNKNOWN, 1, &status);
282 fclose(fp); parFree(&par2);
283 if(ret!=TPCERROR_OK) {
284 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
285 return(12);
286 }
287 if(verbose>0) printf("%s saved.\n", parfile1);
288 return(0);
289
290 }
291
292
293 /*
294 * We are here only if target file exists.
295 */
296 /* Read the previous contents. */
297 if(verbose>1) printf("reading %s\n", parfile1);
298 ret=parRead(&par1, parfile1, &status);
299 if(ret!=TPCERROR_OK) {
300 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
301 parFree(&par1); parFree(&par2); return(6);
302 }
303 if(verbose>1) {
304 printf("fileformat1 := %s\n", parFormattxt(par1.format));
305 printf("parNr1 := %d\n", par1.parNr);
306 printf("tacNr1 := %d\n", par1.tacNr);
307 }
308
309 /* Check whether parameters and/or TACs match between the files */
310 int sametacs=0, samepars=0;
311 if(parCompareParameterNames(&par1, &par2, -1, 0, &status)==0) samepars=1;
312 if(parCompareTacNames(&par1, &par2, -1, 0, &status)==0) sametacs=1;
313 if(verbose>1) {
314 if(samepars) printf("All parameters match.\n"); else printf("Parameters do not match.\n");
315 if(sametacs) printf("All TACs match.\n"); else printf("TACs do not match.\n");
316 }
317
318
319 /*
320 * If new and old TACs do match, then add new parameter column(s)
321 */
322 if(sametacs) {
323
324 if(drymode) {
325 printf("%d parameter(s) would be written in %s\n", parNr, parfile1);
326 parFree(&par1); parFree(&par2);
327 return(0);
328 }
329
330 if(verbose>1) printf("adding %d parameter(s) in %s\n", parNr, parfile1);
331
332 /* Allocate more space */
333 ret=parAllocateMore(&par1, par2.parNr, 0);
334 if(ret!=TPCERROR_OK) {
335 fprintf(stderr, "Error: cannot add parameters to data.\n");
336 parFree(&par1); parFree(&par2); return(7);
337 }
338
339 /* Copy */
340 int ti, pi, pj=par1.parNr;
341 for(pi=0; pi<par2.parNr; pi++, pj++) {
342 strcpy(par1.n[pj].name, par2.n[pi].name);
343 par1.n[pj].unit=par2.n[pi].unit;
344 for(ti=0; ti<par1.tacNr; ti++) {
345 par1.r[ti].p[pj]=par2.r[ti].p[pi];
346 par1.r[ti].sd[pj]=par2.r[ti].sd[pi];
347 par1.r[ti].cl1[pj]=par2.r[ti].cl1[pi];
348 par1.r[ti].cl2[pj]=par2.r[ti].cl2[pi];
349 }
350 }
351 par1.parNr+=parNr;
352
353 /* Remove WSS data */
354 for(ti=0; ti<par1.tacNr; ti++) par1.r[ti].wss=nan("");
355
356
357 /* Save file */
358 if(verbose>1) printf(" saving\n");
359 fp=fopen(parfile1, "w");
360 if(fp==NULL) {
361 fprintf(stderr, "Error: cannot open file for writing.\n");
362 parFree(&par1); parFree(&par2); return(11);
363 }
364 ret=parWrite(&par1, fp, PAR_FORMAT_UNKNOWN, 1, &status);
365 fclose(fp); parFree(&par1); parFree(&par2);
366 if(ret!=TPCERROR_OK) {
367 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
368 return(12);
369 }
370 if(verbose>0) printf("%d parameter(s) saved in %s\n", parNr, parfile1);
371 return(0);
372 }
373
374 /*
375 * If new and old parameters do match but TACs did not, then add new TAC row(s)
376 */
377 if(samepars) {
378
379 if(drymode) {
380 printf("%d TAC(s) would be written in %s\n", tacNr, parfile1);
381 parFree(&par1); parFree(&par2);
382 return(0);
383 }
384
385 if(verbose>1) printf("adding %d TAC(s) in %s\n", tacNr, parfile1);
386
387 /* Allocate more space */
388 ret=parAllocateMore(&par1, 0, par2.tacNr);
389 if(ret!=TPCERROR_OK) {
390 fprintf(stderr, "Error: cannot add TACs to data.\n");
391 parFree(&par1); parFree(&par2); return(7);
392 }
393
394 /* Copy */
395 if(verbose>2) printf("copying...\n");
396 int pi, ti, tj=par1.tacNr;
397 for(ti=0; ti<par2.tacNr; ti++, tj++) {
398 par1.r[tj].model=par2.r[ti].model;
399 strcpy(par1.r[tj].name, par2.r[ti].name);
400 par1.r[tj].start=par2.r[ti].start;
401 par1.r[tj].end=par2.r[ti].end;
402 par1.r[tj].fitNr=par2.r[ti].fitNr;
403 par1.r[tj].dataNr=par2.r[ti].dataNr;
404 par1.r[tj].wss=par2.r[ti].wss;
405 for(pi=0; pi<par2.parNr; pi++) {
406 par1.r[tj].p[pi]=par2.r[ti].p[pi];
407 par1.r[tj].sd[pi]=par2.r[ti].sd[pi];
408 par1.r[tj].cl1[pi]=par2.r[ti].cl1[pi];
409 par1.r[tj].cl2[pi]=par2.r[ti].cl2[pi];
410 }
411 }
412 par1.tacNr+=tacNr;
413
414 /* Save file */
415 if(verbose>1) printf(" saving\n");
416 fp=fopen(parfile1, "w");
417 if(fp==NULL) {
418 fprintf(stderr, "Error: cannot open file for writing.\n");
419 parFree(&par1); parFree(&par2); return(11);
420 }
421 ret=parWrite(&par1, fp, PAR_FORMAT_UNKNOWN, 1, &status);
422 fclose(fp); parFree(&par1); parFree(&par2);
423 if(ret!=TPCERROR_OK) {
424 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
425 return(12);
426 }
427 if(verbose>0) printf("%d TAC(s) saved in %s\n", tacNr, parfile1);
428 return(0);
429 }
430
431
432 /*
433 * Check if there are common TAC names
434 */
435 ret=parSelectByAnother(&par2, &par1, &parNr, &tacNr, &status);
436 if(verbose>1) printf("%d common TAC names\n%d common parameter names\n", tacNr, parNr);
437 if(ret!=TPCERROR_OK || tacNr<1) {
438 fprintf(stderr, "Error: incompatible contents for adding.\n");
439 parFree(&par1); parFree(&par2);
440 return(1);
441 }
442 /* Copy */
443 parNr=par1.parNr;
444 ret=parCombineTACs(&par1, &par2, &status);
445 if(ret!=TPCERROR_OK) {
446 fprintf(stderr, "Error: incompatible contents for adding.\n");
447 parFree(&par1); parFree(&par2);
448 return(1);
449 }
450 //printf("parNr %d -> %d\n", parNr, par1.parNr);
451 /* Save */
452 if(drymode) {
453 printf("%d new parameter(s) would be written in %s\n", par1.parNr-parNr, parfile1);
454 parFree(&par1); parFree(&par2);
455 return(0);
456 }
457 {
458 if(verbose>1) printf(" saving\n");
459 fp=fopen(parfile1, "w");
460 if(fp==NULL) {
461 fprintf(stderr, "Error: cannot open file for writing.\n");
462 parFree(&par1); parFree(&par2); return(11);
463 }
464 ret=parWrite(&par1, fp, PAR_FORMAT_UNKNOWN, 1, &status);
465 fclose(fp);
466 if(ret!=TPCERROR_OK) {
467 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
468 parFree(&par1); parFree(&par2); return(12);
469 }
470 printf("%d new parameter(s) saved in %s\n", par1.parNr-parNr, parfile1);
471 parFree(&par1); parFree(&par2);
472 return(0);
473 }
474
475 /* Free memory */
476 parFree(&par1); parFree(&par2);
477
478 fprintf(stderr, "Error: incompatible contents for adding.\n");
479 return(1);
480}
481/*****************************************************************************/
482
483/*****************************************************************************/
int parDeletePar(PAR *par, int pi)
Definition par.c:478
void parFree(PAR *par)
Definition par.c:75
void parInit(PAR *par)
Definition par.c:25
int parDeleteTAC(PAR *par, int ti)
Definition par.c:519
int parAllocateMore(PAR *par, int parNr, int tacNr)
Definition par.c:183
int parSelectByAnother(PAR *d1, PAR *d2, int *pn, int *pr, TPCSTATUS *status)
Definition parcomb.c:22
int parCombineTACs(PAR *d1, PAR *d2, TPCSTATUS *status)
Definition parcomb.c:99
int parCompareTacNames(PAR *d1, PAR *d2, const int i, const int casens, TPCSTATUS *status)
Definition parcomp.c:157
int parCompareParameterNames(PAR *d1, PAR *d2, const int i, const int casens, TPCSTATUS *status)
Definition parcomp.c:28
char * parFormattxt(parformat c)
Definition pario.c:59
int parWrite(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
Definition pario.c:148
int parRead(PAR *par, const char *fname, TPCSTATUS *status)
Definition pario.c:232
int parSelectTACs(PAR *d, const char *region_name, int reset, TPCSTATUS *status)
Definition parselect.c:24
int parSelectParameters(PAR *d, const char *par_name, int reset, TPCSTATUS *status)
Definition parselect.c:120
int parSelectedTACs(PAR *d)
Definition parselect.c:100
int parSelectedParameters(PAR *d)
Definition parselect.c:199
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
int strTokenNr(const char *s1, const char *s2)
Definition stringext.c:25
char * strdup(const char *s)
Definition stringext.c:185
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
int strTokenNCpy(const char *s1, const char *s2, int i, char *s3, int count)
Definition stringext.c:53
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
Definition tpcpar.h:100
int format
Definition tpcpar.h:102
int parNr
Definition tpcpar.h:108
int tacNr
Definition tpcpar.h:104
PARR * r
Definition tpcpar.h:114
PARN * n
Definition tpcpar.h:112
int unit
Definition tpcpar.h:86
char sw
Definition tpcpar.h:94
char name[MAX_PARNAME_LEN+1]
Definition tpcpar.h:82
double wss
Definition tpcpar.h:72
int fitNr
Definition tpcpar.h:58
char name[MAX_TACNAME_LEN+1]
Definition tpcpar.h:50
int dataNr
Definition tpcpar.h:62
double * cl2
Definition tpcpar.h:70
char sw
Definition tpcpar.h:74
unsigned int model
Definition tpcpar.h:48
double * p
Definition tpcpar.h:64
double start
Definition tpcpar.h:52
double * sd
Definition tpcpar.h:66
double * cl1
Definition tpcpar.h:68
double end
Definition tpcpar.h:54
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
Header file for library libtpcextensions.
@ TPCERROR_CANNOT_OPEN
Cannot open file.
@ TPCERROR_OK
No error.
Header file for library libtpcift.
Header file for libtpcpar.
@ PAR_FORMAT_CSV_UK
UK CSV.
Definition tpcpar.h:33
@ PAR_FORMAT_UNKNOWN
Unknown format.
Definition tpcpar.h:28