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