TPCCLIB
Loading...
Searching...
No Matches
imgssegm.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 <time.h>
15/*****************************************************************************/
16#include "libtpcmisc.h"
17#include "libtpcmodel.h"
18#include "libtpccurveio.h"
19#include "libtpcimgio.h"
20#include "libtpcimgp.h"
21#include "libtpcmodext.h"
22/*****************************************************************************/
23//unsigned _stklen = 16777216; /* need a 16MB stack (not necessary on UNIX) */
24/*****************************************************************************/
25
26/*****************************************************************************/
27static char *info[] = {
28 "Testing image segmentation for static PET image.",
29 "This program can be used for method testing purposes only!",
30 " ",
31 "Segmented image will contain the segment numbers as integers 0, 1, 2, 3, ...",
32 " ",
33 "Usage: @P [Options] image segmimage",
34 " ",
35 "Options:",
36 " -stdoptions", // List standard options like --help, -v, etc
37 " ",
38 "See also: imginteg, imgaumc, imgthrs, imgfsegm",
39 " ",
40 "Keywords: image, smoothing, mask, threshold",
41 0};
42/*****************************************************************************/
43
44/*****************************************************************************/
45/* Turn on the globbing of the command line, since it is disabled by default in
46 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
47 In Unix&Linux wildcard command line processing is enabled by default. */
48/*
49#undef _CRT_glob
50#define _CRT_glob -1
51*/
52int _dowildcard = -1;
53/*****************************************************************************/
54
55/*****************************************************************************/
57void psegListNr(
58 unsigned int *list,
59 unsigned int n
60) {
61 if(n<1) {printf("(empty)\n"); return;}
62 if(n==1) {printf("%u\t1\n", list[0]); return;}
63
64 unsigned int *sg=malloc(2*n*sizeof(unsigned int)); if(sg==NULL) return;
65 unsigned int *sn=sg+n;
66 sg[0]=list[0]; sn[0]=1;
67 unsigned int s=1;
68 for(unsigned int i=1; i<n; i++) {
69 unsigned int j;
70 /* check if this segment number is listed already */
71 for(j=0; j<s; j++)
72 if(list[i]==sg[j]) { // yes
73 sn[j]++; break;
74 }
75 if(j==s) { // no
76 sg[s]=list[i]; sn[s]=1; s++;
77 }
78 }
79 for(unsigned int j=0; j<s; j++)
80 printf("%u\t%u\n", sg[j], sn[j]);
81 free(sg);
82}
83/*****************************************************************************/
85void psegListContinuous(
86 unsigned int *list,
87 unsigned int n
88) {
89 if(n<1) {printf("(empty)\n"); return;}
90 if(n==1) {list[0]=0; return;}
91
92 unsigned int *sg=malloc(2*n*sizeof(unsigned int)); if(sg==NULL) return;
93 unsigned int *sn=sg+n;
94 sg[0]=list[0]; sn[0]=1;
95 unsigned int s=1;
96 for(unsigned int i=1; i<n; i++) {
97 unsigned int j;
98 /* check if this segment number is listed already */
99 for(j=0; j<s; j++)
100 if(list[i]==sg[j]) { // yes
101 sn[j]++; break;
102 }
103 if(j==s) { // no
104 sg[s]=list[i]; sn[s]=1; s++;
105 }
106 }
107 //printf("Nr of segments: %u\n", s);
108
109 //printf("Unsorted list:\n");
110 //for(unsigned int j=0; j<s; j++) printf("%u\t%u\n", sg[j], sn[j]);
111 // Sort by pixel number
112 for(unsigned int j=0; j<s; j++)
113 for(unsigned int k=j+1; k<s; k++) if(sn[k]>sn[j]) {
114 unsigned int t=sg[j]; sg[j]=sg[k]; sg[k]=t;
115 t=sn[j]; sn[j]=sn[k]; sn[k]=t;
116 }
117 //printf("Sorted list:\n");
118 //for(unsigned int j=0; j<s; j++) printf("%u\t%u\n", sg[j], sn[j]);
119
120 /* Reset tag numbers */
121 for(unsigned int i=0; i<n; i++)
122 for(unsigned int j=0; j<s; j++) if(sg[j]==list[i]) {list[i]=j; break;}
123
124 free(sg);
125}
126/*****************************************************************************/
128void psegListImg(
129 unsigned int *list,
130 unsigned int n,
131 IMG *img
132) {
133 if(img==NULL || n<1) {printf("(empty)\n"); return;}
134 if((unsigned int )img->dimz*img->dimy*img->dimx!=n) {printf("(error)\n"); return;}
135 //if(n==1) {printf("%u\t1\n", list[0]); return;}
136
137 unsigned int *sg=malloc(2*n*sizeof(unsigned int)); if(sg==NULL) {printf("(error)\n"); return;}
138 unsigned int *sn=sg+n;
139
140 sg[0]=list[0]; sn[0]=1;
141 unsigned int s=1;
142 for(unsigned int i=1; i<n; i++) {
143 unsigned int j;
144 /* check if this segment number is listed already */
145 for(j=0; j<s; j++)
146 if(list[i]==sg[j]) { // yes
147 //pmean[j]+=img->pixel[i];
148 sn[j]++; break;
149 }
150 if(j==s) { // no
151 //pmean[s]+=img->pixel[i];
152 sg[s]=list[i]; sn[s]=1; s++;
153 }
154 }
155 printf("Nr of segments: %u\n", s);
156
157 /* Calculate mean and SD for each segment */
158 double *pmean=malloc(2*s*sizeof(double)); if(pmean==NULL) {printf("(error)\n"); free(sg); return;}
159 double *psd=pmean+s;
160 for(unsigned int j=0; j<s; j++) {
161 pmean[j]=psd[j]=0.0;
162 unsigned int pi=0;
163 double *p=malloc(sn[j]*sizeof(double));
164 if(p==NULL) {printf("(error)\n"); free(sg); free(pmean); return;}
165 for(unsigned int i=1; i<n && pi<sn[j]; i++) if(list[i]==sg[j]) p[pi++]=img->pixel[i];
166 pmean[j]=dmean(p, pi, psd+j);
167 free(p);
168 }
169
170 for(unsigned int j=0; j<s; j++)
171 printf("%u\t%u\t%g\t%g\n", sg[j], sn[j], pmean[j], psd[j]);
172
173 free(sg); free(pmean);
174}
175/*****************************************************************************/
177void psegListCombineEqual(
178 unsigned int *list,
179 unsigned int n,
180 IMG *img
181) {
182 if(img==NULL || n<1) {printf("(empty)\n"); return;}
183 if((unsigned int )img->dimz*img->dimy*img->dimx!=n) {printf("(error)\n"); return;}
184 //if(n==1) {printf("%u\t1\n", list[0]); return;}
185
186 unsigned int *sg=malloc(2*n*sizeof(unsigned int)); if(sg==NULL) {printf("(error)\n"); return;}
187 unsigned int *sn=sg+n;
188
189 sg[0]=list[0]; sn[0]=1;
190 unsigned int s=1;
191 for(unsigned int i=1; i<n; i++) {
192 unsigned int j;
193 /* check if this segment number is listed already */
194 for(j=0; j<s; j++)
195 if(list[i]==sg[j]) { // yes
196 //pmean[j]+=img->pixel[i];
197 sn[j]++; break;
198 }
199 if(j==s) { // no
200 //pmean[s]+=img->pixel[i];
201 sg[s]=list[i]; sn[s]=1; s++;
202 }
203 }
204 //printf("Nr of segments: %u\n", s);
205
206 /* Calculate mean and SD for each segment */
207 double *pmean=malloc(2*s*sizeof(double)); if(pmean==NULL) {printf("(error)\n"); free(sg); return;}
208 double *psd=pmean+s;
209 for(unsigned int j=0; j<s; j++) {
210 pmean[j]=psd[j]=0.0;
211 unsigned int pi=0;
212 double *p=malloc(sn[j]*sizeof(double));
213 if(p==NULL) {printf("(error)\n"); free(sg); free(pmean); return;}
214 for(unsigned int i=1; i<n && pi<sn[j]; i++) if(list[i]==sg[j]) p[pi++]=img->pixel[i];
215 pmean[j]=dmean(p, pi, psd+j);
216 free(p);
217 }
218
219 for(unsigned int j=0; j<s; j++) {
220 if(sn[j]==0) continue;
221 if(fabs(psd[j])>1.0E-08) continue;
222 for(unsigned int k=j+1; k<s; k++) {
223 if(sn[k]==0) continue;
224 if(fabs(psd[k])>1.0E-08) continue;
225 if(fabs(pmean[j]-pmean[k])>1.0E-08) continue;
226 printf("combining\n");
227 printf(" %u\t%u\t%g\t%g\n", sg[j], sn[j], pmean[j], psd[j]);
228 printf(" %u\t%u\t%g\t%g\n", sg[k], sn[k], pmean[k], psd[k]);
229 sn[k]=0;
230 for(unsigned int i=0; i<n; i++) if(list[i]==sg[k]) list[i]=sg[j];
231 }
232 }
233
234 free(sg); free(pmean);
235}
236/*****************************************************************************/
241double psegListCombineMostSimilar(
242 unsigned int *list,
243 unsigned int n,
244 IMG *img
245) {
246 if(img==NULL || n<1) {printf("(empty)\n"); return(nan(""));}
247 if((unsigned int )img->dimz*img->dimy*img->dimx!=n) {printf("(error)\n"); return(nan(""));}
248 //if(n==1) {printf("%u\t1\n", list[0]); return;}
249
250 unsigned int *sg=malloc(2*n*sizeof(unsigned int)); if(sg==NULL) {printf("(error)\n"); return(nan(""));}
251 unsigned int *sn=sg+n;
252
253 sg[0]=list[0]; sn[0]=1;
254 unsigned int s=1;
255 for(unsigned int i=1; i<n; i++) {
256 unsigned int j;
257 /* check if this segment number is listed already */
258 for(j=0; j<s; j++)
259 if(list[i]==sg[j]) { // yes
260 //pmean[j]+=img->pixel[i];
261 sn[j]++; break;
262 }
263 if(j==s) { // no
264 //pmean[s]+=img->pixel[i];
265 sg[s]=list[i]; sn[s]=1; s++;
266 }
267 }
268 //printf("Nr of segments: %u\n", s);
269
270 /* Calculate mean and SD for each segment */
271 double *pmean=malloc(2*s*sizeof(double)); if(pmean==NULL) {printf("(error)\n"); free(sg); return(nan(""));}
272 double *psd=pmean+s;
273 for(unsigned int j=0; j<s; j++) {
274 pmean[j]=psd[j]=0.0;
275 unsigned int pi=0;
276 double *p=malloc(sn[j]*sizeof(double));
277 if(p==NULL) {printf("(error)\n"); free(sg); free(pmean); return(nan(""));}
278 for(unsigned int i=1; i<n && pi<sn[j]; i++) if(list[i]==sg[j]) p[pi++]=img->pixel[i];
279 pmean[j]=dmean(p, pi, psd+j);
280 free(p);
281 }
282
283 double min_t=1.0E+10;
284 unsigned int min_j=s+1, min_k=s+1;
285 for(unsigned int j=0; j<s; j++) {
286 if(sn[j]==0) continue;
287 for(unsigned int k=j+1; k<s; k++) {
288 if(sn[k]==0) continue;
289 if(fabs(psd[k])<1.0E-08 && fabs(psd[j])<1.0E-08) continue;
290 // t = | mean1 - mean2 | / sqrt( (sd1^2)/n1 + (sd2^2)/n2 )
291 double t=fabs(pmean[j]-pmean[k])/sqrt(psd[j]*psd[j]/(double)sn[j] + psd[k]*psd[k]/(double)sn[k]);
292 if(t<min_t) {
293 min_t=t;
294 min_j=j; min_k=k;
295 }
296 }
297 }
298 if(min_j>s || min_k>s) {
299 printf("nothing to combine.\n");
300 free(sg); free(pmean);
301 return(nan(""));
302 }
303 if(min_t>5.0 /*0.2*/) {
304 printf("smallest t=%g is too large, nothing to combine.\n", min_t);
305 free(sg); free(pmean);
306 return(nan(""));
307 }
308
309 printf("combining, t=%g\n", min_t);
310 printf(" %u\t%u\t%g\t%g\n", sg[min_j], sn[min_j], pmean[min_j], psd[min_j]);
311 printf(" %u\t%u\t%g\t%g\n", sg[min_k], sn[min_k], pmean[min_k], psd[min_k]);
312 sn[min_k]=0;
313 for(unsigned int i=0; i<n; i++) if(list[i]==sg[min_k]) list[i]=sg[min_j];
314
315 free(sg); free(pmean);
316 return(min_t);
317}
318/*****************************************************************************/
323int psegListPxlMove(
324 unsigned int *list,
325 unsigned int n,
326 IMG *img
327) {
328 if(img==NULL || n<1) {printf("(empty)\n"); return(2);}
329 if((unsigned int )img->dimz*img->dimy*img->dimx!=n) {printf("(error)\n"); return(2);}
330
331 unsigned int *sg=malloc(2*n*sizeof(unsigned int)); if(sg==NULL) {printf("(error)\n"); return(2);}
332 unsigned int *sn=sg+n;
333
334 sg[0]=list[0]; sn[0]=1;
335 unsigned int s=1;
336 for(unsigned int i=1; i<n; i++) {
337 unsigned int j;
338 /* check if this segment number is listed already */
339 for(j=0; j<s; j++)
340 if(list[i]==sg[j]) { // yes
341 //pmean[j]+=img->pixel[i];
342 sn[j]++; break;
343 }
344 if(j==s) { // no
345 //pmean[s]+=img->pixel[i];
346 sg[s]=list[i]; sn[s]=1; s++;
347 }
348 }
349 //printf("Nr of segments: %u\n", s);
350
351 /* Calculate mean and SD for each segment */
352 double *pmean=malloc(2*s*sizeof(double)); if(pmean==NULL) {printf("(error)\n"); free(sg); return(3);}
353 double *psd=pmean+s;
354 for(unsigned int j=0; j<s; j++) {
355 pmean[j]=psd[j]=0.0;
356 unsigned int pi=0;
357 double *p=malloc(sn[j]*sizeof(double));
358 if(p==NULL) {printf("(error)\n"); free(sg); free(pmean); return(4);}
359 for(unsigned int i=1; i<n && pi<sn[j]; i++) if(list[i]==sg[j]) p[pi++]=img->pixel[i];
360 pmean[j]=dmean(p, pi, psd+j);
361 free(p);
362 }
363
364 /* Find the worst pixel in each segment and check if would fit better into another segment */
365 unsigned int moved=0;
366 for(unsigned int j=0; j<s; j++) {
367 if(fabs(psd[j])<1.0E-08) continue; // all pixels in this segment fit well already
368 double max_dif=0.0, pxlv=nan("");
369 unsigned int max_i=n+1;
370 for(unsigned int i=0; i<n; i++) if(list[i]==sg[j]) {
371 double d=fabs(pmean[j]-img->pixel[i]);
372 if(d>max_dif) {max_dif=d; max_i=i; pxlv=img->pixel[i];}
373 }
374 if(max_i>n || max_dif<1.0E-06) continue;
375 printf(" group %u largest dif is %g\n", sg[j], max_dif);
376 /* Is the mean of another group closer? */
377 unsigned int better_k=s+1;
378 double min_d=max_dif;
379 for(unsigned int k=0; k<s; k++) if(k!=j) {
380 double d=fabs(pmean[k]-pxlv);
381 if(d<min_d) {min_d=d; better_k=k;}
382 }
383 if(better_k>s) continue;
384 printf(" group %u would be better match with dif %g\n", sg[better_k], min_d);
385 printf(" pixel value is %g; means of own and better groups are %g and %g\n", pxlv, pmean[j], pmean[better_k]);
386 list[max_i]=sg[better_k];
387 moved++;
388 }
389
390 free(sg); free(pmean);
391 if(moved==0) return(1);
392 return(0);
393}
394/*****************************************************************************/
398int imgSegmentStaticTest(
400 IMG *img,
403 IMG *out,
405 int verbose
406) {
407 if(verbose>0) {printf("%s(IMG, IMG, ...)\n", __func__); fflush(stdout);}
408 if(img==NULL || img->status<IMG_STATUS_OCCUPIED || out==NULL) return(1);
409
410 /* Number of pixels */
411 unsigned int pxlNr=img->dimz*img->dimy*img->dimx;
412 if(verbose>1) printf("pxlNr := %u\n", pxlNr);
413 if(pxlNr<54) {
414 if(verbose>0) fprintf(stderr, "Error: too few pixels.\n");
415 return(2);
416 }
417
418 /* Number of blocks in each dimension */
419 unsigned int bdx=1+(img->dimx-1)/3;
420 unsigned int bdy=1+(img->dimy-1)/3;
421 unsigned int bdz=1+(img->dimz-1)/3;
422 if(verbose>2) printf("block dimensions x y z := %u %u %u\n", bdx, bdy, bdz);
423
424
425 /*
426 * Allocate memory for segmented image
427 */
428 imgEmpty(out);
429 if(imgAllocateWithHeader(out, img->dimz, img->dimy, img->dimx, 1, img)) {
430 if(verbose>0) fprintf(stderr, "Error: cannot allocate memory for segmented image.\n");
431 return(3);
432 }
433
434
435 /*
436 * Allocate a list of segment numbers for each pixel
437 */
438 unsigned int *pseg=malloc(sizeof(unsigned int)*pxlNr);
439 if(pseg==NULL) {
440 fprintf(stderr, "Error: cannot allocate memory.\n");
441 imgEmpty(out); return(4);
442 }
443 /* Initiate segmentation by defining each (preferably) 3x3x3 volume as one segment */
444 unsigned int s=0, si=0;
445 for(int zi=0; zi<img->dimz; zi++)
446 for(int yi=0; yi<img->dimy; yi++)
447 for(int xi=0; xi<img->dimx; xi++) {
448 s=(zi/3)*bdx*bdy + (yi/3)*bdx + (xi/3);
449 pseg[si]=s;
450 si++;
451 }
452 //if(verbose>4) psegListNr(pseg, si);
453
454 if(verbose>2) psegListImg(pseg, si, img);
455
456 psegListCombineEqual(pseg, si, img);
457 if(verbose>2) psegListImg(pseg, si, img);
458
459 double t=0.0;
460 do {
461 if(verbose>2) printf("combining most similar\n");
462 t=psegListCombineMostSimilar(pseg, si, img);
463 } while(!isnan(t));
464 if(verbose>2) psegListImg(pseg, si, img);
465
466 do {
467 if(verbose>2) printf("move pixels between segments\n");
468 } while(psegListPxlMove(pseg, si, img)==0);
469 if(verbose>2) psegListImg(pseg, si, img);
470
471 psegListCombineEqual(pseg, si, img);
472 if(verbose>2) psegListImg(pseg, si, img);
473
474 do {
475 if(verbose>2) printf("combining most similar\n");
476 t=psegListCombineMostSimilar(pseg, si, img);
477 } while(!isnan(t));
478 if(verbose>2) psegListImg(pseg, si, img);
479
480 /* Make segment number contiguous */
481 psegListContinuous(pseg, si);
482
483 if(verbose>2) psegListImg(pseg, si, img);
484
485 /* Write segments into output image */
486 si=0;
487 for(int zi=0; zi<out->dimz; zi++)
488 for(int yi=0; yi<out->dimy; yi++)
489 for(int xi=0; xi<out->dimx; xi++) {
490 out->m[zi][yi][xi][0]=(float)pseg[si];
491 si++;
492 }
493 free(pseg);
494
495
496
497
498
499 return(0);
500}
501/*****************************************************************************/
502
503/*****************************************************************************/
507int main(int argc, char **argv)
508{
509 int ai, help=0, version=0, verbose=1;
510 char petfile[FILENAME_MAX], segfile[FILENAME_MAX];
511 int ret;
512
513
514 /*
515 * Get arguments
516 */
517 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
518 petfile[0]=segfile[0]=(char)0;
519 /* Get options */
520 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
521 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
522 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
523 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
524 return(1);
525 } else break;
526
527 /* Print help or version? */
528 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
529 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
530 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
531
532 /* Process other arguments, starting from the first non-option */
533 if(ai<argc) {strlcpy(petfile, argv[ai++], FILENAME_MAX);}
534 if(ai<argc) {strlcpy(segfile, argv[ai++], FILENAME_MAX);}
535 if(ai<argc) {
536 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
537 return(1);
538 }
539
540 /* Did we get all the information that we need? */
541 if(!segfile[0]) {
542 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
543 return(1);
544 }
545 /* Check that output files do not have the same name as input */
546 if(strcasecmp(petfile, segfile)==0) {
547 fprintf(stderr, "Error: same file name for input and output data.\n");
548 return(1);
549 }
550
551
552 /* In verbose mode print arguments and options */
553 if(verbose>1) {
554 printf("petfile := %s\n", petfile);
555 printf("segfile := %s\n", segfile);
556 }
557 if(verbose>9) IMG_TEST=verbose-9; else IMG_TEST=0;
558
559
560 /*
561 * Read image
562 */
563 if(verbose>0) fprintf(stdout, "reading image %s\n", petfile);
564 IMG img; imgInit(&img);
565 ret=imgRead(petfile, &img);
566 if(ret) {
567 fprintf(stderr, "Error: %s\n", img.statmsg); if(verbose>1) imgInfo(&img);
568 return(2);
569 }
570 if(verbose>1) {
571 printf("image dimensions: %d %d %d\n", img.dimz, img.dimy, img.dimx);
572 printf("image frame nr: %d\n", img.dimt);
573 }
574 /* Check that only one frame */
575 if(img.dimt>1) {
576 fprintf(stderr, "Error: image must be static (one frame).\n");
577 imgEmpty(&img); return(2);
578 }
579 if(imgNaNs(&img, 1)>0)
580 if(verbose>0) fprintf(stderr, "Warning: missing pixel values.\n");
581
582
583 /*
584 * Segmentation
585 */
586 if(verbose>0) fprintf(stdout, "segmenting image %s\n", petfile);
587 IMG seg; imgInit(&seg);
588 ret=imgSegmentStaticTest(&img, &seg, verbose-2);
589 if(ret) {
590 fprintf(stderr, "Error: segmentation not successful.\n");
591 imgEmpty(&img); imgEmpty(&seg); return(3);
592 }
593
594
595 /*
596 * Write the segmented image
597 */
598 if(verbose>1) printf("writing segmented image %s\n", segfile);
599 if(imgWrite(segfile, &seg)) {
600 fprintf(stderr, "Error: %s\n", seg.statmsg);
601 imgEmpty(&img); imgEmpty(&seg);
602 return(11);
603 }
604
605 imgEmpty(&img); imgEmpty(&seg);
606 if(verbose>0) printf("done.\n");
607 return(0);
608}
609/*****************************************************************************/
610
611/*****************************************************************************/
int IMG_TEST
Definition img.c:6
void imgInfo(IMG *image)
Definition img.c:359
unsigned long long imgNaNs(IMG *img, int fix)
Definition img.c:658
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
Definition img.c:279
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.
Header file for libtpcimgio.
#define IMG_STATUS_OCCUPIED
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 libtpcmodel.
double dmean(double *data, int n, double *sd)
Definition median.c:73
Header file for libtpcmodext.
float * pixel
unsigned short int dimx
float **** m
char status
unsigned short int dimt
unsigned short int dimz
unsigned short int dimy
const char * statmsg