TPCCLIB
Loading...
Searching...
No Matches
dftcbv.c
Go to the documentation of this file.
1
8/*****************************************************************************/
9#include "tpcclibConfig.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <math.h>
15#include <string.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpccurveio.h"
19#include "libtpcmodel.h"
20#include "libtpcmodext.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Subtracts the contribution of vascular radioactivity from regional",
26 "PET TTACs. Vascular volume fraction Vb can be given as a value that is",
27 "common to all regions, or as regional Vb values in a TAC file, calculated",
28 "from a [O-15]CO study.",
29 " ",
30 "Usage: @P ttacfile btacfile Vb outputfile",
31 " ",
32 "Options:",
33 " -noneg",
34 " Negative TAC values are set to 0.",
35 " -pv | -tv",
36 " Equation Ct=Cpet-Vb*Cb is applied by default or with option -pv;",
37 " with option -tv equation Ct=(Cpet-Vb*Cb)/(1-Vb) is applied.",
38 " -sim",
39 " Simulate the contribution of vascular radioactivity instead of",
40 " correcting for it, calculating Cpet from Ct using equations above.",
41 " -stdoptions", // List standard options like --help, -v, etc
42 " ",
43 "Example 1:",
44 " @P uo372.tac uo372ab.bld 0.045 uo372cbv.tac",
45 "Example 2:",
46 " @P uo372.dft uo372ab.kbq uo372vb.dft uo372cbv.dft",
47 " ",
48 "Vb values that are >=1.0 are assumed to be percentages.",
49 "Blood TAC can be given in a separate BTAC file, or as a region id inside",
50 "TTAC file.",
51 " ",
52 "See also: imgcbv, p2blood, interpol, taccalc, tacformat",
53 " ",
54 "Keywords: TAC, modelling, vascular fraction, simulation",
55 0};
56/*****************************************************************************/
57
58/*****************************************************************************/
59/* Turn on the globbing of the command line, since it is disabled by default in
60 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
61 In Unix&Linux wildcard command line processing is enabled by default. */
62/*
63#undef _CRT_glob
64#define _CRT_glob -1
65*/
66int _dowildcard = -1;
67/*****************************************************************************/
68
69/*****************************************************************************/
73int main(int argc, char **argv)
74{
75 int ai, help=0, version=0, verbose=1;
76 int ri, fi, ret;
77 int leave_negat=1, pet_volume=1, add_vb=0;
78 char infile[FILENAME_MAX], blfile[FILENAME_MAX], outfile[FILENAME_MAX],
79 *cptr, vbfile[FILENAME_MAX], tmp[256];
80 DFT dft, blood, tdft;
81 double vb=-1.0, t1, t2;
82
83
84 /*
85 * Get arguments
86 */
87 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
88 infile[0]=outfile[0]=blfile[0]=vbfile[0]=(char)0;
89 dftInit(&dft); dftInit(&blood); dftInit(&tdft);
90 /* Options */
91 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
92 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
93 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
94 if(strncasecmp(cptr, "NONEGATIVES", 1)==0) {
95 leave_negat=0; continue;
96 } else if(strncasecmp(cptr, "PV", 1)==0) {
97 pet_volume=1; continue;
98 } else if(strncasecmp(cptr, "TV", 1)==0) {
99 pet_volume=0; continue;
100 } else if(strncasecmp(cptr, "SIMULATE", 3)==0) {
101 add_vb=1; continue;
102 }
103 fprintf(stderr, "Error: unknown option '%s'.\n", argv[ai]);
104 return(1);
105 } else break;
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 /* Process other arguments, starting from the first non-option */
113 for(; ai<argc; ai++) {
114 if(!infile[0]) {strlcpy(infile, argv[ai], FILENAME_MAX); continue;}
115 else if(!blfile[0]) {strlcpy(blfile, argv[ai], FILENAME_MAX); continue;}
116 else if(!vbfile[0] && vb<0.0) {
117 if(access(argv[ai], 0)==0) {
118 strlcpy(vbfile, argv[ai], FILENAME_MAX); continue;
119 }
120 ret=atof_with_check(argv[ai], &vb);
121 if(ret==0) {if(vb>=1.0) vb/=100.; if(vb>=0.0) continue;}
122 fprintf(stderr, "Error: invalid Vb: '%s'.\n", argv[ai]);
123 return(1);
124 }
125 else if(!outfile[0]) {strlcpy(outfile, argv[ai], FILENAME_MAX); continue;}
126 fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]);
127 return(1);
128 }
129
130 /* Is something missing? */
131 if(!outfile[0]) {
132 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
133 return(1);
134 }
135
136
137 /* In verbose mode print arguments and options */
138 if(verbose>1) {
139 printf("infile := %s\n", infile);
140 printf("blfile := %s\n", blfile);
141 printf("vbfile := %s\n", vbfile);
142 printf("pet_volume := %d\n", pet_volume);
143 printf("vb := %g\n", vb);
144 printf("leave_negat := %d\n", leave_negat);
145 printf("add_vb := %d\n", add_vb);
146 }
147
148 if(verbose>1) {
149 printf("\napplying formula:\n");
150 if(add_vb==0) {
151 if(pet_volume==0) printf("Ct=(Cpet-Vb*Cb)/(1-Vb)\n");
152 else printf("Ct=Cpet-Vb*Cb\n");
153 } else {
154 if(pet_volume==0) printf("Cpet=(1-Vb)*Ct+Vb*Cb\n");
155 else printf("Cpet=Ct+Vb*Cb\n");
156 }
157 printf("\n");
158 }
159
160 /*
161 * Read regional TACs
162 */
163 if(verbose>1) printf("reading %s\n", infile);
164 if(dftRead(infile, &dft)) {
165 fprintf(stderr, "Error in reading '%s': %s\n", infile, dfterrmsg);
166 return(2);
167 }
168
169 /*
170 * Read blood TAC
171 */
172 if(verbose>1) printf("reading %s\n", blfile);
173 ret=dftReadinput(&blood, &dft, blfile, &ri, &t1, &t2, 0, tmp, verbose-3);
174 if(ret!=0) {
175 fprintf(stderr, "Error in reading '%s': %s\n", blfile, tmp);
176 dftEmpty(&dft); return(3);
177 }
178 if(verbose>2) printf("blood_filetype := %d\n", ri);
179 /* Check blood time range */
180 if((dft.frameNr>1 && t1>dft.x[1]) || (dft.x[dft.frameNr-1]>1.2*t2)) {
181 fprintf(stderr, "Warning: blood TAC is clearly shorter than tissue TAC.\n");
182 }
183
184 /*
185 * If Vb values are given in a file, then read that
186 */
187 if(vbfile[0]) {
188 if(verbose>1) printf("reading %s\n", vbfile);
189 if(dftRead(vbfile, &tdft)) {
190 fprintf(stderr, "Error in reading '%s': %s\n", vbfile, dfterrmsg);
191 dftEmpty(&dft); dftEmpty(&blood); return(4);
192 }
193 if(tdft.frameNr>1) {
194 fprintf(stderr, "Error: Vb file contains more than one sample time.\n");
195 dftEmpty(&dft); dftEmpty(&blood); dftEmpty(&tdft); return(4);
196 }
197 /* check regions */
198 ret=0;
199 if(dft.voiNr!=tdft.voiNr)
200 ret=1;
201 else {
202 for(ri=0; ri<dft.voiNr; ri++) {
203 if(strcmp(dft.voi[ri].name, tdft.voi[ri].name)!=0) ret=2;
204 if(strcmp(dft.voi[ri].voiname, tdft.voi[ri].voiname)!=0) ret=3;
205 if(strcmp(dft.voi[ri].hemisphere, tdft.voi[ri].hemisphere)!=0) ret=4;
206 if(strcmp(dft.voi[ri].place, tdft.voi[ri].place)!=0) ret=5;
207 if(ret) break;
208 }
209 }
210 if(ret) {
211 fprintf(stderr, "Error: Vb file does not contain the same regions.\n");
212 dftEmpty(&dft); dftEmpty(&blood); dftEmpty(&tdft); return(4);
213 }
214 /* check that Vb is fraction */
215 for(ri=ret=0; ri<tdft.voiNr; ri++) if(tdft.voi[ri].y[0]>=1.0) ret=1;
216 if(ret) {
217 for(ri=0; ri<tdft.voiNr; ri++) tdft.voi[ri].y[0]/=100.;
218 for(ri=ret=0; ri<tdft.voiNr; ri++) if(tdft.voi[ri].y[0]>=1.0) ret=1;
219 if(ret) {
220 fprintf(stderr, "Error: invalid contents in Vb file.\n");
221 dftEmpty(&dft); dftEmpty(&blood); dftEmpty(&tdft); return(4);
222 }
223 fprintf(stderr, "Warning: Vb values were converted to fractions.\n");
224 }
225 }
226
227
228 /*
229 * Make subtraction, or add Vb contribution
230 */
231 if(add_vb==0) {
232 if(verbose>1) printf("subtracting blood\n");
233 for(ri=0; ri<dft.voiNr; ri++) {
234 if(vbfile[0]) {
235 vb=tdft.voi[ri].y[0];
236 if(verbose>2) printf("Vb=%g for %s\n", vb, dft.voi[ri].name);
237 }
238 for(fi=0; fi<dft.frameNr; fi++) {
239 dft.voi[ri].y2[fi]=dft.voi[ri].y[fi];
240 if(!isnan(dft.voi[ri].y2[fi])) {
241 dft.voi[ri].y2[fi]-=vb*blood.voi[0].y[fi];
242 if(pet_volume==0) dft.voi[ri].y2[fi]/=(1.0-vb);
243 if(leave_negat==0 && dft.voi[ri].y2[fi]<0.0) dft.voi[ri].y2[fi]=0.0;
244 }
245 }
246 } /* next region */
247 } else {
248 if(verbose>1) printf("adding blood\n");
249 for(ri=0; ri<dft.voiNr; ri++) {
250 if(vbfile[0]) {
251 vb=tdft.voi[ri].y[0];
252 if(verbose>2) printf("Vb=%g for %s\n", vb, dft.voi[ri].name);
253 }
254 for(fi=0; fi<dft.frameNr; fi++) {
255 dft.voi[ri].y2[fi]=dft.voi[ri].y[fi];
256 if(!isnan(dft.voi[ri].y2[fi])) {
257 if(pet_volume==0) dft.voi[ri].y2[fi]*=(1.0-vb);
258 dft.voi[ri].y2[fi]+=vb*blood.voi[0].y[fi];
259 if(leave_negat==0 && dft.voi[ri].y2[fi]<0.0) dft.voi[ri].y2[fi]=0.0;
260 }
261 }
262 } /* next region */
263 }
264 if(verbose>20) dftPrint(&dft);
265
266
267 /*
268 * Save data
269 */
270 if(verbose>1) printf("writing %s\n", outfile);
271 for(ri=0; ri<dft.voiNr; ri++) for(fi=0; fi<dft.frameNr; fi++)
272 dft.voi[ri].y[fi]=dft.voi[ri].y2[fi];
273 ret=dftWrite(&dft, outfile);
274 if(ret) {
275 fprintf(stderr, "Error (%d) in writing '%s': %s\n", ret, outfile, dfterrmsg);
276 dftEmpty(&dft); dftEmpty(&blood); dftEmpty(&tdft);
277 return(11);
278 }
279 if(verbose>0) printf(" %s written.\n", outfile);
280
281 dftEmpty(&dft); dftEmpty(&blood); dftEmpty(&tdft);
282 return(0);
283}
284/*****************************************************************************/
285
286/*****************************************************************************/
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
void dftInit(DFT *data)
Definition dft.c:38
char dfterrmsg[64]
Definition dft.c:6
void dftEmpty(DFT *data)
Definition dft.c:20
int dftReadinput(DFT *input, DFT *tissue, char *filename, int *filetype, double *ti1, double *ti2, int verifypeak, char *status, int verbose)
Definition dftinput.c:25
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
void dftPrint(DFT *data)
Definition dftio.c:538
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
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
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
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
Header file for libtpcmodel.
Header file for libtpcmodext.
Voi * voi
int voiNr
int frameNr
double * x
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]