TPCCLIB
Loading...
Searching...
No Matches
imgflowm.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "tpcclibConfig.h"
11/*****************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15#include <string.h>
16#include <math.h>
17#include <time.h>
18/*****************************************************************************/
19#include "libtpcmisc.h"
20#include "libtpccurveio.h"
21#include "libtpcimgio.h"
22#include "libtpcimgp.h"
23#include "libtpcmodel.h"
24#include "libtpcmodext.h"
25/*****************************************************************************/
26#define NNLS_N 3
27/*****************************************************************************/
28
29/*****************************************************************************/
30static char *info[] = {
31 "Estimation of rate constants K1 (perfusion), k2, and Va from dynamic",
32 "radiowater PET image in ECAT 6.3, ECAT 7.x, NIfTI-1, or Analyze 7.5 file",
33 "format using. The two-compartment model equations",
34 " dCt(t)/dt = K1*Ca(t) - k2*Ct(t)",
35 " Croi(t) = Va*Ca(t) + Ct(t)",
36 "are linearized (1) into equation",
37 " Croi(t) = Va*Ca(t) + (K1+Va*k2)*Integral[Ca(t)] - k2*Integral[Croi(t)]",
38 "from which the model parameters are solved using Lawson-Hanson non-negative",
39 "least squares (NNLS) method (2).",
40 " ",
41 "Arterial blood curve (BTAC) must be corrected for decay and time delay,",
42 "with sample times in seconds. Dynamic PET image must be corrected for decay.",
43 " ",
44 "Since time delay varies inside PET image, this program requires a mask image",
45 "which specifies to which pixels the model is applied. If output file(s) do",
46 "not exist, the output files are created with zero pixel values where mask",
47 "image has value 0. If output file(s) exist, the pre-existing pixel values",
48 "outside the mask are not changed.",
49 " ",
50 "Usage: @P [Options] btacfile imgfile maskfile flowfile",
51 " ",
52 "Options:",
53 " -end=<Fit end time (sec)>",
54 " Use data from 0 to end time; by default, all of it.",
55 " -k2=<filename>",
56 " Parametric k2 image is saved; in some situations perfusion calculation",
57 " from k2 can be more accurate than the default assumption of f=K1.",
58 " Perfusion can be calculated from k2 using equation f=k2*pH2O, where",
59 " pH2O is the physiological partition coefficient of water in tissue.",
60 " -Va=<filename> | -Va=0",
61 " Parametric Va image is saved, or set Va to 0 if image is pre-corrected",
62 " for arterial blood volume; by default Va is fitted.",
63 " -max=<Max value>",
64 " Upper limit for blood flow (K1) values.",
65 " -noneg",
66 " Pixels with negative K1 estimates are set to zero.",
67 " -stdoptions", // List standard options like --help, -v, etc
68 " ",
69 "The units of pixel values in the blood flow (K1) image is",
70 "(mL blood)/((mL tissue) * min), in k2 image 1/min, and",
71 "in Va image (mL blood/mL tissue).",
72 " ",
73 "Example 1. Calculation of perfusion and arterial blood volume image,",
74 " stopping fit at 180 s:",
75 " @P -Va=p234va.v -end=180 p234d1.bld p234.nii p234_mask1.nii p234flow.nii",
76 " ",
77 "Example 2. Dynamic image is pre-corrected for vascular activity,",
78 " and full data length is used:",
79 " @P -Va=0 p345dc2.bld p345_vacorr.nii p345flow.nii",
80 " ",
81 "References:",
82 "1. Blomqvist G. On the construction of functional maps in positron",
83 " emission tomography. J Cereb Blood Flow Metab. 1984;4:629-632.",
84 "2. Lawson CL & Hanson RJ. Solving least squares problems.",
85 " Prentice-Hall, 1974.",
86 "3. Ohta S, Meyer E, Thompson CJ, Gjedde A. Oxygen consumption of the",
87 " living human brain measured after a single inhalation of positron",
88 " emitting oxygen. J Cereb Blood Flow Metab. 1992;12:179-192.",
89 " ",
90 "See also: imgflow, imgdelay, fitdelay, imgcbv, fit_h2o, imgcalc",
91 " ",
92 "Keywords: image, modelling, perfusion, blood flow, radiowater, mask",
93 0};
94/*****************************************************************************/
95
96/*****************************************************************************/
97/* Turn on the globbing of the command line, since it is disabled by default in
98 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
99 In Unix&Linux wildcard command line processing is enabled by default. */
100/*
101#undef _CRT_glob
102#define _CRT_glob -1
103*/
104int _dowildcard = -1;
105/*****************************************************************************/
106
107/*****************************************************************************/
108/*
109 * main()
110 */
111int main(int argc, char *argv[])
112{
113 int ai, help=0, version=0, verbose=1;
114 int weight=0, dataNr=0;
115 char inpfile[FILENAME_MAX], petfile[FILENAME_MAX], maskfile[FILENAME_MAX];
116 char k2file[FILENAME_MAX], vafile[FILENAME_MAX], k1file[FILENAME_MAX];
117 double upperLimit=nan("");
118 double lowerLimit=nan("");
119 double fittime=nan("");
120 int fitVa=1;
121 double *cp, *cpi, *ct, *cti, Va;
122
123
124
125 /*
126 * Get arguments
127 */
128 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
129 inpfile[0]=petfile[0]=k1file[0]=k2file[0]=vafile[0]=maskfile[0]=(char)0;
130 /* Get options */
131 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
132 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
133 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
134 if(strcasecmp(cptr, "W")==0) {
135 weight=1; continue;
136 } else if(strncasecmp(cptr, "k2=", 3)==0) {
137 strlcpy(k2file, cptr+3, FILENAME_MAX); if(strlen(k2file)) continue;
138 } else if(strcasecmp(cptr, "VA=0")==0) {
139 fitVa=0; continue;
140 } else if(strncasecmp(cptr, "VA=", 3)==0 || strncasecmp(cptr, "VB=", 3)==0) {
141 strlcpy(vafile, cptr+3, FILENAME_MAX); if(strlen(vafile)) continue;
142 } else if(strncasecmp(cptr, "noneg", 2)==0) {
143 lowerLimit=0.0; continue;
144 } else if(strncasecmp(cptr, "MAX=", 4)==0) {
145 upperLimit=atof_dpi(cptr+4); if(upperLimit>0.0) continue;
146 } else if(strncasecmp(cptr, "END=", 4)==0) {
147 fittime=atof_dpi(cptr+4)/60.; if(fittime>0.0) continue;
148 }
149 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
150 return(1);
151 } else break;
152
153 /* Print help or version? */
154 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
155 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
156 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
157
158 /* Process other arguments, starting from the first non-option */
159 if(ai<argc) strlcpy(inpfile, argv[ai++], FILENAME_MAX);
160 if(ai<argc) strlcpy(petfile, argv[ai++], FILENAME_MAX);
161 if(ai<argc) strlcpy(maskfile, argv[ai++], FILENAME_MAX);
162 if(ai<argc) strlcpy(k1file, argv[ai++], FILENAME_MAX);
163 if(ai<argc) {fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]); return(1);}
164 /* Did we get all the information that we need? */
165 if(!k1file[0]) {
166 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
167 return(1);
168 }
169 if(!(fittime>0.0)) fittime=1.0E+020;
170
171 /* In verbose mode print arguments and options */
172 if(verbose>1) {
173 printf("inpfile := %s\n", inpfile);
174 printf("petfile := %s\n", petfile);
175 printf("maskfile := %s\n", maskfile);
176 printf("k1file := %s\n", k1file);
177 if(k2file[0]) printf("k2file := %s\n", k2file);
178 printf("fitVa := %d\n", fitVa);
179 if(vafile[0]) printf("vafile := %s\n", vafile);
180 if(!isnan(upperLimit)) printf("upperLimit := %f\n", upperLimit);
181 if(!isnan(lowerLimit)) printf("lowerLimit := %f\n", lowerLimit);
182 if(isfinite(fittime)) printf("fittime := %g [sec]\n", 60.0*fittime);
183 printf("weight := %d\n", weight);
184 fflush(stdout);
185 }
186 if(verbose>10) IMG_TEST=verbose-10; else IMG_TEST=0;
187
188
189 /*
190 * Read PET image and input TAC
191 */
192 if(verbose>1) printf("reading data files\n");
193 DFT tac; dftInit(&tac);
194 IMG img; imgInit(&img);
195 {
196 char tmp[FILENAME_MAX+1];
197 int ret=imgReadModelingData(
198 petfile, NULL, inpfile, NULL, NULL, &fittime, &dataNr, &img,
199 NULL, &tac, 1, stdout, verbose-2, tmp);
200 if(ret!=0) {
201 fprintf(stderr, "Error: %s.\n", tmp);
202 if(verbose>1) printf(" ret := %d\n", ret);
203 return(2);
204 }
205 if(imgNaNs(&img, 1)>0)
206 if(verbose>0) fprintf(stderr, "Warning: missing pixel values.\n");
207 }
208 /* Set time unit to min, also for integrals in y2[] */
209 if(tac.timeunit==TUNIT_SEC) for(int i=0; i<tac.frameNr; i++) tac.voi[0].y2[i]/=60.0;
210 dftTimeunitConversion(&tac, TUNIT_MIN);
211 if(verbose>1) {
212 printf("fittimeFinal := %g s\n", 60.0*fittime);
213 printf("dataNr := %d\n", dataNr);
214 }
215 /* Check that image is dynamic */
216 if(dataNr<3) {
217 fprintf(stderr, "Error: too few time frames for fitting.\n");
218 if(verbose>0) imgInfo(&img);
219 imgEmpty(&img); dftEmpty(&tac); return(2);
220 }
221
222 /*
223 * Read mask image
224 */
225 if(verbose>1) printf("reading mask image\n");
226 IMG mask; imgInit(&mask);
227 {
228 int ret=imgRead(maskfile, &mask);
229 if(ret!=0) {
230 fprintf(stderr, "Error: cannot read mask %s.\n", maskfile);
231 if(verbose>1) printf(" ret := %d\n", ret);
232 imgEmpty(&img); dftEmpty(&tac); return(2);
233 }
234 if(imgMatchMatrixSize(&img, &mask)) {
235 fprintf(stderr, "Error: bad mask for image.\n");
236 imgEmpty(&img); dftEmpty(&tac); imgEmpty(&mask); return(2);
237 }
238 }
239
240
241
242 /* Allocate memory for tissue TAC and integral */
243 {
244 int ret=dftAddmem(&tac, 1);
245 if(ret!=0) {
246 fprintf(stderr, "Error (%d) in allocating memory.\n", ret);
247 imgEmpty(&img); dftEmpty(&tac); imgEmpty(&mask);
248 return(3);
249 }
250 strcpy(tac.voi[0].voiname, "input");
251 strcpy(tac.voi[1].voiname, "tissue");
252 }
253
254
255
256 /*
257 * Read pre-existing result images, or if not existing,
258 * allocate result images and fill the header info
259 */
260 IMG k1img, k2img, vaimg;
261 imgInit(&k1img); imgInit(&k2img); imgInit(&vaimg);
262 {
263 int ret=0;
264 if(imgRead(k1file, &k1img)==0) {
265 if((ret=imgMatchMatrixSize(&img, &k1img)))
266 fprintf(stderr, "Error: wrong matrix size in existing K1 map.\n");
267 } else {
268 if((ret=imgAllocateWithHeader(&k1img, img.dimz, img.dimy, img.dimx, 1, &img))) {
269 fprintf(stderr, "Error: cannot allocate memory.\n");
270 } else {
271 for(int zi=0; zi<img.dimz; zi++)
272 for(int yi=0; yi<img.dimy; yi++)
273 for(int xi=0; xi<img.dimx; xi++)
274 k1img.m[zi][yi][xi][0]=0.0;
275 k1img.unit=IMGUNIT_ML_PER_ML_PER_MIN;
277 k1img.start[0]=img.start[0]; k1img.end[0]=img.end[dataNr-1];
278 }
279 }
280 /* optional maps */
281 if(ret==0 && k2file[0]) {
282 if(imgRead(k2file, &k2img)==0) {
283 if((ret=imgMatchMatrixSize(&img, &k2img)))
284 fprintf(stderr, "Error: wrong matrix size in existing k2 map.\n");
285 } else {
286 if((ret=imgAllocateWithHeader(&k2img, img.dimz, img.dimy, img.dimx, 1, &k1img))) {
287 fprintf(stderr, "Error: cannot allocate memory.\n");
288 } else {
289 for(int zi=0; zi<img.dimz; zi++)
290 for(int yi=0; yi<img.dimy; yi++)
291 for(int xi=0; xi<img.dimx; xi++)
292 k2img.m[zi][yi][xi][0]=0.0;
293 k2img.unit=IMGUNIT_PER_MIN;
294 }
295 }
296 }
297 if(ret==0 && vafile[0]) {
298 if(imgRead(vafile, &vaimg)==0) {
299 if((ret=imgMatchMatrixSize(&img, &vaimg)))
300 fprintf(stderr, "Error: wrong matrix size in existing Va map.\n");
301 } else {
302 if((ret=imgAllocateWithHeader(&vaimg, img.dimz, img.dimy, img.dimx, 1, &k1img))) {
303 fprintf(stderr, "Error: cannot allocate memory.\n");
304 } else {
305 for(int zi=0; zi<img.dimz; zi++)
306 for(int yi=0; yi<img.dimy; yi++)
307 for(int xi=0; xi<img.dimx; xi++)
308 vaimg.m[zi][yi][xi][0]=0.0;
309 vaimg.unit=IMGUNIT_ML_PER_ML;
310 }
311 }
312 }
313 /* quit if error */
314 if(ret) {
315 imgEmpty(&img); dftEmpty(&tac); imgEmpty(&mask);
316 imgEmpty(&k1img); imgEmpty(&k2img); imgEmpty(&vaimg);
317 return(4);
318 }
319 }
320
321
322 /*
323 * Allocate memory required by NNLS
324 */
325 int nnls_n, nnls_m, nnls_index[NNLS_N];
326 double *nnls_a[NNLS_N], *nnls_b, *nnls_zz, nnls_x[NNLS_N], *nnls_mat,
327 nnls_wp[NNLS_N], *dptr, nnls_rnorm;
328 if(verbose>1) printf("allocating memory for NNLS\n");
329 nnls_n=NNLS_N; nnls_m=dataNr;
330 nnls_mat=(double*)malloc(((nnls_n+2)*nnls_m)*sizeof(double));
331 if(nnls_mat==NULL) {
332 fprintf(stderr, "Error: cannot allocate memory for NNLS.\n");
333 imgEmpty(&img); dftEmpty(&tac); imgEmpty(&mask);
334 imgEmpty(&k1img); imgEmpty(&k2img); imgEmpty(&vaimg);
335 return(5);
336 }
337 dptr=nnls_mat;
338 for(int n=0; n<nnls_n; n++) {nnls_a[n]=dptr; dptr+=nnls_m;}
339 nnls_b=dptr; dptr+=nnls_m; nnls_zz=dptr;
340
341 /* Copy weights if available */
342 /* or set them to frame lengths */
343 if(verbose>2) printf("working with NNLS weights\n");
344 if(weight==1 && img.isWeight==0) {
345 for(int m=0; m<nnls_m; m++) img.weight[m]=img.end[m]-img.start[m];
346 img.isWeight=1;
347 }
348 /* Compute NNLS weights */
349 if(img.isWeight) {
350 for(int m=0; m<nnls_m; m++) {
351 tac.w[m]=img.weight[m]; if(tac.w[m]<=1.0e-20) tac.w[m]=0.0;
352 }
353 }
354
355
356 /*
357 * Compute pixel-by-pixel
358 */
359 cp=tac.voi[0].y; cpi=tac.voi[0].y2;
360 ct=tac.voi[1].y; cti=tac.voi[1].y2;
361 if(verbose>0) fprintf(stdout, "computing pixel-by-pixel\n");
362 for(int zi=0; zi<img.dimz; zi++) {
363 if(verbose>2) printf("computing plane %d\n", img.planeNumber[zi]);
364 else if(img.dimz>1 && verbose>0) {fprintf(stdout, "."); fflush(stdout);}
365 for(int yi=0; yi<img.dimy; yi++) {
366 for(int xi=0; xi<img.dimx; xi++) {
367
368 /* Check the mask */
369 if(!(fabs(mask.m[zi][yi][xi][0])>1.0E-12)) continue;
370
371 /* Initiate pixel output values */
372 k1img.m[zi][yi][xi][0]=0.0;
373 if(k2file[0]) k2img.m[zi][yi][xi][0]=0.0;
374 if(vafile[0]) vaimg.m[zi][yi][xi][0]=0.0;
375
376 /*
377 * Estimate K1, k2 and Va
378 */
379 nnls_m=dataNr; nnls_n=NNLS_N; if(fitVa==0) nnls_n--;
380 /* Copy and integrate pixel curve */
381 for(int m=0; m<nnls_m; m++) ct[m]=img.m[zi][yi][xi][m];
382 petintegral(tac.x1, tac.x2, ct, nnls_m, cti, NULL);
383 /* if AUC at the end is <= zero, then forget this pixel */
384 if(cti[nnls_m-1]<=0.0) continue;
385 /* Fill NNLS A matrix: */
386 /* function #1: tissue integral x -1 */
387 for(int m=0; m<nnls_m; m++) nnls_a[0][m]=-cti[m];
388 /* function #2: integral of input */
389 for(int m=0; m<nnls_m; m++) nnls_a[1][m]=cpi[m];
390 /* function #3: input curve */
391 if(nnls_n>2) for(int m=0; m<nnls_m; m++) nnls_a[2][m]=cp[m];
392 /* Fill NNLS B array: tissue */
393 for(int m=0; m<nnls_m; m++) nnls_b[m]=ct[m];
394 /* Apply data weights */
395 if(img.isWeight) nnlsWght(nnls_n, nnls_m, nnls_a, nnls_b, tac.w);
396 /* NNLS */
397 if(nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm,
398 nnls_wp, nnls_zz, nnls_index)>1) continue; /* no solution is possible */
399 if(nnls_n>2) Va=nnls_x[2]; else Va=0.0;
400 k1img.m[zi][yi][xi][0]=nnls_x[1];
401 if(nnls_n>2) k1img.m[zi][yi][xi][0]-=Va*nnls_x[0];
402 if(k2file[0]) k2img.m[zi][yi][xi][0]=nnls_x[0];
403 if(vafile[0]) vaimg.m[zi][yi][xi][0]=Va;
404
405 /* Enforce K1 limits, if requested */
406 if(!isnan(upperLimit) && k1img.m[zi][yi][xi][0]>upperLimit)
407 k1img.m[zi][yi][xi][0]=upperLimit;
408 if(!isnan(lowerLimit) && k1img.m[zi][yi][xi][0]<lowerLimit)
409 k1img.m[zi][yi][xi][0]=lowerLimit;
410
411 /* Va limit */
412 if(vafile[0] && vaimg.m[zi][yi][xi][0]>1.0) vaimg.m[zi][yi][xi][0]=1.0;
413
414 } /* next column */
415 } /* next row */
416 } /* next plane */
417 if(verbose>0) fprintf(stdout, "done.\n");
418
419 /* No need for dynamic image, NNLS matrix or curves any more */
420 free(nnls_mat); imgEmpty(&img); dftEmpty(&tac);
421
422
423 /*
424 * Save parametric image(s)
425 */
426 if(verbose>0) printf("writing parametric images\n");
427 {
428 /* K1 */
429 int ret=imgWrite(k1file, &k1img);
430 if(ret) {
431 fprintf(stderr, "Error: %s\n", k1img.statmsg);
432 if(verbose>1) printf("ret := %d\n", ret);
433 imgEmpty(&k1img); imgEmpty(&k2img); imgEmpty(&vaimg); imgEmpty(&mask);
434 return(13);
435 }
436 if(verbose>0) fprintf(stdout, "Flow image %s saved.\n", k1file);
437 /* k2 */
438 if(k2file[0]) {
439 ret=imgWrite(k2file, &k2img);
440 if(ret) {
441 fprintf(stderr, "Error: %s\n", k2img.statmsg);
442 imgEmpty(&k1img); imgEmpty(&k2img); imgEmpty(&vaimg); imgEmpty(&mask);
443 return(14);
444 }
445 if(verbose>0) fprintf(stdout, "k2 image %s saved.\n", k2file);
446 }
447 /* Va */
448 if(vafile[0]) {
449 ret=imgWrite(vafile, &vaimg);
450 if(ret) {
451 fprintf(stderr, "Error: %s\n", vaimg.statmsg);
452 imgEmpty(&k1img); imgEmpty(&k2img); imgEmpty(&vaimg); imgEmpty(&mask);
453 return(16);
454 }
455 if(verbose>0) fprintf(stdout, "Va image %s saved.\n", vafile);
456 }
457 }
458
459 if(verbose>2) printf("before quitting, free memory\n");
460 imgEmpty(&k1img); imgEmpty(&k2img); imgEmpty(&vaimg); imgEmpty(&mask);
461 fflush(stdout);
462
463 return(0);
464}
465/*****************************************************************************/
466
467/*****************************************************************************/
double atof_dpi(char *str)
Definition decpoint.c:59
void dftInit(DFT *data)
Definition dft.c:38
int dftAddmem(DFT *dft, int voiNr)
Definition dft.c:107
void dftEmpty(DFT *data)
Definition dft.c:20
int dftTimeunitConversion(DFT *dft, int tunit)
Definition dftunit.c:119
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 imgMatchMatrixSize(IMG *d1, IMG *d2)
Definition imgcomp.c:447
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 petintegral(double *x1, double *x2, double *y, int nr, double *ie, double *iie)
Integrate PET TAC data to frame mid times.
Definition integr.c:771
Header file for libtpccurveio.
Header file for libtpcimgio.
#define IMG_DC_NONCORRECTED
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.
int nnls(double **a, int m, int n, double *b, double *x, double *rnorm, double *w, double *zz, int *index)
Definition nnls.c:37
int nnlsWght(int N, int M, double **A, double *b, double *weight)
Definition nnls.c:257
Header file for libtpcmodext.
Voi * voi
int timeunit
double * w
double * x1
double * x2
int frameNr
unsigned short int dimx
float **** m
char decayCorrection
char unit
int * planeNumber
float * weight
float * start
unsigned short int dimz
unsigned short int dimy
float * end
const char * statmsg
char isWeight
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y