9#include "tpcclibConfig.h"
22static char *info[] = {
23 "Add or remove the sample (time frame) weighting information to TAC file",
24 "for parameter estimations and curve fitting using formula (Mazoyer et al):",
25 " weight=(frame duration)^2 / (decay corrected trues in a frame)",
27 " weight=(frame duration)",
29 "TACs are assumed to be corrected for decay.",
30 "The relative weights are adjusted using a scan information file (SIF),",
31 "or TACs in the file (volume weighted average of all regions or given region);",
32 "in the latter case the units in TAC file must be set correctly.",
34 "Usage: @P [Options] tacfile [sif | tacname]",
38 " Existing weights are removed.",
39 " -L Weights are not calculated, but existing weights are printed",
40 " on screen. Return code is non-zero if data does not contain weights.",
42 " Weights are based only on frame length or sampling interval.",
43 " With -wfm the range of weights is reduced using value given with",
45 " With -wfd the late frames are given less weight by using formula:",
46 " weight=(frame duration)*exp(-t*ln(2)/halflife) (Thiele et al., 2008).",
48 " Isotope, for example C-11, in case it is not found inside SIF or TAC",
49 " file. Isotope is only needed with SIF, and with option -wfd.",
51 " Weights are moderated by adding (1/value)*max true counts to",
52 " all counts, if (max trues)/value > (min trues). By default, value=100.",
53 " You can set value to zero to apply full range of weights.",
55 " SIF data based on TAC file is written in given file; cannot be used",
56 " if SIF is given as argument.",
59 "Note that absolute weights cannot be calculated. Relative weights are",
60 "scaled so that average weight is 1.0.",
62 "This program is deprecated: for new projects use tacweigh!",
65 "1. Mazoyer BM, Huesman RH, Budinger TF, Knittel BL. Dynamic PET data",
66 " analysis. J Comput Assist Tomogr 1986; 10:645-653.",
67 "2. Thiele F, Buchert R. Evaluation of non-uniform weighting in non-linear",
68 " regression for pharmacokinetic neuroreceptor modelling.",
69 " Nucl Med Commun. 2008; 29:179-188.",
71 "See also: sifcat, sifisot, eframe, imgweigh, tacframe, imghead, tacdecay",
73 "Keywords: TAC, SIF, modelling, weighting",
92int main(
int argc,
char **argv)
94 int ai, help=0, version=0, verbose=1;
102 double WCORR_LIMIT=100.0;
103 char *cptr, siffile[FILENAME_MAX], dftfile[FILENAME_MAX], tmp[FILENAME_MAX];
104 char newfile[FILENAME_MAX], isotope_name[128];
105 double halflife=-1.0;
113 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
114 siffile[0]=dftfile[0]=newfile[0]=isotope_name[0]=(char)0;
117 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
118 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
120 if(strncasecmp(cptr,
"L", 1)==0) {
121 print_weights=1;
continue;
122 }
else if(strcasecmp(cptr,
"RM")==0 || strcasecmp(cptr,
"DEL")==0) {
123 remove_weights=1;
continue;
124 }
else if(strncasecmp(cptr,
"I=", 2)==0) {
128 strcpy(isotope_name, cptr);
130 if(halflife>0.0)
continue;
132 }
else if(strncasecmp(cptr,
"SIF=", 4)==0) {
133 cptr+=4;
strlcpy(newfile, cptr, FILENAME_MAX);
134 if(strlen(newfile)>0)
continue;
135 }
else if(strncasecmp(cptr,
"moderate=", 9)==0) {
136 cptr+=9; WCORR_LIMIT=
atof_dpi(cptr);
if(cptr!=NULL)
continue;
137 }
else if(strcasecmp(cptr,
"WF")==0) {
138 weight_method=1;
continue;
139 }
else if(strcasecmp(cptr,
"WFM")==0) {
140 weight_method=2;
continue;
141 }
else if(strcasecmp(cptr,
"WFD")==0) {
142 weight_method=3;
continue;
144 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
149 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
157 fprintf(stderr,
"Error: missing command-line argument.\n");
160 strlcpy(dftfile, argv[ai], FILENAME_MAX);
163 fprintf(stderr,
"Error (%d) in reading '%s': %s\n",
168 if(!(halflife>0.0) && strlen(dft.
isotope)>0)
176 strlcpy(siffile, argv[ai], FILENAME_MAX);
177 if(!(halflife>0.0)) {
187 for(ri=0; ri<dft.
voiNr; ri++)
if(dft.
voi[ri].
sw) {head_voi=ri;
break;}
190 fprintf(stderr,
"Error: no TAC matching '%s' was found.\n", argv[ai]);
192 fprintf(stderr,
"Error: %d TACs match '%s'.\n", n, argv[ai]);
200 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
207 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
210 if(newfile[0] && siffile[0]) {
211 fprintf(stderr,
"Warning: option -SIF is ignored.\n");
212 strcpy(newfile,
""); fflush(stderr);
213 }
else if(newfile[0] && halflife<=0.0) {
214 fprintf(stderr,
"Error: SIF file cannot be saved without isotope.\n");
217 if(weight_method==3 && halflife<=0.0) {
218 fprintf(stderr,
"Error: option -wfd cannot be used without isotope.\n");
224 printf(
"dftfile := %s\n", dftfile);
225 printf(
"remove_weights := %d\n", remove_weights);
226 printf(
"isotope_name := %s\n", isotope_name);
227 printf(
"halflife := %g\n", halflife);
228 printf(
"print_weights := %d\n", print_weights);
229 printf(
"sif.frameNr := %d\n", sif.
frameNr);
230 printf(
"dft.frameNr := %d\n", dft.
frameNr);
231 printf(
"head_voi := %d\n", head_voi);
232 printf(
"WCORR_LIMIT := %g\n", WCORR_LIMIT);
233 printf(
"weight_method := %d\n", weight_method);
234 if(newfile[0]) printf(
"newfile := %s\n", newfile);
244 fprintf(stdout,
"contains_weights := ");
245 if(dft.
isweight==0) fprintf(stdout,
"no\n");
else fprintf(stdout,
"yes\n");
247 if(print_weights!=0) {
248 if(verbose>2) printf(
"printing existing weights\n");
250 fprintf(stdout,
"%s does not contain weights.\n", dftfile);
254 fprintf(stdout,
"start[]\tend[]\tweight\n");
255 for(
int i=0; i<dft.
frameNr; i++)
256 fprintf(stdout,
"%g\t%g\t%.4e\n", dft.
x1[i], dft.
x2[i], dft.
w[i]);
260 fprintf(stdout,
"time[]\tweight\n");
261 for(
int i=0; i<dft.
frameNr; i++) fprintf(stdout,
"%g\t%.4e\n", dft.
x[i], dft.
w[i]);
272 if(remove_weights!=0) {
273 if(verbose>1) printf(
"removing weights\n");
275 fprintf(stderr,
" data does not contain weights.\n");
279 if((ret=
dftWrite(&dft, dftfile))!=0) {
280 fprintf(stderr,
"Error (%d) in writing '%s': %s\n",ret,dftfile,
dfterrmsg);
283 if(verbose>0) fprintf(stdout,
" weights removed.\n");
297 if(verbose>2) printf(
"SIF will be used; checking for necessary data\n");
298 if(halflife<=0.0 && (weight_method==0 || weight_method==3)) {
300 fprintf(stderr,
"Error: isotope is required with SIF file.\n");
304 fprintf(stderr,
"Error: frames in DFT and SIF do not match.\n");
308 if(weight_method==0) {
311 }
else if(weight_method==1) {
313 }
else if(weight_method==2) {
317 }
else if(weight_method==3) {
320 fprintf(stderr,
"Error: invalid weight setting.\n");
332 if(verbose>1) printf(
"creating SIF data from regional data\n");
340 if(verbose>3) printf(
"last_frame_time := %g\n", lf);
343 fprintf(stderr,
"Warning: unknown time unit; assumed min.\n");
344 }
else if(lf>360.0) {
346 fprintf(stderr,
"Warning: unknown time unit; assumed sec.\n");
348 fprintf(stderr,
"Error: unknown time unit.\n");
358 fprintf(stderr,
"Warning: unknown calibration unit; assumed MBq/cc.\n");
361 fprintf(stderr,
"Error: unknown calibration unit.\n");
368 fprintf(stderr,
"Error: out of memory.\n");
373 for(
int i=0; i<dft.
frameNr; i++) {
374 sif.
x1[i]=dft.
x1[i]; sif.
x2[i]=dft.
x2[i];
379 for(
int i=0; i<dft.
frameNr; i++) {sif.
x1[i]*=60.; sif.
x2[i]*=60.;}
392 for(
int fi=0; fi<dft.
frameNr; fi++) {
394 for(
int ri=0; ri<dft.
voiNr; ri++) {
395 f=dft.
voi[ri].
size;
if(f<=0.0) f=1.0;
396 if(!isnan(dft.
voi[ri].
y[fi]))
397 {w+=f; sif.
trues[fi]+=f*dft.
voi[ri].
y[fi];}
399 if(w!=0.0) sif.
trues[fi]/=w;
405 case CUNIT_BQ_PER_ML: cf=0.001;
break;
406 case CUNIT_KBQ_PER_ML: cf=1.0;
break;
407 case CUNIT_MBQ_PER_ML: cf=1000.0;
break;
408 case CUNIT_NCI_PER_ML: cf=0.037;
break;
414 for(
int i=0; i<sif.
frameNr; i++)
418 if(weight_method==0) {
420 }
else if(weight_method==1) {
422 }
else if(weight_method==2) {
426 }
else if(weight_method==3) {
429 fprintf(stderr,
"Error: invalid weight setting.\n");
437 for(
int fi=0; fi<sif.
frameNr; fi++) {
438 f=exp(-((sif.
x1[fi]+sif.
x2[fi])/2.0)*0.693147/halflife );
445 fprintf(stderr,
"Error: %s\n", tmp);
449 fprintf(stderr,
"Warning in writing %s : %s\n", newfile,
siferrmsg);
451 fprintf(stdout,
"SIF data written in %s\n", newfile);
467 if(verbose>1) printf(
"add weights to DFT\n");
470 fprintf(stderr,
"Warning: existing weight was overwritten.\n");
479 if(verbose>2) printf(
"writing DFT file\n");
484 fprintf(stderr,
"Error: cannot write '%s'.\n", dftfile);
487 if(verbose>0) fprintf(stdout,
"weights added to %s\n", dftfile);
int backupExistingFile(char *filename, char *backup_ext, char *status)
double atof_dpi(char *str)
double dft_kBqMax(DFT *data)
int dftSelectRegions(DFT *dft, char *region_name, int reset)
int dftRead(char *filename, DFT *data)
int dftWrite(DFT *data, char *filename)
void dftUnitToDFT(DFT *dft, int dunit)
char * hlCorrectIsotopeCode(char *isocode)
double hlFromIsotope(char *isocode)
Header file for libtpccurveio.
#define DFT_FORMAT_STANDARD
#define DFT_TIME_STARTEND
#define DFT_FORMAT_UNKNOWN
Header file for libtpcimgio.
void sifModerateTrues(SIF *sif, double limit)
void sifModerateWeights(SIF *sif, double limit)
int sifWrite(SIF *data, char *filename)
void sifWeightByFrames(SIF *data, double halflife)
Calculate weights for frames in SIF data based on frame lengths. Weights are normalized to have an av...
void sifWeight(SIF *data, double halflife)
Calculate weights for frames in SIF data based on true counts. Weights are normalized to have an aver...
int sifSetmem(SIF *data, int frameNr)
void sifWeightNorm(SIF *data)
int sifRead(char *filename, SIF *data)
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
int petCunitId(const char *unit)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
int studynr_from_fname(char *fname, char *studynr)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
char studynr[MAX_STUDYNR_LEN+1]
char unit[MAX_UNITS_LEN+1]
char studynr[MAX_STUDYNR_LEN+1]