TPCCLIB
Loading...
Searching...
No Matches
patlak.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 <math.h>
15#include <string.h>
16#include <time.h>
17/******************************************************************************/
18#include "libtpcmisc.h"
19#include "libtpcmodel.h"
20#include "libtpccurveio.h"
21#include "libtpcsvg.h"
22#include "libtpcmodext.h"
23/*****************************************************************************/
24
25/*****************************************************************************/
26#ifndef DEFAULT_LC
27#define DEFAULT_LC 1.00
28#endif
29#ifndef DEFAULT_DENSITY
30#define DEFAULT_DENSITY 1.00
31#endif
32#ifndef BAD_FIT
33#define BAD_FIT 9.999E19
34#endif
35#ifndef MAX_PARAMETERS
36#define MAX_PARAMETERS 6
37#endif
38/*****************************************************************************/
39
40/*****************************************************************************/
41static char *info[] = {
42 "Calculates the net influx (uptake) rate constant Ki (ml/(min*ml)) as slope of",
43 "the Patlak plot (1,2,3) from regional PET time-activity curves (TTACs).",
44 " ",
45 "Usage: @P [Options] ttac_file input start_time end_time result_file",
46 " ",
47 "Input can be either a TAC file containing arterial plasma PTAC or reference",
48 "region TAC, or name or number of reference region in the TTAC file.",
49 "Start and end times of the line fit to the plot must be given in minutes.",
50 " ",
51 "Options for calculation of metabolic rate:",
52 " -Ca=<value>",
53 " Concentration of native substrate in arterial plasma (mM),",
54 " for example plasma glucose in [18F]FDG studies.",
55 " With this option the metabolic rate (umol/(min*100 g)) is calculated.",
56 " -LC=<value>",
57 " Lumped Constant in MR calculation; default is 1.0.",
58 " -density=<value>",
59 " Tissue density in MR calculation; default is 1.0 g/ml.",
60 " ",
61 "General options:",
62 " -ic=<y axis intercept>",
63 " Force y axis intercept to specified value; for FUR or Ri calculation",
64 " use regfur.",
65 " -sd=<y|n>",
66 " Standard deviations are saved (y, default) or not saved (n) in results.",
67 " -mid=<Y|n>",
68 " Frame middle times are used (y), or not used (n, default), even if frame",
69 " start and end times are available. For compatibility with old software.",
70 " -svg=<Filename>",
71 " Plots are written in specified file in Scalable Vector Graphics (SVG) 1.1",
72 " format; specification in https://www.w3.org/TR/SVG/",
73 " -bw",
74 " Black-and-white plot.",
75 " -plotdata=<Filename>",
76 " Data for plots is written in specified file in XHTML table format for",
77 " easy importing in Excel or OpenOffice spreadsheet, where the data can",
78 " be viewed; if filename extension is .dft, data is written in DFT format.",
79 " -stdoptions", // List standard options like --help, -v, etc
80 " ",
81 "Options for selecting the least-squares line fit method:",
82 " -C Traditional regression model (default)",
83 " -M Median of two-point slopes and intercepts (Cornish-Bowden)",
84 " -P Perpendicular regression model (4)",
85 " -R Iterative method (York 1966, Lybanon 1984, Reed 1992)",
86 " In the present software version, the weights are not used in the fit.",
87 " ",
88 "Example 1: tissue curves are in ut1234.tac and plasma curve in ut1234ap.dat;",
89 "fitted data range is from 10 to 60 min; standard deviations are not needed;",
90 "plot is saved in file ut2345patlak.svg",
91 " @P -sd=n -svg=ut1234patlak.svg ut1234.tac ut1234ap.dat 10 60 ut1234.res",
92 " ",
93 "Example 2: tissue curves in ut1234.tac, including reference region 'cer'",
94 " @P ut1234.tac cer 10 60 ut1234.res",
95 " ",
96 "References:",
97 "1. Gjedde A. Calculation of cerebral glucose phosphorylation from brain",
98 " uptake of glucose analogs in vivo: a re-examination. Brain Res. 1982;",
99 " 257:237-274.",
100 "2. Patlak CS, Blasberg RG, Fenstermacher JD. Graphical evaluation of",
101 " blood-to-brain transfer constants from multiple-time uptake data.",
102 " J Cereb Blood Flow Metab 1983;3:1-7.",
103 "3. Patlak CS, Blasberg RG. Graphical evaluation of blood-to-brain transfer",
104 " constants from multiple-time uptake data. Generalizations.",
105 " J Cereb Blood Flow Metab 1985;5:584-590.",
106 "4. Varga J & Szabo Z. Modified regression model for the Logan plot.",
107 " J Cereb Blood Flow Metab 2002; 22:240-244.",
108 " ",
109 "See also: imgki, fitk3, fitkloss, lhsolki, regfur, logan, rescoll",
110 " ",
111 "Keywords: TAC, MTGA, Patlak plot, modelling, Ki",
112 0};
113/*****************************************************************************/
114
115/*****************************************************************************/
116/* Turn on the globbing of the command line, since it is disabled by default in
117 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
118 In Unix&Linux wildcard command line processing is enabled by default. */
119/*
120#undef _CRT_glob
121#define _CRT_glob -1
122*/
123int _dowildcard = -1;
124/*****************************************************************************/
125
126/*****************************************************************************/
130int main(int argc, char **argv)
131{
132 int ai, help=0, version=0, verbose=1;
133 DFT data, input;
134 int save_stat=1, always_mid=0;
135 double LC=-1.0, Ca=-1.0, density=-1.0;
136 double fixed_Ic=-9.E99;
137 int color_scale=0; // 0=colour, 2=black-and-white.
138 int ri, fi, pi, ret, inputtype, llsq_model=0;
139 char dfile[FILENAME_MAX], ifile[FILENAME_MAX], rfile[FILENAME_MAX],
140 pfile[FILENAME_MAX], sfile[FILENAME_MAX], tmp[1024], *cptr;
141 double tstart, tstop, Ki, KiSD, Ic, IcSD, SWSS;
142 double istart;
143 double f, xm, ym, xs, ys;
144//double *w, *wx, *wy, *cx, *cy;
145 RES res;
146
147 double *t, *theta, *dv, *ci, *ici, *ct;
148 int dataNr=0, first, last;
149
150
151
152 /*
153 * Get arguments
154 */
155 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
156 dfile[0]=ifile[0]=rfile[0]=pfile[0]=sfile[0]=(char)0; tstart=tstop=-1;
157 dftInit(&data); dftInit(&input); resInit(&res);
158 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* Get parameters */
159 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
160 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
161 cptr=argv[ai]+1;
162 if(strncasecmp(cptr, "SD=", 3)==0) {
163 save_stat=1; cptr+=3; if(strlen(cptr)<1) continue;
164 if(strncasecmp(cptr, "yes", 1)==0) {save_stat=1; continue;}
165 else if(strncasecmp(cptr, "no", 1)==0) {save_stat=0; continue;}
166 } else if(strcasecmp(cptr, "LOSS")==0 || strcasecmp(cptr, "KLOSS")==0) {
167 fprintf(stderr, "Error: estimation of kloss is removed in this version.\n");
168 fflush(stderr);
169 return(1);
170 } else if(strncasecmp(cptr, "CA=", 3)==0) {
171 Ca=atof_dpi(cptr+3); if(Ca>0.0) continue;
172 } else if(strncasecmp(cptr, "LC=", 3)==0) {
173 LC=atof_dpi(cptr+3); if(LC>0.0) continue;
174 } else if(strncasecmp(cptr, "D=", 2)==0) {
175 density=atof_dpi(cptr+2); if(density>0.0) continue;
176 } else if(strncasecmp(cptr, "DENSITY=", 8)==0) {
177 density=atof_dpi(cptr+8); if(density>0.0) continue;
178 } else if(strncasecmp(cptr, "IC=", 3)==0) {
179 fixed_Ic=atof_dpi(cptr+3);
180 if(fixed_Ic==0.0 && verbose>=0)
181 fprintf(stdout, "Suggestion: for FUR calculation use regfur.\n");
182 continue;
183 } else if(strncasecmp(cptr, "MID", 3)==0) {
184 always_mid=1; cptr+=3; if(strlen(cptr)<2) continue;
185 if(*cptr=='=') cptr++;
186 if(strncasecmp(cptr, "yes", 1)==0) {
187 always_mid=1; continue;
188 } else if(strncasecmp(cptr, "no", 1)==0) {
189 always_mid=0; continue;
190 }
191 } else if(strncasecmp(cptr, "SVG=", 4)==0) {
192 strlcpy(sfile, cptr+4, FILENAME_MAX); if(strlen(sfile)>0) continue;
193 } else if(strncasecmp(cptr, "PLOTDATA=", 9)==0) {
194 strlcpy(pfile, cptr+9, FILENAME_MAX); if(strlen(pfile)>0) continue;
195 /* Check if regression method was specified */
196 } else if(strcasecmp(cptr, "C")==0) {
197 llsq_model=0; continue;
198 } else if(strcasecmp(cptr, "R")==0) {
199 llsq_model=1; continue;
200 } else if(strcasecmp(cptr, "P")==0) {
201 llsq_model=2; continue;
202 } else if(strcasecmp(cptr, "M")==0) {
203 llsq_model=3; continue;
204 } else if(strcasecmp(cptr, "BW")==0) {
205 color_scale=2; continue;
206 }
207 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]); fflush(stderr);
208 return(1);
209 } else break;
210
211 /* Print help or version? */
212 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
213 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
214 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
215
216 /* Process other arguments, starting from the first non-option */
217 for(; ai<argc; ai++) {
218 if(!dfile[0]) {strlcpy(dfile, argv[ai], FILENAME_MAX); continue;}
219 if(!ifile[0]) {strlcpy(ifile, argv[ai], FILENAME_MAX); continue;}
220 if(tstart<0) {tstart=atof_dpi(argv[ai]); continue;}
221 if(tstop<0) {tstop=atof_dpi(argv[ai]); continue;}
222 if(!rfile[0]) {strlcpy(rfile, argv[ai], FILENAME_MAX); continue;}
223 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]); fflush(stderr);
224 return(1);
225 }
226
227 /* Is something missing? */
228 if(!rfile[0]) {
229 fprintf(stderr, "Error: missing result file name.\n");
230 return(1);
231 }
232 /* If MR will be calculated, set defaults and give warnings as necessary */
233 if(Ca>0.0) {
234 if(LC<0.0) {
235 LC=DEFAULT_LC;
236 fprintf(stderr, "Warning: LC not set, using default %g\n", LC);
237 }
238 if(density<0.0) {
239 density=DEFAULT_DENSITY;
240 fprintf(stderr, "Warning: tissue density not set, using default %g\n", density);
241 }
242 } else { /* Warnings if density or LC set when MR will not be calculated */
243 if(LC>0.0) fprintf(stderr, "Warning: LC was set but is not used.\n");
244 if(density>0.0) fprintf(stderr, "Warning: tissue density was set but is not used.\n");
245 fflush(stderr);
246 }
247 /* Check the time range */
248 if(tstop<tstart || (tstop==tstart && fixed_Ic<=-1.E99)) {
249 fprintf(stderr, "Error: invalid time range %g-%g.\n", tstart, tstop);
250 fflush(stderr); return(1);
251 }
252 if(fixed_Ic>-1.E99) { /* if y intercept is constrained, then ... */
253 llsq_model=0; /* cannot use any fancy method for line fitting */
254 }
255
256
257 /* In verbose mode print arguments and options */
258 if(verbose>1) {
259 printf("%s", argv[0]); for(ai=1; ai<argc; ai++) printf(" %s", argv[ai]);
260 printf("\n");
261 }
262 if(verbose>2) {
263 printf("llsq_model := %d\nsave_stat := %d\n", llsq_model, save_stat);
264 printf("dfile := %s\n", dfile);
265 printf("pfile := %s\n", pfile);
266 printf("rfile := %s\n", rfile);
267 printf("ifile := %s\n", ifile);
268 printf("sfile := %s\n", sfile);
269 printf("tstart := %g\ntstop := %g\n", tstart, tstop);
270 if(Ca>0.0) {
271 printf("Ca := %g\n", Ca);
272 printf("LC := %g\n", LC);
273 printf("density := %g\n", density);
274 }
275 printf("always_mid := %d\n", always_mid);
276 if(fixed_Ic>-1.E99) printf("fixed_Ic := %g\n", fixed_Ic);
277 if(color_scale==2) printf("color_scale := black-and-white\n");
278 fflush(stdout);
279 }
280
281
282 /*
283 * Read tissue data
284 */
285 if(verbose>1) printf("reading %s\n", dfile);
286 if(dftRead(dfile, &data)) {
287 fprintf(stderr, "Error in reading '%s': %s\n", dfile, dfterrmsg);
288 return(2);
289 }
290 if(data.frameNr==1 && fixed_Ic<=-1.E99) {
291 /* If static study, then automatically set IC to zero */
292 fixed_Ic=0.0;
293 if(verbose>=0) fprintf(stdout, "Suggestion: for FUR calculation use regfur.\n");
294 }
295 if(dft_nr_of_NA(&data)>0) { // check if file contains NAs (missing values)
296 fprintf(stderr, "Error: missing values in %s\n", dfile);
297 dftEmpty(&data); return(2);
298 }
299 if(data.frameNr==1 && data.timetype==DFT_TIME_MIDDLE)
300 data.x2[0]=data.x1[0]=data.x[0];
301 // like if we had only frame mid times
302 if(always_mid!=0) data.timetype=DFT_TIME_MIDDLE;
303
304
305 /* Sort the samples by time in case data is catenated from several curves */
306 (void)dftSortByFrame(&data);
307
308 /* Make sure that there is no overlap in frame times */
309 if(data.timetype==DFT_TIME_STARTEND) {
310 if(verbose>1) fprintf(stdout, "checking frame overlap in %s\n", dfile);
311 ret=dftDeleteFrameOverlap(&data);
312 if(ret) {
313 fprintf(stderr, "Error: %s has overlapping frame times.\n", dfile);
314 dftEmpty(&data); fflush(stderr); return(2);
315 }
316 }
317 /* Set time unit to min */
318 ret=dftTimeunitConversion(&data, TUNIT_MIN);
319 if(ret) fprintf(stderr, "Warning: check that regional data times are in minutes.\n");
320 /* Get and check fit time range */
321 dataNr=fittime_from_dft(&data, &tstart, &tstop, &first, &last, verbose-8);
322 if(verbose>2) {
323 printf("dataNr_in_range := %d\n", dataNr);
324 printf("first_in_range := %d\n", first);
325 printf("last_in_range := %d\n", last);
326 }
327 if(dataNr<1) {
328 fprintf(stderr, "Error: data does not contain the specified time range.\n");
329 dftEmpty(&data); return(2);
330 } else if(dataNr<2 && fixed_Ic<=-1.E99) {
331 fprintf(stderr, "Error: cannot make plot from less than 2 points.\n");
332 dftEmpty(&data); return(2);
333 } else if(dataNr==2 && fixed_Ic<=-1.E99) {
334 fprintf(stderr, "Warning: only two samples in the time range.\n");
335 }
336 if(verbose>2) {
337 printf("dataNr := %d\n", dataNr);
338 printf("tstart := %g\ntstop := %g\n", tstart, tstop);
339 printf("first := %d\nlast := %d\n", first, last);
340 }
341
342 /*
343 * Read input data, interpolate and calculate AUC at tissue sample times
344 */
345 if(verbose>1) printf("reading input\n");
346 if((ret=dftReadinput(&input, &data, ifile, &inputtype, &istart, NULL, 1, tmp, verbose-6))) {
347 if(ret==101) {
348 if(inputtype==5) fprintf(stderr, "Error: %s.\n", tmp);
349 else fprintf(stderr, "Error in reading '%s': %s\n", ifile, tmp);
350 dftEmpty(&data); fflush(stderr); return(3);
351 }
352 /* Other errors may be caused by much longer tissue data than plasma data.
353 Try to correct that by setting tissue frame nr to match the last fitted frame */
354 if(verbose>1) printf("trying to fix tissue frame nr.\n");
355 data.frameNr=last+1;
356 if((ret=dftReadinput(&input, &data, ifile, &inputtype, &istart, NULL, 1, tmp, verbose-6))) {
357 fprintf(stderr, "Error in reading '%s': %s\n", ifile, tmp);
358 if(verbose>0) printf("dftReadinput() := %d\n", ret);
359 //if(TEST) dftPrint(&data);
360 dftEmpty(&data); fflush(stderr); return(3);
361 }
362 }
363 if(verbose>9) {
364 printf("\nInput data:\n");
365 dftPrint(&input);
366 printf("\nTissue data:\n");
367 dftPrint(&data);
368 }
369 if(inputtype==5) { // Reference region name was given
370 if(verbose>0) fprintf(stdout, "selected reference region := %s\n", input.voi[0].name);
371 for(ri=1; ri<input.voiNr; ri++)
372 fprintf(stderr, "Warning: reference region %s unused.\n", input.voi[ri].name);
373 } else {
374 if(input.voiNr>1) fprintf(stderr, "Warning: only the first of input curves is used.\n");
375 }
376
377 /* Check that original input data started early enough, otherwise AUC(0-T)
378 might be wrong */
379 if(istart>0.3) {
380 fprintf(stderr, "Warning: input TAC should start at time zero.\n");
381 fflush(stderr);
382 }
383
384 /*
385 * Prepare the room for results
386 */
387 if(verbose>1) printf("initializing result data\n");
388 ret=res_allocate_with_dft(&res, &data); if(ret!=0) {
389 fprintf(stderr, "Error: cannot setup memory for results.\n");
390 dftEmpty(&input); dftEmpty(&data); fflush(stderr); return(4);
391 }
392 /* Copy titles & filenames */
393 tpcProgramName(argv[0], 1, 1, res.program, 128);
394 if(verbose>10) printf("res.program := '%s'\n", res.program);
395 strcpy(res.datafile, dfile);
396 if(inputtype==5) strcpy(res.refroi, input.voi[0].name);
397 else strcpy(res.plasmafile, ifile);
398 if(strlen(res.studynr)==0 || strcmp(res.studynr, ".")==0)
399 studynr_from_fname2(dfile, res.studynr, 1);
400 /* Constants */
401 if(Ca>0.0) {res.density=density; res.lc=LC; res.concentration=Ca;}
402 /* Set data range */
403 sprintf(res.datarange, "%g - %g %s", tstart, tstop, petTunit(data.timeunit));
404 res.datanr=dataNr;
405 if(llsq_model==0) strcpy(res.fitmethod, "Traditional regression model");
406 else if(llsq_model==1) strcpy(res.fitmethod, "Iterative method");
407 else if(llsq_model==2) strcpy(res.fitmethod, "Perpendicular regression model");
408 else if(llsq_model==3) strcpy(res.fitmethod, "Median of two-point slopes");
409 /* Set current time to results */
410 res.time=time(NULL);
411 res.isweight=0; /*data.isweight;*/
412 /* Set parameter number, including also the extra "parameters" */
413 /* Set the parameter names */
414 res.parNr=3; if(Ca>0.0) res.parNr++;
415 pi=0;
416 if(Ca>0.0) {
417 strcpy(res.parname[pi], "MR");
418 strcpy(res.parunit[pi], petCunit(CUNIT_UMOL_PER_MIN_PER_100G));
419 pi++;
420 }
421 strcpy(res.parname[pi], "Ki");
422 strcpy(res.parunit[pi], petCunit(CUNIT_ML_PER_ML_PER_MIN));
423 pi++;
424 strcpy(res.parname[pi], "Ic");
425 strcpy(res.parunit[pi], petCunit(CUNIT_ML_PER_ML));
426 pi++;
427 if(llsq_model==1 || llsq_model==3) {
428 strcpy(res.parname[pi], "SqrtWSS");
429 strcpy(res.parunit[pi], data.unit);
430 } else if(llsq_model==0) {
431 strcpy(res.parname[pi], "r");
432 strcpy(res.parunit[pi], petCunit(CUNIT_UNITLESS));
433 } else if(llsq_model==2) {
434 strcpy(res.parname[pi], "SSD");
435 strcpy(res.parunit[pi], petCunit(CUNIT_UNITLESS));
436 }
437
438 /*
439 * Allocate memory for llsqwt() and weights
440 */
441 double w[data.frameNr];
442 double wx[data.frameNr];
443 double wy[data.frameNr];
444 double cx[data.frameNr];
445 double cy[data.frameNr];
446
447
448 /*
449 * Calculate Ki for each region
450 */
451
452 /* One region at a time */
453 for(ri=0; ri<data.voiNr; ri++) {
454 if(verbose>0) {printf("calculating %s\n", data.voi[ri].name); fflush(stdout);}
455
456 /* Set data pointers */
457 theta=data.voi[ri].y2;
458 dv=data.voi[ri].y3;
459 ci=input.voi[0].y; ici=input.voi[0].y2;
460 ct=data.voi[ri].y; t=input.x;
461
462 /* Calculate Patlak plot data */
463 for(fi=data.frameNr-1; fi>=0; fi--) if(ci[fi]!=0.0) {
464 if(verbose>8) {
465 printf("%03d %8.3f : ici=%g ci=%g ct=%g\n", fi+1, t[fi], ici[fi], ci[fi], ct[fi] );
466 }
467 /* theta (x axis) */
468 theta[fi]=ici[fi]/ci[fi]; wx[fi]=1.0;
469 //if(theta[fi]>=0.0) wx[fi]=1.0; else wx[fi]=0.0;
470 /* dv (y axis) */
471 dv[fi]=ct[fi]/ci[fi]; wy[fi]=1.0;
472 // check the close-to-zeroes in the first frames
473 if(data.x[fi]<0.1*data.x[data.frameNr-1]) {
474 if(theta[fi]>theta[data.frameNr-1] || dv[fi]>dv[data.frameNr-1]) {
475 if(verbose>2)
476 printf("Possible close-to-zero plot point at %g -> set to zero.\n", data.x[fi]);
477 theta[fi]=dv[fi]=wx[fi]=wy[fi]=0.0;
478 }
479 }
480 } else if(fixed_Ic>-1.E99) { // this only if input concentration is zero
481 theta[fi]=ici[fi]; dv[fi]=ct[fi]; wx[fi]=wy[fi]=1.0;
482 } else theta[fi]=dv[fi]=wx[fi]=wy[fi]=0.0;
483
484 /* Set x weight to 0, if integral is still <=0, whether weighted or not */
485 for(fi=input.frameNr-1; fi>=0; fi--) if(input.voi[0].y2[fi]<=0.0) break;
486 for(; fi>=0; fi--) wx[fi]=0.0;
487
488 if(verbose>6) {
489 for(fi=first; fi<=last; fi++)
490 printf("%03d %8.3f : %g %g (%g %g)\n",
491 fi+1, data.x[fi], theta[fi], dv[fi], wx[fi], wy[fi] );
492 }
493
494 /* Fit */
495
496 KiSD=Ki=Ic=IcSD=SWSS=0.0;
497
498 if(fixed_Ic>-1.E99) { /* y axis is constrained to fixed_Ic */
499
500 /* Calculate the means and SDs of plot data */
501 ret=mean(&theta[first], &dv[first], dataNr, &xm, &xs, &ym, &ys);
502 /* Calculate the slope through constrained intercept and plot mean */
503 if(fixed_Ic>-1.E99) Ic=fixed_Ic; else Ic=0.0;
504 Ki=(ym-Ic)/xm; if(xm!=0.0) KiSD=ys/xm; SWSS=1.0;
505
506 } else if(llsq_model==1) {
507
508 /* Calculation of LLSQ fit with errors in both coordinates */
509 ret=llsqwt(
510 /* input */
511 &theta[first], &dv[first], dataNr, &wx[first], &wy[first],
512 1.0e-10, /* allowed tolerance in slope estimation */
513 /* input/output */
514 &w[first], /* work vector; effective weights w[i] are returned in it */
515 /* output ; SWSS is already normalized */
516 &Ic, &Ki, &SWSS, &IcSD, &KiSD, cx, cy
517 );
518 if(verbose>5) {
519 printf("%s:\n", data.voi[ri].name);
520 for(fi=first; fi<=last; fi++)
521 printf("%03d %8.3f : %g %g (%g %g -> %g)\n",
522 fi+1, data.x[fi], theta[fi], dv[fi], wx[fi], wy[fi], w[fi] );
523 }
524
525 } else if(llsq_model==2) {
526
527 /* Remove plot points with zero weight */
528 for(fi=first; fi<=last; fi++)
529 if(wx[fi]<=0.0 || wy[fi]<=0.0) theta[fi]=dv[fi]=nan("");
530
531 /* Calculation of perpendicular line fit */
532 ret=llsqperp3(
533 /* input */
534 &theta[first], &dv[first], dataNr,
535 /* output ; SSD is already normalized */
536 &Ki, &Ic, &SWSS
537 );
538
539 } else if(llsq_model==0) {
540
541 /* Remove plot points with zero weight */
542 for(fi=first; fi<=last; fi++)
543 if(wx[fi]<=0.0 || wy[fi]<=0.0) theta[fi]=dv[fi]=nan("");
544
545 if(verbose>9) for(fi=first; fi<=last; fi++)
546 printf(" %d %g %g\n", fi, theta[fi], dv[fi]);
547
548 /* Calculation of linear regression using pearson() */
549 ret=pearson3(
550 /* input */
551 &theta[first], &dv[first], dataNr,
552 /* output */
553 &Ki, &KiSD, &Ic, &IcSD, &SWSS, &f
554 );
555 if(verbose>9) {printf("Ki=%g Ic=%g\n", Ki, Ic); fflush(stdout);}
556
557 } else if(llsq_model==3) {
558
559 /* Remove plot points with zero weight */
560 for(fi=first; fi<=last; fi++)
561 if(wx[fi]<=0.0 || wy[fi]<=0.0) theta[fi]=dv[fi]=nan("");
562
563 /* Calculation of median slope and ic */
564 ret=medianline(
565 &theta[first], &dv[first], dataNr, &Ki, &Ic
566 );
567 }
568
569 if(ret==0) {
570 res.voi[ri].parameter[0]=Ki; if(save_stat) res.voi[ri].sd[0]=KiSD;
571 res.voi[ri].parameter[1]=Ic; if(save_stat) res.voi[ri].sd[1]=IcSD;
572 res.voi[ri].parameter[2]=SWSS;
573 if(verbose>1) {printf("Ki := %g (%g)\n", Ki, KiSD); fflush(stdout);}
574
575 } else {
576 fprintf(stderr, "Error (%d) in linear fit of %s\n", ret, data.voi[ri].name);
577 fflush(stderr);
578 }
579 } /* next region */
580
581
582 /*
583 * Plots
584 */
585 /* Plot data */
586 if(pfile[0]) {
587 if(verbose>0) printf("saving plots\n");
588 sprintf(tmp, "Patlak-plot ");
589 if(strcmp(res.studynr, ".")!=0) strcat(tmp, res.studynr);
590 ret=plotdata(&data, &res, first, last, tmp, "Input integral / Input", "Tissue / Input", pfile);
591 if(ret) {
592 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, pfile);
593 dftEmpty(&data); dftEmpty(&input); resEmpty(&res); fflush(stderr);
594 return(20+ret);
595 }
596 if(verbose>=0) {printf("Plot data written in %s\n", pfile); fflush(stdout);}
597 }
598 /* SVG plot */
599 if(sfile[0]) {
600 if(verbose>0) printf("saving SVG plot\n");
601 sprintf(tmp, "Patlak-plot ");
602 if(strcmp(res.studynr, ".")!=0) strcat(tmp, res.studynr);
603 ret=plot_svg(&data, &res, first, last, tmp, "Input integral / Input", "Tissue / Input",
604 color_scale, sfile, verbose-8);
605 if(ret) {
606 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, sfile);
607 dftEmpty(&data); dftEmpty(&input); resEmpty(&res); fflush(stderr);
608 return(20+ret);
609 }
610 if(verbose>=0) {printf("Plots written in %s\n", sfile); fflush(stdout);}
611 }
612
613
614 /*
615 * Calculate metabolic rate, if necessary
616 * This must not be done before plotting!
617 */
618 if(Ca>0.0) {
619 if(verbose>0) printf("calculating metabolic rates\n");
620 f=100.*Ca/(density*LC);
621 for(ri=0; ri<res.voiNr; ri++) {
622 /* make room for MR */
623 for(fi=res.parNr; fi>0; fi--) {
624 res.voi[ri].parameter[fi]=res.voi[ri].parameter[fi-1];
625 if(save_stat) res.voi[ri].sd[fi]=res.voi[ri].sd[fi-1];
626 }
627 /* Calculate MR and its SD */
628 res.voi[ri].parameter[0]=f*res.voi[ri].parameter[1];
629 if(save_stat) res.voi[ri].sd[0]=f*res.voi[ri].sd[1];
630 }
631 }
632
633
634 /*
635 * Print results on screen
636 */
637 if(verbose>=0) {
638 if(res.voiNr<=128) {resPrint(&res); fprintf(stdout, "\n");}
639 else fprintf(stdout, "Patlak plot calculated from %d regional TACs.\n", res.voiNr);
640 }
641
642 /* If Ki was negative, print the plot data */
643 if(verbose>3) for(ri=0; ri<data.voiNr; ri++) if(res.voi[ri].parameter[0]<0) {
644 printf("%d %s: Ki=%g\n", ri+1, data.voi[ri].name, res.voi[ri].parameter[0]);
645 for(fi=first; fi<=last; fi++)
646 printf("%03d %8.3f : %g %g\n",
647 fi+1, data.x[fi], data.voi[ri].y2[fi], data.voi[ri].y3[fi] );
648 }
649
650 /*
651 * Save results
652 */
653 if(verbose>0) printf("saving results\n");
654 ret=resWrite(&res, rfile, verbose-3);
655 if(ret) {
656 fprintf(stderr, "Error in writing '%s': %s\n", rfile, reserrmsg);
657 dftEmpty(&data); dftEmpty(&input); resEmpty(&res); fflush(stderr);
658 return(11);
659 }
660
661 /* Free memory */
662 dftEmpty(&data); dftEmpty(&input); resEmpty(&res); fflush(stdout);
663
664 return(0);
665}
666/*****************************************************************************/
667
668/*****************************************************************************/
double atof_dpi(char *str)
Definition decpoint.c:59
void dftInit(DFT *data)
Definition dft.c:38
char dfterrmsg[64]
Definition dft.c:6
int dftDeleteFrameOverlap(DFT *dft)
Definition dft.c:1237
int dftSortByFrame(DFT *dft)
Definition dft.c:1169
void dftEmpty(DFT *data)
Definition dft.c:20
int dft_nr_of_NA(DFT *dft)
Definition dft.c:905
int dftReadinput(DFT *input, DFT *tissue, char *filename, int *filetype, double *ti1, double *ti2, int verifypeak, char *status, int verbose)
Definition dftinput.c:25
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
void dftPrint(DFT *data)
Definition dftio.c:538
int res_allocate_with_dft(RES *res, DFT *dft)
Definition dftres.c:14
int dftTimeunitConversion(DFT *dft, int tunit)
Definition dftunit.c:119
int fittime_from_dft(DFT *dft, double *startTime, double *endTime, int *first, int *last, int verbose)
Definition fittime.c:16
Header file for libtpccurveio.
char reserrmsg[64]
Definition result.c:6
void resInit(RES *res)
Definition result.c:52
#define DFT_TIME_MIDDLE
void resPrint(RES *res)
Definition result.c:186
int resWrite(RES *res, char *filename, int verbose)
Definition result.c:565
#define DFT_TIME_STARTEND
void resEmpty(RES *res)
Definition result.c:22
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
int studynr_from_fname2(char *fname, char *studynr, int force)
Definition studynr.c:67
char * petCunit(int cunit)
Definition petunits.c:211
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
void tpcProgramName(const char *program, int version, int copyright, char *prname, int n)
Definition proginfo.c:101
char * petTunit(int tunit)
Definition petunits.c:226
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 llsqperp3(double *x, double *y, int nr, double *slope, double *ic, double *ssd)
Definition llsqwt.c:453
int medianline(double *x, double *y, int nr, double *slope, double *ic)
Definition llsqwt.c:533
int llsqwt(double *x, double *y, int n, double *wx, double *wy, double tol, double *w, double *ic, double *slope, double *nwss, double *sic, double *sslope, double *cx, double *cy)
Definition llsqwt.c:48
int pearson3(double *x, double *y, int nr, double *k, double *kSD, double *b, double *bSD, double *r, double *ySD)
Definition pearson.c:154
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
Definition pearson.c:341
Header file for libtpcmodext.
int plotdata(DFT *dft, RES *res, int first, int last, char *mtitle, char *xtitle, char *ytitle, char *fname)
Definition plotdata.c:217
int plot_svg(DFT *dft, RES *res, int first, int last, char *main_title, char *x_title, char *y_title, int color_scale, char *fname, int verbose)
Definition plotdata.c:17
Header file for libtpcsvg.
int timetype
Voi * voi
int timeunit
double * x1
int voiNr
double * x2
int frameNr
double * x
char unit[MAX_UNITS_LEN+1]
double density
char studynr[MAX_STUDYNR_LEN+1]
double concentration
int parNr
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
int voiNr
int datanr
ResVOI * voi
char program[1024]
char plasmafile[FILENAME_MAX]
char datarange[128]
int isweight
double lc
char datafile[FILENAME_MAX]
char fitmethod[128]
char refroi[64]
char parunit[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
time_t time
double parameter[MAX_RESPARAMS]
double sd[MAX_RESPARAMS]
double * y2
double * y
char name[MAX_REGIONNAME_LEN+1]
double * y3