10#include "tpcclibConfig.h"
24static char *info[] = {
25 "Program for adding Gaussian noise to dynamic PET time-activity curve (TAC)",
26 "or TACs using equations (1, 2):",
27 " SD(t) = TAC(t) * sqrt(Pc/(TAC(t)*exp(-lambda*t)*deltat)",
28 " TAC_noisy(t) = TAC(t) + SD(t)*G(0,1) ,",
29 "where Pc is the proportionality constant that determines the level of noise,",
30 "TAC(t) is the mean activity concentration in the image frame,",
31 "Deltat is the scan frame length, and G(0,1) is a pseudo random number from",
32 "a Gaussian distribution with zero mean and SD of one.",
34 "Usage: @P [Options] tacfile Pc isotope outputfile ",
38 " Set a minimum SD to add a minimum level of noise also to the time",
39 " frames with little or no activity.",
40 " -R=<nr of repeats>",
41 " Specified number of output files (*_NNNN.*) with different set of",
42 " noise are created.",
44 " Common noise SD based on TAC mean is used (y), or SD is based on each TAC",
45 " separately (n, default).",
47 " Noise is not added to TAC but calculated values of SD or CV (for noise)",
48 " are saved instead in the output file.",
50 " If datafile does not contain time unit, times are by default assumed to",
51 " be in minutes. Use this option to set time unit to sec.",
56 "TAC data must contain frame start and end times (PMOD or DFT format).",
57 "TACs are assumed to be decay corrected to zero time.",
58 "Accepted isotope codes include at least O-15, C-11, F-18, Ga-68, N-13, Br-76,",
62 " @P simulated.tac 5.0 C-11 noisy.tac",
65 "1. Chen K, Huang SC, Yu DC. Phys Med Biol 1991;36:1183-1200.",
66 "2. Varga J, Szabo Z. J Cereb Blood Flow Metab 2002;22:240-244.",
68 "See also: fvar4img, var4tac, sim_3tcm, simframe, tacadd, avgttac",
70 "Keywords: TAC, simulation, noise",
89int main(
int argc,
char **argv)
91 int ai, help=0, version=0, verbose=1;
92 char tacfile[FILENAME_MAX], simfile[FILENAME_MAX];
94 unsigned int repeatNr=1;
98 double noiseLevel=nan(
""), minsd=nan(
"");
106 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
107 tacfile[0]=simfile[0]=(char)0;
109 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
111 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
112 if(strncasecmp(cptr,
"SEED=", 5)==0) {
113 seed=atol(cptr+5);
if(seed>0L)
continue;
114 }
else if(strcasecmp(cptr,
"SD")==0 || strcasecmp(cptr,
"STD")==0) {
116 }
else if(strcasecmp(cptr,
"CV")==0) {
118 }
else if(strcasecmp(cptr,
"SEC")==0) {
120 }
else if(strncasecmp(cptr,
"R=", 2)==0) {
121 int rn=atoi(cptr+2);
if(rn>0) {repeatNr=(
unsigned int)rn;
continue;}
122 }
else if(strncasecmp(cptr,
"MINSD=", 6)==0) {
124 }
else if(strncasecmp(cptr,
"COMMON=", 7)==0) {
125 if(strncasecmp(cptr+7,
"YES", 1)==0) {commonSD=1;
continue;}
126 if(strncasecmp(cptr+7,
"NO", 1)==0) {commonSD=0;
continue;}
128 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
137 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
142 if(ai<argc) {
strlcpy(tacfile, argv[ai++], FILENAME_MAX);}
145 if(isnan(noiseLevel) || noiseLevel<0.0) {
146 fprintf(stderr,
"Error: invalid noise level (Pc) '%s'.\n", argv[ai]);
return(1);}
147 if(noiseLevel<1.0E-22) fprintf(stderr,
"Warning: noise level is zero.\n");
153 fprintf(stderr,
"Error: invalid isotope '%s'\n", argv[ai]);
return(1);}
156 if(ai<argc) {
strlcpy(simfile, argv[ai++], FILENAME_MAX);}
158 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
164 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
168 if(repeatNr>9999) {fprintf(stderr,
"Error: too many repeats.\n");
return(1);}
169 if(mode!=0 && repeatNr>1) {
170 fprintf(stderr,
"Error: do not use -R when calculating SD or CV curves.\n");
return(1);
175 printf(
"tacfile := %s\n", tacfile);
176 printf(
"simfile := %s\n", simfile);
177 printf(
"proportionality_constant := %g\n", noiseLevel);
179 if(!isnan(minsd)) printf(
"minsd := %g\n", minsd);
180 printf(
"commonSD := %d\n", commonSD);
181 printf(
"backup_tunit := %s\n",
unitName(tunit));
182 printf(
"mode := %d\n", mode);
183 printf(
"repeatNr := %u\n", repeatNr);
190 if(verbose>1) fprintf(stdout,
"reading %s\n", tacfile);
193 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), tacfile);
198 printf(
"tacNr := %d\n", tac.
tacNr);
199 printf(
"sampleNr := %d\n", tac.
sampleNr);
206 if(verbose>0) printf(
"time unit set to %s\n",
unitName(tac.
tunit));
210 fprintf(stderr,
"Error: missing frame lengths.\n");
214 fprintf(stderr,
"Error: missing frame times.\n");
219 fprintf(stderr,
"Error: missing concentrations.\n");
223 if(tac.
tacNr==1 && commonSD!=0) {
224 if(verbose>0) fprintf(stderr,
"Note: only one TAC in datafile.\n");
234 fprintf(stderr,
"Error: cannot make output data.\n");
241 printf(
"tacNr := %d\n", tac2.
tacNr);
242 printf(
"sampleNr := %d\n", tac2.
sampleNr);
253 for(
int fi=0; fi<tac.
sampleNr; fi++) {
255 for(
int ri=0; ri<tac.
tacNr; ri++) tac2.
w[fi]+=tac.
c[ri].
y[fi];
256 tac2.
w[fi]/=(double)tac.
tacNr;
263 for(
int fi=0; fi<tac.
sampleNr; fi++) {
264 for(
int ri=0; ri<tac.
tacNr; ri++) {
267 if(isnan(tac2.
c[ri].
y[fi])) errcount++;
271 for(
int fi=0; fi<tac.
sampleNr; fi++) {
273 if(isnan(tac2.
w[fi])) errcount++;
275 for(
int fi=0; fi<tac.
sampleNr; fi++)
276 for(
int ri=0; ri<tac.
tacNr; ri++)
277 tac2.
c[ri].
y[fi]=tac2.
w[fi];
280 fprintf(stderr,
"Error: cannot calculate SD from the data.\n");
285 if(!isnan(minsd) && minsd>0.0) {
286 for(
int fi=0; fi<tac.
sampleNr; fi++)
287 for(
int ri=0; ri<tac.
tacNr; ri++)
288 if(minsd>tac2.
c[ri].
y[fi]) tac2.
c[ri].
y[fi]=minsd;
294 if(verbose>1) printf(
"writing SDs in %s\n", simfile);
295 FILE *fp; fp=fopen(simfile,
"w");
297 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", simfile);
303 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
306 if(verbose>=0) printf(
"SDs saved in %s\n", simfile);
312 if(verbose>1) printf(
"calculating CVs\n");
313 for(
int fi=0; fi<tac.
sampleNr; fi++)
314 for(
int ri=0; ri<tac.
tacNr; ri++) {
315 tac2.
c[ri].
y[fi]/=tac.
c[ri].
y[fi];
316 if(!isfinite(tac2.
c[ri].
y[fi])) tac2.
c[ri].
y[fi]=0.0;
318 if(verbose>1) printf(
"writing CVs in %s\n", simfile);
319 FILE *fp; fp=fopen(simfile,
"w");
321 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", simfile);
327 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
330 if(verbose>=0) printf(
"CVs saved in %s\n", simfile);
343 if(verbose>1) printf(
"adding noise\n");
345 for(
int fi=0; fi<tac.
sampleNr; fi++)
346 for(
int ri=0; ri<tac.
tacNr; ri++)
348 if(verbose>1) printf(
"writing noisy data in %s\n", simfile);
349 FILE *fp; fp=fopen(simfile,
"w");
351 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", simfile);
356 printf(
"tacNr := %d\n", tac2.
tacNr);
357 printf(
"sampleNr := %d\n", tac2.
sampleNr);
364 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
367 if(verbose>=0) printf(
"Noisy data saved in %s\n", simfile);
374 if(verbose>0 && repeatNr>10) printf(
"making %d TAC files with Gaussian noise\n", repeatNr);
376 char basisname[FILENAME_MAX], fnextens[FILENAME_MAX];
380 printf(
"basis_of_filename := %s\n", basisname);
381 printf(
"extensions := %s\n", fnextens);
383 if(strlen(basisname)<1 || ((5+strlen(basisname)+strlen(fnextens))>=FILENAME_MAX)) {
384 fprintf(stderr,
"Error: invalid output file name.\n");
390 fprintf(stderr,
"Error: cannot make copy of SDs.\n");
396 snprintf(simfile, FILENAME_MAX,
"%s_%04u%s", basisname, repeatNr, fnextens);
397 if(verbose>2) printf(
" %s\n", simfile);
398 else if(verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
400 for(
int fi=0; fi<tac.
sampleNr; fi++)
401 for(
int ri=0; ri<tac.
tacNr; ri++)
404 FILE *fp; fp=fopen(simfile,
"w");
406 fprintf(stderr,
"\nError: cannot open file for writing (%s)\n", simfile);
412 fprintf(stderr,
"\nError (%d): %s\n", ret,
errorMsg(status.
error));
417 if(verbose>2) printf(
"done.\n");
else if(verbose>0) fprintf(stdout,
"\n");
double atofVerified(const char *s)
char * filenameGetExtensions(const char *s)
Get all extensions of a file name.
void filenameRmExtensions(char *s)
char * isotopeName(int isotope_code)
int isotopeIdentify(const char *isotope)
void mertwiInitWithSeed64(MERTWI *mt, uint64_t seed)
Initialize the state vector mt[] inside data structure for Mersenne Twister MT19937 pseudo-random num...
double mertwiRandomGaussian(MERTWI *mt)
Generate a 64-bit double precision floating point pseudo-random number with normal (Gaussian) distrib...
uint64_t mertwiSeed64(void)
Make uint64_t seed for pseudo-random number generators.
void mertwiInit(MERTWI *mt)
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)
double noiseSD4Frame(double y, double t1, double dt, int isotope, double a)
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 tacRead(TAC *d, const char *fname, TPCSTATUS *status)
char * tacFormattxt(tacformat c)
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
int tacYNaNs(TAC *tac, const int i)
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Header file for library libtpcextensions.
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ UNIT_UNKNOWN
Unknown unit.
char * unitName(int unit_code)
Header file for library libtpcift.
@ ISOTOPE_UNKNOWN
Unknown.
Header file for libtpcrand.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.