TPCCLIB
Loading...
Searching...
No Matches
tacjoin.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 "Join all TACs in TAC files into one file, keeping each TAC separate.",
24 "Sample times can be different. Mid frame time is always used.",
25 " ",
26 "Usage: @P [options] outputfile tacfiles",
27 " ",
28 "Options:",
29 " --force",
30 " Program does not mind if the time or calibration units cannot be",
31 " converted to match.",
32 " -stdoptions", // List standard options like --help, -v, etc
33 " ",
34 "See also: tacblend, tacadd, avgttac, tacnames, tacformat, tac2xml",
35 " ",
36 "Keywords: TAC, tool, plotting",
37 0};
38/*****************************************************************************/
39
40/*****************************************************************************/
41/* Turn on the globbing of the command line, since it is disabled by default in
42 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
43 In Unix&Linux wildcard command line processing is enabled by default. */
44/*
45#undef _CRT_glob
46#define _CRT_glob -1
47*/
48int _dowildcard = -1;
49/*****************************************************************************/
50
51/*****************************************************************************/
55int main(int argc, char **argv)
56{
57 int ai, help=0, version=0, verbose=1;
58 int forceMode=0;
59 char tacfile[FILENAME_MAX], outfile[FILENAME_MAX];
60 int fileNr=0, file1=0;
61
62
63 /*
64 * Get arguments
65 */
66 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
67 tacfile[0]=outfile[0]=(char)0;
68 /* Options */
69 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
70 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
71 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
72 if(strcasecmp(cptr, "F")==0 || strcasecmp(cptr, "FORCE")==0) {
73 forceMode=1; continue;
74 }
75 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
76 return(1);
77 } else break; // tac name argument may start with '-'
78
79 TPCSTATUS status; statusInit(&status);
80 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
81 status.verbose=verbose-3;
82
83 /* Print help or version? */
84 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
85 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
86 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
87
88 /* Process other arguments, starting from the first non-option */
89 if(ai<argc) strlcpy(outfile, argv[ai++], FILENAME_MAX);
90 for(; ai<argc; ai++) {
91 if(fileNr==0) file1=ai;
92 fileNr++;
93 }
94
95 /* In verbose mode print arguments and options */
96 if(verbose>1) {
97 for(ai=0; ai<argc; ai++) printf("%s ", argv[ai]);
98 printf("\n");
99 printf("fileNr := %d\n", fileNr);
100 printf("outfile := %s\n", outfile);
101 printf("forceMode := %d\n", forceMode);
102 fflush(stdout);
103 }
104
105 /* Is something missing? */
106 if(!outfile[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
107 if(fileNr==0) {
108 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
109 return(1);
110 }
111 if(fileNr==1) {
112 fprintf(stderr, "Error: only one input file specified.\n");
113 return(1);
114 }
115
116 /* Check that all input files do exist, and that their name does not match output file name */
117 for(ai=file1; ai<argc; ai++) {
118 strlcpy(tacfile, argv[ai], FILENAME_MAX);
119 if(access(tacfile, 0) == -1) {
120 fprintf(stderr, "Error: input file %s does not exist.\n", tacfile);
121 return(2);
122 }
123 if(strcasecmp(outfile, tacfile)==0) {
124 fprintf(stderr, "Error: input file would be overwritten.\n");
125 return(2);
126 }
127 }
128
129
130 /*
131 * Read all TAC files
132 */
133 /* Allocate memory for an array of TACs */
134 TAC *taclist;
135 taclist=(TAC*)malloc(fileNr*sizeof(TAC));
136 if(taclist==NULL) {
137 fprintf(stderr, "Error: out of memory.\n");
138 return(3);
139 }
140 /* Initiate TAC structures */
141 for(int i=0; i<fileNr; i++) tacInit(taclist+i);
142 /* Read TAC files */
143 for(ai=file1; ai<argc; ai++) {
144 strlcpy(tacfile, argv[ai], FILENAME_MAX);
145 if(verbose>1) printf("reading %s\n", tacfile);
146 int i=ai-file1;
147 if(tacRead(taclist+i, tacfile, &status)) {
148 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
149 for(int j=0; j<i; j++) tacFree(taclist+j);
150 free(taclist); return(3);
151 }
152 if(verbose>2) {
153 printf("fileformat := %s\n", tacFormattxt(taclist[i].format));
154 printf("tacNr := %d\n", taclist[i].tacNr);
155 printf("sampleNr := %d\n", taclist[i].sampleNr);
156 }
157 /* Use mid times */
158 taclist[i].isframe=0;
159 }
160
161 if(verbose>1) printf("checking data...\n");
162
163 /* Convert TAC units when necessary */
164 for(int i=1; i<fileNr; i++) {
165 int ret=tacXUnitConvert(taclist+i, taclist[0].tunit, &status);
167 if(ret==TPCERROR_OK) {
168 ret=tacYUnitConvert(taclist+i, taclist[0].cunit, &status);
170 }
171 if(ret!=TPCERROR_OK) { // failed
172 /* failing is a problem if units are to be verified */
173 if(!forceMode) {
174 fprintf(stderr, "Error: non-compatible TAC units.\n");
175 for(int i=0; i<fileNr; i++) tacFree(taclist+i);
176 free(taclist); return(4);
177 }
178 }
179 }
180
181 /* Add the TACs to the first structure */
182 int rs[fileNr], cs[fileNr]; // place for storing data start indices
183 rs[0]=cs[0]=0;
184 if(verbose>1) {
185 printf("adding %d TACs with %d samples\n", taclist[0].tacNr, taclist[0].sampleNr);
186 fflush(stdout);
187 }
188 for(int i=1; i<fileNr; i++) {
189 cs[i]=taclist[0].tacNr; // always add to the first free column
190 if(taclist[i].tacNr<1) continue;
191 if(verbose>1) {
192 printf("adding %d TACs with %d samples\n", taclist[i].tacNr, taclist[i].sampleNr);
193 fflush(stdout);
194 }
195 /* See if any of the previous structures had the same sample times */
196 int ti=-1;
197 for(int j=0; j<i; j++) {
198 if(taclist[i].tacNr<1 || taclist[j].tacNr<1) continue;
199 if(tacCompareTimes(taclist+j, taclist+i, 0.001, 0.001, NULL)==0) {ti=j; break;}
200 }
201 if(verbose>1 && ti>=0) {
202 printf(" equal sample times in %s and %s\n", argv[file1+i], argv[file1+ti]); fflush(stdout);}
203 if(ti<0) rs[i]=taclist[0].sampleNr; else rs[i]=rs[ti];
204 if(verbose>2) printf(" adding TACs to index %d,%d\n", rs[i], cs[i]);
205 /* Add space for TACs, and for samples, if different sample times */
206 int ret=TPCERROR_OK;
207 if(ti<0) ret=tacAllocateMoreSamples(taclist+0, taclist[i].sampleNr);
208 if(ret==TPCERROR_OK) ret=tacAllocateMore(taclist+0, taclist[i].tacNr);
209 if(ret!=TPCERROR_OK) {
210 fprintf(stderr, "Error: cannot allocate memory.\n");
211 for(int j=0; j<i; j++) tacFree(taclist+j);
212 free(taclist); return(6);
213 }
214 if(verbose>3) {
215 printf(" allocated for %d TACs and %d samples\n", taclist[0]._tacNr, taclist[0]._sampleNr);
216 fflush(stdout);
217 }
218 /* If different sample times, copy those 'below' the previous data */
219 if(ti<0) {
220 if(verbose>3) {printf(" adding new sample times\n"); fflush(stdout);}
221 for(int j=0; j<taclist[i].sampleNr; j++) {
222 taclist[0].x[taclist[0].sampleNr+j]=taclist[i].x[j];
223 taclist[0].x1[taclist[0].sampleNr+j]=taclist[i].x1[j];
224 taclist[0].x2[taclist[0].sampleNr+j]=taclist[i].x2[j];
225 }
226 taclist[0].sampleNr+=taclist[i].sampleNr;
227 }
228 /* Copy the y values and TAC names */
229 if(verbose>3) {printf(" adding new TACs\n"); fflush(stdout);}
230 for(int ci=0; ci<taclist[i].tacNr; ci++) {
231 strcpy(taclist[0].c[cs[i]+ci].name, taclist[i].c[ci].name);
232 for(int ri=0; ri<taclist[i].sampleNr; ri++) {
233 taclist[0].c[cs[i]+ci].y[rs[i]+ri]=taclist[i].c[ci].y[ri];
234 }
235 }
236 taclist[0].tacNr+=taclist[i].tacNr;
237 }
238
239 /* Remove weights */
240 taclist[0].weighting=WEIGHTING_OFF;
241 /* Free the header data */
242 iftFree(&taclist[0].h);
243
244
245 /*
246 * Write joined data
247 */
248 {
249 if(verbose>1) printf("writing %s\n", outfile);
250 FILE *fp; fp=fopen(outfile, "w");
251 if(fp==NULL) {
252 fprintf(stderr, "Error: cannot open file for writing.\n");
253 for(int i=0; i<fileNr; i++) tacFree(taclist+i);
254 free(taclist);
255 return(11);
256 }
257 int ret=tacWrite(taclist+0, fp, TAC_FORMAT_UNKNOWN, 1, &status);
258 fclose(fp);
259 if(ret!=TPCERROR_OK) {
260 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
261 for(int i=0; i<fileNr; i++) tacFree(taclist+i);
262 free(taclist);
263 return(12);
264 }
265 if(verbose>=0) {
266 printf("%d TACs from %d files saved in %s\n", taclist[0].tacNr, fileNr, outfile);
267 }
268 }
269
270 /* Free memory */
271 for(int i=0; i<fileNr; i++) tacFree(taclist+i);
272 free(taclist);
273
274 return(0);
275}
276/*****************************************************************************/
277
278/*****************************************************************************/
void iftFree(IFT *ift)
Definition ift.c:37
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
int sampleNr
Definition tpctac.h:89
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
weights weighting
Definition tpctac.h:115
double * x2
Definition tpctac.h:101
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 tacAllocateMore(TAC *tac, int tacNr)
Definition tac.c:178
int tacCompareTimes(TAC *d1, TAC *d2, const double test_abs, const double test_rel, TPCSTATUS *status)
Definition taccomp.c:201
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 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.
Header file for library libtpcift.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28