TPCCLIB
Loading...
Searching...
No Matches
svar4tac.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 <string.h>
13#include <math.h>
14/*****************************************************************************/
15#include "tpcextensions.h"
16#include "tpcift.h"
17#include "tpctac.h"
18#include "tpcrand.h"
19/*****************************************************************************/
20
21/*****************************************************************************/
22static char *info[] = {
23 "Program for adding Gaussian noise to dynamic PET time-activity curve (TAC)",
24 "or TACs using equation",
25 " TAC_noisy(t) = TAC(t) + (CV/100)*TAC(t)*G(0,1) ,",
26 "G(0,1) is a pseudo random number from a Gaussian distribution",
27 "with zero mean and SD of one.",
28 " ",
29 "Usage: @P [Options] tacfile CV outputfile ",
30 " ",
31 "Options:",
32 " -minsd=<Minimum SD>",
33 " Based on CV only the samples with little or no activity would have",
34 " very little or no noise. With this option at least the given noise",
35 " level (SD) will be added to all samples.",
36 " -x=<N>",
37 " N noisy copies of each TAC are made (by default just one).",
38 " If CV is set to zero, this option can be used to make multiple copies",
39 " from the TACs.",
40 " -separate",
41 " When used with option -x=<N>, copies are written in separate files",
42 " named as (*_NNNN.*).",
43 " -stdoptions", // List standard options like --help, -v, etc
44 " ",
45 "Frame durations or weights are not used, even if available in the TAC file.",
46 " ",
47 "Example:",
48 " @P -minsd=0.2 simulated.tac 10 noisy.tac",
49 " ",
50 "See also: var4tac, fvar4tac, sim_3tcm, sim_h2o, tacadd, tacmean",
51 " ",
52 "Keywords: TAC, simulation, noise",
53 0};
54/*****************************************************************************/
55
56/*****************************************************************************/
57/* Turn on the globbing of the command line, since it is disabled by default in
58 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
59 In Unix&Linux wildcard command line processing is enabled by default. */
60/*
61#undef _CRT_glob
62#define _CRT_glob -1
63*/
64int _dowildcard = -1;
65/*****************************************************************************/
66
67/*****************************************************************************/
71int main(int argc, char **argv)
72{
73 int maxNr=10000; // maximum number of TACs allowed for output
74 int ai, help=0, version=0, verbose=1;
75 char tacfile[FILENAME_MAX], simfile[FILENAME_MAX];
76 double cv=nan("");
77 double minsd=nan("");
78 int nCopies=1;
79 int separate=0;
80
81
82 /*
83 * Get arguments
84 */
85 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
86 tacfile[0]=simfile[0]=(char)0;
87 /* Options */
88 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
89 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
90 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
91 if(strncasecmp(cptr, "MINSD=", 6)==0) {
92 minsd=atofVerified(cptr+6); if(minsd>=0.0) continue;
93 } else if(strncasecmp(cptr, "X=", 2)==0) {
94 if(atoiCheck(cptr+2, &nCopies)==0 && nCopies>0) continue;
95 } else if(strncasecmp(cptr, "SEPARATE", 3)==0) {
96 separate=1; continue;
97 }
98 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
99 return(1);
100 } else break; // tac name argument may start with '-'
101
102 TPCSTATUS status; statusInit(&status);
103 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
104 status.verbose=verbose-1;
105
106 /* Print help or version? */
107 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
108 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
109 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
110
111 /* Process other arguments, starting from the first non-option */
112 if(ai<argc) {strlcpy(tacfile, argv[ai++], FILENAME_MAX);}
113 if(ai<argc) {
114 cv=atofVerified(argv[ai]);
115 if(isnan(cv) || cv<0.0 || cv>1000.0) {
116 fprintf(stderr, "Error: invalid CV%% '%s'.\n", argv[ai]); return(1);}
117 if(cv<1.0) fprintf(stderr, "Warning: CV is set to %g%%.\n", cv);
118 ai++;
119 }
120 if(ai<argc) {strlcpy(simfile, argv[ai++], FILENAME_MAX);}
121 if(ai<argc) {
122 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
123 return(1);
124 }
125
126 /* Is something missing? */
127 if(!simfile[0]) {
128 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
129 return(1);
130 }
131 if(nCopies>maxNr) {
132 fprintf(stderr, "Error: number of copies is too high.\n");
133 return(1);
134 }
135 if(!(cv>0.0) && isnan(minsd)) {
136 if(nCopies==1) {
137 fprintf(stderr, "Error: no variance specified.\n");
138 return(1);
139 }
140 fprintf(stderr, "Warning: no variance specified; only making copies.\n");
141 }
142
143 /* In verbose mode print arguments and options */
144 if(verbose>1) {
145 printf("tacfile := %s\n", tacfile);
146 printf("simfile := %s\n", simfile);
147 printf("CV := %g%%\n", cv);
148 if(!isnan(minsd)) printf("minsd := %g\n", minsd);
149 printf("nCopies := %d\n", nCopies);
150 printf("separate := %d\n", separate);
151 fflush(stdout);
152 }
153 /* If no copies, then no separate copies either */
154 if(nCopies<2) separate=0;
155
156
157 /*
158 * Read original TAC
159 */
160 if(verbose>1) fprintf(stdout, "reading %s\n", tacfile);
161 TAC tac; tacInit(&tac);
162 if(tacRead(&tac, tacfile, &status)!=TPCERROR_OK) {
163 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), tacfile);
164 tacFree(&tac); return(2);
165 }
166 if(verbose>2) {
167 printf("fileformat := %s\n", tacFormattxt(tac.format));
168 printf("tacNr := %d\n", tac.tacNr);
169 printf("sampleNr := %d\n", tac.sampleNr);
170 printf("xunit := %s\n", unitName(tac.tunit));
171 printf("yunit := %s\n", unitName(tac.cunit));
172 if(tacIsWeighted(&tac)) printf("weighting := yes\n");
173 }
174 /* Check for missing sample times */
175 if(tacXNaNs(&tac)>0) {
176 fprintf(stderr, "Warning: missing frame times.\n");
177 }
178 /* Check for missing concentrations */
179 if(tacYNaNs(&tac, -1)>0) {
180 fprintf(stderr, "Warning: missing concentrations.\n");
181 }
182 if(nCopies*tac.tacNr>maxNr) {
183 fprintf(stderr, "Error: number of output TACs is too high.\n");
184 tacFree(&tac); return(1);
185 }
186 int origTacNr=tac.tacNr;
187
188
189 /*
190 * Make space for TAC copies, if requested
191 */
192 if(nCopies>1) {
193 if(verbose>1) fprintf(stdout, "allocating space for copies\n");
194 int ret=tacAllocateMore(&tac, nCopies*tac.tacNr-1);
195 if(ret!=TPCERROR_OK) {
196 fprintf(stderr, "Error: cannot allocate memory for %d additional TACs.\n", nCopies*tac.tacNr-1);
197 tacFree(&tac); return(2);
198 }
199 /* and make the copies */
200 if(verbose>1) fprintf(stdout, "copying TACs\n");
201 ret=0;
202 for(int ci=1; ci<nCopies; ci++) {
203 int ni=ci*tac.tacNr;
204 for(int j=0; j<tac.tacNr; j++) {
205 //printf("copying tac[%d] into [%d]\n", j, ni+j);
206 ret=tacCopyTacc(&tac.c[j], &tac.c[ni+j], tac.sampleNr);
207 if(ret!=TPCERROR_OK) break;
208 }
209 if(ret!=TPCERROR_OK) break;
210 }
211 if(ret!=TPCERROR_OK) {
212 fprintf(stderr, "Error: cannot copy TACs.\n");
213 tacFree(&tac); return(2);
214 }
215 tac.tacNr=nCopies*tac.tacNr;
216 }
217
218 /*
219 * Add noise
220 */
221 if(verbose>1) printf("adding noise\n");
222 //double sd;
224 for(int fi=0; fi<tac.sampleNr; fi++) {
225 for(int ri=0; ri<tac.tacNr; ri++) {
226 double sd=0.01*cv*tac.c[ri].y[fi];
227 if(isnormal(minsd) && sd<minsd) sd=minsd;
228 tac.c[ri].y[fi] += sd*mertwiRandomGaussian(&mt);
229 }
230 }
231
232 /*
233 * Write the file
234 */
235 if(separate==0) {
236 if(verbose>1) printf("writing noisy data in %s\n", simfile);
237 FILE *fp; fp=fopen(simfile, "w");
238 if(fp==NULL) {
239 fprintf(stderr, "Error: cannot open file for writing (%s)\n", simfile);
240 tacFree(&tac); return(11);
241 }
242 int ret=tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, 1, &status);
243 fclose(fp); tacFree(&tac);
244 if(ret!=TPCERROR_OK) {
245 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
246 return(12);
247 }
248 if(verbose>=0) printf("Noisy data saved in %s\n", simfile);
249 } else {
250 if(verbose>1) printf("writing noisy data in %d files\n", nCopies);
251 /* Get the basis of file name and extension */
252 char basisname[FILENAME_MAX], fnextens[FILENAME_MAX];
253 strcpy(basisname, simfile); filenameRmExtensions(basisname);
254 strcpy(fnextens, filenameGetExtensions(simfile));
255 if(verbose>4) {
256 printf("basis_of_filename := %s\n", basisname);
257 printf("extensions := %s\n", fnextens);
258 }
259 if(strlen(basisname)<1 || ((5+strlen(basisname)+strlen(fnextens))>=FILENAME_MAX)) {
260 fprintf(stderr, "Error: invalid output file name.\n");
261 tacFree(&tac); return(1);
262 }
263 /* Save separate files */
264 int currTacNr=tac.tacNr;
265 for(int ni=0; ni<nCopies; ni++) {
266 /* Make output file name */
267 snprintf(simfile, FILENAME_MAX, "%s_%04u%s", basisname, 1+ni, fnextens);
268 if(verbose>2) printf(" %s\n", simfile);
269 /* Set tacNr temporarily to the original number that will be saved in each file */
270 tac.tacNr=origTacNr;
271 /* Save data */
272 FILE *fp; fp=fopen(simfile, "w");
273 if(fp==NULL) {
274 fprintf(stderr, "\nError: cannot open file for writing (%s)\n", simfile);
275 tacFree(&tac); return(11);
276 }
277 int ret=tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, 1, &status);
278 fclose(fp);
279 if(ret!=TPCERROR_OK) {
280 fprintf(stderr, "\nError (%d): %s\n", ret, errorMsg(status.error));
281 tacFree(&tac); return(12);
282 }
283 /* Remove the saved TACs */
284 tac.tacNr=currTacNr;
285 for(int di=0; di<origTacNr; di++) tacDeleteTACC(&tac, 0);
286 currTacNr=tac.tacNr;
287 } /* next file */
288 }
289
290 return(0);
291}
292/*****************************************************************************/
294/*****************************************************************************/
double atofVerified(const char *s)
Definition decpoint.c:75
char * filenameGetExtensions(const char *s)
Get all extensions of a file name.
Definition filename.c:203
void filenameRmExtensions(char *s)
Definition filename.c:89
int atoiCheck(const char *s, int *v)
Definition intutil.c:25
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
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 tacAllocateMore(TAC *tac, int tacNr)
Definition tac.c:178
int tacCopyTacc(TACC *d1, TACC *d2, int sampleNr)
Definition tac.c:233
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 tacDeleteTACC(TAC *d, int i)
Definition tacorder.c:310
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