TPCCLIB
Loading...
Searching...
No Matches
fvar4img.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <string.h>
14#include <time.h>
15/*****************************************************************************/
16#include "libtpcmisc.h"
17#include "libtpcmodel.h"
18#include "libtpccurveio.h"
19#include "libtpcimgio.h"
20#include "libtpcimgp.h"
21#include "libtpcmodext.h"
22/*****************************************************************************/
23
24/*****************************************************************************/
25static char *info[] = {
26 "Program for adding Gaussian noise to dynamic PET image",
27 "using equations (1, 2):",
28 " SD(t) = TAC(t) * sqrt(Pc/(TAC(t)*exp(-lambda*t)*deltat)",
29 " TAC_noisy(t) = TAC(t) + SD(t)*G(0,1) ,",
30 "where Pc is the proportionality constant that determines the level of noise,",
31 "TAC(t) is the mean activity concentration in the image frame,",
32 "Deltat is the scan frame length, and G(0,1) is a pseudo random number from",
33 "a Gaussian distribution with zero mean and SD of one.",
34 " ",
35 "Image must be in ECAT (6.3 or 7) format, or, Analyze 7.5 or NIfTI-1 format",
36 "with SIF.",
37 "Image is assumed to be decay corrected to zero time.",
38 " ",
39 "Usage: @P [Options] image Pc outputimage ",
40 " ",
41 "Options:",
42 " -seed=<seed for random number generator>",
43 " Computer clock is used by default.",
44 " -i=<O-15|N-13|C-11|F-18|Ge-68|Ga-68|Br-76|Rb-82|Cu-62>",
45 " Specifies the isotope.",
46 " -minsd=<SD>",
47 " Set a minimum SD to add a minimum level of noise also to the image",
48 " frames with no activity.",
49 " -efile=<TAC filename>",
50 " Save image mean TAC and SD that were used in noise simulation.",
51 " -stdoptions", // List standard options like --help, -v, etc
52 " ",
53 "Example:",
54 " @P -i=C-11 simulated.v 5.0 noisy.v",
55 " ",
56 "References:",
57 "1. Chen K, Huang SC, Yu DC. Phys Med Biol 1991;36:1183-1200.",
58 "2. Varga J, Szabo Z. J Cereb Blood Flow Metab 2002;22:240-244.",
59 " ",
60 "See also: dft2img, flat2img, eframe, imgdecay, fvar4tac, img2tif",
61 " ",
62 "Keywords: image, simulation, noise",
63 0};
64/*****************************************************************************/
65
66/*****************************************************************************/
67/* Turn on the globbing of the command line, since it is disabled by default in
68 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
69 In Unix&Linux wildcard command line processing is enabled by default. */
70/*
71#undef _CRT_glob
72#define _CRT_glob -1
73*/
74int _dowildcard = -1;
75/*****************************************************************************/
76
77/*****************************************************************************/
81int main(int argc, char **argv)
82{
83 int ai, help=0, version=0, verbose=1;
84 int ret=0, fi, pi, ri, ci;
85 unsigned long int seed=0L;
86 char imgfile[FILENAME_MAX], outfile[FILENAME_MAX], efile[FILENAME_MAX];
87 char *cptr, tmp[FILENAME_MAX];
88 double pc=-1.0, minsd=-1.0, halflife=0.0;
89 IMG img;
90 DFT tac;
91
92
93 /*
94 * Get arguments
95 */
96 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
97 imgfile[0]=outfile[0]=efile[0]=(char)0;
98 imgInit(&img); dftInit(&tac);
99 /* Options */
100 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
101 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
102 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
103 if(strncasecmp(cptr, "S=", 2)==0) {
104 seed=atol(cptr+2); if(seed>0L) continue;
105 } else if(strncasecmp(cptr, "SEED=", 5)==0) {
106 seed=atol(cptr+5); if(seed>0L) continue;
107 } else if(strncasecmp(cptr, "I=", 2)==0) {
108 cptr=hlCorrectIsotopeCode(cptr+2); if(cptr!=NULL) {
109 halflife=60.0*hlFromIsotope(cptr); if(halflife>0.0) continue;}
110 fprintf(stderr, "Error: invalid isotope with option -i\n"); return(1);
111 } else if(strncasecmp(cptr, "MINSD=", 6)==0) {
112 minsd=atof_dpi(cptr+6); if(minsd>0.0) continue;
113 } else if(strncasecmp(cptr, "EFILE=", 6)==0) {
114 strcpy(efile, cptr+6); if(strlen(efile)>1) continue;
115 }
116 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
117 return(1);
118 } else break;
119
120 /* Print help or version? */
121 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
122 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
123 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
124
125 /* Process other arguments, starting from the first non-option */
126 for(; ai<argc; ai++) {
127 if(!imgfile[0]) {
128 strcpy(imgfile, argv[ai]); continue;
129 } else if(pc<0.0) {
130 pc=atof_dpi(argv[ai]); if(pc>0.0) continue;
131 } else if(!outfile[0]) {
132 strcpy(outfile, argv[ai]); continue;
133 }
134 /* we should never get this far */
135 fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]);
136 return(1);
137 }
138
139 /* Is something missing? */
140 if(!outfile[0]) {
141 fprintf(stderr, "Error: missing command-line argument; try %s --help\n",
142 argv[0]);
143 return(1);
144 }
145 if(strcasecmp(imgfile, outfile)==0) {
146 fprintf(stderr, "Error: must not overwrite input image.\n"); return(1);
147 }
148
149 /* In verbose mode print arguments and options */
150 if(verbose>1) {
151 printf("imgfile := %s\n", imgfile);
152 printf("outfile := %s\n", outfile);
153 printf("proportionality_constant := %g\n", pc);
154 if(halflife>0.0) printf("halflife := %g\n", halflife);
155 if(minsd>0.0) printf("minsd := %g\n", minsd);
156 printf("efile := %s\n", efile);
157 }
158
159
160 /*
161 * Read the contents of the ECAT file to img data structure
162 */
163 if(verbose>1) printf("reading image %s\n", imgfile);
164 if(imgRead(imgfile, &img)) {
165 fprintf(stderr, "Error: %s\n", img.statmsg);
166 if(verbose>1) imgInfo(&img);
167 imgEmpty(&img);
168 return(2);
169 }
170 if(verbose>9) imgInfo(&img);
171 if(imgNaNs(&img, 1)>0)
172 if(verbose>0) fprintf(stderr, "Warning: missing pixel values.\n");
173 /* Check that image is image */
174 if(img.type!=IMG_TYPE_IMAGE) {
175 fprintf(stderr, "Error: %s is not an image.\n", imgfile);
176 imgEmpty(&img); return(1);
177 }
178 /* Check that frame times are available */
179 if(!imgExistentTimes(&img)) {
180 fprintf(stderr, "Error: image does not contain frame times.\n");
181 imgEmpty(&img); return(2);
182 }
183 /* Check that halflife is known */
184 if(img.isotopeHalflife<=0.0 && halflife<=0.0) {
185 fprintf(stderr, "Error: set isotope with option -i\n");
186 imgEmpty(&img); return(3);
187 }
188 /* If user specified the isotope, then use it */
189 if(halflife>0.0) img.isotopeHalflife=halflife;
190 /* Calculate decay correction factors */
191 ret=imgSetDecayCorrFactors(&img, 1);
192 if(ret) {
193 fprintf(stderr, "Error %d in setting decay correction factors.\n", ret);
194 imgEmpty(&img); return(3);
195 }
196
197
198 /* Check if outputfile exists; rename it as backup file, if necessary */
199 ret=backupExistingFile(outfile, NULL, tmp);
200 if(ret!=0) {
201 fprintf(stderr, "Error: %s\n", tmp);
202 imgEmpty(&img); return(11);
203 }
204
205
206 /*
207 * Calculate an average TAC of all image pixels
208 */
209 if(verbose>1) printf("calculating average TAC of all image pixels\n");
210 /* Allocate memory for TAC */
211 ret=dftSetmem(&tac, img.dimt, 2);
212 if(ret) {
213 fprintf(stderr, "Error: cannot allocate memory.\n");
214 imgEmpty(&img); return(5);
215 }
216 /* Set TAC information */
217 strcpy(tac.isotope, imgIsotope(&img));
218 tac._type=1; tac.frameNr=img.dimt; tac.voiNr=2;
219 strcpy(tac.unit, imgUnit(img.unit));
220 tac.timetype=DFT_TIME_STARTEND; tac.timeunit=TUNIT_SEC;
221 strcpy(tac.voi[0].voiname,"Mean"); strcpy(tac.voi[0].name,tac.voi[0].voiname);
222 strcpy(tac.voi[1].voiname,"SD"); strcpy(tac.voi[1].name,tac.voi[1].voiname);
223 for(fi=0; fi<img.dimt; fi++) {
224 tac.x1[fi]=img.start[fi]; tac.x2[fi]=img.end[fi];
225 tac.x[fi]=img.mid[fi];
226 }
228 /* Calculate average of pixel values */
229 ret=imgAverageTAC(&img, img.sd);
230 if(ret) {
231 fprintf(stderr, "Error: cannot calculate average TAC (%d).\n", ret);
232 imgEmpty(&img); dftEmpty(&tac);
233 return(6);
234 }
235 for(fi=0; fi<img.dimt; fi++) tac.voi[0].y[fi]=img.sd[fi];
236 if(verbose>3) dftPrint(&tac);
237
238
239 /*
240 * Compute SD values for each frame
241 */
242 if(verbose>1) printf("calculating SD for each frame\n");
243 ret=noiseSD4SimulationFromDFT(&tac, 0, pc, tac.voi[1].y, tmp, verbose-3);
244 if(ret!=0) {
245 fprintf(stderr,
246 "Error: cannot calculate SD for noise simulation (%d).\n", ret);
247 if(verbose>1) printf(" %s\n", tmp);
248 imgEmpty(&img); dftEmpty(&tac);
249 return(7);
250 }
251 /* Set min SD, if specified by user */
252 if(minsd>0.0)
253 for(fi=0; fi<img.dimt; fi++)
254 if(minsd>tac.voi[1].y[fi]) tac.voi[1].y[fi]=minsd;
255 if(verbose>1) {
256 printf("Frame\t\t\tMean\tSD\n");
257 for(fi=0; fi<img.dimt; fi++)
258 printf("%d\t%g\t%g\t%g\t%g\n",
259 1+fi, tac.x1[fi], tac.x2[fi], tac.voi[0].y[fi], tac.voi[1].y[fi]);
260 }
261 if(verbose>8) dftPrint(&tac);
262 if(efile[0]) { /* Save image mean TAC and SD, if required */
263 if(verbose>1) printf("writing %s\n", efile);
265 if(dftWrite(&tac, efile)) {
266 fprintf(stderr, "Error in writing '%s': %s\n", efile, dfterrmsg);
267 imgEmpty(&img); dftEmpty(&tac); return(11);
268 }
269 if(verbose>0) printf("Mean TAC and noise SD written in %s\n", efile);
270 }
271
272
273 /*
274 * Add noise to the image pixels
275 */
276 if(verbose>1) printf("adding noise to image\n");
277 if(seed>0) GAUSSDEV_SEED=seed;
278 else GAUSSDEV_SEED=drandSeed(0);
279 for(fi=0; fi<img.dimt; fi++) {
280 if(verbose>0 && img.dimt>1) {fprintf(stdout, "."); fflush(stdout);}
281 for(pi=0; pi<img.dimz; pi++)
282 for(ri=0; ri<img.dimy; ri++)
283 for(ci=0; ci<img.dimx; ci++)
284 img.m[pi][ri][ci][fi] += tac.voi[1].y[fi]*gaussdev();
285 }
286 if(verbose>0 && img.dimt>1) {fprintf(stdout, "\n"); fflush(stdout);}
287
288
289 /*
290 * Write the noisy image
291 */
292 if(verbose>1) printf("writing noisy image %s\n", outfile);
293 if(imgWrite(outfile, &img)) {
294 fprintf(stderr, "Error: %s\n", img.statmsg);
295 imgEmpty(&img); dftEmpty(&tac);
296 return(21);
297 }
298
299
300 /*
301 * Free up memory
302 */
303 imgEmpty(&img);
304 dftEmpty(&tac);
305 if(verbose>0) printf("done.\n");
306
307 return(0);
308}
309/*****************************************************************************/
310
311/*****************************************************************************/
int backupExistingFile(char *filename, char *backup_ext, char *status)
Definition backup.c:14
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 dftSetmem(DFT *data, int frameNr, int voiNr)
Definition dft.c:57
void dftEmpty(DFT *data)
Definition dft.c:20
int DFT_NR_OF_DECIMALS
Definition dftio.c:13
void dftPrint(DFT *data)
Definition dftio.c:538
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
double gaussdev()
Definition gaussdev.c:30
long int GAUSSDEV_SEED
Definition gaussdev.c:7
unsigned int drandSeed(short int seed)
Make and optionally set the seed for rand(), drand, drandRange, and drandGaussian().
Definition gaussdev.c:63
char * hlCorrectIsotopeCode(char *isocode)
Definition halflife.c:141
double hlFromIsotope(char *isocode)
Definition halflife.c:55
int imgExistentTimes(IMG *img)
Definition img.c:613
void imgInfo(IMG *image)
Definition img.c:359
unsigned long long imgNaNs(IMG *img, int fix)
Definition img.c:658
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
char * imgIsotope(IMG *img)
Definition imgdecayc.c:76
int imgSetDecayCorrFactors(IMG *image, int mode)
Definition imgdecayc.c:87
int imgAverageTAC(IMG *img, float *tac)
Definition imgeval.c:15
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgWrite(const char *fname, IMG *img)
Definition imgfile.c:136
char * imgUnit(int dunit)
Definition imgunits.c:315
Header file for libtpccurveio.
#define DFT_DECAY_CORRECTED
#define DFT_TIME_STARTEND
Header file for libtpcimgio.
#define IMG_TYPE_IMAGE
Header file for libtpcimgp.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
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.
Header file for libtpcmodext.
int noiseSD4SimulationFromDFT(DFT *dft, int index, double pc, double *sd, char *status, int verbose)
Definition noise.c:79
char decayCorrected
int _type
int timetype
Voi * voi
int timeunit
double * x1
int voiNr
double * x2
int frameNr
char isotope[8]
double * x
char unit[MAX_UNITS_LEN+1]
unsigned short int dimx
char type
float * sd
float **** m
char unit
unsigned short int dimt
float * start
unsigned short int dimz
unsigned short int dimy
float * end
const char * statmsg
float isotopeHalflife
float * mid
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]