TPCCLIB
Loading...
Searching...
No Matches
tacslope.c
Go to the documentation of this file.
1
8/*****************************************************************************/
9#include "tpcclibConfig.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <math.h>
15/*****************************************************************************/
16#include "tpcextensions.h"
17#include "tpcift.h"
18#include "tpctac.h"
19#include "tpcmodels.h"
20#include "tpcpar.h"
21#include "tpcfunc.h"
22#include "tpctacmod.h"
23#include "tpclinopt.h"
24/*****************************************************************************/
25
26/*****************************************************************************/
27static char *info[] = {
28 "Find the highest slope in TAC file. The intercept with x axis",
29 "can be used as an estimate of tracer appearance time.",
30 " ",
31 "Usage: @P [options] tacfile [parfile]",
32 " ",
33 "Options:",
34 " -n=<fitted sample number>",
35 " Number of samples used to determine the slopes; by default 3.",
36 " -positive",
37 " Slope is verified to be positive, and if not, then error is returned.",
38 " -rmbkg",
39 " Sample values before estimated appearance time are set to zero.",
40 " -stdoptions", // List standard options like --help, -v, etc
41 " ",
42 "See also: tactime, fitdelay, taccut, tacpeak, inpstart, tacrange",
43 " ",
44 "Keywords: TAC, input, time delay, time",
45 0};
46/*****************************************************************************/
47
48/*****************************************************************************/
49/* Turn on the globbing of the command line, since it is disabled by default in
50 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
51 In Unix&Linux wildcard command line processing is enabled by default. */
52/*
53#undef _CRT_glob
54#define _CRT_glob -1
55*/
56int _dowildcard = -1;
57/*****************************************************************************/
58
59/*****************************************************************************/
63int main(int argc, char **argv)
64{
65 int ai, help=0, version=0, verbose=1;
66 char tacfile[FILENAME_MAX], parfile[FILENAME_MAX];
67 int rmBkg=0; // 1=set values before appearance time to zero
68 int reqPos=0; // 1=error, if slope is not positive
69 int nFit=3; // Nr of samples used in line fits
70
71 /*
72 * Get arguments
73 */
74 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
75 tacfile[0]=parfile[0]=(char)0;
76 /* Options */
77 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
78 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
79 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
80 if(strncasecmp(cptr, "RMBKG", 2)==0) {
81 rmBkg=1; reqPos=1; continue;
82 } else if(strncasecmp(cptr, "POSITIVE", 3)==0) {
83 reqPos=1; continue;
84 } else if(strncasecmp(cptr, "N=", 2)==0) {
85 if(atoiCheck(cptr+2, &nFit)==0 && nFit>1) continue;
86 }
87 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
88 return(1);
89 } else break; // tac name argument may start with '-'
90
91 TPCSTATUS status; statusInit(&status);
92 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
93 status.verbose=verbose-1;
94
95 /* Print help or version? */
96 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
97 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
98 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
99
100
101 /* Arguments */
102 if(ai<argc) strlcpy(tacfile, argv[ai++], FILENAME_MAX);
103 if(ai<argc) strlcpy(parfile, argv[ai++], FILENAME_MAX);
104 if(ai<argc) {fprintf(stderr, "Error: too many arguments.\n"); return(1);}
105
106 /* Is something missing? */
107 if(!tacfile[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
108
109 /* In verbose mode print arguments and options */
110 if(verbose>1) {
111 for(ai=0; ai<argc; ai++) printf("%s ", argv[ai]);
112 printf("\n");
113 printf("tacfile := %s\n", tacfile);
114 printf("nFit := %d\n", nFit);
115 printf("reqPos := %d\n", reqPos);
116 printf("rmBkg := %d\n", rmBkg);
117 }
118
119
120 /*
121 * Read the file
122 */
123 if(verbose>1) printf("reading %s\n", tacfile);
124 TAC tac; tacInit(&tac);
125 if(tacRead(&tac, tacfile, &status)!=TPCERROR_OK) {
126 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
127 tacFree(&tac); return(2);
128 }
129 if(verbose>2) {
130 printf("fileformat := %s\n", tacFormattxt(tac.format));
131 printf("tacNr := %d\n", tac.tacNr);
132 printf("sampleNr := %d\n", tac.sampleNr);
133 printf("xunit := %s\n", unitName(tac.tunit));
134 printf("yunit := %s\n", unitName(tac.cunit));
135 }
136 /* Sort the data by sample times (x) */
137 if(tacSortByTime(&tac, &status)!=TPCERROR_OK) {
138 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
139 tacFree(&tac); return(2);
140 }
141 /* Get x range */
142 double xmin, xmax;
143 if(tacXRange(&tac, &xmin, &xmax)!=0) {
144 fprintf(stderr, "Error: invalid data sample times.\n");
145 tacFree(&tac); return(2);
146 }
147 if(verbose>1) {
148 printf("xmin := %g\n", xmin);
149 printf("xmax := %g\n", xmax);
150 }
151 /* Take average of any duplicate samples */
152 if(tacMultipleSamples(&tac, 1, &tac, verbose-2)!=0) {
153 fprintf(stderr, "Error: cannot process duplicate samples.\n");
154 tacFree(&tac); return(2);
155 }
156 /* Check that fitting required nr of samples seems possible */
157 if(nFit>=tac.sampleNr) {
158 fprintf(stderr, "Error: too few samples for fitting.\n");
159 tacFree(&tac); return(2);
160 }
161
162
163 /*
164 * Prepare space for results
165 */
166 if(verbose>1) printf("preparing space for parameters\n");
167 PAR par; parInit(&par);
168 if(parAllocateWithTAC(&par, &tac, 4, &status)!=TPCERROR_OK) {
169 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
170 tacFree(&tac); return(3);
171 }
172 par.tacNr=tac.tacNr;
173 par.parNr=4;
175 for(int i=0; i<tac.tacNr; i++) {
176 par.r[i].model=0;
177 par.r[i].dataNr=tacWSampleNr(&tac);
178 par.r[i].start=xmin;
179 par.r[i].end=xmax;
180 }
181 /* Set parameter names */
182 strcpy(par.n[0].name, "sMax");
183 strcpy(par.n[1].name, "yIc"); par.n[1].unit=tac.cunit;
184 strcpy(par.n[2].name, "Ta"); par.n[2].unit=tac.tunit;
185 strcpy(par.n[3].name, "TsMax"); par.n[3].unit=tac.tunit;
186
187
188 /*
189 * Calculate max slopes
190 */
191 if(verbose>1) {printf("searching for maximal slopes...\n"); fflush(stdout);}
192 for(int i=0; i<tac.tacNr; i++) {
193 double slope, yi, xi, xh;
194 int ret=highestSlope(tac.x, tac.c[i].y, tac.sampleNr, nFit, nan(""), &slope, &yi, &xi, &xh);
195 if(ret) {
196 fprintf(stderr, "Error: cannot calculate max slope.\n");
197 if(verbose>2) fprintf(stderr, "ret := %d\n", ret);
198 tacFree(&tac); parFree(&par); return(4);
199 }
200 par.r[i].p[0]=slope;
201 par.r[i].p[1]=yi;
202 par.r[i].p[2]=xi;
203 par.r[i].p[3]=xh;
204 if(reqPos && !(slope>0.0)) {
205 fprintf(stderr, "Error: slope is not positive.\n");
206 tacFree(&tac); parFree(&par); return(5);
207 }
208 }
209 if(verbose>1) {printf("... done.\n"); fflush(stdout);}
210 /* Current, possibly edited, TAC data is not needed later */
211 tacFree(&tac);
212
213
214 /*
215 * If requested, save parameters
216 */
217 if(parfile[0]) {
218 /* Save file */
219 if(verbose>1) printf(" saving %s\n", parfile);
220 FILE *fp=fopen(parfile, "w");
221 if(fp==NULL) {
222 fprintf(stderr, "Error: cannot open file for writing.\n");
223 parFree(&par); return(11);
224 }
225 int ret=parWrite(&par, fp, PAR_FORMAT_UNKNOWN, 1, &status);
226 fclose(fp);
227 if(ret!=TPCERROR_OK) {
228 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
229 parFree(&par); return(12);
230 }
231 if(verbose>0) printf("parameters saved in %s\n", parfile);
232 }
233
234 /*
235 * Print on screen the mean results, in a format identified by tactime.
236 */
237 for(int pi=0; pi<par.parNr; pi++) {
238 double psum=0.0; int n=0;
239 for(int i=0; i<par.tacNr; i++) if(isfinite(par.r[i].p[pi])) {psum+=par.r[i].p[pi]; n++;}
240 if(n>0) printf("%s := %g\n", par.n[pi].name, psum/(double)n);
241 }
242
243
244 /*
245 * If requested, set to zero the values before Ta
246 */
247 if(rmBkg) {
248 if(verbose>1) printf("setting values before Ta to zero...\n");
249 /* Read TAC file again */
250 if(tacRead(&tac, tacfile, &status)!=TPCERROR_OK) {
251 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
252 tacFree(&tac); parFree(&par); return(6);
253 }
254 /* Set to zero the values before Ta */
255 int nChanged=0;
256 for(int ri=0; ri<tac.tacNr; ri++) {
257 for(int fi=0; fi<tac.sampleNr; fi++)
258 if(!(tac.x[fi]>=par.r[ri].p[2]) && !isnan(tac.c[ri].y[fi]) && tac.c[ri].y[fi]!=0.0) {
259 tac.c[ri].y[fi]=0.0; nChanged++;
260 }
261 }
262 /* If changes were made, then overwrite the original TAC file */
263 if(nChanged==0) {
264 if(verbose>0) printf("no changes made to %s\n", tacfile);
265 } else {
266 if(verbose>1) printf("writing %s\n", tacfile);
267 FILE *fp; fp=fopen(tacfile, "w");
268 if(fp==NULL) {
269 fprintf(stderr, "Error: cannot open file for writing (%s)\n", tacfile);
270 tacFree(&tac); parFree(&par); return(21);
271 }
272 if(tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, 1, &status)!=TPCERROR_OK) {
273 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
274 fclose(fp); tacFree(&tac); parFree(&par); return(22);
275 }
276 fclose(fp);
277 }
278 tacFree(&tac);
279 if(verbose>0) printf("edited TAC file saved.\n");
280 }
281 parFree(&par);
282
283 return(0);
284}
285/*****************************************************************************/
286
287/*****************************************************************************/
int atoiCheck(const char *s, int *v)
Definition intutil.c:25
void parFree(PAR *par)
Definition par.c:75
void parInit(PAR *par)
Definition par.c:25
int parWrite(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
Definition pario.c:148
int parAllocateWithTAC(PAR *par, TAC *tac, int parNr, TPCSTATUS *status)
Allocate PAR based on data in TAC.
Definition partac.c:90
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
int highestSlope(double *x, double *y, const int n, const int slope_n, double x_start, double *m, double *yi, double *xi, double *xh)
Definition regression.c:179
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
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 name[MAX_PARNAME_LEN+1]
Definition tpcpar.h:82
int dataNr
Definition tpcpar.h:62
unsigned int model
Definition tpcpar.h:48
double * p
Definition tpcpar.h:64
double start
Definition tpcpar.h:52
double end
Definition tpcpar.h:54
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
TACC * c
Definition tpctac.h:117
unit tunit
Definition tpctac.h:109
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 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 tacSortByTime(TAC *d, TPCSTATUS *status)
Definition tacorder.c:74
int tacMultipleSamples(TAC *d1, const int fixMode, TAC *d2, const int verbose)
Check TAC data for multiple samples with the same sample time. Optionally replace the multiple sample...
Definition tacorder.c:336
unsigned int tacWSampleNr(TAC *tac)
Definition tacw.c:219
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:124
Header file for library libtpcextensions.
@ TPCERROR_OK
No error.
char * unitName(int unit_code)
Definition units.c:143
Header file for libtpcfunc.
Header file for library libtpcift.
Header file for libtpclinopt.
Header file for libtpcmodels.
Header file for libtpcpar.
@ PAR_FORMAT_UNKNOWN
Unknown format.
Definition tpcpar.h:28
@ PAR_FORMAT_TSV_UK
UK TSV (point as decimal separator).
Definition tpcpar.h:35
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28
Header file for libtpctacmod.