9#include "tpcclibConfig.h"
25static char *info[] = {
26 "PET TACs are simulated with short sample time intervals.",
27 "This program sums up those points within specified time frames to simulate",
28 "a measured PET tissue uptake curve.",
30 "Usage: @P [options] tacfile framefile newfile [isotope]",
34 " Sample times are known to be in seconds or minutes, but is not",
35 " specified or is wrong in TAC file.",
37 " Frame mid time is written in output file instead of start and end times.",
38 " -i Calculates integrals at frame mid times, instead of frame averages;",
39 " not available with [isotope].",
40 " -ii Calculates 2nd integrals at frame mid times, instead of frame averages;",
41 " not available with [isotope].",
43 " Program allows extensive extrapolation.",
46 "TAC file can contain more than one TAC.",
47 "Time frames data can be in SIF or TAC format. Alternatively, file can consist",
48 "of one or two columns of data, containing either 1) frame durations, or",
49 "2) frame start times and frame durations; frame time units must be same",
50 "as in the datafile. Frames are allowed to overlap.",
52 "If the isotope is specified, the correction for physical decay is at first",
53 "removed, then PET framing is simulated, and after that the framed data",
54 "is decay corrected again, based on the frame start time and length as is",
55 "the normal procedure when collecting PET image data.",
56 "Verify that time units are correct when using this possibility.",
58 "See also: interpol, tacframe, tac4frpl, tactime, fit2dat, sim_3tcm",
60 "Keywords: TAC, SIF, simulation, interpolation, time frame",
79int main(
int argc,
char **argv)
81 int ai, help=0, version=0, verbose=1;
87 char datfile[FILENAME_MAX], frafile[FILENAME_MAX], outfile[FILENAME_MAX];
95 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
96 datfile[0]=frafile[0]=outfile[0]=(char)0;
98 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
100 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
101 if(strcasecmp(cptr,
"C")==0 || strcasecmp(cptr,
"Y")==0) {
103 }
else if(strcasecmp(cptr,
"I")==0) {
105 }
else if(strcasecmp(cptr,
"II")==0) {
107 }
else if(strncasecmp(cptr,
"MINUTES", 3)==0) {
109 }
else if(strncasecmp(cptr,
"SECONDS", 3)==0) {
111 }
else if(strcasecmp(cptr,
"MID")==0) {
112 midFrame=1;
continue;
113 }
else if(strcasecmp(cptr,
"F")==0 || strcasecmp(cptr,
"FORCE")==0) {
114 forceMode=1;
continue;
116 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
125 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
130 if(ai<argc)
strlcpy(datfile, argv[ai++], FILENAME_MAX);
131 if(ai<argc)
strlcpy(frafile, argv[ai++], FILENAME_MAX);
132 if(ai<argc)
strlcpy(outfile, argv[ai++], FILENAME_MAX);
135 fprintf(stderr,
"Error: invalid isotope argument '%s'.\n", argv[ai]);
139 fprintf(stderr,
"Error: decay option cannot be used with integrals.\n");
145 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
151 fprintf(stderr,
"Error: missing file name; use option --help\n");
157 printf(
"datfile := %s\n", datfile);
158 printf(
"frafile := %s\n", frafile);
159 printf(
"outfile := %s\n", outfile);
160 printf(
"mode := %d\n", mode);
161 printf(
"forceMode := %d\n", forceMode);
163 printf(
"midFrame := %d\n", midFrame);
172 if(verbose>1) {fprintf(stdout,
"reading %s\n", datfile); fflush(stdout);}
175 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), datfile);
180 printf(
"tacNr := %d\n", tac.
tacNr);
181 printf(
"sampleNr := %d\n", tac.
sampleNr);
182 if(tac.
isframe) printf(
"frames := yes\n");
else printf(
"frames := no\n");
187 fprintf(stderr,
"Error: invalid sample times.\n");
192 tac.
tunit=knownTimeunit;
196 fprintf(stderr,
"Error: invalid sample times.\n");
201 fprintf(stderr,
"Warning: assuming that sample times are in seconds.\n");
204 fprintf(stderr,
"Warning: assuming that sample times are in minutes.\n");
216 if(verbose>1) printf(
"removing decay correction.\n");
218 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), datfile);
227 if(verbose>1) printf(
"reading frame data in %s\n", frafile);
232 fp=fopen(frafile,
"r");
234 fprintf(stderr,
"Error: cannot open %s\n", frafile);
240 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), frafile);
246 if(verbose>2) printf(
"frame times from SIF\n");
249 if(verbose>2) printf(
"not SIF, trying to read as TAC file.\n");
252 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), frafile);
257 printf(
"tacNr := %d\n", sif.
tacNr);
258 printf(
"sampleNr := %d\n", sif.
sampleNr);
260 printf(
"isframe := %d\n", sif.
isframe);
266 if(verbose>2) printf(
"seems to be valid TAC file\n");
268 fprintf(stderr,
"Error: no frame start and end times in %s\n", frafile);
271 if(verbose>2) printf(
"just one column containing frame lengths\n");
272 sif.
x1[0]=0.0; sif.
x2[0]=sif.
x[0]; sif.
x[0]=0.5*(sif.
x1[0]+sif.
x2[0]);
274 sif.
x1[i]=sif.
x2[i-1]; sif.
x2[i]=sif.
x1[i]+sif.
x[i]; sif.
x[i]=0.5*(sif.
x1[i]+sif.
x2[i]);
278 if(verbose>2) printf(
"two columns, probably containing frame start times and lengths\n");
280 sif.
x1[i]=sif.
x[i]; sif.
x2[i]=sif.
x1[i]+sif.
c[0].
y[i]; sif.
x[i]=0.5*(sif.
x1[i]+sif.
x2[i]);
284 fprintf(stderr,
"Error: invalid format in %s\n", frafile);
298 double xmin1, xmax1, xmin2, xmax2;
300 fprintf(stderr,
"Error: invalid sample times in %s.\n", datfile);
304 fprintf(stderr,
"Error: invalid frame times in %s.\n", frafile);
307 if(xmax2<0.1*xmax1 || xmax2>10.*xmax1) {
308 fprintf(stderr,
"Warning: PET frame times may not be in same unit as TAC data.\n");
311 if(verbose>0 && xmax1<xmax2) {
312 printf(
"Note: extrapolation needed from %g to %g\n", xmax1, xmax2); fflush(stdout);}
315 fprintf(stderr,
"Error: required extrapolation is too risky.\n");
319 if(forceMode==0 && xmin2<0.95*xmin1) {
320 printf(
"Note: extrapolation needed from %g to %g\n", xmin1, xmin2); fflush(stdout);
323 for(
int i=0; i<tac.
tacNr; i++) a+=tac.
c[i].
y[0];
324 a/=(double)tac.
tacNr;
326 fprintf(stderr,
"Error: required extrapolation is too risky.\n");
338 fprintf(stderr,
"Error: cannot setup new TAC data.\n");
342 fprintf(stderr,
"Error: cannot setup new TAC data.\n");
364 if(verbose>1) {printf(
"interpolating\n"); fflush(stdout);}
367 for(
int i=0; i<tac2.
tacNr; i++) {
368 double *y=NULL, *yi=NULL, *yii=NULL;
369 if(mode==0) y=tac2.
c[i].
y;
else if(mode==1) yi=tac2.
c[i].
y;
else yii=tac2.
c[i].
y;
371 tac2.
x1, tac2.
x2, y, yi, yii, tac2.
sampleNr, 3, 1, verbose-10);
375 fprintf(stderr,
"Error: cannot interpolate the data.\n");
376 if(verbose>1) printf(
" ret := %d\n", ret);
385 if(verbose>1) printf(
"correcting for decay.\n");
402 if(verbose>1) printf(
"saving %s\n", outfile);
404 FILE *fp; fp=fopen(outfile,
"w");
406 fprintf(stderr,
"Error: cannot open file for writing\n");
418 if(mode==0) printf(
" %d frames saved.\n", tac2.
sampleNr);
419 else if(mode==1) printf(
" %d integral frames saved.\n", tac2.
sampleNr);
420 else if(mode==2) printf(
" %d 2nd integral frames saved.\n", tac2.
sampleNr);
int csvRead(CSV *csv, FILE *fp, TPCSTATUS *status)
double lambdaFromIsotope(int isotope)
char * filenameGetExtension(const char *s)
Get the last extension of a file name.
int liInterpolateForPET(double *x, double *y, const int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear TAC interpolation and/or integration to PET frames.
char * isotopeName(int isotope_code)
int isotopeIdentify(const char *isotope)
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
int tacReadSIF(TAC *tac, CSV *csv, IFT *hdr, TPCSTATUS *status)
void statusInit(TPCSTATUS *s)
char * errorMsg(tpcerror e)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
int tacAllocateMoreSamples(TAC *tac, int addNr)
Allocate memory for more samples in TAC data.
int tacGetIsotope(TAC *tac)
int tacDecayCorrection(TAC *tac, int isotope, int mode, TPCSTATUS *status)
void tacSetIsotope(TAC *tac, int isotope)
int tacFormatWriteSupported(tacformat format)
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
int tacFormatIdentify(const char *s)
char * tacFormattxt(tacformat c)
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
int tacYNaNs(TAC *tac, const int i)
int tacSortByTime(TAC *d, TPCSTATUS *status)
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
int tacDeleteMissingSamples(TAC *d)
Delete those samples (time frames) from TAC structure, which contain only missing y values,...
int tacXCopy(TAC *tac1, TAC *tac2, int i1, int i2)
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Header file for library libtpccsv.
Header file for library libtpcextensions.
@ UNIT_UNKNOWN
Unknown unit.
char * unitName(int unit_code)
Header file for library libtpcift.
Header file for library libtpcisotope.
@ ISOTOPE_UNKNOWN
Unknown.
Header file for libtpcli.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
@ TAC_FORMAT_TSV_UK
UK TSV (point as decimal separator).
@ TAC_FORMAT_PMOD
PMOD TAC format.
@ TAC_FORMAT_SIMPLE
x and y's with space delimiters
@ TAC_FORMAT_DFT
Data format of Turku PET Centre.