10#include "tpcclibConfig.h"
27enum {MODEL_UNKNOWN, MODEL_SRTM, MODEL_SRTM2};
31static char *info[] = {
32 "Computation of parametric image of binding potential (BPnd) from",
33 "dynamic PET image in ECAT, NIfTI, or Analyze format applying simplified",
34 "reference tissue model (SRTM) [1]:",
35 " ______ K1' ___________ ",
36 " | | --> | | dCt(t)= ",
37 " | | <-- | Cr | +R1*dCr(t) ",
38 " | | k2'|___________| +k2*Cr(t) ",
39 " | | ____________________ -(k2/(1+BPnd))*Ct(t)",
40 " | Cp | K1 | k3 | | Ct(t)=Cf(t)+Cb(t) ",
41 " | | --> | Cf -------> Cb | ",
42 " | | <-- | <------- | ",
43 " | | k2 | | k4 | R1=K1/K1'=k2/k2' ",
44 " |______| |___________|________| BPnd=k3/k4 ",
46 "The model is transformed to general linear least squares functions [2],",
47 "which are solved using Lawson-Hanson non-negative least squares (NNLS)",
48 "algorithm [3]. BPnd is estimated directly without division [4].",
50 "Dynamic PET image and reference region TAC must be corrected for decay.",
52 "Usage: @P [Options] imgfile rtacfile bpfile",
56 " STRM2 method (5) is applied; in brief, traditional SRTM method is",
57 " used first to calculate median k2' from all pixels where BPnd>0; then",
58 " SRTM is run another time with fixed k2'",
60 " Programs computes also an R1 image.",
62 " Programs computes also a k2 image.",
64 " Program computes also a k2' image",
65 " -theta3=<filename> or -t3=<filename>",
66 " Program computes also a theta3 image; theta3 = k2/(1+BPnd)+lambda",
68 " Program writes regression parameters in the specified image file",
69 " -dual=<filename> or -du=<filename>",
70 " Program writes number of i in set p in NNLS dual solution vector in",
71 " the specified image file",
73 " Pixels with AUC less than (threshold/100 x ref AUC) are set to zero",
76 " Instead of BP, program saves the DVR (=BP+1) values.",
77 " -end=<Fit end time (min)>",
78 " Use data from 0 to end time; by default, model is fitted to all frames.",
82 " @P ua2918dy1.v ua2918cer.dft ua2918bp.v",
85 "1. Lammertsma AA, Hume SP. Simplified reference tissue model for PET",
86 " receptor studies. NeuroImage 1996;4:153-158.",
87 "2. Blomqvist G. On the construction of functional maps in positron emission",
88 " tomography. J Cereb Blood Flow Metab 1984;4:629-632.",
89 "3. Lawson CL & Hanson RJ. Solving least squares problems.",
90 " Prentice-Hall, 1974.",
91 "4. Zhou Y, Brasic J, Endres CJ, Kuwabara H, Kimes A, Contoreggi C, Maini A,",
92 " Ernst M, Wong DF. Binding potential image based statistical mapping for",
93 " detection of dopamine release by [11C]raclopride dynamic PET.",
94 " NeuroImage 2002;16:S91.",
95 "5. Wu Y, Carson RE. Noise reduction in the simplified reference tissue",
96 " model for neuroreceptor functional imaging. J Cereb Blood Flow Metab.",
97 " 2002;22:1440-1452.",
99 "See also: imgdv, imgbfbp, imgratio, imgunit, eframe, imgdecay, img2dft",
101 "Keywords: image, modelling, binding potential, SRTM, SRTM2, reference input",
120int main(
int argc,
char **argv)
122 int ai, help=0, version=0, verbose=1;
123 int pi, yi, xi, fi, ret;
124 int model=MODEL_SRTM, bp_plus_one=0, weight=0;
126 char inpfile[FILENAME_MAX], petfile[FILENAME_MAX], bpfile[FILENAME_MAX];
127 char r1file[FILENAME_MAX], k2file[FILENAME_MAX], k2sfile[FILENAME_MAX];
128 char t3file[FILENAME_MAX], regfile[FILENAME_MAX], dualfile[FILENAME_MAX];
129 char *cptr, tmp[512];
130 float threshold, calcThreshold=0.0;
131 double fittime=-1.0, f;
133 IMG pet, bpout, r1out, k2out, k2sout, t3out, tout, dualout;
134 clock_t fitStart, fitFinish;
136 double *ct, *cti, *cr, *cri;
138 int nnls_n, nnls_m, n, m, nnls_index[NNLS_N];
139 double *nnls_a[NNLS_N], *nnls_b, *nnls_zz, nnls_x[NNLS_N], *nnls_mat,
140 nnls_wp[NNLS_N], *dptr, nnls_rnorm;
147 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
148 inpfile[0]=petfile[0]=bpfile[0]=r1file[0]=k2file[0]=k2sfile[0]=(char)0;
149 t3file[0]=regfile[0]=dualfile[0]=(char)0;
151 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
153 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
154 if(strcasecmp(cptr,
"DVR")==0 || strcasecmp(cptr,
"BP+1")==0) {
155 bp_plus_one=1;
continue;
156 }
else if(*cptr==
'w' || *cptr==
'W') {
158 }
else if(strncasecmp(cptr,
"R1=", 3)==0) {
159 strlcpy(r1file, cptr+3, FILENAME_MAX);
continue;
160 }
else if(strncasecmp(cptr,
"k2=", 3)==0) {
161 strlcpy(k2file, cptr+3, FILENAME_MAX);
continue;
162 }
else if(strncasecmp(cptr,
"k2s=", 4)==0) {
163 strlcpy(k2sfile, cptr+4, FILENAME_MAX);
continue;
164 }
else if(strncasecmp(cptr,
"theta3=", 7)==0) {
165 strlcpy(t3file, cptr+7, FILENAME_MAX);
continue;
166 }
else if(strncasecmp(cptr,
"t3=", 3)==0) {
167 strlcpy(t3file, cptr+3, FILENAME_MAX);
continue;
168 }
else if(strncasecmp(cptr,
"dual=", 5)==0) {
169 strlcpy(dualfile, cptr+5, FILENAME_MAX);
continue;
170 }
else if(strncasecmp(cptr,
"du=", 3)==0) {
171 strlcpy(dualfile, cptr+3, FILENAME_MAX);
continue;
172 }
else if(strncasecmp(cptr,
"RP=", 3)==0) {
173 strlcpy(regfile, cptr+3, FILENAME_MAX);
continue;
174 }
else if(strncasecmp(cptr,
"THR=", 4)==0) {
176 if(!ret && v>=0.0 && v<=200.0) {calcThreshold=(float)(0.01*v);
continue;}
177 }
else if(strncasecmp(cptr,
"END=", 4)==0) {
178 fittime=
atof_dpi(cptr+4);
if(fittime>0.0)
continue;
179 }
else if(strcasecmp(cptr,
"SRTM2")==0) {
180 model=MODEL_SRTM2;
continue;
182 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
187 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
192 if(ai<argc)
strlcpy(petfile, argv[ai++], FILENAME_MAX);
193 if(ai<argc)
strlcpy(inpfile, argv[ai++], FILENAME_MAX);
194 if(ai<argc)
strlcpy(bpfile, argv[ai++], FILENAME_MAX);
196 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
201 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
204 if(strcasecmp(petfile, bpfile)==0 || strcasecmp(petfile, r1file)==0 ||
205 strcasecmp(petfile, k2file)==0 || strcasecmp(petfile, regfile)==0)
207 fprintf(stderr,
"Error: check the output filenames.\n");
212 printf(
"inpfile := %s\n", inpfile);
213 printf(
"petfile := %s\n", petfile);
214 printf(
"bpfile := %s\n", bpfile);
215 if(r1file[0]) printf(
"r1file := %s\n", r1file);
216 if(k2file[0]) printf(
"k2file := %s\n", k2file);
217 if(k2sfile[0]) printf(
"k2sfile := %s\n", k2sfile);
218 if(t3file[0]) printf(
"t3file := %s\n", t3file);
219 if(dualfile[0]) printf(
"dualfile := %s\n", dualfile);
220 if(regfile[0]) printf(
"regfile := %s\n", regfile);
221 printf(
"calcThreshold :=%g\n", calcThreshold);
222 printf(
"bp_plus_one := %d\n", bp_plus_one);
223 printf(
"weight := %d\n", weight);
224 if(fittime>0.0) printf(
"required_fittime := %g min\n", fittime);
225 printf(
"model := %d\n", model);
236 petfile, NULL, inpfile, NULL, NULL, &fittime, &fitdimt, &pet,
237 NULL, &tac, 1, stdout, verbose-2, tmp);
239 fprintf(stderr,
"Error: %s.\n", tmp);
240 if(verbose>1) printf(
" ret := %d\n", ret);
244 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
247 for(fi=0; fi<tac.
frameNr; fi++) tac.
voi[0].
y2[fi]/=60.0;
254 fprintf(stderr,
"Error: %s does not contain isotope halflife;\n", petfile);
255 fprintf(stderr,
" this is required with option -theta3=<filename>\n");
260 if(verbose>1) fprintf(stdout,
"lambda := %g [1/min]\n", lambda);
263 printf(
"fittimeFinal := %g min\n", fittime);
264 printf(
"fitdimt := %d\n", fitdimt);
268 fprintf(stderr,
"Error: too few time frames for fitting.\n");
278 fprintf(stderr,
"Error: cannot allocate memory.\n");
279 if(verbose>0) printf(
" ret := %d\n", ret);
288 threshold=calcThreshold*tac.
voi[0].
y2[fitdimt-1];
289 if(verbose>2) printf(
"threshold_AUC := %g\n", threshold);
295 if(verbose>1) printf(
"allocating memory for parametric images\n");
301 if(ret==0 && r1file[0])
303 if(ret==0 && k2file[0])
305 if(ret==0 && (k2sfile[0] || model==MODEL_SRTM2))
307 if(ret==0 && t3file[0])
309 if(ret==0 && dualfile[0])
312 fprintf(stderr,
"Error (%d): out of memory.\n", ret);
319 if(verbose>1) fprintf(stdout,
"setting parametric image headers\n");
321 tout.
unit=(char)CUNIT_UNITLESS;
322 bpout.
unit=(char)CUNIT_UNITLESS;
324 r1out.
unit=(char)CUNIT_UNITLESS;
328 k2out.
unit=(char)CUNIT_PER_MIN;
331 if(k2sfile[0] || model==MODEL_SRTM2) {
332 k2sout.
unit=(char)CUNIT_PER_MIN;
336 t3out.
unit=(char)CUNIT_PER_MIN;
340 dualout.
unit=(char)CUNIT_UNITLESS;
348 if(verbose>1) printf(
"allocating memory for NNLS\n");
349 nnls_n=NNLS_N; nnls_m=fitdimt;
350 nnls_mat=(
double*)malloc(((nnls_n+2)*nnls_m)*
sizeof(
double));
352 fprintf(stderr,
"Error: cannot allocate memory for NNLS.\n");
358 for(n=0, dptr=nnls_mat; n<nnls_n; n++) {nnls_a[n]=dptr; dptr+=nnls_m;}
359 nnls_b=dptr; dptr+=nnls_m; nnls_zz=dptr;
363 if(verbose>2) printf(
"working with NNLS weights\n");
370 for(m=0; m<nnls_m; m++) {
372 if(tac.
w[m]<=1.0e-20) tac.
w[m]=0.0;
381 if(verbose>0) fprintf(stdout,
"computing SRTM pixel-by-pixel\n");
384 int thresholded_nr=0, nosolution_nr=0;
386 for(pi=0; pi<pet.
dimz; pi++) {
387 if(verbose>2) printf(
"computing plane %d\n", pet.
planeNumber[pi]);
388 else if(pet.
dimz>1 && verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
389 for(yi=0; yi<pet.
dimy; yi++) {
390 for(xi=0; xi<pet.
dimx; xi++) {
392 for(n=0; n<nnls_n; n++) tout.
m[0][yi][xi][n]=0.0;
394 for(fi=0; fi<tac.
frameNr; fi++) ct[fi]=pet.
m[pi][yi][xi][fi];
396 if(verbose>6 && pi==pet.
dimz/2 && yi==pet.
dimy/3 && xi==pet.
dimx/3) {
397 printf(
"\nExample pixel pi=%d yi=%d xi=%d\n", pi, yi, xi);
398 printf(
" Cr Cri Ct Cti\n");
399 for(m=0; m<nnls_m; m++)
400 printf(
"%12.4f %12.4f %12.4f %12.4f\n", cr[m],cri[m],ct[m],cti[m]);
403 if(cti[fitdimt-1]<threshold) {
409 if(model==MODEL_SRTM2 ||
410 r1file[0] || k2file[0] || k2sfile[0] || t3file[0])
414 for(m=0; m<nnls_m; m++) nnls_a[0][m]=cr[m];
416 for(m=0; m<nnls_m; m++) nnls_a[1][m]=cri[m];
418 for(m=0; m<nnls_m; m++) nnls_a[2][m]=-cti[m];
420 for(m=0; m<nnls_m; m++) nnls_b[m]=ct[m];
423 if(verbose>6 && pi==pet.
dimz/2 && yi==pet.
dimy/3 && xi==pet.
dimx/3) {
424 printf(
"Matrix A Array B\n");
425 for(m=0; m<nnls_m; m++) {
426 printf(
"%12.3f %12.3f %12.3f %12.3f\n",
427 nnls_a[0][m], nnls_a[1][m], nnls_a[2][m], nnls_b[m]);
431 ret=
nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm,
432 nnls_wp, nnls_zz, nnls_index);
434 nosolution_nr++;
continue;
436 for(n=0; n<nnls_n; n++) tout.
m[pi][yi][xi][n]=nnls_x[n];
438 if(r1file[0]) r1out.
m[pi][yi][xi][0]=nnls_x[0];
440 if(k2file[0]) k2out.
m[pi][yi][xi][0]=nnls_x[1];
443 if(nnls_wp[2]==0.0) t3out.
m[pi][yi][xi][0]=nnls_x[2]+lambda;
444 else t3out.
m[pi][yi][xi][0]=0.0;
447 if(k2sfile[0] || model==MODEL_SRTM2) {
448 if(nnls_x[2]>0.0) f=nnls_x[1]/nnls_x[2];
else f=0.0;
449 if(f>1.0 && nnls_x[0]>0.0 && nnls_x[1]>0.0)
450 k2sout.
m[pi][yi][xi][0]=nnls_x[1]/nnls_x[0];
455 if(model==MODEL_SRTM2)
continue;
457 for(n=0; n<nnls_n; n++) tout.
m[0][yi][xi][n]=0.0;
461 for(m=0; m<nnls_m; m++) nnls_a[0][m]=cr[m];
463 for(m=0; m<nnls_m; m++) nnls_a[1][m]=cri[m];
465 for(m=0; m<nnls_m; m++) nnls_a[2][m]=-ct[m];
467 for(m=0; m<nnls_m; m++) nnls_b[m]=cti[m];
470 if(verbose>6 && pi==pet.
dimz/2 && yi==pet.
dimy/3 && xi==pet.
dimx/3) {
471 printf(
"Matrix A Array B\n");
472 for(m=0; m<nnls_m; m++) {
473 printf(
"%12.3f %12.3f %12.3f %12.3f\n",
474 nnls_a[0][m], nnls_a[1][m], nnls_a[2][m], nnls_b[m]);
479 ret=
nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm,
480 nnls_wp, nnls_zz, nnls_index);
482 for(n=0; n<nnls_n; n++) tout.
m[pi][yi][xi][n]=nnls_x[n];
484 bpout.
m[pi][yi][xi][0]=nnls_x[1];
485 if(!bp_plus_one) bpout.
m[pi][yi][xi][0]-=1.0;
486 if(verbose>6 && pi==pet.
dimz/2 && yi==pet.
dimy/3 && xi==pet.
dimx/3) {
487 for(n=0; n<nnls_n; n++) printf(
" nnls_x[%d]=%g", n, nnls_x[n]);
488 printf(
" bpout.m[%d][%d][%d][0]=%g\n",
489 pi, yi, xi, bpout.
m[pi][yi][xi][0]);
492 for(n=m=0; n<nnls_n; n++)
if(nnls_wp[n]==0.0) m++;
493 if(dualfile[0]) dualout.
m[pi][yi][xi][0]=m;
500 fprintf(stdout,
"\n");
501 if(model==MODEL_SRTM2) fprintf(stdout,
"first step ");
502 fprintf(stdout,
"done.\n");
504 if(verbose>1 || thresholded_nr>0)
505 fprintf(stdout,
"%d pixels were not fitted due to threshold.\n",
507 if(verbose>1 || nosolution_nr>0)
508 fprintf(stdout,
"no NNLS solution for %d pixels.\n", nosolution_nr);
514 if(model==MODEL_SRTM2) {
516 if(verbose>0) fprintf(stdout,
"calculating median of k2'\n");
518 for(n=pi=0; pi<pet.
dimz; pi++)
519 for(yi=0; yi<pet.
dimy; yi++)
for(xi=0; xi<pet.
dimx; xi++)
520 if(k2sout.
m[pi][yi][xi][0]>0.0001) n++;
521 if(verbose>1) fprintf(stdout,
"BP>0 and k2'>0 in %d pixels.\n", n);
523 double *k2sarray, k2smedian, sd;
524 k2sarray=(
double*)malloc(n*
sizeof(
double));
526 fprintf(stderr,
"Error: cannot allocate memory for k2' values.\n");
534 for(n=pi=0; pi<pet.
dimz; pi++)
535 for(yi=0; yi<pet.
dimy; yi++)
for(xi=0; xi<pet.
dimx; xi++)
536 if(k2sout.
m[pi][yi][xi][0]>0.0001)
537 k2sarray[n++]=k2sout.
m[pi][yi][xi][0];
538 k2smedian=
dmedian(k2sarray, n);
539 if(verbose>0) fprintf(stdout,
"k2s_median := %g\n", k2smedian);
541 f=
dmean(k2sarray, n, &sd);
542 fprintf(stdout,
"k2s_mean := %g +- %g\n", f, sd);
547 if(verbose>1) fprintf(stdout,
"allocating memory for the second NNLS\n");
548 nnls_n=2; nnls_m=fitdimt;
549 nnls_mat=(
double*)malloc(((nnls_n+2)*nnls_m)*
sizeof(
double));
551 fprintf(stderr,
"Error: cannot allocate memory for NNLS.\n");
557 for(n=0, dptr=nnls_mat; n<nnls_n; n++) {nnls_a[n]=dptr; dptr+=nnls_m;}
558 nnls_b=dptr; dptr+=nnls_m; nnls_zz=dptr;
560 if(verbose>0) fprintf(stdout,
"computing SRTM2 2nd step pixel-by-pixel\n");
564 thresholded_nr=0; nosolution_nr=0;
565 for(pi=0; pi<pet.
dimz; pi++) {
566 if(verbose>2) printf(
"computing plane %d\n", pet.
planeNumber[pi]);
567 else if(pet.
dimz>1 && verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
568 for(yi=0; yi<pet.
dimy; yi++) {
569 for(xi=0; xi<pet.
dimx; xi++) {
571 for(n=0; n<(nnls_n+1); n++) tout.
m[0][yi][xi][n]=0.0;
572 bpout.
m[pi][yi][xi][0]=0.0;
574 for(fi=0; fi<tac.
frameNr; fi++) ct[fi]=pet.
m[pi][yi][xi][fi];
577 if(cti[fitdimt-1]<threshold) {
578 thresholded_nr++;
continue;
584 for(m=0; m<nnls_m; m++) nnls_a[0][m]=cr[m]+k2smedian*cri[m];
585 for(m=0; m<nnls_m; m++) nnls_a[1][m]=-ct[m];
587 for(m=0; m<nnls_m; m++) nnls_b[m]=k2smedian*cti[m];
592 ret=
nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm,
593 nnls_wp, nnls_zz, nnls_index);
595 nosolution_nr++;
continue;
597 for(n=0; n<nnls_n; n++) tout.
m[pi][yi][xi][n]=nnls_x[n];
599 bpout.
m[pi][yi][xi][0]=nnls_x[0];
600 if(!bp_plus_one) bpout.
m[pi][yi][xi][0]-=1.0;
601 if(verbose>6 && pi==pet.
dimz/2 && yi==pet.
dimy/3 && xi==pet.
dimx/3) {
602 for(n=0; n<nnls_n; n++) printf(
"\n nnls_x[%d]=%g", n, nnls_x[n]);
603 printf(
" bpout.m[%d][%d][%d][0]=%g\n",
604 pi, yi, xi, bpout.
m[pi][yi][xi][0]);
608 if(!r1file[0])
continue;
611 for(m=0; m<nnls_m; m++) nnls_a[0][m]=cr[m]+k2smedian*cri[m];
612 for(m=0; m<nnls_m; m++) nnls_a[1][m]=-k2smedian*cti[m];
614 for(m=0; m<nnls_m; m++) nnls_b[m]=ct[m];
619 ret=
nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm,
620 nnls_wp, nnls_zz, nnls_index);
623 r1out.
m[pi][yi][xi][0]=nnls_x[0];
631 fprintf(stdout,
"\ndone.\n");
633 if(verbose>1 || thresholded_nr>0)
634 fprintf(stdout,
"%d pixels were not fitted due to threshold.\n",
636 if(verbose>1 || nosolution_nr>0)
637 fprintf(stdout,
"no NNLS solution for %d pixels.\n", nosolution_nr);
648 if(verbose>1) fprintf(stdout,
"writing parametric images\n");
651 fprintf(stderr,
"Error: %s\n", bpout.
statmsg);
658 if(!bp_plus_one) fprintf(stdout,
"BP image written in %s\n", bpfile);
659 else fprintf(stdout,
"(BP+1) image written in %s\n", bpfile);
664 fprintf(stderr,
"Error: %s\n", r1out.
statmsg);
670 if(verbose>0) fprintf(stdout,
"R1 image written in %s\n", r1file);
675 fprintf(stderr,
"Error: %s\n", k2out.
statmsg);
681 if(verbose>0) fprintf(stdout,
"k2 image written in %s\n", k2file);
686 fprintf(stderr,
"Error: %s\n", k2sout.
statmsg);
692 if(verbose>0) fprintf(stdout,
"k2' image written in %s\n", k2sfile);
697 fprintf(stderr,
"Error: %s\n", t3out.
statmsg);
703 if(verbose>0) fprintf(stdout,
"theta3 image written in %s\n", t3file);
708 fprintf(stderr,
"Error: %s\n", dualout.
statmsg);
715 fprintf(stdout,
"dual solution image written in %s\n", dualfile);
720 fprintf(stderr,
"Error: %s\n", tout.
statmsg);
727 fprintf(stdout,
"Regression parameter image written in %s\n", regfile);
735 if(verbose>1) fprintf(stdout,
"parameter estimation time := %.1f [s]\n",
736 (
double)(fitFinish-fitStart) / CLOCKS_PER_SEC );
int atof_with_check(char *double_as_string, double *result_value)
double atof_dpi(char *str)
int dftAddmem(DFT *dft, int voiNr)
int dftTimeunitConversion(DFT *dft, int tunit)
unsigned long long imgNaNs(IMG *img, int fix)
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
void imgEmpty(IMG *image)
int imgWrite(const char *fname, IMG *img)
int petintegral(double *x1, double *x2, double *y, int nr, double *ie, double *iie)
Integrate PET TAC data to frame mid times.
Header file for libtpccurveio.
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)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Header file for libtpcmodel.
int nnls(double **a, int m, int n, double *b, double *x, double *rnorm, double *w, double *zz, int *index)
int nnlsWght(int N, int M, double **A, double *b, double *weight)
double dmean(double *data, int n, double *sd)
double dmedian(double *data, int n)
Header file for libtpcmodext.
char voiname[MAX_REGIONSUBNAME_LEN+1]