TPCCLIB
Loading...
Searching...
No Matches
imgfsegm.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 <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpcmodel.h"
19#include "libtpccurveio.h"
20#include "libtpcimgio.h"
21#include "libtpcimgp.h"
22#include "libtpcmodext.h"
23/*****************************************************************************/
24unsigned _stklen = 16777216; /* need a 16MB stack (not necessary on UNIX) */
25/*****************************************************************************/
26
27/*****************************************************************************/
28static char *info[] = {
29 "Flexible image segmentation (clustering) for dynamic PET image (1).",
30 "This program can be used for method testing purposes only!",
31 "Default stack size on Windows may be too small, causing program to crash.",
32 " ",
33 "User must provide threshold percentage to exclude the background (bkgthrs),",
34 "maximal CV percentage allowed for pixels in the same cluster (maxcv),",
35 "and threshold percentage for correlation coefficient between cluster TACs",
36 "(ccthrs).",
37 " ",
38 "Static cluster image will contain the cluster numbers as integers, where",
39 "0 represents pixels below background threshold, and 1, 2, 3, ... represent",
40 "clusters in DECREASING order of TAC integrals.",
41 " ",
42 "Usage: @P [Options] image bkgthrs maxcv ccthrs clusterimage",
43 " ",
44 "Options:",
45 " -ctac=<filename for cluster TACs>",
46 " Cluster TACs are saved in TAC format.",
47 " -cf=<filename for correction factor image>",
48 " Save image file that will contain correction factors for individual",
49 " pixels, calculated as (AUC of cluster avg TAC)/(AUC of pixel TAC).",
50 " -sm=<filename for smoothed dynamic image>",
51 " TACs in the original dynamic image are replaced by the cluster TACs",
52 " which have been divided by the correction factors.",
53 " -stdoptions", // List standard options like --help, -v, etc
54 " ",
55 "Example:",
56 " @P -ctac=b123cluster.dat b123dy1.v 30 5 50 b123cluster.v",
57 " ",
58 "References:",
59 "1. Bentourkia M. A flexible image segmentation prior to parametric",
60 " estimation. Comput Med Imaging Graph. 2001;25:501-506.",
61 " ",
62 "See also: imgthrs, imgdysmo, imgfiltg, imgmask, img2tif, ecat2ana, pxl2tac",
63 " ",
64 "Keywords: image, smoothing, mask, threshold",
65 0};
66/*****************************************************************************/
67
68/*****************************************************************************/
69/* Turn on the globbing of the command line, since it is disabled by default in
70 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
71 In Unix&Linux wildcard command line processing is enabled by default. */
72/*
73#undef _CRT_glob
74#define _CRT_glob -1
75*/
76int _dowildcard = -1;
77/*****************************************************************************/
78
79/*****************************************************************************/
83int main(int argc, char **argv)
84{
85 int ai, help=0, version=0, verbose=1;
86 char petfile[FILENAME_MAX], clufile[FILENAME_MAX],
87 tacfile[FILENAME_MAX], corfile[FILENAME_MAX],
88 smofile[FILENAME_MAX];
89 double bkgthrs, maxcv, ccthrs;
90 char *cptr;
91 int ret;
92
93
94 /*
95 * Get arguments
96 */
97 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
98 petfile[0]=clufile[0]=tacfile[0]=corfile[0]=smofile[0]=(char)0;
99 /* Get options */
100 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
101 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
102 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
103 if(strncasecmp(cptr, "CTAC=", 5)==0) {
104 strlcpy(tacfile, cptr+5, FILENAME_MAX); continue;
105 } else if(strncasecmp(cptr, "CF=", 3)==0) {
106 strlcpy(corfile, cptr+3, FILENAME_MAX); continue;
107 } else if(strncasecmp(cptr, "SM=", 3)==0) {
108 strlcpy(smofile, cptr+3, FILENAME_MAX); continue;
109 } else if(strncasecmp(cptr, "SMO=", 4)==0) {
110 strlcpy(smofile, cptr+4, FILENAME_MAX); continue;
111 }
112 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
113 return(1);
114 } else break;
115
116 /* Print help or version? */
117 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
118 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
119 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
120
121 /* Process other arguments, starting from the first non-option */
122 if(ai<argc) {strlcpy(petfile, argv[ai++], FILENAME_MAX);}
123 if(ai<argc) {
124 ret=atof_with_check(argv[ai], &bkgthrs);
125 if(ret!=0 || bkgthrs>=100.0) {
126 fprintf(stderr, "Error: invalid background threshold.\n");
127 return(1);
128 }
129 if(bkgthrs<0.0) bkgthrs=0.0; else bkgthrs/=100.0;
130 ai++;
131 }
132 if(ai<argc) {
133 ret=atof_with_check(argv[ai], &maxcv);
134 if(ret!=0 || maxcv>=100.0) {
135 fprintf(stderr, "Error: invalid CV limit.\n");
136 return(1);
137 }
138 if(maxcv<0.0) maxcv=0.0; else maxcv/=100.0;
139 ai++;
140 }
141 if(ai<argc) {
142 ret=atof_with_check(argv[ai], &ccthrs);
143 if(ret!=0 || ccthrs>=100.0) {
144 fprintf(stderr, "Error: invalid correlation coefficient threshold.\n");
145 return(1);
146 }
147 if(ccthrs<0.0) ccthrs=0.0; else ccthrs/=100.0;
148 ai++;
149 }
150 if(ai<argc) {strlcpy(clufile, argv[ai++], FILENAME_MAX);}
151 if(ai<argc) {
152 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
153 return(1);
154 }
155
156 /* Did we get all the information that we need? */
157 if(!clufile[0]) {
158 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
159 return(1);
160 }
161 /* Check that output files do not have the same name as input */
162 if(strcasecmp(petfile, clufile)==0 || strcasecmp(petfile, tacfile)==0 ||
163 strcasecmp(petfile, corfile)==0 || strcasecmp(petfile, smofile)==0) {
164 fprintf(stderr, "Error: same filename for input and output data.\n");
165 return(1);
166 }
167
168
169 /* In verbose mode print arguments and options */
170 if(verbose>1) {
171 printf("petfile := %s\n", petfile);
172 printf("clufile := %s\n", clufile);
173 if(tacfile[0]) printf("tacfile:=%s\n", tacfile);
174 if(corfile[0]) printf("corfile:=%s\n", corfile);
175 if(smofile[0]) printf("smofile:=%s\n", smofile);
176 printf("bkgthrs := %g\n", 100.*bkgthrs);
177 printf("maxcv := %g\n", 100.*maxcv);
178 printf("ccthrs := %g\n", 100.*ccthrs);
179 }
180 if(verbose>9) IMG_TEST=verbose-9; else IMG_TEST=0;
181
182
183 /*
184 * Read image
185 */
186 if(verbose>0) fprintf(stdout, "reading image %s\n", petfile);
187 IMG img; imgInit(&img);
188 ret=imgRead(petfile, &img);
189 if(ret) {
190 fprintf(stderr, "Error: %s\n", img.statmsg); if(verbose>1) imgInfo(&img);
191 return(2);
192 }
193 if(verbose>1) {
194 printf("image dimensions: %d %d %d\n", img.dimz, img.dimy, img.dimx);
195 printf("image frame nr: %d\n", img.dimt);
196 }
197 /* Check that at least two frames */
198 if(img.dimt<2) {
199 fprintf(stderr, "Error: image is not dynamic.\n");
200 imgEmpty(&img); return(2);
201 }
202 if(imgNaNs(&img, 1)>0)
203 if(verbose>0) fprintf(stderr, "Warning: missing pixel values.\n");
204 /* Check that frame times are available */
205 if(!imgExistentTimes(&img)) {
206 fprintf(stderr, "Error: image does not contain frame times.\n");
207 imgEmpty(&img); return(2);
208 }
209 /* For raw (sinogram) data, divide counts by frame duration */
210 ret=imgRawCountsPerTime(&img, 1);
211 if(ret) {
212 fprintf(stderr, "Error: cannot correct sinogram counts.\n");
213 if(verbose>1) printf("ret=%d\n", ret);
214 imgEmpty(&img); return(2);
215 }
216
217 /* Calculate the integral (area-under-curve) image */
218 if(verbose>0) printf("calculating AUC image...\n");
219 IMG sumimg; imgInit(&sumimg);
220 ret=imgFrameIntegral(&img, 0, img.dimt-1, &sumimg, verbose-5);
221 if(ret) {
222 fprintf(stderr, "Error: cannot calculate AUC image.\n");
223 if(verbose>1) printf("ret=%d\n", ret);
224 imgEmpty(&img); return(4);
225 }
226 /* Set unit */
227 sumimg.unit=CUNIT_UNITLESS;
228
229 /* Search for maximum AUC pixel value */
230 if(verbose>0) printf("searching for max AUC pixel value...\n");
231 float maxauc;
232 ret=imgMax(&sumimg, &maxauc);
233 if(ret) {
234 fprintf(stderr, "Error: cannot find maximum AUC.\n");
235 if(verbose>1) printf("ret=%d\n", ret);
236 imgEmpty(&img); imgEmpty(&sumimg);
237 return(5);
238 }
239 if(verbose>1) printf("AUCmax := %g\n", maxauc);
240
241 /* Make a mask image by thresholding with given background limit */
242 float minauc=maxauc*bkgthrs;
243 if(verbose>0) {
244 printf("thresholding image (min=%g, max=%g)...\n", minauc, maxauc);
245 fflush(stdout);
246 }
247 IMG templimg; imgInit(&templimg);
248 ret=imgsegmThresholdMask(&sumimg, (float)minauc, (float)maxauc, &templimg);
249 if(ret) {
250 fprintf(stderr, "Error: cannot do thresholding.\n");
251 if(verbose>1) printf("ret=%d\n", ret);
252 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
253 return(6);
254 }
255 if(verbose>10) {
256 char tmp[FILENAME_MAX+20], buf[128];
257 sprintf(tmp, "%s.templimg.tif", petfile);
258 float g=-1.0;
259 ret=tiffWriteImg(&templimg, -1, -1, &g, PET_GRAYSCALE_INV, tmp, 0, 0,
260 verbose-10, buf);
261 if(ret) {fprintf(stderr, "Error: %s\n", buf); fflush(stderr);}
262 }
263
264 /* Calculate the CVmax */
265 double meanauc, CVmax, CVlim;
266 meanauc=0.5*(minauc+maxauc);
267 CVmax= ((maxauc-meanauc)*(maxauc-meanauc) +
268 (minauc-meanauc)*(minauc-meanauc)) / meanauc;
269 CVlim=maxcv*CVmax;
270 if(verbose>1) {
271 printf("CVmax :=%g\nCVlim := %g\n", CVmax, CVlim);
272 fflush(stdout);
273 }
274
275 /* Convert mask image to cluster image */
276 if(verbose>0) printf("conversion of mask to initial cluster image...\n");
277 /* 0th cluster is formed by pixels below background threshold,
278 others get temp value -1 */
279 ret=imgsegmMaskToCluster(&templimg);
280 if(ret) {
281 fprintf(stderr, "Error: cannot make cluster template.\n");
282 if(verbose>1) printf("ret=%d\n", ret);
283 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
284 return(7);
285 }
286
287 /* Search all clusters */
288 if(verbose>0) {printf("searching for clusters...\n"); fflush(stdout);}
289 int pi, ri, ci, clusterID=0, clusterNr=0;;
290 do {
291 /* Find max pixel value, excluding pixels belonging to existing clusters */
292 if(verbose>4) {
293 printf("finding max pixel value for %dth cluster.\n", clusterID+2);
294 fflush(stdout);
295 }
296 ret=imgsegmFindMaxOutsideClusters(&sumimg, &templimg, &maxauc,
297 &pi, &ri, &ci);
298 if(ret>0) { /* something was very wrong */
299 fprintf(stderr, "Error: cannot search max AUC.\n");
300 if(verbose>1) printf("ret=%d\n", ret);
301 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
302 return(8);
303 } else if(ret==-1) { /* we are done */
304 if(verbose>4) fprintf(stdout, "All pixels included in clusters.\n");
305 break;
306 } else { /* ok, we found a maximum */
307 if(verbose>4) {
308 printf("Max %g found at [%d][%d][%d] (%g)\n", maxauc, pi, ri, ci,
309 templimg.m[pi][ri][ci][0]);
310 fflush(stdout);
311 }
312 /* Check whether all of its neighbours already belong to some cluster */
313 ret=imgsegmCheckNeighbours(&templimg, pi, ri, ci);
314 /* If so, then find the neighbour with best correlation, and add */
315 /* this to the same cluster */
316 if(ret) {
317 ret=imgsegmFindBestNeighbour(&img, &templimg, pi, ri, ci);
318 if(verbose>4) {
319 printf("All neighbours are part of clusters; this was added to %d.\n",
320 (int)templimg.m[pi][ri][ci][0]);
321 fflush(stdout);
322 }
323 continue;
324 }
325 /* Otherwise, this is the basis of a new cluster */
326 if(verbose>4) {
327 printf("At least one neighbour is free.\n"); fflush(stdout);
328 }
329 clusterID++;
330 }
331
332 /* Expand the cluster volume around this pixel */
333 if(verbose>4) {
334 printf("expanding the cluster around pixel [%d][%d][%d]\n", pi, ri, ci);
335 fflush(stdout);
336 }
337 ret=imgsegmClusterExpand(&templimg, &sumimg, &img, clusterID,
338 pi, ri, ci, pi, ri, ci, CVlim, ccthrs, verbose-5);
339 if(ret>1) {
340 fprintf(stderr, "Error: problem in clustering.\n");
341 if(verbose>1) printf("ret=%d\n", ret);
342 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
343 return(9);
344 }
345 if(verbose>20) {
346 char tmp[FILENAME_MAX+20], buf[128];
347 sprintf(tmp, "%s.step%d.tif", petfile, clusterID);
348 printf("writing %s of temporary cluster situation\n", tmp);
349 fflush(stdout);
350 float g=(float)clusterID;
351 ret=tiffWriteImg(&templimg, -1, -1, &g, PET_GRAYSCALE_INV, tmp, 0, 0,
352 verbose-10, buf);
353 if(ret) {fprintf(stderr, "Error: %s\n", buf); fflush(stderr);}
354 }
355 if(verbose==1) {fprintf(stdout, "."); fflush(stdout);}
356 } while(ret==0);
357 if(verbose==1) {fprintf(stdout, "\n"); fflush(stdout);}
358 clusterNr=clusterID;
359 if(verbose>0) {printf("\n%d clusters found.\n", clusterNr); fflush(stdout);}
360
361
362 /*
363 * Write the cluster image
364 */
365 if(verbose>1) printf("writing cluster image %s\n", clufile);
366 if(imgWrite(clufile, &templimg)) {
367 fprintf(stderr, "Error: %s\n", templimg.statmsg);
368 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
369 return(11);
370 }
371
372 /* If user did not ask for any optional data to be saved, then that's it */
373 if(!tacfile[0] && !corfile[0] && !smofile[0]) {
374 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
375 if(verbose>0) printf("done.\n");
376 return(0);
377 }
378
379
380 /*
381 * Calculate average TACs from each cluster
382 */
383 if(verbose>0) printf("calculating cluster average TACs...\n");
384 DFT tac; dftInit(&tac);
385 ret=clusterTACs(&img, &templimg, clusterNr, &tac, verbose-2);
386 if(ret) {
387 fprintf(stderr, "Error: cannot calculate cluster average TACs.\n");
388 if(verbose>1) printf("ret=%d\n", ret);
389 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
390 return(12);
391 }
392 if(tacfile[0]) {
393 /* Save TACs */
394 if(verbose>1) printf("writing cluster average TACs in %s\n", tacfile);
395 ret=dftWrite(&tac, tacfile);
396 if(ret) {
397 fprintf(stderr, "Error: %s\n", dfterrmsg);
398 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
399 dftEmpty(&tac); return(13);
400 }
401 }
402
403 /* If user did not ask for any further data to be saved, then that's it */
404 if(!corfile[0] && !smofile[0]) {
405 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
406 if(verbose>0) printf("done.\n");
407 dftEmpty(&tac); return(0);
408 }
409
410
411 /*
412 * Calculate the correction image
413 */
414 if(verbose>0) printf("calculating correction image...\n");
415 /* Integrate the cluster TACs */
416 if(verbose>2) printf("integrating cluster TACs...\n");
417 for(int i=0; i<tac.voiNr; i++) {
418 ret=petintegrate(tac.x1, tac.x2, tac.voi[i].y, tac.frameNr,
419 tac.voi[i].y2, NULL);
420 if(ret) {
421 fprintf(stderr, "Error: cannot integrate cluster TACs.\n");
422 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
423 dftEmpty(&tac); return(14);
424 }
425 }
426 /* Convert the sum image to correction image */
427 if(verbose>2) printf("calculating image...\n");
428 for(pi=0; pi<sumimg.dimz; pi++)
429 for(ri=0; ri<sumimg.dimy; ri++)
430 for(ci=0; ci<sumimg.dimx; ci++) {
431 clusterID=(int)templimg.m[pi][ri][ci][0];
432 if(clusterID>0 && sumimg.m[pi][ri][ci][0]>1.0E-006) {
433 sumimg.m[pi][ri][ci][0]=
434 tac.voi[clusterID-1].y2[tac.frameNr-1]/sumimg.m[pi][ri][ci][0];
435 } else sumimg.m[pi][ri][ci][0]=1.0;
436 }
437 if(corfile[0]) {
438 if(verbose>1) printf("writing correction image %s\n", corfile);
439 if(imgWrite(corfile, &sumimg)) {
440 fprintf(stderr, "Error: %s\n", sumimg.statmsg);
441 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
442 dftEmpty(&tac); return(15);
443 }
444 }
445
446
447 /*
448 * Calculate and save the smoothed dynamic image, if required
449 */
450 if(smofile[0]) {
451 if(verbose>0) printf("calculating smoothed dynamic image...\n");
452 /* Replace pixel TACs with cluster mean TACs times cf */
453 int fi;
454 for(pi=0; pi<sumimg.dimz; pi++)
455 for(ri=0; ri<sumimg.dimy; ri++)
456 for(ci=0; ci<sumimg.dimx; ci++) {
457 clusterID=(int)templimg.m[pi][ri][ci][0];
458 if(clusterID>0) {
459 for(fi=0; fi<img.dimt; fi++)
460 img.m[pi][ri][ci][fi]=
461 tac.voi[clusterID-1].y[fi]/sumimg.m[pi][ri][ci][0];
462 } else {
463 for(fi=0; fi<img.dimt; fi++)
464 img.m[pi][ri][ci][fi]=0.0;
465 }
466 }
467 /* For raw data (sinogram), multiply counts by frame duration */
468 ret=imgRawCountsPerTime(&img, 0);
469 if(ret) {
470 fprintf(stderr, "Error: cannot correct sinogram counts.\n");
471 dftEmpty(&tac); imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
472 return(17);
473 }
474 /* Save the smoothed image */
475 if(verbose>1) printf("writing smoothed image %s\n", smofile);
476 if(imgWrite(smofile, &img)) {
477 fprintf(stderr, "Error: %s\n", img.statmsg);
478 dftEmpty(&tac); imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
479 return(18);
480 }
481 }
482
483
484 dftEmpty(&tac);
485 imgEmpty(&img); imgEmpty(&sumimg); imgEmpty(&templimg);
486 if(verbose>0) printf("done.\n");
487 return(0);
488}
489/*****************************************************************************/
490
491/*****************************************************************************/
int clusterTACs(IMG *dimg, IMG *cimg, int nr, DFT *tac, int verbose)
Definition cluster_tac.c:15
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 dftWrite(DFT *data, char *filename)
Definition dftio.c:594
int IMG_TEST
Definition img.c:6
int imgExistentTimes(IMG *img)
Definition img.c:613
void imgInfo(IMG *image)
Definition img.c:359
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 imgFrameIntegral(IMG *img, int first, int last, IMG *iimg, int verbose)
Definition imgarithm.c:346
int imgRawCountsPerTime(IMG *img, int operation)
Definition imgarithm.c:442
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgWrite(const char *fname, IMG *img)
Definition imgfile.c:136
int imgMax(IMG *img, float *maxvalue)
Definition imgminmax.c:15
int imgsegmThresholdMask(IMG *img, float minValue, float maxValue, IMG *timg)
Definition imgsegm.c:39
int imgsegmCheckNeighbours(IMG *cimg, int pi, int ri, int ci)
Definition imgsegm.c:398
int imgsegmMaskToCluster(IMG *img)
Definition imgsegm.c:142
int imgsegmFindBestNeighbour(IMG *dimg, IMG *cimg, int pi, int ri, int ci)
Definition imgsegm.c:427
int imgsegmFindMaxOutsideClusters(IMG *sumimg, IMG *cluster, float *max, int *plane, int *row, int *col)
Definition imgsegm.c:166
int imgsegmClusterExpand(IMG *cimg, IMG *simg, IMG *dimg, int clusterID, int pi, int ri, int ci, int pj, int rj, int cj, float CVlim, float CClim, int verbose)
Definition imgsegm.c:219
int tiffWriteImg(IMG *img, int plane, int frame, float *maxvalue, int colorscale, char *fname, int matXdim, int matYdim, int verbose, char *status)
Definition imgtiff.c:15
int petintegrate(double *x1, double *x2, double *y, int nr, double *newyi, double *newyii)
Definition integr.c:334
Header file for libtpccurveio.
Header file for libtpcimgio.
Header file for libtpcimgp.
#define PET_GRAYSCALE_INV
Definition libtpcimgp.h:34
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
double * x1
int voiNr
double * x2
int frameNr
unsigned short int dimx
float **** m
char unit
unsigned short int dimt
unsigned short int dimz
unsigned short int dimy
const char * statmsg
double * y2
double * y