TPCCLIB
Loading...
Searching...
No Matches
imghist.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 <math.h>
13#include <string.h>
14#include <unistd.h>
15#include <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpccurveio.h"
19#include "libtpcimgio.h"
20#include "libtpcimgp.h"
21#include "libtpcsvg.h"
22#include "libtpcmodext.h"
23/*****************************************************************************/
24
25/*****************************************************************************/
26static char *info[] = {
27 "Make histogram of the voxel values in PET image.",
28 "PET image file must be in ECAT, NIfTI, or Analyze format.",
29 "Resulting histogram file contains the bin as the two first columns,",
30 "and the proportion (0-1) of values in the bin in the next column.",
31 "In case of dynamic PET data a separate histogram is made from each frame",
32 "and saved as its own column in the histogram file.",
33 " ",
34 "Usage: @P [Options] petfile [histogram]",
35 " ",
36 "Options:",
37 " -bin=<Binsize as absolute value> or -per=<Binsize as percentage>",
38 " Set the bin size using these options; by default, bin size is 10%",
39 " of maximum-minimum voxel value in the whole image.",
40 " -nr",
41 " Nr of voxels in each bin is written in histogram file; proportion",
42 " of them is written by default.",
43 " -pos[itive]",
44 " Include only voxels with value > 0.",
45 " -svg=<filename>",
46 " Histogram is plotted in specified SVG file.",
47 " -stdoptions", // List standard options like --help, -v, etc
48 " ",
49 "See also: imginteg, imgmax, imgposv, imglkup, hist4dat, imgqntls, imgthrs",
50 " ",
51 "Keywords: image, histogram, threshold",
52 0};
53/*****************************************************************************/
54
55/*****************************************************************************/
56/* Turn on the globbing of the command line, since it is disabled by default in
57 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
58 In Unix&Linux wildcard command line processing is enabled by default. */
59/*
60#undef _CRT_glob
61#define _CRT_glob -1
62*/
63int _dowildcard = -1;
64/*****************************************************************************/
65
66/*****************************************************************************/
70int main(int argc, char **argv)
71{
72 int ai, help=0, version=0, verbose=1;
73 char petfile[FILENAME_MAX], svgfile[FILENAME_MAX], hisfile[FILENAME_MAX];
74 char *cptr;
75 int ret=0;
76 int report_proportions=1;
77 int positives=0;
78 double bin_size=-1.0, bin_perc=-1.0;
79
80
81 /*
82 * Get arguments
83 */
84 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
85 petfile[0]=hisfile[0]=svgfile[0]=(char)0;
86 /* Get options */
87 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
88 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
89 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
90 if(strncasecmp(cptr, "SVG=", 4)==0) {
91 if(strlcpy(svgfile, cptr+4, FILENAME_MAX)>1) continue;
92 } else if(strncasecmp(cptr, "BIN=", 4)==0) {
93 ret=atof_with_check(cptr+4, &bin_size);
94 if(ret==0 && bin_size>0.0) continue;
95 } else if(strncasecmp(cptr, "PER=", 4)==0) {
96 ret=atof_with_check(cptr+4, &bin_perc);
97 if(ret==0 && bin_perc>0.0) continue;
98 } else if(strcasecmp(cptr, "NR")==0) {
99 report_proportions=0; continue;
100 } else if(strncasecmp(cptr, "POSITIVES", 3)==0) {
101 positives=1; continue;
102 }
103 fprintf(stderr, "Error: invalid 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 if(ai<argc) strlcpy(petfile, argv[ai++], FILENAME_MAX);
114 if(ai<argc) strlcpy(hisfile, argv[ai++], FILENAME_MAX);
115 if(ai<argc) {
116 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
117 return(1);
118 }
119 /* Did we get all the information that we need? */
120 if(!petfile[0]) {
121 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
122 return(1);
123 }
124 if(bin_size>0.0 && bin_perc>0.0) {
125 fprintf(stderr, "Error: options -bin and -per cannot be used together.\n");
126 return(1);
127 }
128 if(bin_size<=0.0 && bin_perc<=0.0) bin_perc=10.0;
129
130 /* In verbose mode print arguments and options */
131 if(verbose>1) {
132 printf("petfile := %s\n", petfile);
133 if(hisfile[0]) printf("hisfile := %s\n", hisfile);
134 if(svgfile[0]) printf("svgfile := %s\n", svgfile);
135 if(bin_size>0.0) printf("bin_size := %g\n", bin_size);
136 if(bin_perc>0.0) printf("bin_percentage := %g\n", bin_perc);
137 printf("positives_only := %d\n", positives);
138 }
139
140
141
142 /*
143 * Read PET data
144 */
145 if(verbose>0) fprintf(stdout, "reading %s\n", petfile);
146 IMG img; imgInit(&img);
147 ret=imgRead(petfile, &img);
148 if(ret) {
149 fprintf(stderr, "Error: %s\n", img.statmsg);
150 if(verbose>1) printf("ret=%d\n", ret);
151 imgEmpty(&img); return(2);
152 }
153 if(verbose>1) {
154 printf("image_size := %d x %d x %d\n", img.dimx, img.dimy, img.dimz);
155 if(img.dimt>1) printf("frame_nr := %d\n", img.dimt);
156 }
157 if(imgNaNs(&img, 1)>0)
158 if(verbose>0) fprintf(stderr, "Warning: missing pixel values.\n");
159
160 /* Find the minimum and maximum voxel value in the whole PET data */
161 float maxv, minv;
162 imgMinMax(&img, &minv, &maxv);
163 if(verbose>1) printf("min := %g\nmax := %g\n", minv, maxv);
164 /* Refine the minimum */
165 if(positives) {
166 if(minv<0.0) minv=0.0;
167 } else {
168 /* If minimum is just a little over zero, then set it to zero */
169 if(minv>0.0 && minv<0.05*maxv)
170 minv=0.0;
171 }
172 if(verbose>1) printf("refined_min := %g\n", minv);
173 /* Calculate the value range */
174 double rangev=(double)maxv-(double)minv;
175 if(verbose>2) printf("max-min := %g\n", rangev);
176
177 /* Set bin size based on bin percentage, if necessary */
178 if(bin_size<=0.0) {
179 bin_size=0.01*bin_perc*rangev;
180 if(verbose>1) printf("bin_size := %g\n", bin_size);
181 }
182 if(bin_size<1.0E-020) {
183 fprintf(stderr, "Error: invalid bin size.\n");
184 imgEmpty(&img); return(2);
185 }
186
187 /* How many bins we may need? */
188 int bin_nr=(int)ceil(rangev/bin_size);
189 if(verbose>1) printf("estimated_bin_nr := %d\n", bin_nr);
190 if(bin_nr<2) {
191 fprintf(stderr, "Error: invalid number of bins.\n");
192 imgEmpty(&img); return(2);
193 } else if(bin_nr>10000) {
194 fprintf(stderr, "Error: too many bins.\n");
195 imgEmpty(&img); return(2);
196 }
197
198 /* Allocate memory for histogram data */
199 DFT hist; dftInit(&hist);
200 ret=dftSetmem(&hist, bin_nr+1, img.dimt);
201 if(ret!=0) {
202 fprintf(stderr, "Error: cannot allocate memory for the histogram.\n");
203 imgEmpty(&img); return(3);
204 }
205 hist.frameNr=bin_nr+1;
206 hist.voiNr=img.dimt;
209 /* Set bins as TAC frame times */
210 /* Bins should be in calculated from zero, even if bins closest to zero
211 are not actually used */
212 {
213 int n=0;
214 double x=0.0;
215 if(minv<0.0) {while(x>minv) x-=bin_size;}
216 else if(minv>0.0) {while(x+bin_size<minv) x+=bin_size;}
217 //printf("n=%d x=%g\n", n, x);
218 hist.x1[n]=x; hist.x2[n]=hist.x1[n]+bin_size;
219 n++; x+=bin_size;
220 while(x<=maxv && n<hist.frameNr) {
221 //printf("n=%d x=%g\n", n, x);
222 hist.x1[n]=x; hist.x2[n]=hist.x1[n]+bin_size;
223 x+=bin_size;
224 n++;
225 }
226 hist.frameNr=n;
227 }
228 for(int i=0; i<hist.frameNr; i++) hist.x[i]=0.5*(hist.x1[i]+hist.x2[i]);
229
230 /* Set TAC column name(s) */
231 if(hist.voiNr==1) {
232 strcpy(hist.voi[0].name, "static");
233 } else {
234 for(int i=0; i<hist.voiNr; i++) sprintf(hist.voi[i].name, "fr%d", 1+i);
235 }
236
237
238 /*
239 * Go through the PET data and bin voxel values
240 */
241 if(verbose>1) printf("computing histogram...\n");
242 long long voxNr=0;
243 int zi, yi, xi, ti, bi;
244 for(zi=0; zi<img.dimz; zi++)
245 for(yi=0; yi<img.dimy; yi++)
246 for(xi=0; xi<img.dimx; xi++)
247 for(ti=0; ti<img.dimt; ti++) {
248 if(positives && img.m[zi][yi][xi][ti]<1.0E-010) continue;
249 voxNr++;
250 for(bi=bin_nr-1; bi>0; bi--) {
251 if(img.m[zi][yi][xi][ti]>hist.x1[bi]) {
252 hist.voi[ti].y[bi]+=1.0; break;
253 }
254 }
255 if(bi==0) hist.voi[ti].y[0]+=1.0;
256 }
257 if(verbose>1) printf("included_pixel_nr := %lld\n", voxNr);
258 if(voxNr<1) {
259 fprintf(stderr, "Error: no positive voxel values.\n");
260 imgEmpty(&img); dftEmpty(&hist);
261 return(4);
262 }
263 /* Calculate proportion of pixels in each bin, if requested */
264 if(report_proportions) {
265 double c=1.0/(double)voxNr;
266 for(ti=0; ti<hist.voiNr; ti++)
267 for(bi=0; bi<hist.frameNr; bi++)
268 hist.voi[ti].y[bi]*=c;
269 }
270
271 /* PET data is needed no more */
272 imgEmpty(&img);
273
274
275 /*
276 * Save or print the histogram, if required
277 */
278 if(!hisfile[0] && !svgfile[0]) {
279 printf("\nHistogram:\n"); fflush(stdout);
280 dftPrint(&hist);
281 dftEmpty(&hist); return(0);
282 }
283 if(hisfile[0]) {
284 if(verbose>1) printf("writing %s\n", hisfile);
285 if(dftWrite(&hist, hisfile)) {
286 fprintf(stderr, "Error in writing '%s': %s\n", hisfile, dfterrmsg);
287 dftEmpty(&hist); return(11);
288 }
289 if(verbose>0) printf("Histogram written in %s\n", hisfile);
290 }
291
292 /*
293 * Saving and/or plotting of fitted TACs
294 */
295 if(svgfile[0]) {
296 if(verbose>1) printf("saving SVG plot\n");
297
298 /* Create a second TAC struct for plotting lines */
299 DFT hist2; dftInit(&hist2); ret=dftdup(&hist, &hist2);
300 if(ret) {
301 fprintf(stderr, "Error: cannot plot histogram.\n");
302 dftEmpty(&hist); dftEmpty(&hist2);
303 return(21);
304 }
305
306 /* Save SVG plot */
307 ret=plot_fit_svg(&hist, &hist2, "", svgfile, verbose-8);
308 if(ret) {
309 fprintf(stderr, "Error: cannot plot the histogram.\n");
310 dftEmpty(&hist); dftEmpty(&hist2);
311 return(22);
312 }
313 if(verbose>0) printf("Histogram plotted in %s\n", svgfile);
314
315 dftEmpty(&hist2);
316 }
317
318 dftEmpty(&hist);
319
320 return(0);
321}
322/*****************************************************************************/
323
324/*****************************************************************************/
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
void dftInit(DFT *data)
Definition dft.c:38
int dftdup(DFT *dft1, DFT *dft2)
Definition dft.c:655
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
void dftPrint(DFT *data)
Definition dftio.c:538
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
unsigned long long imgNaNs(IMG *img, int fix)
Definition img.c:658
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 imgMinMax(IMG *img, float *minvalue, float *maxvalue)
Definition imgminmax.c:154
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
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.
int plot_fit_svg(DFT *dft1, DFT *dft2, char *main_title, char *fname, int verbose)
Definition plotfit.c:216
Header file for libtpcsvg.
int _type
int timetype
Voi * voi
double * x1
int voiNr
double * x2
int frameNr
double * x
unsigned short int dimx
float **** m
unsigned short int dimt
unsigned short int dimz
unsigned short int dimy
const char * statmsg
double * y
char name[MAX_REGIONNAME_LEN+1]