9#include "tpcclibConfig.h"
23static char *info[] = {
24 "Convert the head-curve (count-rate) data file from ECAT HR+ (*.r) or",
25 "HRRT (*.hc) to TAC file format that is suitable for correction of ",
26 "time delay between blood/plasma and tissue TACs.",
27 "Some usual errors in count-rate data is automatically corrected.",
28 "Output data is corrected for physical decay.",
30 "Usage: @P [Options] headcurve isotope outputfile",
34 " Sample times are written in minutes or seconds;",
35 " by default in sec for tracers with short half-life, otherwise in min.",
37 " If file is not in HR+ or HRRT head-curve format, it is still saved",
38 " with the new name.",
40 " -format=<format-id>",
41 " Accepted format-id's for the output count-rate file:",
42 " CSV-INT - CSV format with semicolons and decimal commas.",
43 " CSV-UK - CSV format with commas and decimal points.",
44 " TSV-INT - TSV format with tabs and decimal commas.",
45 " TSV-UK - TSV format with tabs and decimal points.",
46 " PMOD - PMOD tac and bld format.",
47 " DFT - TPC TAC format (default).",
48 " SIMPLE - txt file with tabs and decimal points.",
52 " @P -format=simple is129.r C-11 is129.cr",
54 "See also: fitdelay, imghead, tacmean, dftscale, tac2svg, tacdecay",
56 "Keywords: ECAT HR+, HRRT, input, time delay, count-rate, head-curve",
75int main(
int argc,
char **argv)
77 int ai, help=0, version=0, verbose=1;
82 char *cptr, petfile[FILENAME_MAX], crfile[FILENAME_MAX];
90 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
92 petfile[0]=crfile[0]=(char)0;
94 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
96 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
97 if(strncasecmp(cptr,
"MIN", 1)==0) {
99 }
else if(strncasecmp(cptr,
"SEC", 1)==0) {
101 }
else if(strncasecmp(cptr,
"COPY", 1)==0) {
103 }
else if(strncasecmp(cptr,
"F=", 2)==0) {
108 if(strcasecmp(cptr,
"CR")==0 || strcasecmp(cptr,
"HEAD")==0) {
110 }
else if(strncasecmp(cptr,
"FORMAT=", 7)==0) {
115 if(strcasecmp(cptr,
"CR")==0 || strcasecmp(cptr,
"HEAD")==0) {
118 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
123 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
132 for(; ai<argc; ai++) {
134 strcpy(petfile, argv[ai]);
continue;
138 fprintf(stderr,
"Error: invalid isotope '%s'\n", argv[ai]);
140 }
else if(!crfile[0]) {
141 strcpy(crfile, argv[ai]);
continue;
143 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
152 strcpy(crfile, petfile);
155 strcat(crfile,
".cr");
168 printf(
"petfile := %s\n", petfile);
169 printf(
"crfile := %s\n", crfile);
171 printf(
"time_unit := %s\n",
unitName(time_unit));
172 printf(
"copy_cr := %d\n", copy_cr);
173 printf(
"outputformat := %s\n",
tacFormattxt(outputformat));
179 if(verbose>1) printf(
"reading %s\n", petfile);
180 ret=
tacRead(&tac, petfile, &status);
182 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), petfile);
188 printf(
"columnNr := %d\n", tac.
tacNr);
189 printf(
"frameNr := %d\n", tac.
sampleNr);
199 if(verbose>0) printf(
"identified as HRRT format.\n");
203 if(i==0) tac.
x1[i]=0.0;
else tac.
x1[i]=tac.
x2[i-1];
208 tac.
x[i]=0.5*(tac.
x1[i]+tac.
x2[i]);
212 tac.
c[0].
y[i]=tac.
c[2].
y[i]-tac.
c[1].
y[i];
219 if(n>0 && verbose>1) printf(
"%d negative point(s) deleted.\n", n);
223 strcpy(tac.
c[0].
name,
"CR");
227 if(verbose>0) printf(
"identified as HR+ format.\n");
232 if(i==0) tac.
x1[i]=0.0;
else tac.
x1[i]=tac.
x2[i-1];
237 tac.
x[i]=0.5*(tac.
x1[i]+tac.
x2[i]);
241 for(i=n=0; i<tac.
sampleNr && n<5; i++) {
242 tac.
c[0].
y[i]=tac.
c[2].
y[i]-tac.
c[3].
y[i];
243 if(tac.
c[0].
y[i]>0.0) n=0;
else n++;
246 if(verbose>1) printf(
"leaving %d/%d points.\n", i-3, tac.
sampleNr);
252 if(tac.
c[0].
y[i]<=0.0 && tac.
c[4].
y[i]<=0.0) {
256 if(n>0 && verbose>1) printf(
"%d negative point(s) deleted.\n", n);
261 if(tac.
c[4].
y[i]>0.0) {i++;
continue;}
262 a=0.75*(tac.
c[0].
y[i-1]+tac.
c[0].
y[i+1]);
265 if(n>0 && verbose>1) printf(
"%d outlier point(s) deleted.\n", n);
267 i=tac.
sampleNr-1;
while(tac.
c[0].
y[i]<=0.0) i--;
269 if(verbose>1) printf(
"%d trailing zeroes deleted.\n", tac.
sampleNr-i+1);
274 strcpy(tac.
c[0].
name,
"CR");
278 fprintf(stderr,
"Error: not identified as HRRT or HR+ countrate file\n");
281 if(verbose>0) printf(
"not identified as HRRT or HR+ countrate file.\n");
294 if(d>tac.
c[0].
y[i-1] || d>tac.
c[0].
y[i+1]) {
295 tac.
c[1].
y[i]=tac.
c[0].
y[i];
continue;}
296 a=0.5*(tac.
c[0].
y[i-1]+tac.
c[0].
y[i+1]);
297 d=fabs(tac.
c[0].
y[i-1]-tac.
c[0].
y[i+1]);
298 if(tac.
c[0].
y[i]>(a-d)) {tac.
c[1].
y[i]=tac.
c[0].
y[i];
continue;}
299 tac.
c[1].
y[i]=nan(
""); n++;
303 for(i=1; i<tac.
sampleNr-1; i++) tac.
c[0].
y[i]=tac.
c[1].
y[i];
305 if(verbose>1) printf(
"%d outlier point(s) deleted.\n", n);
312 fprintf(stderr,
"Error: invalid data in %s\n", petfile);
321 if(verbose>1) printf(
"correcting data for physical decay\n");
332 tac.
x1[i], tac.
x2[i]-tac.
x1[i]);
337 fprintf(stderr,
"Warning: time unit unknown.\n");
351 iftPut(&tac.
h,
"cr_duration", tmp, (
char)1, NULL);
352 if(verbose>0) fprintf(stdout,
"cr_duration := %s\n", tmp);
364 if(verbose>1) printf(
"writing %s\n", crfile);
365 FILE *fp; fp=fopen(crfile,
"w");
367 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", crfile);
370 ret=
tacWrite(&tac, fp, outputformat, 1, &status);
374 fprintf(stderr,
"Error: writing format %s is not supported.\n",
382 if(verbose>0) printf(
"CR data written in %s\n", crfile);
double decayCorrectionFactorFromIsotope(int isotope, double starttime, double duration)
char * filenameGetExtension(const char *s)
Get the last extension of a file name.
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
char * isotopeName(int isotope_code)
double isotopeHalflife(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)
void statusInit(TPCSTATUS *s)
char * errorMsg(tpcerror e)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
char name[MAX_TACNAME_LEN+1]
IFT h
Optional (but often useful) header information.
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int tacSetHeaderDecayCorrection(IFT *h, decaycorrection dc)
int tacSetHeaderIsotope(IFT *h, const char *s)
char * tacDefaultExtension(tacformat c)
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 tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
int tacDeleteSample(TAC *d, int i)
Delete a certain sample (time frame) from TAC structure.
Header file for library libtpcextensions.
@ UNIT_UNKNOWN
Unknown unit.
@ TPCERROR_UNSUPPORTED
Unsupported file type.
char * unitName(int unit_code)
Header file for library libtpcift.
Header file for library libtpcisotope.
@ DECAY_CORRECTED
Data is corrected for physical decay.
@ ISOTOPE_UNKNOWN
Unknown.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
@ TAC_FORMAT_SIMPLE
x and y's with space delimiters
@ TAC_FORMAT_HRPLUS_HC
HR+ head curve format (reading supported).
@ TAC_FORMAT_DFT
Data format of Turku PET Centre.
@ TAC_FORMAT_HRRT_HC
HRRT head curve format (reading supported).