TPCCLIB
Loading...
Searching...
No Matches
inpstart.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "tpcclibConfig.h"
11/*****************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15#include <string.h>
16#include <math.h>
17/*****************************************************************************/
18#include "libtpcmisc.h"
19#include "libtpcmodel.h"
20#include "libtpccurveio.h"
21#include "libtpcmodext.h"
22/*****************************************************************************/
23
24/*****************************************************************************/
25/* Local functions */
26int dftFixPeak(DFT *dft, int verbose);
27/*****************************************************************************/
28
29/*****************************************************************************/
30static char *info[] = {
31 "Verifies that peak is not missed in an input TAC file.",
32 "Return code is zero, if no problems were encountered.",
33 "This may be used in scripts for a rough test if venous plasma TAC can",
34 "be used as input in Patlak analysis, but it must not replace visual",
35 "inspection.",
36 " ",
37 "Usage: @P [Options] <TAC file(s)>",
38 " ",
39 "Options:",
40 " -fix",
41 " Minor problems are corrected; always check the result before use.",
42 " -stdoptions", // List standard options like --help, -v, etc
43 " ",
44 "Example 1: check that specified data files are suitable as input TACs",
45 " @P *vp.kbq",
46 " ",
47 "See also: tacframe, tactime, avgbolus, taccat, interpol",
48 " ",
49 "Keywords: TAC, input, plasma, peak, zero",
50 0};
51/*****************************************************************************/
52
53/*****************************************************************************/
54/* Turn on the globbing of the command line, since it is disabled by default in
55 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
56 In Unix&Linux wildcard command line processing is enabled by default. */
57/*
58#undef _CRT_glob
59#define _CRT_glob -1
60*/
61int _dowildcard = -1;
62/*****************************************************************************/
63
64/*****************************************************************************/
68int main(int argc, char **argv)
69{
70 int ai, help=0, version=0, verbose=1;
71 int ri, fileNr=0, ffi=0, ret, errorCount=0, doFix=0, fixed, checked=0;
72 char *cptr, tmp[256], dftfile[FILENAME_MAX];
73 DFT dft;
74
75
76 /*
77 * Get arguments
78 */
79 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
80 dftfile[0]=(char)0;
81 dftInit(&dft);
82 /* Options */
83 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
84 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
85 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
86 if(strcasecmp(cptr, "FIX")==0) {
87 doFix=1; continue;
88 }
89 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
90 return(1);
91 } else break;
92
93 /* Print help or version? */
94 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
95 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
96 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
97
98 /* Process other arguments, starting from the first non-option */
99 for(; ai<argc; ai++) {
100 if(ffi==0) ffi=ai;
101 fileNr++;
102 }
103
104 /* Is something missing? */
105 if(fileNr==0) {
106 fprintf(stderr, "Error: missing file name for input data.\n");
107 return(1);
108 }
109
110 /* In verbose mode print arguments and options */
111 if(verbose>1) {
112 printf("fileNr := %d\n", fileNr);
113 printf("doFix := %d\n", doFix);
114 }
115
116
117 /*
118 * Do one file at a time
119 */
120 for(ai=ffi; ai<argc; ai++) {
121 fixed=0;
122 strlcpy(dftfile, argv[ai], FILENAME_MAX);
123 if(verbose>0 && fileNr>1) fprintf(stdout, "%s:\n", dftfile);
124
125 /* Read data */
126 if(verbose>3) printf("reading %s\n", dftfile);
127 ret=dftRead(dftfile, &dft);
128 if(ret) {
129 fprintf(stderr, "Error in reading '%s': %s\n", dftfile, dfterrmsg);
130 return(2);
131 }
132
133 /* Make sure data is sorted by increasing sample time */
134 dftSortByFrame(&dft);
135
136 /* Check the data for missing samples */
137 if(dft_nr_of_NA(&dft)>0) {
138 if(verbose>0) printf(" missing sample(s).\n");
139 if(doFix==0) {dftEmpty(&dft); errorCount++; continue;}
140 /* Try to fix NaNs */
141 if(verbose>1) printf(" trying to fix...\n");
142 ret=dftNAfill(&dft);
143 if(ret==0) {
144 if(verbose>1) printf(" corrected.\n");
145 fixed++;
146 } else {
147 fprintf(stderr,
148 "Error: missing samples can not be corrected automatically.\n");
149 dftEmpty(&dft); return(2);
150 }
151 }
152
153 /* Check for the peak */
154 if(dft.voiNr==1) { // just one TAC inside DFT
155 checked++;
156 ret=dftVerifyPeak(&dft, 0, verbose-2, tmp);
157 if(ret==0) { // All is well
158 if(verbose>0) printf(" ok\n");
159 dftEmpty(&dft); continue;
160 } else if(ret==1) {
161 fprintf(stderr, "Error: program can not verify the peak.\n");
162 if(verbose>0) fprintf(stderr, "Error: %s\n", tmp);
163 dftEmpty(&dft); return(1);
164 } else if(ret<0) { // Warning
165 /* Different messages depending on whether it is to fixed or not */
166 if(doFix==0) { // no correction
167 if(verbose<=0) fprintf(stdout, "%s:\n", dftfile);
168 printf(" TAC may have minor problems\n");
169 } else { // correction will be tried
170 if(verbose>0) printf(" TAC may have minor problems\n");
171 }
172 errorCount++;
173 } else { // Problem was found
174 /* Different messages depending on whether it is to fixed or not */
175 if(doFix==0) { // no correction
176 if(verbose<=0) fprintf(stdout, "%s:\n", dftfile);
177 printf(" Error: TAC must be corrected before using as input\n");
178 } else { // correction will be tried
179 if(verbose>0)
180 printf(" TAC must be corrected before using as input\n");
181 }
182 errorCount++;
183 }
184 if(doFix) {
185 if(verbose>1) printf(" trying to fix...\n");
186 ret=dftFixPeak(&dft, verbose-2);
187 if(ret==0) { // correction succeeded
188 if(verbose>0) printf(" corrected.\n");
189 fixed++; errorCount--;
190 } else { // could not be corrected
191 if(verbose<=0) fprintf(stdout, "%s:\n", dftfile);
192 printf(" Error: peak can not be corrected automatically.\n");
193 printf(" Correct the input TAC manually!\n");
194 }
195 }
196 } else { // several TACs inside DFT
197
198 int localErrorCount=0;
199 for(ri=0; ri<dft.voiNr; ri++) {
200 if(verbose>0) fprintf(stdout, " TAC %s:\n", dft.voi[ri].name);
201 checked++;
202 ret=dftVerifyPeak(&dft, ri, verbose-2, tmp);
203 if(ret==0) { // All is well
204 if(verbose>0) printf(" ok\n");
205 } else if(ret==1) {
206 fprintf(stderr, "Error: program can not verify the peak.\n");
207 if(verbose>0) fprintf(stderr, "Error: %s\n", tmp);
208 dftEmpty(&dft); return(1);
209 } else if(ret<0) { // Warning
210 if(verbose>0) printf(" TAC may have minor problems\n");
211 localErrorCount++;
212 } else { // Problem was found
213 if(verbose>0)
214 printf(" TAC must be corrected before using as input\n");
215 localErrorCount++;
216 }
217 } // next TAC
218 if(localErrorCount>0 && doFix) {
219 if(verbose>1) printf(" trying to fix...\n");
220 ret=dftFixPeak(&dft, verbose-2);
221 if(ret<=0) {
222 if(verbose>0) printf(" corrected.\n");
223 fixed++; localErrorCount=0;
224 } else {
225 printf(" peaks can not be corrected automatically.\n");
226 }
227 }
228 errorCount+=localErrorCount;
229 }
230
231 /* Write edited file */
232 if(fixed>0) {
233 if(verbose>2) printf(" writing corrected data...\n");
234 ret=dftWrite(&dft, dftfile);
235 if(ret!=0) {
236 fprintf(stderr, "Error in writing '%s': %s\n", dftfile, dfterrmsg);
237 dftEmpty(&dft);
238 return(11);
239 }
240 if(verbose>1) printf(" corrected TAC written in file.\n");
241 }
242
243 /* Prepare to the next file */
244 dftEmpty(&dft);
245 } /* next file */
246
247 if(verbose>0 && checked>1) {
248 if(errorCount==0)
249 printf("All files appear as suitable to be used as model input.\n");
250 else
251 printf("%d possibly severe problem(s) encountered.\n", errorCount);
252 }
253 return(errorCount);
254}
255/*****************************************************************************/
256
257/*****************************************************************************/
259
268 DFT *dft,
270 int verbose
271) {
272 int ri, ret, mini, maxi, n, warn=0, fixnr=0;
273 double minx, maxx, miny, maxy, dif, d, slope, ic;
274 char tmp[256];
275
276 if(verbose>0) printf("dftFixPeak(dft, %d)\n", verbose);
277 /* Check the arguments */
278 if(dft==NULL || dft->frameNr<1 || dft->voiNr<1) return 1;
279
280 /* If less than 3 samples, then this can not be suitable as input TAC */
281 if(dft->frameNr<3) return 2;
282
283 /* Check if any correction is needed for any TAC */
284 if(dftVerifyPeak(dft, -1, 0, NULL)==0) {
285 if(verbose>1) printf("TAC does not need to be corrected\n");
286 return 0;
287 }
288
289 /* Check if problem was something else than missing initial rise */
290 if(dft->x[0]<=0.001) {
291 if(verbose>1) printf("TAC already has zero sample\n");
292 return 2;
293 }
294
295 /* Allocate memory for new sample points to be added */
296 double zx, zy[dft->voiNr];
297 zx=0.0; if(dft->timetype==DFT_TIME_STARTEND) zx=0.5*dft->x1[0];
298
299 /* Go through all TACs */
300 for(ri=0; ri<dft->voiNr; ri++) {
301 zy[ri]=0.0;
302 if(verbose>1 && dft->voiNr>1)
303 printf("checking region %d: %s\n", 1+ri, dft->voi[ri].name);
304
305 /* Check if any correction is needed for this TAC */
306 if(dft->voiNr>1 && dftVerifyPeak(dft, ri, 0, NULL)==0) continue; // next TAC
307
308 /* Get the TAC min and max */
309 ret=dftMinMaxTAC(dft, ri, &minx, &maxx, &miny, &maxy, NULL, NULL,
310 &mini, &maxi);
311 if(ret!=0) {
312 if(verbose>0) printf("Error %d in dftMinMaxTAC()\n", ret);
313 return 1;
314 }
315
316 /* If peak is not much higher than lowest value, that may indicate
317 a problem */
318 if(maxy<1.5*miny) {
319 if(verbose>0) printf("TAC does not have a clear peak.\n");
320 return 2;
321 }
322 if(maxy<5.0*miny) {
323 if(verbose>1) printf("TAC does not have a clear peak.\n");
324 warn++;
325 }
326
327 /* If the first sample is the peak:
328 then add zero sample unless sample time is not too late */
329 if(maxi==0) {
330 if(verbose>1) printf("peak at the first sample.\n");
331 if(dft->timetype==DFT_TIME_STARTEND) {
332 dif=dft->x1[maxi]/(dft->x2[maxi]-dft->x1[maxi]);
333 } else {
334 dif=dft->x[maxi]/(dft->x[maxi+1]-dft->x[maxi]);
335 }
336 if(verbose>2) printf("dif := %g\n", dif);
337 if(dif>5.0) {
338 if(verbose>1)
339 printf("peak at the first sample, which is too late.\n");
340 return 2;
341 } else if(dif>1.0 && maxy<=10.*miny) {
342 if(verbose>1)
343 printf("peak at the first sample and bad peak/tail ratio.\n");
344 return 2;
345 }
346 if(verbose>1) printf("zero sample added.\n");
347 // default zeroes are good for this TAC
348 fixnr++; continue;
349 }
350
351 /* If first sample is closer to peak and relatively high, then
352 it is not safe to guess the start sample */
353 if(dft->x[0]>0.75*maxx) {
354 if(dft->voi[ri].y[0]>0.50*maxy) {
355 if(verbose>1) printf("The first sample is relatively late and high.\n");
356 return 2;
357 }
358 }
359
360 /* Try to estimate zero point from ascending part */
361 n=maxi+1; if(n>6) n/=2; else if(n>3) n--;
362 ret=highest_slope(dft->x, dft->voi[ri].y, maxi+1, n,
363 &slope, &ic, &d, NULL);
364 if(ret!=0 || d>=maxx) {
365 if(verbose>0) printf("ascending part of TAC not available.\n");
366 if(verbose>1) printf("ret=%d\n", ret);
367 return 2;
368 }
369 if(verbose>2) {
370 printf("based on ascending part:\n");
371 printf(" slope: %g\n", slope);
372 printf(" ic: %g\n", ic);
373 printf(" new x intercept: %g\n", d);
374 }
375 if(dft->timetype==DFT_TIME_STARTEND) {
376 /* If start and end times, then set the y value */
377 zy[ri]=slope*zx+ic;
378 if(zy[ri]>0.5*dft->voi[ri].y[0]) zy[ri]=0.5*dft->voi[ri].y[0];
379 else if(zy[ri]<0.0) zy[ri]=0.0;
380 } else if(dft->voiNr>1) {
381 /* If more than one TAC, then only set the y value */
382 zy[ri]=slope*zx+ic;
383 if(zy[ri]>0.5*dft->voi[ri].y[0]) zy[ri]=0.5*dft->voi[ri].y[0];
384 else if(zy[ri]<0.0) zy[ri]=0.0;
385 } else {
386 /* Otherwise change the sample time */
387 if(d<0.0) {
388 if(ic<0.5*dft->voi[ri].y[0]) d=0.5*dft->x[0]; else d=0.0;
389 }
390 if(d>=dft->x[0]) d=0.5*dft->x[0];
391 zx=d;
392 }
393 fixnr++;
394
395 } // next TAC
396
397 /* If TAC(s) were fixed, only then add the zero sample */
398 if(fixnr>0) {
399 ret=dftFillInitialGap(dft); if(ret!=0) return 1;
400 dft->x[0]=zx;
401 for(ri=0; ri<dft->voiNr; ri++) {
402 dft->voi[ri].y[0]=zy[ri];
403 if(verbose>1) printf("zero sample added at (%g,%g).\n", zx, zy[ri]);
404 }
405 }
406
407 /* Check TACs are fine after corrections */
408 ret=dftVerifyPeak(dft, -1, 0, tmp);
409 if(verbose>0) {
410 if(verbose>2) printf("dftVerifyPeak()=%d\n", ret);
411 if(verbose>1) fprintf(stderr, "Note: %s\n", tmp);
412 if(ret>1) printf("correction was not successful\n");
413 }
414 return(ret);
415}
416/*****************************************************************************/
417
418/*****************************************************************************/
void dftInit(DFT *data)
Definition dft.c:38
int dftMinMaxTAC(DFT *dft, int tacindex, double *minx, double *maxx, double *miny, double *maxy, int *mini, int *maxi, int *mins, int *maxs)
Definition dft.c:1024
char dfterrmsg[64]
Definition dft.c:6
int dftSortByFrame(DFT *dft)
Definition dft.c:1169
void dftEmpty(DFT *data)
Definition dft.c:20
int dftFillInitialGap(DFT *dft)
Definition dft.c:1385
int dft_nr_of_NA(DFT *dft)
Definition dft.c:905
int dftNAfill(DFT *dft)
Definition dft.c:930
int dftVerifyPeak(DFT *dft, int index, int verbose, char *status)
Definition dftinput.c:747
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
int dftFixPeak(DFT *dft, int verbose)
Definition inpstart.c:266
Header file for libtpccurveio.
#define DFT_TIME_STARTEND
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
Header file for libtpcmodel.
int highest_slope(double *x, double *y, int n, int slope_n, double *m, double *c, double *xi, double *xh)
Definition pearson.c:424
Header file for libtpcmodext.
int timetype
Voi * voi
double * x1
int voiNr
double * x2
int frameNr
double * x
double * y
char name[MAX_REGIONNAME_LEN+1]