TPCCLIB
Loading...
Searching...
No Matches
var4tac.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "tpcclibConfig.h"
11/*****************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <math.h>
16/*****************************************************************************/
17#include "tpcextensions.h"
18#include "tpcift.h"
19#include "tpctac.h"
20#include "tpcrand.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Program for adding Gaussian noise to dynamic PET time-activity curve (TAC)",
26 "or TACs using equation",
27 " TAC_noisy(t) = TAC(t) + (CV/100)*TAC(t)*G(0,1) ,",
28 "G(0,1) is a pseudo random number from a Gaussian distribution",
29 "with zero mean and SD of one.",
30 " ",
31 "Usage: @P [Options] tacfile CV outputfile ",
32 " ",
33 "Options:",
34 " -minsd=<Percentage of maximal SD>",
35 " Based on CV only the time frames with little or no activity would have",
36 " very little or no noise. With this option the noise level (SD) in all",
37 " time frames will be at least the given percentage of the maximal SD",
38 " of all time frames and TACs.",
39 " -stdoptions", // List standard options like --help, -v, etc
40 " ",
41 "Frame durations are not used, even if available in the TAC file.",
42 "If TAC file contains weight column, then the specified amount of variance is",
43 "added to frames with weight=1, and higher or lower variance to those",
44 "frames with lower or higher weight.",
45 " ",
46 "Example:",
47 " @P simulated.tac 10 noisy.tac",
48 " ",
49 "See also: svar4tac, fvar4tac, sim_3tcm, tacweigh, tacadd, avgttac",
50 " ",
51 "Keywords: TAC, simulation, noise",
52 0};
53/*****************************************************************************/
54
55/*****************************************************************************/
56/* Turn on the globbing of the command line, since it is disabled by default in
57 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
58 In Unix&Linux wildcard command line processing is enabled by default. */
59/*
60#undef _CRT_glob
61#define _CRT_glob -1
62*/
63int _dowildcard = -1;
64/*****************************************************************************/
65
66/*****************************************************************************/
70int main(int argc, char **argv)
71{
72 int ai, help=0, version=0, verbose=1;
73 char tacfile[FILENAME_MAX], simfile[FILENAME_MAX];
74 double minsd=nan("");
75 double cv=nan("");
76
77
78 /*
79 * Get arguments
80 */
81 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
82 tacfile[0]=simfile[0]=(char)0;
83 /* Options */
84 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
85 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
86 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
87 if(strncasecmp(cptr, "MINSD=", 6)==0) {
88 minsd=atofVerified(cptr+6);
89 if(isnan(minsd) || minsd<0.0 || minsd>100.0) {
90 fprintf(stderr, "Error: invalid minimum SD percentage '%s'.\n", argv[ai]); return(1);}
91 if(minsd<0.9) fprintf(stderr, "Warning: minimum SD is set to %g%%.\n", minsd);
92 continue;
93 }
94 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
95 return(1);
96 } else break; // tac name argument may start with '-'
97
98 TPCSTATUS status; statusInit(&status);
99 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
100 status.verbose=verbose-1;
101
102 /* Print help or version? */
103 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
104 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
105 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
106
107 /* Process other arguments, starting from the first non-option */
108 if(ai<argc) {strlcpy(tacfile, argv[ai++], FILENAME_MAX);}
109 if(ai<argc) {
110 cv=atofVerified(argv[ai]);
111 if(isnan(cv) || cv<0.0 || cv>1000.0) {
112 fprintf(stderr, "Error: invalid CV%% '%s'.\n", argv[ai]); return(1);}
113 if(cv<1.0) fprintf(stderr, "Warning: CV is set to %g%%.\n", cv);
114 ai++;
115 }
116 if(ai<argc) {strlcpy(simfile, argv[ai++], FILENAME_MAX);}
117 if(ai<argc) {
118 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
119 return(1);
120 }
121
122 /* Is something missing? */
123 if(!simfile[0]) {
124 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
125 return(1);
126 }
127
128 /* In verbose mode print arguments and options */
129 if(verbose>1) {
130 printf("tacfile := %s\n", tacfile);
131 printf("simfile := %s\n", simfile);
132 if(!isnan(minsd)) printf("minsd := %g\n", minsd);
133 fflush(stdout);
134 }
135
136
137 /*
138 * Read original TAC
139 */
140 if(verbose>1) fprintf(stdout, "reading %s\n", tacfile);
141 TAC tac; tacInit(&tac);
142 if(tacRead(&tac, tacfile, &status)!=TPCERROR_OK) {
143 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), tacfile);
144 tacFree(&tac); return(2);
145 }
146 if(verbose>2) {
147 printf("fileformat := %s\n", tacFormattxt(tac.format));
148 printf("tacNr := %d\n", tac.tacNr);
149 printf("sampleNr := %d\n", tac.sampleNr);
150 printf("xunit := %s\n", unitName(tac.tunit));
151 printf("yunit := %s\n", unitName(tac.cunit));
152 if(tacIsWeighted(&tac)) printf("weighting := yes\n");
153 }
154 /* Check for missing sample times */
155 if(tacXNaNs(&tac)>0) {
156 fprintf(stderr, "Warning: missing frame times.\n");
157 }
158 /* Check for missing concentrations */
159 if(tacYNaNs(&tac, -1)>0) {
160 fprintf(stderr, "Warning: missing concentrations.\n");
161 }
162
163
164 /*
165 * If min SD was given, then the maximum concentration in the data is needed.
166 * Find it anyway as an additional data check.
167 */
168 {
169 double ymax=nan("");
170 for(int fi=0; fi<tac.sampleNr; fi++)
171 for(int ri=0; ri<tac.tacNr; ri++) {
172 if(!isfinite(ymax) || tac.c[ri].y[fi]>ymax) ymax=tac.c[ri].y[fi];
173 }
174 if(verbose>1) printf("ymax := %g\n", ymax);
175 if(!(ymax>0.0)) {
176 fprintf(stderr, "Error: invalid concentration data.\n");
177 tacFree(&tac); return(2);
178 }
179 /* Convert minsd percentage to the actual min SD */
180 if(!isnan(minsd)) {
181 minsd*=0.01; // min SD was given as percent
182 minsd*=(0.01*cv)*ymax; // CV was given as percent
183 if(verbose>1) printf("final_minsd := %g\n", minsd);
184 }
185 }
186
187
188 /*
189 * Add noise
190 */
191 if(verbose>1) printf("adding noise\n");
192 double sd;
194 for(int fi=0; fi<tac.sampleNr; fi++) {
195 for(int ri=0; ri<tac.tacNr; ri++) {
196 sd=0.01*cv*tac.c[ri].y[fi];
197 if(tacIsWeighted(&tac) && tac.w[fi]>0.0) sd/=tac.w[fi];
198 if(minsd>sd) sd=minsd;
199 tac.c[ri].y[fi] += sd*mertwiRandomGaussian(&mt);
200 }
201 }
202
203
204 /*
205 * Write the file
206 */
207 if(verbose>1) printf("writing noisy data in %s\n", simfile);
208 FILE *fp; fp=fopen(simfile, "w");
209 if(fp==NULL) {
210 fprintf(stderr, "Error: cannot open file for writing (%s)\n", simfile);
211 tacFree(&tac); return(11);
212 }
213 int ret=tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, 1, &status);
214 fclose(fp); tacFree(&tac);
215 if(ret!=TPCERROR_OK) {
216 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
217 return(12);
218 }
219 if(verbose>=0) printf("Noisy data saved in %s\n", simfile);
220
221 return(0);
222}
223/*****************************************************************************/
225/*****************************************************************************/
double atofVerified(const char *s)
Definition decpoint.c:75
void mertwiInitWithSeed64(MERTWI *mt, uint64_t seed)
Initialize the state vector mt[] inside data structure for Mersenne Twister MT19937 pseudo-random num...
Definition mertwi.c:94
double mertwiRandomGaussian(MERTWI *mt)
Generate a 64-bit double precision floating point pseudo-random number with normal (Gaussian) distrib...
Definition mertwi.c:354
uint64_t mertwiSeed64(void)
Make uint64_t seed for pseudo-random number generators.
Definition mertwi.c:76
void mertwiInit(MERTWI *mt)
Definition mertwi.c:28
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:635
double * y
Definition tpctac.h:75
Definition tpctac.h:87
unit cunit
Definition tpctac.h:105
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
double * w
Definition tpctac.h:111
TACC * c
Definition tpctac.h:117
unit tunit
Definition tpctac.h:109
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
void tacFree(TAC *tac)
Definition tac.c:106
void tacInit(TAC *tac)
Definition tac.c:24
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
char * tacFormattxt(tacformat c)
Definition tacio.c:98
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
Definition tacio.c:332
int tacYNaNs(TAC *tac, const int i)
Definition tacnan.c:47
int tacXNaNs(TAC *tac)
Definition tacnan.c:23
int tacIsWeighted(TAC *tac)
Definition tacw.c:24
Header file for library libtpcextensions.
@ TPCERROR_OK
No error.
char * unitName(int unit_code)
Definition units.c:143
Header file for library libtpcift.
Header file for libtpcrand.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28