TPCCLIB
Loading...
Searching...
No Matches
sim_rtcm.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 "tpcpar.h"
19#include "tpccm.h"
20/*****************************************************************************/
21
22/*****************************************************************************/
23static char *info[] = {
24 "Simulation of PET tissue time-radioactivity concentration curves (TAC) from",
25 "reference tissue TAC based on a selected reference tissue input compartment",
26 "model.",
27 "Available reference tissue input models, and model parameters:",
28 " FRTM; (Full) reference tissue model; R1, k2, k3, BP [1]",
29 " SRTM: Simplified reference tissue model; R1, k2, BP [2]",
30 " RRTM: Reduced reference tissue model; R1, k2, k3 (k4=0)",
31 " TRTM: Transport-limited reference tissue model; R1, k2, k3 [3]",
32 " ",
33 "Usage: @P [options] parfile [reffile simfile]",
34 " ",
35 "Options:",
36 " -model=<FRTM|SRTM|RRTM|TRTM>",
37 " Select the model used to simulate the TACs; by default the model is",
38 " read from the parameter file.",
39 " -sub | -nosub",
40 " TACs of sub-compartments (Cf and Cb) are also written (-sub) into",
41 " simfile, or not written (-nosub, default); effective only with FRTM.",
42 " -stdoptions", // List standard options like --help, -v, etc
43 " ",
44 "To create a template parameter file, do not enter names for reference TAC",
45 "and simulated TACs, but give the model with option -model.",
46 " ",
47 "References:",
48 "1. Cunningham VJ, Hume SP, Price GR, Ahier RG, Cremer JE, Jones AKP.",
49 " Compartmental analysis of diprenorphine binding to opiate receptors",
50 " in the rat in vivo and its comparison with equilibrium data in vitro.",
51 " J Cereb Blood Flow Metab 1991;11:1-9.",
52 "2. Lammertsma AA, Hume SP. Simplified reference tissue model for PET",
53 " receptor studies. NeuroImage 1996;4:153-158.",
54 "3. Herholz K, Lercher M, Wienhard K, Bauer B, Lenz O, Heiss W-D.",
55 " PET measurement of cerebral acetylcholine esterase activity without",
56 " blood sampling. Eur J Nucl Med 2001;28:472-477.",
57 " ",
58 "See also: sim_3tcm, fit_frtm, fit_srtm, fit_rrtm, fit_trtm, tacadd, simframe",
59 " ",
60 "Keywords: TAC, simulation, reference tissue, reference input",
61 0};
62/*****************************************************************************/
63
64/*****************************************************************************/
65/* Turn on the globbing of the command line, since it is disabled by default in
66 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
67 In Unix&Linux wildcard command line processing is enabled by default. */
68/*
69#undef _CRT_glob
70#define _CRT_glob -1
71*/
72int _dowildcard = -1;
73/*****************************************************************************/
74
75/*****************************************************************************/
76//enum {MODEL_UNKNOWN, MODEL_FRTM, MODEL_RRTM, MODEL_SRTM, MODEL_TRTM};
77//static char *model_str[] = {"Unknown","FRTM","RRTM","SRTM","TRTM",0};
78//static int model_parNr[6]={0,4,3,3,3,0};
79/*****************************************************************************/
80
81/*****************************************************************************/
85int main(int argc, char **argv)
86{
87 int ai, help=0, version=0, verbose=1;
88 char reffile[FILENAME_MAX], simfile[FILENAME_MAX], parfile[FILENAME_MAX];
89 char *cptr;
90 unsigned int model=0, parNr=0;
91 int save_only_total=1;
92 TAC tac, sim;
93 PAR par;
94 int n, ret;
95
96 /*
97 * Get arguments
98 */
99 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
100 tacInit(&tac); tacInit(&sim); parInit(&par);
101 reffile[0]=simfile[0]=parfile[0]=(char)0;
102 /* Options */
103 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
104 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
105 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
106 if(strncasecmp(cptr, "MODEL=", 6)==0 && strlen(cptr)>7) {
107 cptr+=6;
108 model=modelCodeIndex(cptr);
109 //for(int i=1; i<5; i++) if(strcasecmp(cptr, model_str[i])==0) {
110 // model=i; break;}
111 if(model==0 && strcasecmp(cptr, "RTCM")==0) model=modelCodeIndex("FRTM");
112 if(model!=0) continue;
113 fprintf(stderr, "Error: invalid model selection.\n"); return(1);
114 } else if(strncasecmp(cptr, "SUB", 3)==0) {
115 save_only_total=0; continue;
116 } else if(strncasecmp(cptr, "NOSUB", 3)==0) {
117 save_only_total=1; continue;
118 }
119 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
120 return(1);
121 } else break; // tac name argument may start with '-'
122
123 TPCSTATUS status; statusInit(&status);
124 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
125 status.verbose=verbose-1;
126
127 /* Print help or version? */
128 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
129 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
130 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
131
132 /* Process other arguments, starting from the first non-option */
133 for(; ai<argc; ai++) {
134 if(!parfile[0]) {
135 strlcpy(parfile, argv[ai], FILENAME_MAX); continue;
136 } else if(!reffile[0]) {
137 strlcpy(reffile, argv[ai], FILENAME_MAX); continue;
138 } else if(!simfile[0]) {
139 strlcpy(simfile, argv[ai], FILENAME_MAX); continue;
140 }
141 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
142 return(1);
143 }
144
145 /* Is something missing? */
146 if(!parfile[0]) {
147 fprintf(stderr, "Error: missing parameter file; use option --help\n");
148 return(1);
149 }
150 if(reffile[0] && !simfile[0]) {
151 fprintf(stderr, "Error: missing filename for simulated TACs.\n");
152 return(1);
153 }
154
155
156 /* In verbose mode print arguments and options */
157 if(verbose>1) {
158 if(model!=0) printf("model := %s\n", modelCode(model));
159 printf("parfile := %s\n", parfile);
160 printf("reffile := %s\n", reffile);
161 printf("simfile := %s\n", simfile);
162 printf("save_only_total := %d\n", save_only_total);
163 }
164
165 /*
166 * Make template parameter file, if no other filenames were given,
167 * and then quit
168 */
169 if(!reffile[0]) {
170 parNr=modelParNr(model);
171 if(model==0 || parNr==0) {
172 fprintf(stderr, "Error: unknown simulation model; use option -model.\n");
173 return(1);
174 }
175 ret=parAllocate(&par, parNr, 3);
176 if(ret) {
177 fprintf(stderr, "Error: cannot allocate memory for parameters.\n");
178 parFree(&par); return(1);
179 }
180 par.parNr=parNr; par.tacNr=3;
181 for(int i=0; i<par.tacNr; i++) {
182 sprintf(par.r[i].name, "tac%d", 1+i);
183 par.r[i].model=model;
184 //par.r[i].start=0.0;
185 //par.r[i].end=90.0;
186 par.r[i].p[0]=1.0;
187 par.r[i].p[1]=0.2;
188 }
189 strcpy(par.n[0].name, "R1"); par.n[0].unit=UNIT_UNITLESS;
190 strcpy(par.n[1].name, "k2"); par.n[1].unit=UNIT_PER_MIN;
191 if(!strcmp(modelCode(model), "FRTM")) {
192 strcpy(par.n[2].name, "k3"); par.n[2].unit=UNIT_PER_MIN;
193 strcpy(par.n[3].name, "BPnd"); par.n[3].unit=UNIT_UNITLESS;
194 par.r[0].p[2]=0.05;
195 par.r[0].p[3]=1.0;
196 for(int i=1; i<par.tacNr; i++) {
197 par.r[i].p[2]=2.0*par.r[i-1].p[2];
198 par.r[i].p[3]=2.0*par.r[i-1].p[3];
199 }
200 } else if(!strcmp(modelCode(model), "SRTM")) {
201 strcpy(par.n[2].name, "BPnd"); par.n[2].unit=UNIT_UNITLESS;
202 par.r[0].p[2]=1.0;
203 for(int i=1; i<par.tacNr; i++) {
204 par.r[i].p[2]=2.0*par.r[i-1].p[2];
205 }
206 } else if(!strcmp(modelCode(model), "RRTM") ||
207 !strcmp(modelCode(model), "TRTM"))
208 {
209 strcpy(par.n[2].name, "k3"); par.n[2].unit=UNIT_PER_MIN;
210 par.r[0].p[2]=0.05;
211 for(int i=1; i<par.tacNr; i++) {
212 par.r[i].p[2]=2.0*par.r[i-1].p[2];
213 }
214 }
215 if(verbose>1) printf("writing %s\n", parfile);
216 FILE *fp; fp=fopen(parfile, "w");
217 if(fp==NULL) {
218 fprintf(stderr, "Error: cannot open file for writing (%s)\n", parfile);
219 parFree(&par); return(11);
220 }
221 ret=parWrite(&par, fp, PAR_FORMAT_CSV_UK, 1, &status);
222 fclose(fp);
223 parFree(&par); return(0);
224 }
225
226 /*
227 * Read parameter file to get parameters for the simulation, and
228 * set model in case it was given with command-line option.
229 */
230 if(verbose>1) fprintf(stdout, "reading %s\n", parfile);
231 if(parRead(&par, parfile, &status)) {
232 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), parfile);
233 parFree(&par);
234 return(3);
235 }
236 if(verbose>5) parWrite(&par, stdout, PAR_FORMAT_TSV_UK, 1, NULL);
237
238 if(model!=0) for(int i=0; i<par.tacNr; i++) par.r[i].model=model;
239 /* Check the validity of model and its parameters */
240 for(int i=0; i<par.tacNr; i++) {
241 if(verbose>3)
242 printf("model %s for tac %s\n", modelCode(par.r[i].model), par.r[i].name);
243 /* check that we got at least as many parameters as the model has */
244 if(modelParNr(par.r[i].model)>(unsigned int)par.parNr) {
245 fprintf(stderr, "Error: invalid parameters for selected model.\n");
246 parFree(&par); return(3);
247 }
248 /* check that we can find the obligatory model parameters */
249 ret=0;
250 if(parFindParameter(&par, "R1")<0) ret++;
251 if(parFindParameter(&par, "k2")<0) ret++;
252 if(!strcmp(modelCode(par.r[i].model), "FRTM")) {
253 if(parFindParameter(&par, "k3")<0) ret++;
254 if(parFindParameter(&par, "BPnd")<0) ret++;
255 } else if(!strcmp(modelCode(par.r[i].model), "SRTM")) {
256 if(parFindParameter(&par, "BPnd")<0) ret++;
257 } else if(!strcmp(modelCode(par.r[i].model), "RRTM") ||
258 !strcmp(modelCode(par.r[i].model), "TRTM"))
259 {
260 if(parFindParameter(&par, "k3")<0) ret++;
261 } else {
262 fprintf(stderr, "Error: invalid model for this simulation.\n");
263 if(verbose>1) printf("model := %s\n", modelCode(par.r[i].model));
264 parFree(&par); return(3);
265 }
266 if(ret) {
267 fprintf(stderr, "Error: required parameters not available.\n");
268 parFree(&par); return(3);
269 }
270 }
271
272 /*
273 * Read reference input TAC
274 */
275 if(verbose>1) fprintf(stdout, "reading %s\n", reffile);
276 ret=tacRead(&tac, reffile, &status);
277 if(ret!=TPCERROR_OK) {
278 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), reffile);
279 tacFree(&tac); parFree(&par); return(4);
280 }
281 if(verbose>2) {
282 printf("fileformat := %s\n", tacFormattxt(tac.format));
283 printf("tacNr := %d\n", tac.tacNr);
284 printf("sampleNr := %d\n", tac.sampleNr);
285 printf("xunit := %s\n", unitName(tac.tunit));
286 printf("yunit := %s\n", unitName(tac.cunit));
287 }
288 if(tac.tacNr>1) {
289 fprintf(stderr,
290 "Warning: reference file contains %d TACs; using the first.\n", tac.tacNr);
291 tac.tacNr=1;
292 }
293 if(tac.sampleNr<2) {
294 fprintf(stderr, "Error: too few samples in reference TAC.\n");
295 tacFree(&tac); parFree(&par); return(4);
296 }
297 if(tac.sampleNr<10) {
298 fprintf(stderr, "Warning: too few samples for reliable simulation.\n");
299 }
300
301 /*
302 * Allocate space for simulated data
303 */
304 n=par.tacNr; if(!save_only_total) n*=3;
305 if(verbose>1)
306 printf("allocating memory for %d samples and %d TACs\n", tac.sampleNr, n);
307 ret=tacAllocate(&sim, tac.sampleNr, n);
308 if(ret!=TPCERROR_OK) {
309 fprintf(stderr, "Error: %s\n", errorMsg(ret));
310 tacFree(&sim); tacFree(&tac); parFree(&par); return(5);
311 }
312 sim.sampleNr=tac.sampleNr;
313 sim.tacNr=n;
315 sim.cunit=tac.cunit;
316 sim.tunit=tac.tunit;
317 sim.format=tac.format;
318 sim.isframe=0;
319 for(int j=0; j<sim.sampleNr; j++) sim.x[j]=tac.x[j];
320
321 /*
322 * Simulation
323 */
324 if(verbose>1) printf("simulating\n");
325 n=0; // sim tac struct index
326 double *px=tac.x;
327 double *py=tac.c[0].y;
328 double *pf, *pb, *pt;
329 double R1, k2, k3, k4, BP;
330 int i, ii;
331 for(i=0; i<par.tacNr; i++) {
332 if(verbose>2) printf("simulating %s\n", sim.c[i].name);
333 ii=parFindParameter(&par, "R1"); if(ii>=0) R1=par.r[i].p[ii]; else R1=0.0;
334 ii=parFindParameter(&par, "k2"); if(ii>=0) k2=par.r[i].p[ii]; else k2=0.0;
335 ii=parFindParameter(&par, "k3"); if(ii>=0) k3=par.r[i].p[ii]; else k3=0.0;
336 ii=parFindParameter(&par, "k4"); if(ii>=0) k4=par.r[i].p[ii]; else k4=0.0;
337 ii=parFindParameter(&par, "BPnd"); if(ii>=0) BP=par.r[i].p[ii]; else BP=0.0;
338 if(fabs(BP)>1.0E-50) k4=k3/BP; else if(fabs(k4)>1.0E-50) BP=k3/k4;
339 if(verbose>3) {printf("R1 := %g\n", R1); printf("k2 := %g\n", k2);}
340 strcpy(sim.c[n].name, par.r[i].name);
341 pt=sim.c[n].y; pf=pb=NULL;
342 ret=0;
343 if(!strcmp(modelCode(par.r[i].model), "FRTM")) {
344 if(verbose>3) {printf("k3 := %g\n", k3); printf("k4 := %g\n", k4);}
345 if(!save_only_total) {
346 strcpy(sim.c[n+1].name, par.r[i].name); strcat(sim.c[n+1].name, "_free");
347 pf=sim.c[n+1].y;
348 strcpy(sim.c[n+2].name, par.r[i].name); strcat(sim.c[n+2].name, "_bound");
349 pb=sim.c[n+2].y;
350 }
351 ret=simRTCM(px, py, tac.sampleNr, R1, k2, k3, k4, pt, pf, pb);
352 if(save_only_total) n++; else n+=3;
353 } else if(!strcmp(modelCode(par.r[i].model), "SRTM")) {
354 if(verbose>3) {printf("BP := %g\n", BP);}
355 ret=simSRTM(px, py, tac.sampleNr, R1, k2, BP, pt);
356 n++;
357 } else if(!strcmp(modelCode(par.r[i].model), "RRTM")) {
358 if(verbose>3) {printf("k3 := %g\n", k3);}
359 ret=simRTCM(px, py, tac.sampleNr, R1, k2, k3, 0.0, pt, NULL, NULL);
360 n++;
361 } else if(!strcmp(modelCode(par.r[i].model), "TRTM")) {
362 if(verbose>3) {printf("k3 := %g\n", k3);}
363 ret=simTRTM(px, py, tac.sampleNr, R1, k2, k3, pt);
364 n++;
365 }
366 if(ret) {
367 fprintf(stderr, "Error: invalid data for simulation.\n");
368 if(verbose>1) printf("sim_return_code := %d\n", ret);
369 tacFree(&sim); tacFree(&tac); parFree(&par); return(8);
370 }
371 }
372 sim.tacNr=n;
373 /* simulation done */
374 tacFree(&tac); parFree(&par);
375
376
377
378 /*
379 * Write useful header information
380 */
381 ii=iftFindKey(&par.h, "studynr", 0);
382 if(ii<0) ii=iftFindKey(&par.h, "study", 0);
383 if(ii>=0) {
384 iftPut(&sim.h, par.h.item[ii].key, par.h.item[ii].value, 1, NULL);
385 }
386
387
388 /*
389 * Save simulated data
390 */
391 if(verbose>1) printf("writing %s\n", simfile);
392 FILE *fp; fp=fopen(simfile, "w");
393 if(fp==NULL) {
394 fprintf(stderr, "Error: cannot open file for writing (%s)\n", simfile);
395 tacFree(&sim); return(11);
396 }
397 ret=tacWrite(&sim, fp, TAC_FORMAT_UNKNOWN, 1, &status);
398 fclose(fp); tacFree(&sim);
399 if(ret!=TPCERROR_OK) {
400 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
401 return(12);
402 }
403 if(verbose>=0) printf("%s saved.\n", simfile);
404
405 return(0);
406}
407/*****************************************************************************/
408
409/*****************************************************************************/
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
Definition ift.c:63
int iftFindKey(IFT *ift, const char *key, int start_index)
Definition iftfind.c:30
char * modelCode(const unsigned int i)
Definition modell.c:176
unsigned int modelParNr(const unsigned int code)
Definition modell.c:256
unsigned int modelCodeIndex(const char *s)
Definition modell.c:237
void parFree(PAR *par)
Definition par.c:75
int parAllocate(PAR *par, int parNr, int tacNr)
Definition par.c:108
void parInit(PAR *par)
Definition par.c:25
int parWrite(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
Definition pario.c:148
int parRead(PAR *par, const char *fname, TPCSTATUS *status)
Definition pario.c:232
int parFindParameter(PAR *d, const char *par_name)
Definition parselect.c:219
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
int simTRTM(double *t, double *cr, const int nr, const double R1, const double k2, const double k3, double *ct)
Definition simrtcm.c:182
int simRTCM(double *t, double *cr, const int nr, const double R1, const double k2, const double k3, const double k4, double *ct, double *cta, double *ctb)
Definition simrtcm.c:32
int simSRTM(double *t, double *cr, const int nr, const double R1, const double k2, const double BP, double *ct)
Definition simrtcm.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
char * value
Definition tpcift.h:37
char * key
Definition tpcift.h:32
IFT_ITEM * item
Definition tpcift.h:57
Definition tpcpar.h:100
IFT h
Optional (but often useful) header information.
Definition tpcpar.h:147
int parNr
Definition tpcpar.h:108
int tacNr
Definition tpcpar.h:104
PARR * r
Definition tpcpar.h:114
PARN * n
Definition tpcpar.h:112
int unit
Definition tpcpar.h:86
char name[MAX_PARNAME_LEN+1]
Definition tpcpar.h:82
char name[MAX_TACNAME_LEN+1]
Definition tpcpar.h:50
unsigned int model
Definition tpcpar.h:48
double * p
Definition tpcpar.h:64
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
Definition tpctac.h:87
double * x
Definition tpctac.h:97
unit cunit
Definition tpctac.h:105
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
weights weighting
Definition tpctac.h:115
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
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
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
Header file for libtpccm.
Header file for library libtpcextensions.
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ UNIT_UNITLESS
Unitless.
@ UNIT_PER_MIN
1/min
@ TPCERROR_OK
No error.
char * unitName(int unit_code)
Definition units.c:143
Header file for library libtpcift.
Header file for libtpcpar.
@ PAR_FORMAT_CSV_UK
UK CSV.
Definition tpcpar.h:33
@ PAR_FORMAT_TSV_UK
UK TSV (point as decimal separator).
Definition tpcpar.h:35
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28