TPCCLIB
Loading...
Searching...
No Matches
sim_mbf.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 "tpcpar.h"
21#include "tpccm.h"
22/*****************************************************************************/
23
24/*****************************************************************************/
25static char *info[] = {
26 "Simulation of radiowater PET time-radioactivity concentration curves (TACs)",
27 "for myocardial muscle and LV cavity based on MBF model by Iida et al (1, 2)",
28 "as represented in ref 3.",
29 " ",
30 "Usage: @P [options] bloodfile MBF PTF Va Beta simfile",
31 " ",
32 "Options:",
33 " -pH2O=<Partition coefficient for water>",
34 " Enter the partition coefficient of water; 0.9464 by default.",
35 " -sub | -nosub",
36 " TAC of perfusbale tissue (Ct) is written (-sub)",
37 " or not written (-nosub, default) into the simfile.",
38 " -stdoptions", // List standard options like --help, -v, etc
39 " ",
40 "MBF must be given in units mL/(mL*min), and PTF and Va as fractions.",
41 "TACs of regional muscle, LV cavity, and optionally perfusable tissue are ",
42 "written in the given simfile, overwriting any previous contents.",
43 " ",
44 "For accurate results, blood input TAC should be noiseless and have very",
45 "short sampling intervals. Simulated curves can thereafter",
46 "be interpolated to represent PET frames using program simframe.",
47 " ",
48 "Example:",
49 " @P s3456ab.bld 1.24 0.6 0.3 0.8 s3456sim.tac",
50 " ",
51 "References:",
52 "1. Iida H, Rhodes CG, de Silva R, Yamamoto Y, Araujo LI, Maseri A, Jones T.",
53 " Myocardial tissue fraction - correction for partial volume effects and",
54 " measure of tissue viability. J Nucl Med 1991; 32:2169-2175.",
55 "2. Iida H, Rhodes CG, de Silva R, Araujo LI, Bloomfield P, Lammertsma AA,",
56 " Jones T. Use of the left ventricular time-activity curve as a noninvasive",
57 " input function in dynamic oxygen-15-water positron emission tomography.",
58 " J Nucl Med 1992; 33:1669-1677.",
59 "3. Oikonen V. Model equations for myocardial perfusion studies with [15O]H2O",
60 " PET. https://www.turkupetcentre.net/reports/tpcmod0005.pdf",
61 " ",
62 "See also: fitmbf, b2t_h2o, sim_3tcm, tacadd, simframe, simimyoc",
63 " ",
64 "Keywords: simulation, myocardium, perfusion, radiowater",
65 0};
66/*****************************************************************************/
67
68/*****************************************************************************/
69/* Turn on the globbing of the command line, since it is disabled by default in
70 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
71 In Unix&Linux wildcard command line processing is enabled by default. */
72/*
73#undef _CRT_glob
74#define _CRT_glob -1
75*/
76int _dowildcard = -1;
77/*****************************************************************************/
78
79/*****************************************************************************/
83int main(int argc, char **argv)
84{
85 int ai, help=0, version=0, verbose=1;
86 char blofile[FILENAME_MAX], simfile[FILENAME_MAX];
87 double PTF=-1.0, MBF=-1.0, Beta=-1.0, Va=-1.0, pc=0.9464;
88 char *cptr;
89 int n, ret;
90 int originallySec=0;
91 int save_ct=0;
92
93
94 /*
95 * Get arguments
96 */
97 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
98 blofile[0]=simfile[0]=(char)0;
99 /* Options */
100 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
101 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
102 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
103 if(strncasecmp(cptr, "P=", 2)==0) {
104 pc=atofVerified(cptr+2); if(pc>0.0 && pc<=1.0) continue;
105 } else if(strncasecmp(cptr, "PH2O=", 5)==0) {
106 pc=atofVerified(cptr+5); if(pc>0.0 && pc<=1.0) continue;
107 } else if(strncasecmp(cptr, "NOSUB", 5)==0) {
108 save_ct=0; continue;
109 } else if(strncasecmp(cptr, "SUB", 3)==0) {
110 save_ct=1; continue;
111 }
112 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
113 return(1);
114 } else break; // tac name argument may start with '-'
115
116 TPCSTATUS status; statusInit(&status);
117 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
118 status.verbose=verbose-1;
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 if(ai<argc) {strlcpy(blofile, argv[ai++], FILENAME_MAX);}
127 if(ai<argc) {
128 MBF=atofVerified(argv[ai++]);
129 if(MBF<0.0 || MBF>20.0) {
130 fprintf(stderr, "Error: invalid MBF (%g).\n", MBF); return(1);}
131 }
132 if(ai<argc) {
133 PTF=atofVerified(argv[ai++]);
134 if(PTF<=0.0 || PTF>1.0) {
135 fprintf(stderr, "Error: invalid PTF (%g).\n", PTF); return(1);}
136 }
137 if(ai<argc) {
138 Va=atofVerified(argv[ai++]);
139 if(Va<0.0 || Va>1.0) {
140 fprintf(stderr, "Error: invalid Va (%g).\n", Va); return(1);}
141 }
142 if(ai<argc) {
143 Beta=atofVerified(argv[ai++]);
144 if(Beta<=0.0 || Beta>1.0) {
145 fprintf(stderr, "Error: invalid Beta (%g).\n", Beta); return(1);}
146 }
147 if(ai<argc) {strlcpy(simfile, argv[ai++], FILENAME_MAX);}
148 if(ai<argc) {
149 /* we should never get this far */
150 fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]);
151 return(1);
152 }
153 /* Did we get all the information that we need? */
154 if(!simfile[0]) {
155 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
156 return(1);
157 }
158
159 /* In verbose mode print arguments and options */
160 if(verbose>1) {
161 printf("blofile := %s\n", blofile);
162 printf("simfile := %s\n", simfile);
163 printf("MBF := %g\n", MBF);
164 printf("PTF := %g\n", PTF);
165 printf("Va := %g\n", Va);
166 printf("Beta := %g\n", Beta);
167 printf("pH2O := %g\n", pc);
168 }
169
170
171 /*
172 * Read arterial BTAC
173 */
174 if(verbose>1) fprintf(stdout, "reading %s\n", blofile);
175 TAC input; tacInit(&input);
176 ret=tacRead(&input, blofile, &status);
177 if(ret!=TPCERROR_OK) {
178 fprintf(stderr, "Error: %s (%s)\n", errorMsg(status.error), blofile);
179 tacFree(&input); return(2);
180 }
181 if(verbose>2) {
182 printf("fileformat := %s\n", tacFormattxt(input.format));
183 printf("tacNr := %d\n", input.tacNr);
184 printf("sampleNr := %d\n", input.sampleNr);
185 printf("xunit := %s\n", unitName(input.tunit));
186 printf("yunit := %s\n", unitName(input.cunit));
187 }
188 if(input.tacNr>1) {
189 fprintf(stderr,
190 "Warning: input file contains %d TACs; using the first.\n", input.tacNr);
191 input.tacNr=1;
192 }
193 if(input.sampleNr<2) {
194 fprintf(stderr, "Error: too few samples in input TAC.\n");
195 tacFree(&input); return(2);
196 }
197 if(input.sampleNr<10) {
198 fprintf(stderr, "Warning: too few samples for reliable simulation.\n");
199 }
200 /* Guess time units, if necessary */
201 if(input.tunit==UNIT_UNKNOWN) {
202 if(input.x[input.sampleNr-1]>20.0) {
203 if(verbose>1) printf("Note: assuming that times are in seconds.\n");
204 input.tunit=UNIT_SEC;
205 } else {
206 if(verbose>1) printf("Note: assuming that times are in minutes.\n");
207 input.tunit=UNIT_MIN;
208 }
209 }
210 /* Convert time to min if necessary */
211 if(input.tunit==UNIT_SEC) {
212 tacXUnitConvert(&input, UNIT_MIN, &status);
213 originallySec=1;
214 }
215
216
217 /*
218 * Allocate space for simulated data
219 */
220 TAC sim; tacInit(&sim);
221 n=3;
222 if(verbose>1)
223 printf("allocating memory for %d samples and %d TACs\n", input.sampleNr, n);
224 ret=tacAllocate(&sim, input.sampleNr, n);
225 if(ret!=TPCERROR_OK) {
226 fprintf(stderr, "Error: %s\n", errorMsg(ret));
227 tacFree(&sim); tacFree(&input); return(4);
228 }
229 sim.sampleNr=input.sampleNr;
230 sim.tacNr=n;
232 sim.cunit=input.cunit;
233 sim.tunit=input.tunit;
234 sim.format=input.format;
235 sim.isframe=0;
236 for(int j=0; j<sim.sampleNr; j++) sim.x[j]=input.x[j];
237 strcpy(sim.c[0].name, "muscle");
238 strcpy(sim.c[1].name, "lvcav");
239 strcpy(sim.c[2].name, "Ct");
240
241
242 /*
243 * Simulation
244 */
245 if(verbose>1) printf("simulating\n");
246 ret=simC1(input.x, input.c[0].y, input.sampleNr, MBF, MBF/pc, sim.c[2].y);
247 if(ret) {
248 fprintf(stderr, "Error: cannot simulate TTAC.\n");
249 if(verbose>1) printf("ret := %d\n", ret);
250 tacFree(&sim); tacFree(&input); return(6);
251 }
252
253 /*
254 * Calculate regional muscle and LV curves
255 */
256 for(int i=0; i<sim.sampleNr; i++) {
257 /* Calculate muscle region TAC */
258 sim.c[0].y[i] = PTF*sim.c[2].y[i] + Va*input.c[0].y[i];
259 /* Calculate LV cavity region TAC */
260 sim.c[1].y[i] = Beta*input.c[0].y[i] + (1.0-Beta)*sim.c[2].y[i];
261 }
262
263 /* simulation done */
264 tacFree(&input);
265
266
267 /* Convert time to sec if necessary */
268 if(originallySec) {
269 tacXUnitConvert(&sim, UNIT_SEC, &status);
270 }
271
272
273 /*
274 * Save simulated data
275 */
276 if(verbose>1) printf("writing %s\n", simfile);
277 if(save_ct==0) sim.tacNr=2;
278 FILE *fp; fp=fopen(simfile, "w");
279 if(fp==NULL) {
280 fprintf(stderr, "Error: cannot open file for writing (%s)\n", simfile);
281 tacFree(&sim); return(11);
282 }
283 ret=tacWrite(&sim, fp, TAC_FORMAT_UNKNOWN, 1, &status);
284 fclose(fp); tacFree(&sim);
285 if(ret!=TPCERROR_OK) {
286 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
287 return(12);
288 }
289 if(verbose>=0) printf("%s saved.\n", simfile);
290
291 return(0);
292}
293/*****************************************************************************/
294
295/*****************************************************************************/
double atofVerified(const char *s)
Definition decpoint.c:75
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 simC1(double *t, double *ca, const int nr, const double k1, const double k2, double *ct)
Definition sim1cm.c:93
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 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
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
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
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_MIN
minutes
@ UNIT_UNKNOWN
Unknown unit.
@ UNIT_SEC
seconds
@ TPCERROR_OK
No error.
char * unitName(int unit_code)
Definition units.c:143
Header file for library libtpcift.
Header file for libtpcpar.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28