TPCCLIB
Loading...
Searching...
No Matches
p2blood.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 "libtpccurveio.h"
16#include "libtpcmisc.h"
17/*****************************************************************************/
18#include "pbconv.h"
19/*****************************************************************************/
20
21/*****************************************************************************/
22static char *info[] = {
23 "Convert plasma time-activity curve (TAC) collected during a PET study",
24 "to blood TAC, based on tracer-dependent population-based",
25 "RBC/plasma or plasma/blood ratio functions over time.",
26 " ",
27 "Usage: @P [Options] tracer plasmafile HCr bloodfile",
28 " ",
29 "Options:",
30 " -Log",
31 " Log information is saved in output file.",
32 " -stdoptions", // List standard options like --help, -v, etc
33 " ",
34 "The following human PET tracer TACs can be converted:",
35 " AH690",
36 " ratio is assumed to follow a population average curve.",
37 " AH691",
38 " ratio is assumed to follow a population average curve.",
39 " Carfentanil",
40 " ratio is assumed to follow a population average curve",
41 " (unpublished measurements from eight 70-min PET studies).",
42 " FBPA",
43 " ratio is assumed to rise from zero with slope 0.00888",
44 " (unpublished measurement from 10 subjects).",
45 " FDG",
46 " ratio is assumed to be 0.8 in the beginning and to rise with",
47 " slope 0.0012/min (Phelps ME et al. Ann Neurol 1979;6:371-388).",
48 " FDOPA",
49 " ratio is assumed to follow equation R(t)=(Rmax*t)/(Th+t),",
50 " where Rmax=1.446 and Th=83.56 (unpublished results).",
51 " Flu[mazenil]",
52 " ratio is assumed to follow an average curve based on two",
53 " subjects with assumed HCR=0.43.",
54 " FLUORIDE",
55 " ratio is assumed to be 1.23 in the beginning and to decrease slowly",
56 " with slope 0.00123/min (Hawkins et al., JNM 1992;33:633-642.).",
57 " FMPEP-D2",
58 " ratio is assumed to follow a population average curve.",
59 " FTHA",
60 " concentration in red blood cells is assumed to be zero.",
61 " MEAIB",
62 " ratio is assumed to rise from zero with slope 0.00398",
63 " (unpublished measurement from 7 subjects).",
64 " Metomidate or MTO",
65 " concentration is the same in RBC and plasma water.",
66 " ORM-B",
67 " ratio is assumed to follow a population average curve",
68 " (unpublished measurement from 6 subjects studied twice).",
69 " Palm[itate]",
70 " ratio is assumed to follow a population average curve",
71 " (unpublished measurement from 8 subjects).",
72 " PBR28HAB, PBR28MAB, PBR28LAB",
73 " ratio is assumed to follow a binding-type specific population average",
74 " curve (unpublished measurements from 90-min PET studies).",
75 " PE2I",
76 " ratio is assumed to follow a population average curve",
77 " (unpublished measurements from ten 70-min PET studies).",
78 " PIB or 6OHBTA1",
79 " ratio is assumed to follow a population average curve,",
80 " currently based on 15 subjects.",
81 " PK11195",
82 " ratio is assumed to follow a curve based on one",
83 " subject with measured HCr.",
84 " SMW139",
85 " ratio is assumed to follow a population average curve,",
86 " currently based on 11 subjects.",
87 " UCB-J",
88 " ratio is assumed to follow a population average curve,",
89 " currently based on 7 subjects.",
90 "For mice and rats (these conversion do not utilize hematocrit):",
91 " MOUSEFDG1",
92 " plasma-to-blood ratio is assumed to follow the function published by",
93 " Yu AS et al. J Nucl Med 2009;50(6):966-973.",
94 " MOUSEFDG2",
95 " plasma-to-blood ratio is assumed to follow the function published by",
96 " Huang et al. J Nucl Med 2017;58(4):611-616.",
97 " RATFDG",
98 " plasma-to-blood ratio is assumed to follow the function published by",
99 " Weber et al. Eur J Nucl Med 2002;29(3):319-s323.",
100 " ",
101 "Codes for tracers that have below mentioned properties:",
102 " norbc",
103 " concentration in red blood cells is assumed to be zero.",
104 " inwater",
105 " concentration is the same in RBC and plasma water.",
106 " ",
107 "Times must be in minutes in data files, or seconds, if appropriately",
108 "specified inside the file.",
109 " ",
110 "The hematocrit (HCr, HCT) is normally between 0.40-0.51 in men and 0.36-0.47",
111 "in women. Note that HCr is lower in small vessels in tissue.",
112 " ",
113 "Example: estimate blood curve from measured FDG plasma TAC:",
114 " @P FDG i3344ap.kbq 0.38 i3344ab.kbq",
115 " ",
116 "See also: b2plasma, b2rbc, bpr2cpr, taccalc, taccat, fit_bpr, p2bfuncs",
117 " ",
118 "Keywords: input, modelling, simulation, blood, plasma, RBC, hematocrit",
119 0};
120/*****************************************************************************/
121
122/*****************************************************************************/
123/* Turn on the globbing of the command line, since it is disabled by default in
124 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
125 In Unix&Linux wildcard command line processing is enabled by default. */
126/*
127#undef _CRT_glob
128#define _CRT_glob -1
129*/
130int _dowildcard = -1;
131/*****************************************************************************/
132
133/*****************************************************************************/
137int main(int argc, char **argv)
138{
139 int ai, help=0, version=0, verbose=1;
140 int fi, ri, ret;
141 int tracer=-1;
142 int save_log=0;
143 int times_converted=0;
144 char ifile[FILENAME_MAX], ofile[FILENAME_MAX], *cptr;
145 char tmp[1024];
146 DFT data;
147 double HCR=-1.0;
148 int ratio_type=0; // 0=RBC/plasma; 1=plasma/blood
149
150
151 /*
152 * Get arguments
153 */
154 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
155 ifile[0]=ofile[0]=(char)0;
156 dftInit(&data);
157 /* Options */
158 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
159 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
160 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
161 cptr=argv[ai]+1;
162 if(strcasecmp(cptr, "L")==0 || strcasecmp(cptr, "LOG")==0) {
163 save_log=1; continue;
164 }
165 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
166 return(1);
167 } else break;
168
169 /* Print help or version? */
170 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
171 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
172 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
173
174 /* Next argument must be the tracer code */
175 if(ai<argc) {
176 tracer=tracer_code(argv[ai]);
177 if(tracer<0) {
178 fprintf(stderr, "Error: invalid tracer code '%s'.\n", argv[ai]);
179 return(1);
180 }
181 ai++;
182 }
183
184 /* Next argument must be the input file */
185 if(ai<argc) {strcpy(ifile, argv[ai]); ai++;}
186
187 /* Next argument must be the hematocrit */
188 if(ai<argc) {
189 HCR=atof_dpi(argv[ai]); if(HCR>1.0) HCR/=100.0;
190 if(HCR<0.01 || HCR>1.0) {fprintf(stderr, "Error: bad HCr %g.\n", HCR); return(1);}
191 ai++;
192 }
193
194 /* Next argument must be the output file */
195 if(ai<argc) {strcpy(ofile, argv[ai]); ai++;}
196
197 /* Is something extra? */
198 if(ai<argc) {
199 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
200 return(1);
201 }
202
203 /* Is something missing? */
204 if(!ofile[0]) {
205 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
206 return(1);
207 }
208
209 /* In verbose mode print arguments and options */
210 if(verbose>1) {
211 printf("save_log := %d\n", save_log);
212 printf("ifile := %s\n", ifile);
213 printf("ofile := %s\n", ofile);
214 printf("HCR := %.2f\n", HCR);
215 printf("tracer := %d\n", tracer);
216 }
217
218
219 /*
220 * Read TAC data
221 */
222 if(verbose>1) printf("reading %s\n", ifile);
223 if(dftRead(ifile, &data)) {
224 fprintf(stderr, "Error in reading '%s': %s\n", ifile, dfterrmsg);
225 return(2);
226 }
227 if(data.voiNr>1) {
228 fprintf(stderr, "Warning: %s contains %d TACs.\n", ifile, data.voiNr);
229 }
230
231 /* Convert sample times from sec to min, if necessary */
232 if(data.timeunit==TUNIT_UNKNOWN) {
233 fprintf(stderr, "Warning: sample times are assumed to be in minutes.\n");
234 }
235 if(data.timeunit==TUNIT_SEC) {
236 if(verbose>1) printf("Sample times are converted to min\n");
237 dftSec2min(&data); times_converted=1;
238 }
239
240
241 /*
242 * Calculate the ratio curve
243 */
244 if(verbose>1) printf("calculating ratio curve\n");
245 /* Try first RBC/plasma curve */
246 ratio_type=0; if(verbose>2) printf("trying RBC/plasma ratio\n");
247 ret=rbc_plasma_ratio(tracer, data.x, data.voi[0].y2, data.frameNr);
248 /* If tracer was not identified, then try plasma/blood ratio */
249 if(ret==-1) {
250 ratio_type=1; if(verbose>2) printf("trying plasma/blood ratio\n");
251 ret=plasma_to_blood_ratio(tracer, data.x, data.voi[0].y2, data.frameNr);
252 }
253 if(ret) {
254 fprintf(stderr, "Error (%d): cannot calculate ratio.\n", ret);
255 dftEmpty(&data); return(5);
256 }
257 if(verbose>2) printf("ratio_type := %d\n", ratio_type);
258 if(ratio_type==1 && verbose>1)
259 fprintf(stderr, "Note: HCr is not used in conversion.\n");
260 if(verbose>3) {
261 if(ratio_type==0) strcpy(tmp, "RBC-to-plasma");
262 else strcpy(tmp, "plasma-to-blood");
263 for(fi=0; fi<data.frameNr; fi++)
264 printf("%s[%g] := %.3f\n", tmp, data.x[fi], data.voi[0].y2[fi]);
265 }
266
267
268 /*
269 * Calculate blood TAC
270 */
271 if(verbose>1) printf("calculating blood curve\n");
272 if(ratio_type==0)
273 for(fi=0; fi<data.frameNr; fi++)
274 for(ri=0; ri<data.voiNr; ri++)
275 data.voi[ri].y3[fi]=
276 data.voi[ri].y[fi] * (HCR*data.voi[0].y2[fi] + (1-HCR));
277 else
278 for(fi=0; fi<data.frameNr; fi++)
279 for(ri=0; ri<data.voiNr; ri++)
280 data.voi[ri].y3[fi]= data.voi[ri].y[fi] / data.voi[0].y2[fi];
281
282
283 /* Convert sample times back from min to sec, if necessary */
284 if(times_converted==1) {
285 if(verbose>1) printf("Sample times are converted to sec\n");
286 dftMin2sec(&data);
287 }
288
289 /*
290 * Save data
291 */
292 for(fi=0; fi<data.frameNr; fi++)
293 for(ri=0; ri<data.voiNr; ri++)
294 data.voi[ri].y[fi]=data.voi[ri].y3[fi];
295 if(save_log!=0) {
296 if(verbose>1) printf("saving log information\n");
297 strcat(data.comments, "\n# converted to blood\n");
298 if(ratio_type==0) {sprintf(tmp, "# HCT := %.2f\n", HCR); strcat(data.comments, tmp);}
299 sprintf(tmp, "# tracer_code := %d\n", tracer); strcat(data.comments, tmp);
300 if(ratio_type==0) strcpy(tmp, "# ratio := RBC/plasma\n");
301 else strcpy(tmp, "# ratio := plasma/blood\n");
302 strcat(data.comments, tmp);
303 }
304 if(verbose>1) printf("writing %s\n", ofile);
305 if(dftWrite(&data, ofile)) {
306 fprintf(stderr, "Error in writing '%s': %s\n", ofile, dfterrmsg);
307 dftEmpty(&data); return(11);
308 }
309 if(verbose>0) printf("Blood TAC written in %s\n", ofile);
310
311 /* Free memory */
312 dftEmpty(&data);
313
314 return(0);
315}
316/*****************************************************************************/
317
318/*****************************************************************************/
double atof_dpi(char *str)
Definition decpoint.c:59
void dftInit(DFT *data)
Definition dft.c:38
char dfterrmsg[64]
Definition dft.c:6
void dftEmpty(DFT *data)
Definition dft.c:20
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
void dftSec2min(DFT *dft)
Definition dftunit.c:160
void dftMin2sec(DFT *dft)
Definition dftunit.c:145
Header file for libtpccurveio.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
int rbc_plasma_ratio(int tracer, double *t, double *r, int nr)
Definition pbconv.c:83
int tracer_code(char *tracer)
Definition pbconv.c:32
int plasma_to_blood_ratio(int tracer, double *t, double *r, int nr)
Definition pbconv.c:248
Header file for pbconv.c.
Voi * voi
int timeunit
char comments[_DFT_COMMENT_LEN+1]
int voiNr
int frameNr
double * x
double * y2
double * y
double * y3