TPCCLIB
Loading...
Searching...
No Matches
imglkup.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//#include <float.h>
18/*****************************************************************************/
19#include "libtpcmisc.h"
20#include "libtpccurveio.h"
21#include "libtpcimgio.h"
22#include "libtpcimgp.h"
23//#include "libtpcmodext.h"
24/*****************************************************************************/
25#define LKUP_HIST_NR 25
26/*****************************************************************************/
27
28/*****************************************************************************/
29static char *info[] = {
30 "Replace the voxel values in PET image or scan file with the values from",
31 "a look-up table.",
32 "PET image file must be in ECAT, NIfTI, or Analyze format.",
33 "The look-up table must contain two columns: program looks from the first",
34 "column a matching value for the voxel value, and replaces the voxel value",
35 "with the value from the second column of the table.",
36 "Look-up table must be sorted in ascending order.",
37 " ",
38 "Usage: @P [Options] petfile lkupfile outputfile",
39 " ",
40 "Options:",
41 " -c[losest]",
42 " If exact match in look-up table is not found, the closest value",
43 " is selected; by default, value is interpolated from the table.",
44 " -dyn[amic]",
45 " By default, dynamic PET data is considered as an error, because",
46 " this program is mostly used in autoradiography method with static or",
47 " or integrated PET data; this option enables usage of dynamic data.",
48 " -his=<Filename>",
49 " Histogram of the results is written in TAC format in specified file.",
50/*
51 " -u=<unit id>",
52 " Set image unit to a specified value: 0=unknown, 1=cnts/sec,",
53 " 2=counts, 3=kBq/mL, 4=sec*kBq/mL, 5=1/sec, 6=1/min, 7=mL/mL,",
54 " 8=mL/dL, 9=mL/(mL*min), 10=mL/(dL*min), 11=unitless, 12=nCi/mL,",
55 " 13=MBq/mL, 14=Bq/cc, 15=uCi/cc, 16=umol/(min*100g), 17=mg/(min*100g)",
56*/
57 " -stdoptions", // List standard options like --help, -v, etc
58 " ",
59 "See also: arlkup, imginteg, taclkup, imgcalc, imgunit, img2dft",
60 " ",
61 "Keywords: image, look-up table, autoradiography, ARG, perfusion, radiowater",
62 0};
63/*****************************************************************************/
64
65/*****************************************************************************/
66/* Turn on the globbing of the command line, since it is disabled by default in
67 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
68 In Unix&Linux wildcard command line processing is enabled by default. */
69/*
70#undef _CRT_glob
71#define _CRT_glob -1
72*/
73int _dowildcard = -1;
74/*****************************************************************************/
75
76/*****************************************************************************/
80int main(int argc, char **argv)
81{
82 int ai, help=0, version=0, verbose=1;
83 int ret=0;
84 char petfile[FILENAME_MAX], lkupfile[FILENAME_MAX], outfile[FILENAME_MAX];
85 char *cptr, hisfile[FILENAME_MAX];
86 int takeClosest=0;
87 int acceptDynamic=0;
88
89
90 /*
91 * Get arguments
92 */
93 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
94 petfile[0]=outfile[0]=lkupfile[0]=hisfile[0]=(char)0;
95 /* Get options */
96 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
97 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
98 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
99 if(strncasecmp(cptr, "CLOSEST", 1)==0) {
100 takeClosest=1; continue;
101 } else if(strncasecmp(cptr, "DYNAMIC", 3)==0) {
102 acceptDynamic=1; continue;
103 } else if(strncasecmp(cptr, "HIS=", 4)==0) {
104 strlcpy(hisfile, cptr+4, FILENAME_MAX); if(strlen(hisfile)>0) continue;
105 }
106 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
107 return(1);
108 } else break;
109
110 /* Print help or version? */
111 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
112 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
113 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
114
115 /* Process other arguments, starting from the first non-option */
116 if(ai<argc) strlcpy(petfile, argv[ai++], FILENAME_MAX);
117 if(ai<argc) strlcpy(lkupfile, argv[ai++], FILENAME_MAX);
118 if(ai<argc) strlcpy(outfile, argv[ai++], FILENAME_MAX);
119 if(ai<argc) {
120 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
121 return(1);
122 }
123 /* Did we get all the information that we need? */
124 if(!outfile[0]) {
125 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
126 return(1);
127 }
128 if(strcasecmp(petfile, outfile)==0) {
129 fprintf(stderr, "Error: same name for input and output file.\n");
130 return(1);
131 }
132
133 /* In verbose mode print arguments and options */
134 if(verbose>1) {
135 printf("petfile := %s\n", petfile);
136 printf("lkupfile := %s\n", lkupfile);
137 printf("outfile := %s\n", outfile);
138 if(hisfile[0]) printf("hisfile := %s\n", hisfile);
139 printf("takeClosest := %d\n", takeClosest);
140 printf("acceptDynamic := %d\n", acceptDynamic);
141 }
142
143
144
145
146 /*
147 * Read the look-up table
148 */
149 if(verbose>0) printf("reading %s\n", lkupfile);
150 DFT table; dftInit(&table);
151 if(dftRead(lkupfile, &table)) {
152 fprintf(stderr, "Error: %s\n", dfterrmsg);
153 return(2);
154 }
155 if(verbose>20) dftPrint(&table);
156 int tableSize=table.frameNr;
157 double *table1=table.x; double *table2=table.voi[0].y;
158 if(table.voiNr>1 || tableSize<2) {
159 fprintf(stderr, "Error: invalid look-up table %s\n", lkupfile);
160 dftEmpty(&table); return(2);
161 }
162 if(verbose>1) {
163 printf("Look-up y: %g - %g\n", table2[0], table2[tableSize-1]);
164 printf("Look-up x: %g - %g\n", table1[0], table1[tableSize-1]);
165 }
166
167
168
169 /*
170 * Read PET file
171 */
172 if(verbose>0) fprintf(stdout, "reading %s\n", petfile);
173 IMG img; imgInit(&img);
174 ret=imgRead(petfile, &img);
175 if(ret) {
176 fprintf(stderr, "Error: %s\n", img.statmsg);
177 if(verbose>1) printf("ret=%d\n", ret);
178 dftEmpty(&table); imgEmpty(&img); return(3);
179 }
180 if(verbose>10) imgInfo(&img);
181 /* Check the frame number */
182 if(acceptDynamic==0 && img.dimt>1) {
183 fprintf(stderr, "Error: file contains more than one frame.\n");
184 dftEmpty(&table); imgEmpty(&img); return(3);
185 }
186
187
188 /*
189 * Prepare histogram data
190 */
191 if(verbose>1) printf("allocating memory for the histogram\n");
192 DFT hist; dftInit(&hist);
193 ret=dftSetmem(&hist, LKUP_HIST_NR, 1);
194 if(ret!=0) {
195 fprintf(stderr, "Error: cannot allocate memory for histogram.\n");
196 dftEmpty(&table); imgEmpty(&img); return(4);
197 }
198 hist.voiNr=1; hist.frameNr=LKUP_HIST_NR;
200 strcpy(hist.voi[0].name, "n");
201 /* Calculate histogram bins and initiate the histogram values */
202 double histogram_bin=(table2[tableSize-1]-table2[0])/(double)LKUP_HIST_NR;
203 if(verbose>2) printf("histogram_bin_size := %g\n", histogram_bin);
204 hist.x1[0]=table2[0]; hist.x2[0]=hist.x1[0]+histogram_bin;
205 for(int i=1; i<hist.frameNr; i++) {
206 hist.x1[i]=hist.x2[i-1];
207 hist.x2[i]=hist.x1[i]+histogram_bin;
208 }
209 for(int i=0; i<hist.frameNr; i++) hist.voi[0].y[i]=0.0;
210
211
212
213
214 /*
215 * Replace voxel values with numbers from the look-up table
216 */
217 if(verbose>0) {fprintf(stdout, "using look-up table\n"); fflush(stdout);}
218 double v;
219 int low, high, mid, n;
220 int zi, yi, xi, ti;
221 for(zi=0; zi<img.dimz; zi++) {
222 for(yi=0; yi<img.dimy; yi++) {
223 for(xi=0; xi<img.dimx; xi++) {
224 for(ti=0; ti<img.dimt; ti++) {
225 v=(double)img.m[zi][yi][xi][ti]; //printf("%g ->\n", v);
226 if(isnan(v)) continue;
227 if(v<table1[0]) { /* check if below table values */
228 v=table2[0];
229 //hist.voi[0].y[0]+=1.0;
230 } else if(v>table1[tableSize-1]) { /* check if over table values */
231 v=table2[tableSize-1];
232 //hist.voi[0].y[hist.frameNr-1]+=1.0;
233 } else { /* binary search */
234 low=mid=0; high=tableSize-1; ret=1;
235 while(low<=high) {
236 mid=(low+high)/2;
237 if(v<table1[mid]) high=mid-1;
238 else if(v>table1[mid]) low=mid+1;
239 else {v=table2[mid]; ret=0; break;}
240 }
241 /* If not found, get the closest/interpolated value */
242 if(ret) {
243 n=high; high=low; low=n;
244 if(takeClosest) {
245 if(v-table1[low]<table1[high]-v) v=table2[low];
246 else v=table2[high];
247 } else {
248 v=table2[low]+
249 (v-table1[low])*(table2[high]-table2[low])
250 /(table1[high]-table1[low]);
251 }
252 }
253 /* Add to histogram data */
254 for(n=0; n<hist.frameNr; n++)
255 if(v>=hist.x1[n] && v<=hist.x2[n]) {
256 hist.voi[0].y[n]+=1.0; break;
257 }
258 }
259 img.m[zi][yi][xi][ti]=(float)v; //printf(" %g\n", v);
260 } // next frame
261 } // next column
262 } // next row
263 } // next plane
264 if(verbose>0 && img.dimz>2) {fprintf(stdout, "\n"); fflush(stdout);}
265
266 /* Copy the unit */
267 img.unit=petCunitId(table.unit);
268
269 /* No need for look-up table anymore */
270 dftEmpty(&table);
271
272
273
274 /*
275 * Write the modified image
276 */
277 if(verbose>1) fprintf(stdout, "writing %s\n", outfile);
278 if(imgWrite(outfile, &img)) {
279 fprintf(stderr, "Error: %s\n", img.statmsg);
280 if(verbose>1) printf("ret=%d\n", ret);
281 imgEmpty(&img);
282 return(11);
283 }
284 if(verbose>0) printf("Written %s\n", outfile);
285 imgEmpty(&img);
286
287
288 /*
289 * Save or print the histogram, if required
290 */
291 if(!hisfile[0] && verbose<=1) {
292 dftEmpty(&hist); return(0);
293 }
294 if(!hisfile[0]) {
295 printf("\nHistogram:\n"); fflush(stdout);
296 dftPrint(&hist);
297 dftEmpty(&hist); return(0);
298 }
299 if(verbose>1) printf("writing %s\n", hisfile);
300 if(dftWrite(&hist, hisfile)) {
301 fprintf(stderr, "Error in writing '%s': %s\n", hisfile, dfterrmsg);
302 dftEmpty(&hist); return(21);
303 }
304 if(verbose>0) fprintf(stdout, "Histogram written in %s\n", hisfile);
305 dftEmpty(&hist);
306
307 return(0);
308}
309/*****************************************************************************/
310
311/*****************************************************************************/
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 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
void imgInfo(IMG *image)
Definition img.c:359
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgWrite(const char *fname, IMG *img)
Definition imgfile.c:136
Header file for libtpccurveio.
#define DFT_FORMAT_PMOD
#define DFT_TIME_STARTEND
Header file for libtpcimgio.
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
int petCunitId(const char *unit)
Definition petunits.c:74
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
int _type
int timetype
Voi * voi
double * x1
int voiNr
double * x2
int frameNr
double * x
char unit[MAX_UNITS_LEN+1]
unsigned short int dimx
float **** m
char unit
unsigned short int dimt
unsigned short int dimz
unsigned short int dimy
const char * statmsg
double * y
char name[MAX_REGIONNAME_LEN+1]