TPCCLIB
Loading...
Searching...
No Matches
imgcbv.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 <math.h>
14#include <string.h>
15#include <unistd.h>
16#include <time.h>
17/*****************************************************************************/
18#include "libtpcmisc.h"
19#include "libtpcimgio.h"
20#include "libtpcimgp.h"
21#include "libtpcmodext.h"
22/*****************************************************************************/
23
24/*****************************************************************************/
25static char *info[] = {
26 "Subtracts the contribution of vascular radioactivity from dynamic PET",
27 "image. Vascular volume fraction Vb can be given as a value that is common",
28 "to all image voxels, or as separate value for each image voxel in a",
29 "(preferably smoothed) Vb image, usually calculated from a [O-15]CO study.",
30 "Vb must be given as a volume fraction, not percentage, whether it is given",
31 "directly or inside the Vb image.",
32 " ",
33 "Usage: @P [Options] imgfile btacfile Vb outputfile",
34 " ",
35 "Options:",
36 " -noneg",
37 " Negative voxel values are set to 0.",
38 " -pv | -tv",
39 " Equation Ct=Cpet-Vb*Cb is applied by default or with option -pv;",
40 " with option -tv equation Ct=(Cpet-Vb*Cb)/(1-Vb) is applied.",
41 " -sim",
42 " Simulate the contribution of vascular radioactivity instead of",
43 " correcting for it, calculating Cpet from Ct using equations above.",
44 " -stdoptions", // List standard options like --help, -v, etc
45 " ",
46 "Example 1: Vascular volume fraction in all tissue is assumed to be 0.04:",
47 " imgcbv ua2918dy1.img ua2918ab.kbq 0.04 ua2918cbv.img",
48 "Example 2: Vascular volume fraction is given in specific image file:",
49 " imgcbv ua2918dy1.v ua2918ab.kbq ua2918vb.v ua2918cbv.v",
50 " ",
51 "See also: taccbv, imgcalc, p2blood, imgunit, tacunit",
52 " ",
53 "Keywords: image, modelling, vascular fraction, simulation",
54 0};
55/*****************************************************************************/
56
57/*****************************************************************************/
58/* Turn on the globbing of the command line, since it is disabled by default in
59 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
60 In Unix&Linux wildcard command line processing is enabled by default. */
61/*
62#undef _CRT_glob
63#define _CRT_glob -1
64*/
65int _dowildcard = -1;
66/*****************************************************************************/
67
68/*****************************************************************************/
70
78 const char *file1,
80 const char *file2,
82 int verbose
83) {
84 int ii, mi, ret;
85 char tmp[1024];
86 ECAT_HEADERS ehdr;
87
88 if(verbose>1) printf("ecatCopyHeaders(%s, %s)\n", file1, file2);
89 if(file1==NULL || file2==NULL) return(1);
90
91
92 /* Read headers */
93 ehdrInitiate(&ehdr);
94 ret=ecat7ReadHeaders(file1, &ehdr, verbose-1); if(ret!=0) return(10);
95 /* Remove main header information that should NOT be copied */
96 strcpy(tmp, "user_process_code");
97 ii=iftGet(&ehdr.mh, tmp, 0); iftDeleteItem(&ehdr.mh, ii, 0);
98 strcpy(tmp, "ecat_calibration_factor");
99 ii=iftGet(&ehdr.mh, tmp, 0); iftDeleteItem(&ehdr.mh, ii, 0);
100
101 /* Remove subheader information that should NOT be copied */
102 for(mi=0; mi<ehdr.nr; mi++) {
103 strcpy(tmp, "scale_factor");
104 ii=iftGet(&ehdr.m[mi].sh, tmp, 0); iftDeleteItem(&ehdr.m[mi].sh, ii, 0);
105 strcpy(tmp, "image_min");
106 ii=iftGet(&ehdr.m[mi].sh, tmp, 0); iftDeleteItem(&ehdr.m[mi].sh, ii, 0);
107 strcpy(tmp, "image_max");
108 ii=iftGet(&ehdr.m[mi].sh, tmp, 0); iftDeleteItem(&ehdr.m[mi].sh, ii, 0);
109 strcpy(tmp, "scan_min");
110 ii=iftGet(&ehdr.m[mi].sh, tmp, 0); iftDeleteItem(&ehdr.m[mi].sh, ii, 0);
111 strcpy(tmp, "scan_max");
112 ii=iftGet(&ehdr.m[mi].sh, tmp, 0); iftDeleteItem(&ehdr.m[mi].sh, ii, 0);
113 }
114
115 /* Write headers */
116 ret=ecat7WriteHeaders(file2, &ehdr, verbose-1);
117 ehdrEmpty(&ehdr);
118 if(ret!=0) return(10+ret);
119
120 return 0;
121}
122
123/*****************************************************************************/
124
125/*****************************************************************************/
129int main(int argc, char **argv)
130{
131 int ai, help=0, version=0, verbose=1;
132 int ret;
133 int leave_negat=1,
134 pet_volume=1,
135 add_vb=0;
136 char infile[FILENAME_MAX], blfile[FILENAME_MAX], outfile[FILENAME_MAX],
137 *cptr, tmp[FILENAME_MAX+128],
138 vbfile[FILENAME_MAX];
139 double vb=0.0;
140 double endtime;
141 float f;
142 DFT blood;
143 IMG img, vbimg;
144 int isvalue=0;
145
146
147 /*
148 * Get arguments
149 */
150 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
151 infile[0]=outfile[0]=blfile[0]=vbfile[0]=(char)0;
152 imgInit(&img); imgInit(&vbimg); dftInit(&blood);
153 /* Options */
154 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
155 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
156 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
157 if(strncasecmp(cptr, "NONEGATIVES", 1)==0) {
158 leave_negat=0; continue;
159 } else if(strncasecmp(cptr, "PV", 1)==0) {
160 pet_volume=1; continue;
161 } else if(strncasecmp(cptr, "TV", 1)==0) {
162 pet_volume=0; continue;
163 } else if(strncasecmp(cptr, "SIMULATE", 3)==0) {
164 add_vb=1; continue;
165 }
166 fprintf(stderr, "Error: unknown option '%s'.\n", argv[ai]);
167 return(1);
168 } else break;
169
170 /* Print help or version? */
171 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
172 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
173 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
174
175 /* Process other arguments, starting from the first non-option */
176 for(; ai<argc; ai++) {
177 if(!infile[0]) {
178 strlcpy(infile, argv[ai], FILENAME_MAX); continue;
179 } else if(!blfile[0]) {
180 strlcpy(blfile, argv[ai], FILENAME_MAX); continue;
181 } else if(isvalue==0 && !vbfile[0]) {
182 double v;
183 ret=atof_with_check(argv[ai], &v);
184 if(ret==0) {
185 isvalue=1; vb=v;
186 if(vb>=1.0) {
187 fprintf(stderr, "Warning: Vb fraction is set to %.3f\n", vb);
188 }
189 } else {
190 strlcpy(vbfile, argv[ai], FILENAME_MAX);
191 }
192 continue;
193 } else if(!outfile[0]) {
194 strlcpy(outfile, argv[ai], FILENAME_MAX); continue;
195 }
196 fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]);
197 return(1);
198 }
199
200 /* Is something missing? */
201 if(!outfile[0]) {
202 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
203 return(1);
204 }
205
206
207 /* In verbose mode print arguments and options */
208 if(verbose>1) {
209 printf("infile := %s\n", infile);
210 printf("blfile := %s\n", blfile);
211 printf("vbfile := %s\n", vbfile);
212 printf("pet_volume := %d\n", pet_volume);
213 printf("vb := %g\n", vb);
214 printf("leave_negat := %d\n", leave_negat);
215 printf("add_vb := %d\n", add_vb);
216 }
217 if(verbose>1) {
218 printf("\napplying formula:\n");
219 if(add_vb==0) {
220 if(pet_volume==0) printf("Ct=(Cpet-Vb*Cb)/(1-Vb)\n");
221 else printf("Ct=Cpet-Vb*Cb\n");
222 } else {
223 if(pet_volume==0) printf("Cpet=(1-Vb)*Ct+Vb*Cb\n");
224 else printf("Cpet=Ct+Vb*Cb\n");
225 }
226 printf("\n");
227 }
228
229 /* Check that output file is not the same as the input file */
230 if(strcasecmp(infile, outfile)==0) {
231 fprintf(stderr, "Error: original file must not be overwritten.\n");
232 return(1);
233 }
234
235
236 /*
237 * Read PET image and blood TAC
238 */
239 if(verbose>1) printf("reading data files\n");
240 endtime=-1.0;
242 infile, NULL, blfile, NULL, NULL, &endtime, &ai, &img,
243 NULL, &blood, 0, stdout, verbose-1, tmp);
244 if(ret!=0) {
245 fprintf(stderr, "Error in reading data: %s.\n", tmp);
246 if(verbose>1) printf(" ret := %d\n", ret);
247 return(2);
248 }
249 if(verbose>2) printf("endtime := %g min\n", endtime);
250 /* Convert blood sample times to min */
251 dftTimeunitConversion(&blood, TUNIT_MIN);
252 if(verbose>3) dftPrint(&blood);
253
254
255 /*
256 * If Vb values are given in an image file, then read that
257 */
258 if(vbfile[0]) {
259 if(verbose>1) printf("reading %s\n", vbfile);
260 ret=imgRead(vbfile, &vbimg);
261 if(ret) {
262 fprintf(stderr, "Error: %s\n", vbimg.statmsg);
263 imgEmpty(&img); dftEmpty(&blood); return(8);
264 }
265 /* Check if data is raw or image */
266 if(vbimg.type!=IMG_TYPE_IMAGE) {
267 fprintf(stderr, "Error: %s is not an image.\n", vbfile);
268 imgEmpty(&img); dftEmpty(&blood); imgEmpty(&vbimg); return(8);
269 }
270 if(vbimg.dimt>1) {
271 fprintf(stderr, "Error: Vb image contains > 1 frame.\n");
272 imgEmpty(&img); dftEmpty(&blood); imgEmpty(&vbimg); return(8);
273 }
274 /* check dimensions */
275 ret=0;
276 if(img.dimz!=vbimg.dimz) ret=1;
277 if(img.dimx!=vbimg.dimx) ret+=2;
278 if(img.dimy!=vbimg.dimy) ret+=4;
279 if(ret) {
280 fprintf(stderr, "Error: Vb image has different dimensions.\n");
281 imgEmpty(&img); dftEmpty(&blood); imgEmpty(&vbimg); return(8);
282 }
283 /* check that Vb is a fraction */
284 ret=imgMax(&vbimg, &f);
285 if(verbose>2) printf("Maximum value in Vb image: %g\n", f);
286 if(f>1.0) {
287 ret=imgArithmConst(&vbimg, 0.01, '*', 1.0, verbose-4);
288 fprintf(stderr, "Warning: Vb values were converted to fractions.\n");
289 }
290 }
291
292 /*
293 * Make subtraction
294 */
295 if(verbose>1) printf("subtracting\n");
296 {
297 int fi, zi, xi, yi;
298 for(zi=0; zi<img.dimz; zi++)
299 for(yi=0; yi<img.dimy; yi++)
300 for(xi=0; xi<img.dimx; xi++) {
301 if(vbfile[0]) vb=vbimg.m[zi][yi][xi][0];
302 for(fi=0; fi<img.dimt; fi++) {
303 img.m[zi][yi][xi][fi]-=vb*blood.voi[0].y[fi];
304 if(pet_volume==0) img.m[zi][yi][xi][fi]/=(1.0-vb);
305 if(leave_negat==0 && img.m[zi][yi][xi][fi]<0.0)
306 img.m[zi][yi][xi][fi]=0.0;
307 }
308 }
309 }
310 dftEmpty(&blood); imgEmpty(&vbimg);
311
312
313 /*
314 * Save new image
315 */
316 if(verbose) fprintf(stdout, "writing image %s\n", outfile);
317 ret=imgWrite(outfile, &img);
318 if(ret) {
319 fprintf(stderr, "Error: %s\n", img.statmsg);
320 imgEmpty(&img); dftEmpty(&blood); imgEmpty(&vbimg); return(13);
321 }
322 if(verbose>1) fprintf(stdout, "Vb corrected image %s saved.\n", outfile);
323
324 if(img._fileFormat==IMG_E7 || img._fileFormat==IMG_E7_2D) {
325 imgEmpty(&img);
326 if(verbose>1) printf("copying header information\n");
327 ret=ecat7CopyHeadersNoQuant(infile, outfile, verbose-1);
328 if(verbose>0 && ret!=0)
329 printf("copying headers not successful (%d).\n", ret);
330 }
331
332 imgEmpty(&img);
333 if(verbose>0) printf("done.\n");
334 return(0);
335}
336/*****************************************************************************/
337
338/*****************************************************************************/
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
void dftInit(DFT *data)
Definition dft.c:38
void dftEmpty(DFT *data)
Definition dft.c:20
void dftPrint(DFT *data)
Definition dftio.c:538
int dftTimeunitConversion(DFT *dft, int tunit)
Definition dftunit.c:119
void ehdrEmpty(ECAT_HEADERS *ehdr)
Definition ecat7ift.c:47
int ecat7WriteHeaders(const char *fname, ECAT_HEADERS *ehdr, int verbose)
Definition ecat7ift.c:755
void ehdrInitiate(ECAT_HEADERS *ehdr)
Definition ecat7ift.c:21
int ecat7ReadHeaders(const char *fname, ECAT_HEADERS *ehdr, int verbose)
Definition ecat7ift.c:687
int iftDeleteItem(IFT *ift, int item, int verbose)
Definition ift.c:169
int iftGet(IFT *ift, char *key, int verbose)
Definition iftsrch.c:15
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgArithmConst(IMG *img, float operand, char operation, float ulimit, int verbose)
Definition imgarithm.c:100
int ecat7CopyHeadersNoQuant(const char *file1, const char *file2, int verbose)
Definition imgcbv.c:76
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgWrite(const char *fname, IMG *img)
Definition imgfile.c:136
int imgReadModelingData(char *petfile, char *siffile, char *inputfile1, char *inputfile2, char *inputfile3, double *fitdur, int *fitframeNr, IMG *img, DFT *inp, DFT *iinp, int verifypeak, FILE *loginfo, int verbose, char *status)
Definition imginput.c:24
int imgMax(IMG *img, float *maxvalue)
Definition imgminmax.c:15
Header file for libtpcimgio.
#define IMG_E7
#define IMG_E7_2D
#define IMG_TYPE_IMAGE
Header file for libtpcimgp.
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 libtpcmodext.
Voi * voi
ECAT_MATRIX * m
unsigned short int dimx
char type
float **** m
int _fileFormat
unsigned short int dimt
unsigned short int dimz
unsigned short int dimy
const char * statmsg
double * y