TPCCLIB
Loading...
Searching...
No Matches
o2_p2w.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/*****************************************************************************/
19
20/*****************************************************************************/
21static char *info[] = {
22 "Converts arterial plasma TAC from a [O-15]O2 PET study",
23 "to blood [O-15]H2O TAC (1).",
24 " ",
25 "Usage: @P [Options] plasmafile bloodfile",
26 " ",
27 "Options:",
28 " -HCT=<Hematocrit>",
29 " Specify the hematocrit; when specified, the plasma-to-blood ratio",
30 " is calculated using it, assuming that water contents of RBCs and",
31 " plasma are 0.73 and 0.94, respectively.",
32 " -PBR=<Plasma-to-blood ratio>",
33 " Specify the plasma-to-blood ratio; by default 1.12; effective only",
34 " when HCT is not given.",
35 " -SCT=<Sample collect time>",
36 " Plasma sample collection time (usually 20 s) should be given for",
37 " accurate fit with fit_o2bl.",
38 " -stdoptions", // List standard options like --help, -v, etc
39 " ",
40 "References:",
41 "1. Lubberink M, Wong YY, Raijmakers PGHM, Schuit RC, Luurtsema G,",
42 " Boellaard R, Knaapen P, Vonk-Noordegraaf A, Lammertsma AA. Myocardial",
43 " oxygen extraction fraction measured using bolus inhalation of 15O-oxygen",
44 " gas and dynamic PET. J Nucl Med. 2011;52(1):60-66.",
45 " ",
46 "See also: fit_o2bl, o2metab, sim_o2bl, b2t_mo2, fit_mo2, tac2svg, taccalc",
47 " ",
48 "Keywords: input, oxygen, blood, metabolite correction",
49 0};
50/*****************************************************************************/
51
52/*****************************************************************************/
53/* Turn on the globbing of the command line, since it is disabled by default in
54 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
55 In Unix&Linux wildcard command line processing is enabled by default. */
56/*
57#undef _CRT_glob
58#define _CRT_glob -1
59*/
60int _dowildcard = -1;
61/*****************************************************************************/
62
63/*****************************************************************************/
67int main(int argc, char **argv)
68{
69 int ai, help=0, version=0, verbose=1;
70 int ret;
71 char pfile[FILENAME_MAX], bfile[FILENAME_MAX], *cptr;
72 double pb_ratio=1.12, bp_ratio, HCT=-1.0, coll_time=-1.0;
73 TAC tac;
74 double w_p=0.94, w_rbc=0.73;
75 int times_converted=0;
76
77
78 /*
79 * Get arguments
80 */
81 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
82 pfile[0]=bfile[0]=(char)0;
83 tacInit(&tac);
84 /* Options */
85 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
86 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
87 cptr=argv[ai]+1;
88 if(strncasecmp(cptr, "PBR=", 4)==0) {
89 if(!atofCheck(cptr+4, &pb_ratio) && pb_ratio>=1.0 && pb_ratio<2.0)
90 continue;
91 } else if(strncasecmp(cptr, "HCT=", 4)==0) {
92 if(!atofCheck(cptr+4, &HCT) && HCT>0.0 && HCT<1.0) {
93 pb_ratio=-1.0; continue;
94 }
95 } else if(strncasecmp(cptr, "SCT=", 4)==0) {
96 if(!atofCheck(cptr+4, &coll_time) && coll_time>=0.0 && coll_time<60.0)
97 continue;
98 }
99 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
100 return(1);
101 } else break; // tac name argument may start with '-'
102
103 TPCSTATUS status; statusInit(&status);
104 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
105 status.verbose=verbose-1;
106
107 /* Print help or version? */
108 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
109 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
110 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
111
112 /* Arguments */
113 for(; ai<argc; ai++) {
114 if(!pfile[0]) {
115 strlcpy(pfile, argv[ai], FILENAME_MAX); continue;
116 } else if(!bfile[0]) {
117 strlcpy(bfile, argv[ai], FILENAME_MAX); continue;
118 }
119 fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]);
120 return(1);
121 }
122
123 /* Is something missing? */
124 if(!bfile[0]) {
125 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
126 return(1);
127 }
128
129 /* In verbose mode print arguments and options */
130 if(verbose>1) {
131 for(ai=0; ai<argc; ai++)
132 printf("%s ", argv[ai]);
133 printf("\n");
134 printf("bfile := %s\n", bfile);
135 printf("pfile := %s\n", pfile);
136 if(HCT<=0.0) printf("pb_ratio := %g\n", pb_ratio);
137 else printf("HCT := %g\n", HCT);
138 if(coll_time>=0.0) printf("coll_time := %g [s]\n", coll_time);
139 }
140
141 /* Calculate plasma-to-blood ratio from HCT, if necessary */
142 /* And calculate blood-to-plasma ratio */
143 if(HCT>0.0) {
144 if(verbose>1) {
145 printf("w_rbc := %g\n", w_rbc);
146 printf("w_plasma := %g\n", w_p);
147 }
148 bp_ratio= 1.0 - HCT*(1.0 - w_rbc/w_p);
149 pb_ratio=1.0/bp_ratio;
150 if(verbose>1) printf("pb_ratio := %g\n", pb_ratio);
151 } else {
152 bp_ratio=1.0/pb_ratio;
153 }
154 if(verbose>1) printf("bp_ratio := %g\n", bp_ratio);
155
156
157 /*
158 * Read plasma TAC
159 */
160 if(verbose>1) printf("reading %s\n", pfile);
161 ret=tacRead(&tac, pfile, &status);
162 if(ret!=TPCERROR_OK) {
163 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
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 }
173 if(tac.tacNr>1) {
174 fprintf(stderr, "Warning: only first TAC in plasma file is used.\n");
175 tac.tacNr=1;
176 }
177 /* Sort by sample times */
178 tacSortByTime(&tac, NULL);
179 /* Check for missing values */
180 ret=tacNaNs(&tac);
181 if(ret>0) {
182 if(verbose>1) printf("missing concentrations.\n");
183 /* Try to fix missing concentrations */
184 ret=tacFixNaNs(&tac);
185 if(ret!=0) {
186 fprintf(stderr, "Error: missing concentrations in %s.\n", pfile);
187 tacFree(&tac); return(2);
188 }
189 }
190 /* Convert sample times from min to sec, if necessary */
191 if(tac.tunit==UNIT_UNKNOWN) {
192 /* If sample collect time is longer than TAC end time, then
193 TAC is probably in minutes */
194 if(coll_time<tac.x[tac.sampleNr-1]) {
195 tac.tunit=UNIT_MIN;
196 fprintf(stderr, "Warning: sample times are assumed to be in minutes.\n");
197 } else {
198 fprintf(stderr, "Warning: sample times are assumed to be in seconds.\n");
199 tac.tunit=UNIT_SEC;
200 }
201 }
202 if(tac.tunit==UNIT_MIN) {
203 ret=tacXUnitConvert(&tac, UNIT_SEC, &status);
204 if(!ret) {
205 if(verbose>1) printf("Sample times are converted to sec\n");
206 times_converted=1;
207 }
208 }
209
210 /*
211 * Multiply plasma data with bp_ratio
212 */
213 for(int i=0; i<tac.sampleNr; i++) tac.c[0].y[i]*=bp_ratio;
214
215 /*
216 * Set time "frames" based on the collection time
217 */
218 if(coll_time>0.0) {
219 if(verbose>1) printf("setting collection time\n");
220 for(int i=0; i<tac.sampleNr; i++) {
221 /* Check that sample times are not overlapping */
222 if(i>0 && ((tac.x[i]-tac.x[i-1])<coll_time)) {
223 fprintf(stderr, "Error: sample and collection times do not match.\n");
224 tacFree(&tac); return(4);
225 }
226 /* Set frame start and end times based on collection time */
227 tac.x1[i]=tac.x[i]-0.5*coll_time;
228 tac.x2[i]=tac.x[i]+0.5*coll_time;
229 }
230 /* Set TAC type accordingly */
231 tac.isframe=1; /* start and end times */
233 }
234
235 strcpy(tac.c[0].name, "Blood_H2O");
236
237 /*
238 * Convert sample times back to minutes, if necessary
239 */
240 if(times_converted) {
241 if(verbose>1) printf("Sample times are converted back to min\n");
242 tacXUnitConvert(&tac, UNIT_MIN, &status);
243 times_converted=0;
244 }
245
246
247 /*
248 * Write blood file
249 */
250 if(verbose>1) printf("writing %s\n", bfile);
251 FILE *fp; fp=fopen(bfile, "w");
252 if(fp==NULL) {
253 fprintf(stderr, "Error: cannot open file for writing (%s)\n", bfile);
254 tacFree(&tac); return(11);
255 }
256 ret=tacWrite(&tac, fp, TAC_FORMAT_UNKNOWN, 1, &status);
257 fclose(fp); tacFree(&tac);
258 if(ret!=TPCERROR_OK) {
259 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
260 return(12);
261 }
262 if(verbose>=0) printf("Blood curve written in %s\n", bfile);
263
264 return(0);
265}
266/*****************************************************************************/
267
268/*****************************************************************************/
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
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
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
double * x2
Definition tpctac.h:101
unit tunit
Definition tpctac.h:109
double * x1
Definition tpctac.h:99
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 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 tacNaNs(TAC *tac)
Definition tacnan.c:71
int tacFixNaNs(TAC *tac)
Definition tacnan.c:121
int tacSortByTime(TAC *d, TPCSTATUS *status)
Definition tacorder.c:74
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
Header file for library libtpcextensions.
@ 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 library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28
@ TAC_FORMAT_PMOD
PMOD TAC format.
Definition tpctac.h:33
@ TAC_FORMAT_SIMPLE
x and y's with space delimiters
Definition tpctac.h:29