TPCCLIB
Loading...
Searching...
No Matches
tacpeak.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/*****************************************************************************/
24
25/*****************************************************************************/
26static char *info[] = {
27 "Find peak time and value in TAC file.",
28 " ",
29 "Usage: @P [options] tacfile [outputfile]",
30 " ",
31 "Options:",
32 " -decr=<Percentage>",
33 " Estimate time when TAC decreases to specified percentage of peak value.",
34 " -wt",
35 " Peak time is reported as weighted average of subsequent samples.",
36 " -swa",
37 " TAC mean is subtracted from peak value.",
38 " -stdoptions", // List standard options like --help, -v, etc
39 " ",
40 "See also: imgpeak, dftmax, inpstart, tacrange, taccut, tacslope",
41 " ",
42 "Keywords: TAC, peak, max, time",
43 0};
44/*****************************************************************************/
45
46/*****************************************************************************/
47/* Turn on the globbing of the command line, since it is disabled by default in
48 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
49 In Unix&Linux wildcard command line processing is enabled by default. */
50/*
51#undef _CRT_glob
52#define _CRT_glob -1
53*/
54int _dowildcard = -1;
55/*****************************************************************************/
56
57/*****************************************************************************/
61int main(int argc, char **argv)
62{
63 int ai, help=0, version=0, verbose=1;
64 char tacfile[FILENAME_MAX], parfile[FILENAME_MAX];
65 double decr=nan("");
66 int timeAsWAvg=0; // 1=report peak time as activity weighted mean.
67 int subtractWAvg=0; // 1=subtract TAC mean from the peak value.
68
69
70 /*
71 * Get arguments
72 */
73 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
74 tacfile[0]=parfile[0]=(char)0;
75 /* Options */
76 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
77 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
78 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
79 if(strncasecmp(cptr, "DECR=", 5)==0) {
80 if(atofCheck(cptr+5, &decr)==0) {
81 if(decr>1.0 && decr<100.0) continue;
82 }
83 } else if(strcasecmp(cptr, "WT")==0) {
84 timeAsWAvg=1; continue;
85 } else if(strcasecmp(cptr, "SWA")==0) {
86 subtractWAvg=1; continue;
87 }
88 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
89 return(1);
90 } else break; // tac name argument may start with '-'
91
92 TPCSTATUS status; statusInit(&status);
93 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
94 status.verbose=verbose-1;
95
96 /* Print help or version? */
97 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
98 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
99 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
100
101
102 /* Arguments */
103 if(ai<argc) strlcpy(tacfile, argv[ai++], FILENAME_MAX);
104 if(ai<argc) strlcpy(parfile, argv[ai++], FILENAME_MAX);
105 if(ai<argc) {fprintf(stderr, "Error: too many arguments.\n"); return(1);}
106
107 /* Is something missing? */
108 if(!tacfile[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
109
110 /* In verbose mode print arguments and options */
111 if(verbose>1) {
112 for(ai=0; ai<argc; ai++) printf("%s ", argv[ai]);
113 printf("\n");
114 printf("tacfile := %s\n", tacfile);
115 if(parfile[0]) printf("parfile := %s\n", parfile);
116 if(!isnan(decr)) printf("decr_percent := %g\n", decr);
117 printf("timeAsWAvg := %d\n", timeAsWAvg);
118 printf("subtractWAvg := %d\n", subtractWAvg);
119 }
120
121
122 /*
123 * Read the file
124 */
125 if(verbose>1) printf("reading %s\n", tacfile);
126 TAC tac; tacInit(&tac);
127 if(tacRead(&tac, tacfile, &status)!=TPCERROR_OK) {
128 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
129 tacFree(&tac); return(2);
130 }
131 if(verbose>2) {
132 printf("fileformat := %s\n", tacFormattxt(tac.format));
133 printf("tacNr := %d\n", tac.tacNr);
134 printf("sampleNr := %d\n", tac.sampleNr);
135 printf("xunit := %s\n", unitName(tac.tunit));
136 printf("yunit := %s\n", unitName(tac.cunit));
137 }
138 /* Sort the data by sample times (x) */
139 if(tacSortByTime(&tac, &status)!=TPCERROR_OK) {
140 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
141 tacFree(&tac); return(2);
142 }
143 /* Get x range */
144 double xmin, xmax;
145 if(tacXRange(&tac, &xmin, &xmax)!=0) {
146 fprintf(stderr, "Error: invalid data sample times.\n");
147 tacFree(&tac); return(2);
148 }
149 if(verbose>1) {
150 printf("xmin := %g\n", xmin);
151 printf("xmax := %g\n", xmax);
152 }
153 /* Take average of any duplicate samples */
154 if(tacMultipleSamples(&tac, 1, &tac, verbose-2)!=0) {
155 fprintf(stderr, "Error: cannot process duplicate samples.\n");
156 tacFree(&tac); return(2);
157 }
158
159 /*
160 * Prepare space for results
161 */
162 if(verbose>1) printf("preparing space for parameters\n");
163 PAR par; parInit(&par);
164 if(parAllocateWithTAC(&par, &tac, 3, &status)!=TPCERROR_OK) {
165 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
166 tacFree(&tac); return(3);
167 }
168 par.tacNr=tac.tacNr;
169 par.parNr=2; if(!isnan(decr)) par.parNr++;
171 for(int i=0; i<tac.tacNr; i++) {
172 par.r[i].model=0;
173 par.r[i].dataNr=tacWSampleNr(&tac);
174 par.r[i].start=xmin;
175 par.r[i].end=xmax;
176 }
177 /* Set parameter names */
178 strcpy(par.n[0].name, "Peak");
179 strcpy(par.n[1].name, "PeakT");
180 sprintf(par.n[2].name, "T%g%%", roundf(decr));
181
182 /*
183 * Search peak values
184 */
185 if(verbose>1) printf("searching peaks\n");
186 for(int ci=0; ci<tac.tacNr; ci++) {
187
188 if(verbose>2) printf("%s\n", tac.c[ci].name);
189 for(int i=0; i<par.parNr; i++) par.r[ci].p[i]=nan("");
190
191 /* Find peak value and its sample index */
192 double ymax; int imax;
193 if(tacYRange(&tac, ci, NULL, &ymax, NULL, &imax, NULL, NULL)!=0) {
194 fprintf(stderr, "Error: no maximum found for TAC '%s'.\n", tac.c[ci].name);
195 continue;
196 }
197 if(verbose>2) {
198 printf(" maxv := %g\n", ymax);
199 printf(" maxx := %g\n", tac.x[imax]);
200 }
201 par.r[ci].p[0]=ymax;
202 par.r[ci].p[1]=tac.x[imax];
203
204 /* If requested, refine peak time to activity weighted avg */
205 if(timeAsWAvg && imax>0 && imax<tac.sampleNr-1) {
206 double s=0.0, ws=0.0;
207 int i1, i2; i1=imax-1; i2=imax+1; if(i1>0 && i2<tac.sampleNr-1) {i1--; i2++;}
208 for(int i=i1; i<=i2; i++) {s+=tac.c[ci].y[i]*tac.x[i]; ws+=tac.c[ci].y[i];}
209 s/=ws; if(verbose>2) printf(" weighted_maxx := %g\n", s);
210 if(!isnan(s)) par.r[ci].p[1]=s;
211 }
212
213 /* If requested, search time after peak when TAC drops to specified level */
214 if(!isnan(decr)) {
215 double ylim=(decr/100.0)*ymax;
216 double x1=tac.x[imax];
217 double y1=tac.c[ci].y[imax];
218 double x2, y2; x2=y2=nan("");
219 for(int i=imax+1; i<tac.sampleNr; i++) {
220 if(isnan(tac.x[i])) continue;
221 if(isnan(tac.c[ci].y[i])) continue;
222 if(tac.c[ci].y[i]>ylim) {x1=tac.x[i]; y1=tac.c[ci].y[i]; continue;}
223 x2=tac.x[i]; y2=tac.c[ci].y[i];
224 break;
225 }
226 if(isnan(x2) || isnan(y2)) {
227 fprintf(stderr, "Error: TAC '%s' does not drop to specified level.\n", tac.c[ci].name);
228 } else {
229 if(verbose>2) {
230 printf(" prev_sample := (%g, %g)\n", x1, y1);
231 printf(" next_sample := (%g, %g)\n", x2, y2);
232 }
233 if(fabs(y2-y1)>1.0E-20) par.r[ci].p[2]=x1+(ylim-y1)*(x2-x1)/(y2-y1);
234 else par.r[ci].p[2]=0.5*(x1+x2);
235 }
236 }
237
238 /* If requested, compute TAC mean and subtract it from the peak value */
239 if(subtractWAvg) {
240 double auc=tacAUC(&tac, ci, xmin, xmax, NULL);
241 if(isnan(auc)) {
242 fprintf(stderr, "Error: invalid mean of TAC '%s'.\n", tac.c[ci].name);
243 } else {
244 double avg=auc/(xmax-xmin);
245 par.r[ci].p[0]-=avg;
246 }
247 }
248
249 } // next TAC
250 tacFree(&tac);
251
252
253 /*
254 * Print and save parameters
255 */
256 if(verbose>0 || !parfile[0]) parWrite(&par, stdout, PAR_FORMAT_TSV_UK, 1, NULL);
257 if(parfile[0]) {
258 /* Save file */
259 if(verbose>1) printf(" saving %s\n", parfile);
260 FILE *fp=fopen(parfile, "w");
261 if(fp==NULL) {
262 fprintf(stderr, "Error: cannot open file for writing.\n");
263 parFree(&par); return(11);
264 }
265 int ret=parWrite(&par, fp, PAR_FORMAT_UNKNOWN, 1, &status);
266 fclose(fp); parFree(&par);
267 if(ret!=TPCERROR_OK) {
268 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
269 return(12);
270 }
271 if(verbose>0) printf("parameters saved in %s\n", parfile);
272 }
273
274 return(0);
275}
276/*****************************************************************************/
277
278/*****************************************************************************/
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
double tacAUC(TAC *tac, int ti, double t1, double t2, TPCSTATUS *status)
Calculates TAC AUC from t1 to t2.
Definition litac.c:486
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
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
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
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
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 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
int tacYRange(TAC *d, int i, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct.
Definition tacy.c:26
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 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.
Header file for libtpctacmod.