TPCCLIB
Loading...
Searching...
No Matches
tacunit.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 "tpctac.h"
18/*****************************************************************************/
19
20/*****************************************************************************/
21static char *info[] = {
22 "Get the data units of TAC files, or optionally set or convert the units.",
23 " ",
24 "Usage: @P [options] filename(s)",
25 " ",
26 "Options:",
27 " -xset=<unit>",
28 " Set x (sample time) unit; x values are however not changed.",
29 " -yset=<unit>",
30 " Set y (concentration) unit; y values are however not changed.",
31 " -xconv=<unit>",
32 " Conversion of x (sample time) values to specified unit.",
33 " -yconv=<unit>",
34 " Conversion of y (concentration) values to specified unit.",
35 " -x",
36 " Print only the unit of x in stdout.",
37 " -y",
38 " Print only the unit of y in stdout.",
39 " -density=<Density (g/mL)>",
40 " Density is needed when converting per mass to per volume units.",
41 " -units",
42 " List available units and quit.",
43 " -stdoptions", // List standard options like --help, -v, etc
44 " ",
45 "Example 1: convert sample times to minutes and concentrations to kBq/mL",
46 " @P -xconv=min -yconv=kBq/ml iea*.tac",
47 " ",
48 "Example 2: convert concentrations to the same units as in another file",
49 " (in Linux/UNIX/OS X)",
50 " unit=$( @P -y iea2285.tac )",
51 " @P -yconv=$unit iea2285.bld",
52 " ",
53 "See also: taclist, tac2suv, taccalc, imgunit, tacframe, dftmax",
54 " ",
55 "Keywords: TAC, tool, unit, time",
56 0};
57/*****************************************************************************/
58
59/*****************************************************************************/
60/* Turn on the globbing of the command line, since it is disabled by default in
61 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
62 In Unix&Linux wildcard command line processing is enabled by default. */
63/*
64#undef _CRT_glob
65#define _CRT_glob -1
66*/
67int _dowildcard = -1;
68/*****************************************************************************/
69
70/*****************************************************************************/
74int main(int argc, char **argv)
75{
76 int ai, help=0, version=0, verbose=1;
77 int ret;
78 int list_units=0; // 1=list available units and exit
79 int print_x=0, print_y=0; // 1=print unit without anything else
80 int newxunit=-1, newyunit=-1;
81 int oldxunit=-1, oldyunit=-1;
82 int change_x=0; // 0=not changed, 1=also values are changed
83 int change_y=0; // 0=not changed, 1=also values are changed
84 double density=nan("");
85 char tacfile[FILENAME_MAX];
86 TAC tac;
87
88
89 /*
90 * Get arguments
91 */
92 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
93 tacInit(&tac);
94 tacfile[0]=(char)0;
95 /* Options */
96 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
97 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
98 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
99 if(strncasecmp(cptr, "xset=", 5)==0) {
100 cptr+=5;
101 newxunit=unitIdentify(cptr); if(newxunit!=UNIT_UNKNOWN) continue;
102 if(!cptr[0] || strcasecmp(cptr, "UNKNOWN")==0) continue;
103 } else if(strncasecmp(cptr, "yset=", 5)==0) {
104 cptr+=5;
105 newyunit=unitIdentify(cptr); if(newyunit!=UNIT_UNKNOWN) continue;
106 if(!cptr[0] || strcasecmp(cptr, "UNKNOWN")==0) continue;
107 } else if(strncasecmp(cptr, "xconv=", 6)==0) {
108 cptr+=6; change_x=1;
109 newxunit=unitIdentify(cptr); if(newxunit!=UNIT_UNKNOWN) continue;
110 if(!cptr[0] || strcasecmp(cptr, "UNKNOWN")==0) continue;
111 } else if(strncasecmp(cptr, "yconv=", 6)==0) {
112 cptr+=6; change_y=1;
113 newyunit=unitIdentify(cptr); if(newyunit!=UNIT_UNKNOWN) continue;
114 if(!cptr[0] || strcasecmp(cptr, "UNKNOWN")==0) continue;
115 } else if(strcasecmp(cptr, "x")==0) {
116 print_x=1; continue;
117 } else if(strcasecmp(cptr, "y")==0) {
118 print_y=1; continue;
119 } else if(strcasecmp(cptr, "UNITS")==0) {
120 list_units=1; continue;
121 } else if(strncasecmp(cptr, "DENSITY=", 8)==0) {
122 if(atofCheck(cptr+8, &density)==0 && density>0.0) continue;
123 }
124 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
125 return(1);
126 } else break; // tac name argument may start with '-'
127 /* Print help or version? */
128 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
129 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
130 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
131
132 /* In verbose mode print arguments and options */
133 if(verbose>1) {
134 printf("list_units := %d\n", list_units);
135 printf("print_x := %d\n", print_x);
136 printf("print_y := %d\n", print_y);
137 printf("change_x := %d\n", change_x);
138 printf("change_y := %d\n", change_y);
139 if(!isnan(density)) printf("density := %g\n", density);
140 if(newxunit>=0) printf("newxunit := %s\n", unitName(newxunit));
141 if(newyunit>=0) printf("newyunit := %s\n", unitName(newyunit));
142 }
143
144 TPCSTATUS status; statusInit(&status);
145 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
146 status.verbose=verbose-1;
147
148 /* If units are to be listed, then do that and exit */
149 if(list_units) {
150 for(int u=0; u<UNIT_LAST; u++) printf("%s\n", unitName(u));
151 return 0;
152 }
153
154 /* Process other arguments, starting from the first non-option */
155 int n=0, nr_of_changes, err_nr=0;
156 for(; ai<argc; ai++) {
157 /* It should be the TAC filename */
158 strcpy(tacfile, argv[ai]);
159 /* Read TAC file */
160 if(verbose>1) printf("reading %s\n", tacfile);
161 ret=tacRead(&tac, tacfile, &status);
162 if(ret!=TPCERROR_OK) {
163 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
164 tacFree(&tac); return(2);
165 }
166 n++;
167 /* Save original units */
168 oldxunit=tac.tunit;
169 oldyunit=tac.cunit;
170 /* If clean printing was required, then do just that */
171 if(print_x || print_y) {
172 if(print_x) fprintf(stdout, "%s\n", unitName(tac.tunit));
173 if(print_y) fprintf(stdout, "%s\n", unitName(tac.cunit));
174 fflush(stdout); tacFree(&tac); continue;
175 }
176 /* If new units were not set then just print the units */
177 if(newxunit==-1 && newyunit==-1) {
178 fprintf(stdout, "# filename := %s\n", tacfile);
179 fprintf(stdout, "unit := %s\n", unitName(tac.cunit));
180 fprintf(stdout, "timeunit := %s\n", unitName(tac.tunit));
181 /* do not save the data, since it is not modified */
182 fflush(stdout); tacFree(&tac); continue;
183 }
184 nr_of_changes=0;
185 /* X unit */
186 if(newxunit>=0 && newxunit!=oldxunit) {
187 if(change_x==0) {
188 tac.tunit=newxunit;
189 if(verbose>0) fprintf(stdout, "%s: units '%s' replaced by '%s'\n",
190 tacfile, unitName(oldxunit), unitName(newxunit));
191 nr_of_changes++;
192 } else {
193 ret=tacXUnitConvert(&tac, newxunit, &status);
194 if(ret==TPCERROR_OK) {
195 if(verbose>0) fprintf(stdout, "%s: conversion of units '%s' to '%s'\n",
196 tacfile, unitName(oldxunit), unitName(newxunit));
197 nr_of_changes++;
198 } else {
199 err_nr++;
200 fprintf(stderr, "%s:\n", tacfile);
201 fprintf(stderr, "Error: conversion from '%s' to '%s' not supported.\n",
202 unitName(oldxunit), unitName(newxunit));
203 }
204 }
205 fflush(stdout);
206 }
207 /* Y unit */
208 if(newyunit>=0 && newyunit!=oldyunit) {
209 if(change_y==0) {
210 tac.cunit=newyunit;
211 if(verbose>0) fprintf(stdout, "%s: units '%s' replaced by '%s'\n",
212 tacfile, unitName(oldyunit), unitName(newyunit));
213 nr_of_changes++;
214 } else {
215 ret=tacYUnitConvert(&tac, newyunit, &status);
216 if(ret==TPCERROR_OK) {
217 if(verbose>0) fprintf(stdout, "%s: conversion of units '%s' to '%s'\n",
218 tacfile, unitName(oldyunit), unitName(newyunit));
219 nr_of_changes++;
220 } else if(!isnan(density)) {
221 /* Failed, but check if converting gram to mL or vice versa helps */
222 if(unitDividerHasVolume(oldyunit) && unitDividerHasMass(newyunit)) {
223 ret=tacYUnitVolume2Mass(&tac, density, &status);
224 } else if(unitDividerHasMass(oldyunit) && unitDividerHasVolume(newyunit)) {
225 ret=tacYUnitMass2Volume(&tac, density, &status);
226 }
227 if(verbose>1 && ret==TPCERROR_OK)
228 fprintf(stdout, "%s: initial conversion of units '%s' to '%s'\n",
229 tacfile, unitName(oldyunit), unitName(tac.cunit));
230 /* Try conversion again */
231 ret=tacYUnitConvert(&tac, newyunit, &status);
232 if(ret==TPCERROR_OK) {
233 if(verbose>0) fprintf(stdout, "%s: conversion of units '%s' to '%s'\n",
234 tacfile, unitName(oldyunit), unitName(newyunit));
235 nr_of_changes++;
236 }
237 }
238 if(ret!=TPCERROR_OK) {
239 err_nr++;
240 fprintf(stderr, "%s:\n", tacfile);
241 fprintf(stderr, "Error: conversion from '%s' to '%s' not supported.\n",
242 unitName(oldyunit), unitName(newyunit));
243 }
244 }
245 fflush(stdout);
246 }
247 /* No reason to save data, if nothing was changed */
248 if(nr_of_changes==0) {tacFree(&tac); continue;}
249 /* Save modified data */
250 if(verbose>1) printf("writing %s\n", tacfile);
251 FILE *fp; fp=fopen(tacfile, "w");
252 if(fp==NULL) {
253 fprintf(stderr, "Error: cannot open file for writing (%s)\n", tacfile);
254 tacFree(&tac); return(5);
255 }
256 ret=tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, 1, &status);
257 fclose(fp);
258 if(ret!=TPCERROR_OK) {
259 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
260 tacFree(&tac); return(6);
261 }
262 tacFree(&tac);
263 } // next file
264 tacFree(&tac);
265
266 if(n==0) fprintf(stderr, "Error: no TAC(s) were found.\n");
267 if(n==0 || err_nr>0) return(2);
268
269 return(0);
270}
271/*****************************************************************************/
272
273/*****************************************************************************/
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
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
Definition tpctac.h:87
unit cunit
Definition tpctac.h:105
unit tunit
Definition tpctac.h:109
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 tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
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 tacYUnitMass2Volume(TAC *tac, const double density, TPCSTATUS *status)
Definition tacunits.c:169
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
int tacYUnitVolume2Mass(TAC *tac, const double density, TPCSTATUS *status)
Definition tacunits.c:121
Header file for library libtpcextensions.
@ UNIT_UNKNOWN
Unknown unit.
@ UNIT_LAST
end of list
@ TPCERROR_OK
No error.
int unitIdentify(const char *s)
Definition units.c:162
char * unitName(int unit_code)
Definition units.c:143
int unitDividerHasVolume(int u)
Definition units.c:678
int unitDividerHasMass(int u)
Definition units.c:694
Header file for library libtpcift.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28