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 (weighted) concentration in the data is needed.
166 * Find it anyway as an additional data check.
167 */
168 {
169 double f, ymax=-1.0;
170 for(int fi=0; fi<tac.sampleNr; fi++)
171 for(int ri=0; ri<tac.tacNr; ri++) {
172 f=tac.c[ri].y[fi];
173 if(tacIsWeighted(&tac) && tac.w[fi]>0.0) f/=tac.w[fi];
174 if(tac.c[ri].y[fi]>ymax) ymax=tac.c[ri].y[fi];
175 }
176 if(verbose>1) printf("wymax := %g\n", ymax);
177 if(!(ymax>0.0)) {
178 fprintf(stderr, "Error: invalid concentration data.\n");
179 tacFree(&tac); return(2);
180 }
181 /* Convert minsd percentage to the actual min SD */
182 if(!isnan(minsd)) {
183 minsd*=0.01; // min SD was given as percent
184 minsd*=(0.01*cv)*ymax; // CV was given as percent
185 if(verbose>1) printf("final_minsd := %g\n", minsd);
186 }
187 }
188
189
190 /*
191 * Add noise
192 */
193 if(verbose>1) printf("adding noise\n");
194 double sd;
196 for(int fi=0; fi<tac.sampleNr; fi++) {
197 for(int ri=0; ri<tac.tacNr; ri++) {
198 sd=0.01*cv*tac.c[ri].y[fi];
199 if(tacIsWeighted(&tac) && tac.w[fi]>0.0) sd/=tac.w[fi];
200 if(minsd>sd) sd=minsd;
201 tac.c[ri].y[fi] += sd*mertwiRandomGaussian(&mt);
202 }
203 }
204
205
206 /*
207 * Write the file
208 */
209 if(verbose>1) printf("writing noisy data in %s\n", simfile);
210 FILE *fp; fp=fopen(simfile, "w");
211 if(fp==NULL) {
212 fprintf(stderr, "Error: cannot open file for writing (%s)\n", simfile);
213 tacFree(&tac); return(11);
214 }
215 int ret=tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, 1, &status);
216 fclose(fp); tacFree(&tac);
217 if(ret!=TPCERROR_OK) {
218 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
219 return(12);
220 }
221 if(verbose>=0) printf("Noisy data saved in %s\n", simfile);
222
223 return(0);
224}
225/*****************************************************************************/
227/*****************************************************************************/
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:632
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