TPCCLIB
Loading...
Searching...
No Matches
tacblend.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#include <unistd.h>
15/*****************************************************************************/
16#include "tpcextensions.h"
17#include "tpcift.h"
18#include "tpctac.h"
19/*****************************************************************************/
20
21/*****************************************************************************/
22static char *info[] = {
23 "Pools all samples in TAC files. Overlapping samples are preserved.",
24 "Each TAC file must contain the same number of TACs with equal names,",
25 "but sample number can be different.",
26 " ",
27 "Usage: @P [options] outputfile tacfiles",
28 " ",
29 "Options:",
30 " --force",
31 " Program does not mind if the time or calibration units cannot be",
32 " converted to match, or if TAC names do not match.",
33 " -stdoptions", // List standard options like --help, -v, etc
34 " ",
35 "See also: tacadd, taccat, tacjoin, tacunit, avgbolus, avgttac, tacmsamp",
36 " ",
37 "Keywords: TAC, tool",
38 0};
39/*****************************************************************************/
40
41/*****************************************************************************/
42/* Turn on the globbing of the command line, since it is disabled by default in
43 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
44 In Unix&Linux wildcard command line processing is enabled by default. */
45/*
46#undef _CRT_glob
47#define _CRT_glob -1
48*/
49int _dowildcard = -1;
50/*****************************************************************************/
51
52/*****************************************************************************/
56int main(int argc, char **argv)
57{
58 int ai, help=0, version=0, verbose=1;
59 int ret;
60 int checkData=1;
61 char tacfile[FILENAME_MAX], outfile[FILENAME_MAX];
62 int fileNr=0, file1=0;
63
64
65 /*
66 * Get arguments
67 */
68 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
69 tacfile[0]=outfile[0]=(char)0;
70 /* Options */
71 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
72 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
73 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
74 if(strcasecmp(cptr, "F")==0 || strcasecmp(cptr, "FORCE")==0) {
75 checkData=0; continue;
76 }
77 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
78 return(1);
79 } else break; // tac name argument may start with '-'
80
81 TPCSTATUS status; statusInit(&status);
82 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
83 status.verbose=verbose-3;
84
85 /* Print help or version? */
86 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
87 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
88 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
89
90 /* Process other arguments, starting from the first non-option */
91 if(ai<argc) strlcpy(outfile, argv[ai++], FILENAME_MAX);
92 for(; ai<argc; ai++) {
93 if(fileNr==0) file1=ai;
94 fileNr++;
95 }
96
97
98 /* In verbose mode print arguments and options */
99 if(verbose>1) {
100 for(ai=0; ai<argc; ai++) printf("%s ", argv[ai]);
101 printf("\n");
102 printf("fileNr := %d\n", fileNr);
103 printf("outfile := %s\n", outfile);
104 fflush(stdout);
105 }
106
107 /* Is something missing? */
108 if(!outfile[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
109 if(fileNr==0) {
110 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
111 return(1);
112 }
113 if(fileNr==1) {
114 fprintf(stderr, "Error: only one input file specified.\n");
115 return(1);
116 }
117
118
119 /* Check that all input files do exist, and that their name does not match output file name */
120 for(ai=file1; ai<argc; ai++) {
121 strlcpy(tacfile, argv[ai], FILENAME_MAX);
122 if(access(tacfile, 0) == -1) {
123 fprintf(stderr, "Error: input file %s does not exist.\n", tacfile);
124 return(2);
125 }
126 if(strcasecmp(outfile, tacfile)==0) {
127 fprintf(stderr, "Error: input file would be overwritten.\n");
128 return(2);
129 }
130 }
131
132
133 /*
134 * Read the first file
135 */
136 TAC tac, pool;
137 tacInit(&tac); tacInit(&pool);
138 strlcpy(tacfile, argv[file1], FILENAME_MAX);
139 if(verbose>1) printf("reading %s\n", tacfile);
140 ret=tacRead(&pool, tacfile, &status);
141 if(ret!=TPCERROR_OK) {
142 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
143 tacFree(&pool); return(2);
144 }
145 if(checkData) tacSortByName(&pool, &status);
146 if(verbose>2) {
147 printf("fileformat := %s\n", tacFormattxt(pool.format));
148 printf("tacNr := %d\n", pool.tacNr);
149 printf("sampleNr := %d\n", pool.sampleNr);
150 printf("xunit := %s\n", unitName(pool.tunit));
151 printf("yunit := %s\n", unitName(pool.cunit));
152 }
153 if(tacXNaNs(&pool)>0) {
154 fprintf(stderr, "Error: missing x values in %s\n", tacfile);
155 tacFree(&pool); return(2);
156 }
157#if(0)
158 /* Remove any weighting */
160#endif
161
162
163 /*
164 * Add the data from the other files
165 */
166 int differentTUnits=0;
167 int differentCUnits=0;
168 for(ai=file1+1; ai<argc; ai++) {
169 strlcpy(tacfile, argv[ai], FILENAME_MAX);
170 if(verbose>1) printf("reading %s\n", tacfile);
171 ret=tacRead(&tac, tacfile, &status);
172 if(ret!=TPCERROR_OK) {
173 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
174 tacFree(&pool); tacFree(&tac); return(2);
175 }
176 if(checkData) tacSortByName(&tac, &status);
177 if(verbose>2) {
178 printf("fileformat := %s\n", tacFormattxt(tac.format));
179 printf("tacNr := %d\n", tac.tacNr);
180 printf("sampleNr := %d\n", tac.sampleNr);
181 printf("xunit := %s\n", unitName(tac.tunit));
182 printf("yunit := %s\n", unitName(tac.cunit));
183 }
184 if(tacXNaNs(&pool)>0) {
185 fprintf(stderr, "Error: missing x values in %s\n", tacfile);
186 tacFree(&pool); tacFree(&tac); return(2);
187 }
188 /* Check if the TAC number is different */
189 if(pool.tacNr!=tac.tacNr) {
190 fprintf(stderr, "Error: different number of TACs.\n");
191 tacFree(&pool); tacFree(&tac); return(3);
192 }
193 /* Check that TAC names match, if requested */
194 if(checkData && tacCompareNames(&pool, &tac, -1, &status)!=0) {
195 fprintf(stderr, "Error: TAC names do not match.\n");
196 tacFree(&pool); tacFree(&tac); return(3);
197 }
198 /* Try to convert time units to time units in the first file */
199 ret=tacXUnitConvert(&tac, pool.tunit, &status);
201 if(ret!=TPCERROR_OK) {
202 if(verbose>2) fprintf(stderr, "Status: %s\n", errorMsg(status.error));
203 if(checkData) {
204 fprintf(stderr, "Error: non-compatible TAC time units.\n");
205 tacFree(&pool); tacFree(&tac); return(4);
206 }
207 differentTUnits++;
208 }
209 /* Try to convert concentration units to time units in the first file */
210 ret=tacYUnitConvert(&tac, pool.cunit, &status);
212 if(ret!=TPCERROR_OK) {
213 if(verbose>2) fprintf(stderr, "Status: %s\n", errorMsg(status.error));
214 if(checkData) {
215 fprintf(stderr, "Error: non-compatible TAC concentration units.\n");
216 tacFree(&pool); tacFree(&tac); return(5);
217 }
218 differentCUnits++;
219 }
220 /* If at least one of TAC files only has frame mid times, then all have */
221 if(tac.isframe==0) pool.isframe=0;
222 /* Add the new sample values */
223 ret=tacAllocateMoreSamples(&pool, tac.sampleNr);
224 if(ret!=TPCERROR_OK) {
225 fprintf(stderr, "Error: cannot allocate memory.\n");
226 tacFree(&pool); tacFree(&tac); return(6);
227 }
228 for(int i=0; i<tac.sampleNr; i++) {
229 pool.x[pool.sampleNr]=tac.x[i];
230 pool.x1[pool.sampleNr]=tac.x1[i];
231 pool.x2[pool.sampleNr]=tac.x2[i];
232 for(int j=0; j<pool.tacNr; j++) pool.c[j].y[pool.sampleNr]=tac.c[j].y[i];
233 pool.w[pool.sampleNr]=tac.w[i];
234 pool.sampleNr++;
235 }
236 tacFree(&tac);
237 }
238 if(verbose>0 && differentTUnits>1) fprintf(stderr,
239 "Warning: time units could not be converted for %d file(s).\n", differentTUnits);
240 if(verbose>0 && differentCUnits>1) fprintf(stderr,
241 "Warning: concentration units could not be converted for %d file(s).\n", differentCUnits);
242
243 /*
244 * Sort pooled data by sample time
245 */
246 ret=tacSortByTime(&pool, &status);
247 if(ret!=TPCERROR_OK) {
248 fprintf(stderr, "Error: cannot sort the pooled data.\n");
249 tacFree(&pool); return(8);
250 }
251 /* Delete study number, if one exists */
252 (void)tacSetHeaderStudynr(&pool.h, "");
253
254
255 /*
256 * Save data
257 */
258 if(verbose>1) printf("writing %s\n", outfile);
259 FILE *fp; fp=fopen(outfile, "w");
260 if(fp==NULL) {
261 fprintf(stderr, "Error: cannot open file for writing (%s)\n", outfile);
262 tacFree(&tac); return(11);
263 }
264 ret=tacWrite(&pool, fp, TAC_FORMAT_UNKNOWN, 1, &status);
265 fclose(fp);
266 if(ret!=TPCERROR_OK) {
267 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
268 tacFree(&pool); return(12);
269 }
270 if(verbose>=0) {
271 printf("%d samples from %d TAC files pooled.\n", pool.sampleNr, fileNr);
272 printf("%s saved.\n", outfile);
273 }
274 tacFree(&pool);
275
276 return(0);
277}
278/*****************************************************************************/
279
280/*****************************************************************************/
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
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
double * y
Definition tpctac.h:75
Definition tpctac.h:87
double * x
Definition tpctac.h:97
unit cunit
Definition tpctac.h:105
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
double * w
Definition tpctac.h:111
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
weights weighting
Definition tpctac.h:115
double * x2
Definition tpctac.h:101
unit tunit
Definition tpctac.h:109
double * x1
Definition tpctac.h:99
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
void tacFree(TAC *tac)
Definition tac.c:106
void tacInit(TAC *tac)
Definition tac.c:24
int tacAllocateMoreSamples(TAC *tac, int addNr)
Allocate memory for more samples in TAC data.
Definition tac.c:435
int tacCompareNames(TAC *d1, TAC *d2, const int i, TPCSTATUS *status)
Definition taccomp.c:67
int tacSetHeaderStudynr(IFT *h, const char *s)
Definition tacift.c:79
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
char * tacFormattxt(tacformat c)
Definition tacio.c:98
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
Definition tacio.c:332
int tacXNaNs(TAC *tac)
Definition tacnan.c:23
int tacSortByTime(TAC *d, TPCSTATUS *status)
Definition tacorder.c:74
int tacSortByName(TAC *d, TPCSTATUS *status)
Definition tacorder.c:178
int tacYUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:72
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
Header file for library libtpcextensions.
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ TPCERROR_UNKNOWN_UNIT
Unknown data unit.
@ TPCERROR_OK
No error.
char * unitName(int unit_code)
Definition units.c:143
Header file for library libtpcift.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28