13int resQSortComp(
const void *f1,
const void *f2);
14int resQSortName(
const void *voi1,
const void *voi2);
28 free((
char*)(res->
voi));
57 memset(res, 0,
sizeof(
RES));
79 if(res==NULL || voiNr<1)
return(1);
86 if(res->
voi==NULL)
return(2);
112 char *cptr, tmp[1024], *lptr;
114 if(
RESULT_TEST>0) printf(
"resFixParnames(*res)\n");
115 if(res==NULL)
return;
116 if(res->
parNr<1)
return;
120 for(i=n=0; i<res->
parNr; i++) {
121 len=strlen(res->
parname[i]);
if(len<1)
continue;
122 if(strcmp(res->
parname[i],
".")==0)
continue;
127 for(i=0; i<res->
parNr; i++) {
135 for(i=0; i<res->
parNr; i++) {
139 if(len<1) strcat(res->
unitline,
".");
143 printf(
"Parameter names and units:\n");
144 for(i=0; i<res->
parNr; i++)
145 printf(
" %d: '%s' '%s'\n", i+1, res->
parname[i], res->
parunit[i]);
146 printf(
"Created titleline: %s\n", res->
titleline);
147 printf(
"Created unitline: %s\n", res->
unitline);
153 for(i=0; i<res->
parNr; i++) {
157 strcpy(tmp, res->
titleline); lptr=tmp; cptr=strtok(lptr,
" \t\n\r");
158 i=0;
while(cptr!=NULL && i<res->parNr) {
159 if(strcmp(cptr,
".")==0) {i++;
continue;}
162 cptr=strtok(NULL,
" \t\n\r"); i++;
164 strcpy(tmp, res->
unitline); lptr=tmp; cptr=strtok(lptr,
" \t\n\r");
165 i=0;
while(cptr!=NULL && i<res->parNr) {
166 if(strcmp(cptr,
".")==0) {i++;
continue;}
169 cptr=strtok(NULL,
" \t\n\r"); i++;
172 printf(
"Original titleline: %s\n", res->
titleline);
173 printf(
"Original unitline: %s\n", res->
unitline);
174 printf(
"Resolved parameter names and units:\n");
175 for(i=0; i<res->
parNr; i++)
176 printf(
" %d: '%s' '%s'\n", i+1, res->
parname[i], res->
parunit[i]);
208 char *cptr, line[1024], *lptr, tmp[1024];
213 if(verbose>0) printf(
"resRead(%s, *res);\n", filename);
214 if(res==NULL)
return(1);
221 fp=fopen(filename,
"rb");
222 if(fp==NULL) {strcpy(
reserrmsg,
"cannot open file");
return(1);}
230 if(verbose>1) printf(
"reading program name\n");
231 while(fgets(line, 1024, fp)!=NULL) {
233 if(strlen(line)<4 || line[0]==
'#')
continue;
else break;
236 if(strstr(line,
"(c)") || strstr(line,
"(C)")) {
237 i=strlen(line)-1;
while(i>0 && isspace(line[i])) i--; line[i+1]=(char)0;
238 if(i<4) {fclose(fp);
return(2);}
240 }
else {fclose(fp);
return(2);}
243 if(verbose>1) printf(
"reading date and time\n");
244 while(fgets(line, 1024, fp)!=NULL)
if(strlen(line)>2 && line[0]!=
'#')
break;
245 if(strncasecmp(line,
"Date:", 5)) {fclose(fp);
return(4);}
246 cptr=&line[5];
while(isblank(cptr[0])) cptr++;
248 if(verbose>3) printf(
"date_str := %s", cptr);
252 else res->
time=(time_t)0;
256 if(verbose>1) printf(
"reading headers\n");
259 while((lptr=fgets(line, 1024, fp))!=NULL) {
260 if(strlen(line)>2 && line[0]!=
'#')
break;
261 if(lptr!=NULL && verbose>6)
262 printf(
"omitted line[%d] := %s", (
int)strlen(line), line);
264 if(lptr==NULL)
break;
266 n=0;
if(verbose>3) printf(
"line[%d] := %s", (
int)strlen(line), line);
267 if(strncasecmp(line,
"Study", 5)==0) {
268 lptr=&tmp[6]; cptr=strtok(lptr,
" \t\n\r"); n=1;
269 if(cptr!=NULL && strlen(cptr)<1024) {
272 }
else if(strncasecmp(line,
"Data file", 9)==0) {
273 lptr=&tmp[10]; cptr=strtok(lptr,
" \t\n\r"); n=1;
274 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->
datafile, cptr);
275 }
else if(strncasecmp(line,
"ROI file", 8)==0) {
276 lptr=&tmp[9]; cptr=strtok(lptr,
" \t\n\r"); n=1;
277 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->
datafile, cptr);
278 }
else if(strncasecmp(line,
"Plasma file", 11)==0) {
279 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
280 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->
plasmafile, cptr);
282 while(isspace((
int)*cptr)) {*cptr=(char)0; cptr--;}
283 }
else if(strncasecmp(line,
"2nd Plasma file", 15)==0) {
284 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
285 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->
plasmafile2, cptr);
287 while(isspace((
int)*cptr)) {*cptr=(char)0; cptr--;}
288 }
else if(strncasecmp(line,
"Blood file", 10)==0) {
289 lptr=&tmp[11]; cptr=strtok(lptr,
" \t\n\r"); n=1;
290 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->
bloodfile, cptr);
291 }
else if(strncasecmp(line,
"Reference file", 14)==0) {
292 lptr=&tmp[15]; cptr=strtok(lptr,
" \t\n\r"); n=1;
293 if(cptr!=NULL && strlen(cptr)<1024) strcpy(res->
reffile, cptr);
294 }
else if(strncasecmp(line,
"Reference region", 16)==0) {
295 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
296 if(cptr!=NULL && strlen(cptr)<64) strcpy(res->
refroi, cptr);
298 while(isspace((
int)*cptr)) {*cptr=(char)0; cptr--;}
299 }
else if(strncasecmp(line,
"Fit time", 8)==0 || strncasecmp(line,
"Data range", 10)==0) {
300 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
301 if(cptr!=NULL && strlen(cptr)<128) strcpy(res->
datarange, cptr);
303 while(isspace((
int)*cptr)) {*cptr=(char)0; cptr--;}
304 }
else if(strncasecmp(line,
"Data nr", 7)==0) {
305 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
306 if(cptr!=NULL) res->
datanr=atoi(cptr);
307 }
else if(strncasecmp(line,
"Fit method", 10)==0) {
308 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
309 if(cptr!=NULL && strlen(cptr)<128) strcpy(res->
fitmethod, cptr);
311 while(isspace((
int)*cptr)) {*cptr=(char)0; cptr--;}
312 }
else if(strncasecmp(line,
"Tissue density", 14)==0) {
313 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
315 }
else if(strncasecmp(line,
"Lumped constant", 15)==0) {
316 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
318 }
else if(strncasecmp(line,
"Concentration", 13)==0) {
319 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
321 }
else if(strncasecmp(line,
"Beta", 4)==0) {
322 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
324 }
else if(strncasecmp(line,
"Vb", 2)==0) {
325 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
327 }
else if(strncasecmp(line,
"fA", 2)==0) {
328 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
330 }
else if(strncasecmp(line,
"Extraction", 10)==0) {
331 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
333 }
else if(strncasecmp(line,
"Weighting", 9)==0) {
334 cptr=strchr(tmp,
':')+1;
while(isspace((
int)*cptr)) cptr++; n=1;
335 if(strncasecmp(cptr,
"yes", 1)==0) res->
isweight=1;
336 else if(strncasecmp(cptr,
"no", 1)==0) res->
isweight=0;
338 }
else if(strncasecmp(line,
"Data was weighted", 17)==0) {
340 }
else if(strncasecmp(line,
"Data was not weighted", 21)==0) {
342 }
else if(strncasecmp(line,
"Region", 6)==0) {
349 if(verbose>6) printf(
"quit reading headers\n");
352 if(verbose>1) printf(
"reading parameter titles\n");
353 if(verbose>6) printf(
"using previously read line[%d] := %s", (
int)strlen(line), line);
354 if(strncasecmp(line,
"Region", 6)) {fclose(fp);
return(10);}
356 lptr=strpbrk(tmp+6,
" \n\r\t");
if(lptr==NULL) {fclose(fp);
return(10);}
357 cptr=strtok(lptr,
" \n\r\t");
360 if(strcmp(cptr,
".")!=0) {
363 }
else {strcpy(res->
parname[n],
"");}
364 if(verbose>5) printf(
" parname[%d] := '%s'\n", n, res->
parname[n]);
366 }
else {strcpy(res->
parname[n],
"");}
368 cptr=strtok(NULL,
" \n\r\t");
370 if(strcmp(cptr,
".")!=0) {
373 }
else {strcpy(res->
parname[n],
"");}
374 if(verbose>5) printf(
" parname[%d] := '%s'\n", n, res->
parname[n]);
378 res->
parNr=n;
if(verbose>1) printf(
"parNr := %d\n", res->
parNr);
381 if(verbose>2) printf(
"seeking unit line...\n");
382 if(fgetpos(fp, &file_loc)!=0) {fclose(fp);
return(20);}
383 while(fgets(line, 1024, fp)!=NULL && strlen(line)<3) {
384 if(verbose>6) printf(
"omitted line[%d] := %s", (
int)strlen(line), line);
386 if(fgetpos(fp, &file_loc)!=0) {fclose(fp);
return(20);}
388 if(verbose>5) printf(
"possible unit line[%d]: %s", (
int)strlen(line), line);
389 if(strncasecmp(line,
"# Units :", 7)==0 ||
390 strncasecmp(line,
"Units : ", 7)==0 ||
391 strncasecmp(line,
"# Units: ", 7)==0 ||
392 strncasecmp(line,
"Units: ", 6)==0)
394 if(verbose>1) printf(
"reading parameter units\n");
395 strcpy(tmp, line); lptr=strchr(tmp+5,
':');
396 if(lptr!=NULL) lptr++;
else lptr=strpbrk(tmp+6,
" \n\r\t");
397 cptr=strtok(lptr,
" \n\r\t"); n=0;
399 if(strcmp(cptr,
".")!=0) {
402 }
else {strcpy(res->
parunit[n],
"");}
403 if(verbose>5) printf(
" parunit[%d] := '%s'\n", n, res->
parunit[n]);
405 }
else {strcpy(res->
parunit[n],
"");}
407 cptr=strtok(NULL,
" \n\r\t");
409 if(strcmp(cptr,
".")!=0) {
412 }
else strcpy(res->
parunit[n],
"");
413 if(verbose>5) printf(
" parunit[%d] := '%s'\n", n, res->
parunit[n]);
418 if(verbose>5) printf(
" ... not identified as unit line.\n");
420 if(fsetpos(fp, &file_loc)!=0) {fclose(fp);
return(20);}
424 if(verbose>1) printf(
"reading nr of results\n");
426 if(fgetpos(fp, &file_loc)!=0) {fclose(fp);
return(21);}
428 while(fgets(line, 1024, fp)!=NULL) {
429 if(verbose>6) printf(
"line[%d] := %s", (
int)strlen(line), line);
430 if(line[0]==
'#' || line[0]==
';')
continue;
431 i=strlen(line);
if(i<2)
continue;
if(i<3)
break;
435 if(fsetpos(fp, &file_loc)!=0) {fclose(fp);
return(22);}
436 if(verbose>1) printf(
"nr of result lines is %d\n", n);
438 strcpy(
reserrmsg,
"invalid result lines");
439 fclose(fp);
return(23);
443 if(verbose>2) printf(
"allocating memory\n");
445 strcpy(
reserrmsg,
"cannot allocate memory");
446 fclose(fp);
return(25);
450 if(verbose>1) printf(
"reading results to memory\n");
454 while(fgets(line, 1024, fp)!=NULL) {
455 if(verbose>6) printf(
"line[%d] := %s", (
int)strlen(line), line);
456 if(line[0]==
'#' || line[0]==
';')
continue;
457 i=strlen(line);
if(i<2)
continue;
if(i<3)
break;
459 if(verbose>2) printf(
"reading result %d\n", 1+res->
voiNr);
462 if(strchr(tmp,
'\t')==NULL) separtab=0;
else separtab=1;
463 if(separtab) strcpy(separstr,
"\t\n\r");
else strcpy(separstr,
" \t\n\r");
465 if(verbose>20) printf(
" tokenNr := %d\n", tokenNr);
467 if(verbose>20) printf(
"separator: space\n");
469 if(n==0) {fclose(fp);
return(31);}
471 if(n==0) {fclose(fp);
return(31);}
473 if(n==0) {fclose(fp);
return(31);}
477 if(verbose>20) printf(
"separator: tab\n");
479 if(n==0) {fclose(fp);
return(31);}
493 int tokeni=2;
if(!separtab) tokeni=4;
495 for(i=0; i<
MAX_RESPARAMS && tokeni<=tokenNr; i++, tokeni++) {
497 if(n==0) {fclose(fp);
return(32);}
501 if(verbose>5) printf(
" for '%s' parNr:=%d\n", res->
voi[res->
voiNr].
name, i);
505 printf(
"Warning: smaller parNr %d on region '%s'\n", i, res->
voi[res->
voiNr].
name);
515 for(i=0; i<res->
parNr; i++)
518 for(i=0; i<res->
parNr; i++)
523 for(i=0; i<res->
parNr; i++)
529 if(res->
parNr==0) {fclose(fp);
return(33);}
530 if(verbose>0) printf(
"nr of results: %d ; nr of parameters: %d\n", res->
voiNr, res->
parNr);
533 while(fgets(line, 1024, fp)!=NULL) {
535 if(strlen(line)<3 || line[0]==
'#')
continue;
else break;
538 if(strstr(line,
"(c)") || strstr(line,
"(C)")) {
540 "Warning: %s contains more than one set of results; only the 1st one is used.\n", filename);
574 char tmp[1024], is_stdout=0, *cptr;
581 if(verbose>1) printf(
"resWrite(*res, %s, %d)\n", filename, verbose);
583 if(res==NULL) {strcpy(
reserrmsg,
"error in result data");
return(1);}
584 if(res->
voiNr<1) {strcpy(
reserrmsg,
"no result data");
return(1);}
587 cptr=strrchr(filename,
'.');
588 if(cptr!=NULL && (!strncasecmp(cptr,
".htm", 4)))
592 if(!strcasecmp(filename,
"stdout")) is_stdout=1;
600 if(is_stdout) fp=(FILE*)stdout;
601 else if((fp = fopen(filename,
"w")) == NULL) {
602 strcpy(
reserrmsg,
"cannot open file");
return(2);}
605 n=fprintf(fp,
"%s\n\n", res->
program);
608 if(!is_stdout) fclose(fp);
614 fprintf(fp,
"Date:\t%s\n", tmp);
624 if(res->
reffile[0]) fprintf(fp,
"Reference file:\t%s\n", res->
reffile);
625 if(res->
refroi[0]) fprintf(fp,
"Reference region:\t%s\n", res->
refroi);
629 if(res->
datanr>0) fprintf(fp,
"Data nr:\t%d\n", res->
datanr);
633 if(res->
density>0.0) fprintf(fp,
"Tissue density:\t%g\n", res->
density);
634 if(res->
lc>0.0) fprintf(fp,
"Lumped constant:\t%g\n", res->
lc);
637 if(res->
beta>0.0) fprintf(fp,
"Beta:\t%g\n", res->
beta);
638 if(res->
Vb>=0.0) fprintf(fp,
"Vb:\t%g %%\n", res->
Vb);
639 if(res->
fA>=0.0) fprintf(fp,
"fA:\t%g %%\n", res->
fA);
640 if(res->
E>=0.0) fprintf(fp,
"Extraction:\t%g\n", res->
E);
643 if(res->
isweight>0) strcpy(tmp,
"yes");
644 else if(res->
isweight==0) strcpy(tmp,
"no");
645 else strcpy(tmp,
"unknown");
646 fprintf(fp,
"Weighting:\t%s\n", tmp);
649 for(j=0; j<res->
parNr; j++) colwidth[j]=1;
651 for(j=0; j<res->
parNr; j++) {
655 for(j=0; j<res->
parNr; j++) colwidth[j]=strlen(res->
parname[j]);
657 printf(
"col widths after titles were checked:\n");
658 for(i=0; i<res->
parNr; i++)
659 printf(
" par%d : partype=%d colwidth=%d\n", i+1, partype[i], colwidth[i]);
662 for(j=0; j<res->
parNr; j++) {
663 n=strlen(res->
parunit[j]);
if(n>colwidth[j]) colwidth[j]=n;
666 printf(
"col widths after units were checked:\n");
667 for(i=0; i<res->
parNr; i++)
668 printf(
" par%d : partype=%d colwidth=%d\n", i+1, partype[i], colwidth[i]);
671 for(i=0; i<res->
voiNr; i++) {
673 for(j=0; j<res->
parNr; j++) {
674 if(isnan(p[j]))
continue;
675 if(p[j]>=0) n=4;
else n=3;
677 case 0: sprintf(tmp,
"%.0f", p[j]);
break;
678 case 1: sprintf(tmp,
"%.*f", n, p[j]);
break;
680 default: sprintf(tmp,
"%.*e", n, p[j]);
break;
682 n=strlen(tmp);
if(n>colwidth[j]) colwidth[j]=n;
686 printf(
"col widths after result values were checked:\n");
687 for(i=0; i<res->
parNr; i++)
688 printf(
" par%d : partype=%d colwidth=%d\n", i+1, partype[i], colwidth[i]);
693 printf(
" writing title line with %d parameter(s)\n", res->
parNr);
696 fprintf(fp,
"\n%s\t",
"Region");
697 for(i=0; i<res->
parNr; i++) {
698 if(strlen(res->
parname[i])<1) strcpy(tmp,
".");
699 else strcpy(tmp, res->
parname[i]);
700 fprintf(fp,
"\t%s", tmp);
705 for(i=j=0; i<res->
parNr; i++)
if(strlen(res->
parunit[i])>0) j++;
708 printf(
" writing units line with %d parameter(s)\n", j);
711 fprintf(fp,
"%s",
"# Units:");
713 for(i=0; i<res->
parNr; i++) {
714 if(strlen(res->
parunit[i])<1) strcpy(tmp,
".");
715 else strcpy(tmp, res->
parunit[i]);
716 fprintf(fp,
"\t%s", tmp);
724 printf(
" writing %d regional results\n", res->
voiNr); fflush(stdout);
726 for(i=0; i<res->
voiNr; i++) {
727 if(verbose>6) {printf(
" writing region %d\n", 1+i); fflush(stdout);}
730 fprintf(fp,
"%s", res->
voi[i].
name);
736 if(res->
voi[i].
place[0]) strcpy(tmp, res->
voi[i].
place);
else strcpy(tmp,
".");
741 strcpy(tmp, res->
voi[i].
voiname);
else strcpy(tmp,
".");
747 strcpy(tmp, res->
voi[i].
place);
else strcpy(tmp,
".");
751 for(j=0; j<res->
parNr; j++) {
752 if(verbose>15) {printf(
" writing par %d\n", 1+j); fflush(stdout);}
753 if(isnan(p[j])) {fprintf(fp,
"\t.");
continue;}
755 case 0: fprintf(fp,
"\t%.0f", p[j]);
break;
757 if(p[j]>=0) n=4;
else n=3;
758 fprintf(fp,
"\t%.*f", n, p[j]);
761 if(p[j]>=0) n=4;
else n=3;
762 fprintf(fp,
"\t%.*e", n, p[j]);
766 fprintf(fp,
"\n"); fflush(fp);
768 if(verbose>25) {printf(
" sd?\n"); fflush(stdout);}
770 if(verbose>25) {printf(
" parNr=%d\n", res->
parNr); fflush(stdout);}
771 n=0;
for(
int j=0; j<res->
parNr; j++) {
if(!isnan(res->
voi[i].
sd[j])) n++;}
772 if(verbose>25) {printf(
" n=%d\n", n); fflush(stdout);}
774 fprintf(fp,
"SD . .");
775 for(j=0; j<res->
parNr; j++) {
776 if(verbose>15) {printf(
" writing sd %d\n", 1+j); fflush(stdout);}
777 if(!isnan(res->
voi[i].
sd[j])) {
779 case 0: fprintf(fp,
"\t%.0f", res->
voi[i].
sd[j]);
break;
781 if(res->
voi[i].
sd[j]>=0) n=4;
else n=3;
782 fprintf(fp,
"\t%.*f", n, res->
voi[i].
sd[j]);
785 if(res->
voi[i].
sd[j]>=0) n=4;
else n=3;
786 fprintf(fp,
"\t%.*e", n, res->
voi[i].
sd[j]);
793 fprintf(fp,
"\n"); fflush(fp);
796 if(verbose>25) {printf(
" cl1?\n"); fflush(stdout);}
797 n=0;
for(
int j=0; j<res->
parNr; j++)
if(!isnan(res->
voi[i].
cl1[j])) n++;
798 if(verbose>25) {printf(
" n=%d\n", n); fflush(stdout);}
800 fprintf(fp,
"CL 95%% Lower");
801 for(j=0; j<res->
parNr; j++) {
802 if(verbose>15) {printf(
" writing CL1 %d\n", 1+j); fflush(stdout);}
803 if(!isnan(res->
voi[i].
cl1[j])) {
805 case 0: fprintf(fp,
"\t%.0f", res->
voi[i].
cl1[j]);
break;
807 if(res->
voi[i].
cl1[j]>=0) n=4;
else n=3;
808 fprintf(fp,
"\t%.*f", n, res->
voi[i].
cl1[j]);
811 if(res->
voi[i].
cl1[j]>=0) n=4;
else n=3;
812 fprintf(fp,
"\t%.*e", n, res->
voi[i].
cl1[j]);
822 if(verbose>25) {printf(
" cl2?\n"); fflush(stdout);}
823 n=0;
for(
int j=0; j<res->
parNr; j++)
if(!isnan(res->
voi[i].
cl2[j])) n++;
824 if(verbose>25) {printf(
" n=%d\n", n); fflush(stdout);}
826 fprintf(fp,
"CL 95%% Upper");
827 for(j=0; j<res->
parNr; j++) {
828 if(verbose>15) {printf(
" writing CL2 %d\n", 1+j); fflush(stdout);}
829 if(!isnan(res->
voi[i].
cl2[j])) {
831 case 0: fprintf(fp,
"\t%.0f", res->
voi[i].
cl2[j]);
break;
833 if(res->
voi[i].
cl2[j]>=0) n=4;
else n=3;
834 fprintf(fp,
"\t%.*f", n, res->
voi[i].
cl2[j]);
837 if(res->
voi[i].
cl2[j]>=0) n=4;
else n=3;
838 fprintf(fp,
"\t%.*e", n, res->
voi[i].
cl2[j]);
845 fprintf(fp,
"\n"); fflush(fp);
850 if(!is_stdout) {fflush(fp); fclose(fp);}
852 if(verbose>1) {printf(
"resWrite() done.\n"); fflush(stdout);}
878 if(verbose>0) printf(
"resWriteHTML(*res, %s, %d)\n", fname, verbose);
880 if(res==NULL) {strcpy(
reserrmsg,
"error in result data");
return(1);}
881 if(res->
voiNr<1) {strcpy(
reserrmsg,
"no result data");
return(1);}
883 if(!strcasecmp(fname,
"stdout")) is_stdout=1;
888 if(!is_stdout && access(fname, 0) != -1) {
890 if(access(tmp, 0)!=-1) remove(tmp);
896 if(is_stdout) fp=(FILE*)stdout;
897 else if((fp=fopen(fname,
"w"))==NULL) {
898 strcpy(
reserrmsg,
"cannot open file");
return(2);}
903 if(!is_stdout) fclose(fp);
908 fprintf(fp,
"\n<body>\n");
911 fprintf(fp,
"\n<div id=\"tables\">\n");
916 if(!is_stdout) fclose(fp);
921 fprintf(fp,
"</div>\n");
922 n=fprintf(fp,
"</body></html>\n\n");
925 if(!is_stdout) fclose(fp);
930 if(!is_stdout) {fflush(fp); fclose(fp);}
946 if(fp==NULL)
return(1);
947 n=fprintf(fp,
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" ");
948 n+=fprintf(fp,
"\"https://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n");
950 n=fprintf(fp,
"<html xmlns=\"https://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n\n");
967 if(fp==NULL)
return(1);
969 n=fprintf(fp,
"<head>\n");
if(n<6)
return(2);
970 fprintf(fp,
" <title>Tabulated PET results</title>\n");
971 fprintf(fp,
" <meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\" />\n");
972 fprintf(fp,
" <meta http-equiv=\"content-language\" content=\"en-gb\" />\n");
973 fprintf(fp,
" <meta name=\"description\" content=\"Regional PET results\" />\n");
974 fprintf(fp,
" <meta name=\"author\" content=\"%s\" />\n", author_name);
975 fprintf(fp,
" <meta name=\"ProgId\" content=\"Excel.Sheet\" />\n");
976 fprintf(fp,
" <link rel=\"icon\" href=\"https://www.turkupetcentre.net/favicon.ico\" type=\"image/x-icon\" />\n");
977 fprintf(fp,
" <link rel=\"shortcut icon\" href=\"https://www.turkupetcentre.net/favicon.ico\" type=\"image/x-icon\" />\n");
979 fprintf(fp,
" <style type=\"text/css\">\n");
980 fprintf(fp,
" thead {background-color:#999999; color:black;}\n");
982 fprintf(fp,
" table {text-align:left; border-collapse:collapse; empty-cells:show;}\n");
984 fprintf(fp,
" .oddroi {background-color:#FFFFFF; color:black;}\n");
985 fprintf(fp,
" .evenroi {background-color:#CCCCCC; color:black;}\n");
986 fprintf(fp,
" .sd {background-color:#999999; color:blue;}\n");
987 fprintf(fp,
" .cl1 {background-color:#999999; color:green;}\n");
988 fprintf(fp,
" .cl2 {background-color:#999999; color:green;}\n");
989 fprintf(fp,
" .oddstudy {background-color:#FFFFFF; color:black;}\n");
990 fprintf(fp,
" .evenstudy {background-color:#CCCCCC; color:black;}\n");
991 fprintf(fp,
" .oddsum {background-color:#999999; color:black;}\n");
992 fprintf(fp,
" .evensum {background-color:#CCCCCC; color:black;}\n");
993 fprintf(fp,
" #regcontainer ul {margin-left:0; padding-left:0;}\n");
994 fprintf(fp,
" #regcontainer ul li {display:inline; list-style-type:none;}\n");
995 fprintf(fp,
" #regcontainer a {padding:2px 4px;}\n");
996 fprintf(fp,
" <!--table\n");
997 fprintf(fp,
" {mso-displayed-decimal-separator:\"\\.\";\n");
998 fprintf(fp,
" mso-displayed-thousand-separator:\" \";}\n");
999 fprintf(fp,
" -->\n");
1000 fprintf(fp,
" </style>\n");
1002 fprintf(fp,
" <link rel=\"stylesheet\" type=\"text/css\" href=\"https://www.turkupetcentre.net/result.css\" />\n");
1003 fprintf(fp,
"</head>\n");
1020 char *cptr, tmp[1024];
1024 if(
RESULT_TEST>0) printf(
"resWriteHTML_table(*res, fp)\n");
1025 if(fp==NULL || res==NULL)
return(1);
1028 fprintf(fp,
"<table>\n");
1029 fprintf(fp,
"<thead>\n");
1035 i=strlen(tmp)-1;
while(i>0 && isspace(tmp[i])) i--; tmp[i+1]=(char)0;
1038 fprintf(fp,
"<tr align=left><th>Program:</th><td>%s</td></tr>\n", tmp);
1041 fprintf(fp,
"<tr align=left><th>Date:</th><td>%s</td></tr>\n", tmp);
1044 fprintf(fp,
"<tr align=left><th>Study:</th><td>%s</td></tr>\n", res->
studynr);
1047 fprintf(fp,
"<tr align=left><th>Data file:</th><td>%s</td></tr>\n", res->
datafile);
1049 fprintf(fp,
"<tr align=left><th>Plasma file:</th><td>%s</td></tr>\n", res->
plasmafile);
1051 fprintf(fp,
"<tr align=left><th>2nd Plasma file:</th><td>%s</td></tr>\n", res->
plasmafile2);
1053 fprintf(fp,
"<tr align=left><th>Blood file:</th><td>%s</td></tr>\n", res->
bloodfile);
1055 fprintf(fp,
"<tr align=left><th>Reference file:</th><td>%s</td></tr>\n", res->
reffile);
1057 fprintf(fp,
"<tr align=left><th>Reference region:</th><td>%s</td></tr>\n", res->
refroi);
1060 fprintf(fp,
"<tr align=left><th>Data range:</th><td>%s</td></tr>\n", res->
datarange);
1062 fprintf(fp,
"<tr align=left><th>Data nr:</th><td>%d</td></tr>\n", res->
datanr);
1064 fprintf(fp,
"<tr align=left><th>Fit method:</th><td>%s</td></tr>\n", res->
fitmethod);
1067 fprintf(fp,
"<tr align=left><th>Tissue density:</th><td>%g</td></tr>\n", res->
density);
1069 fprintf(fp,
"<tr align=left><th>Lumped constant:</th><td>%g</td></tr>\n", res->
lc);
1071 fprintf(fp,
"<tr align=left><th>Concentration:</th><td>%g</td></tr>\n", res->
concentration);
1073 fprintf(fp,
"<tr align=left><th>Beta:</th><td>%g</td></tr>\n", res->
beta);
1075 fprintf(fp,
"<tr align=left><th>Vb:</th><td>%g %%</td></tr>\n", res->
Vb);
1077 fprintf(fp,
"<tr align=left><th>fA:</th><td>%g %%</td></tr>\n", res->
fA);
1079 fprintf(fp,
"<tr align=left><th>Extraction:</th><td>%g</td></tr>\n", res->
E);
1081 if(res->
isweight>0) strcpy(tmp,
"yes");
1082 else if(res->
isweight==0) strcpy(tmp,
"no");
1083 else strcpy(tmp,
"unknown");
1084 fprintf(fp,
"<tr align=left><th>Weighting:</th><td>%s</td></tr>\n", tmp);
1086 fprintf(fp,
"</thead>\n");
1089 for(j=0; j<res->
parNr; j++) {
1095 fprintf(fp,
"<tbody>\n");
1097 fprintf(fp,
"<tr align=left><th>Region</th>\n");
1098 for(i=0; i<res->
parNr; i++) fprintf(fp,
"<th>%s</th>", res->
parname[i]);
1099 fprintf(fp,
"</tr>\n");
1101 for(i=0; i<res->
voiNr; i++) {
1102 if(i%2) strcpy(tmp,
"evenroi");
else strcpy(tmp,
"oddroi");
1103 fprintf(fp,
"<tr class=\"%s\">", tmp);
1105 if(senc==NULL) fprintf(fp,
"<th>%s</th>", res->
voi[i].
name);
1106 else {fprintf(fp,
"<th>%s</th>", senc); free(senc);}
1108 for(j=0; j<res->
parNr; j++)
switch(partype[j]) {
1109 case 0: fprintf(fp,
"<td>%.0f</td>", p[j]);
break;
1110 case 1: fprintf(fp,
"<td>%.4f</td>", p[j]);
break;
1111 default: fprintf(fp,
"<td>%.4E</td>", p[j]);
break;
1113 fprintf(fp,
"</tr>\n");
1115 p=res->
voi[i].
sd;
for(j=n=0; j<res->
parNr; j++)
if(!isnan(p[j])) n++;
1117 fprintf(fp,
"<tr class=\"sd\">");
1118 fprintf(fp,
"<th>%s</th>",
"SD");
1119 for(j=0; j<res->
parNr; j++) {
1120 if(!isnan(p[j]))
switch(partype[j]) {
1121 case 0: fprintf(fp,
"<td>%.0f</td>", p[j]);
break;
1122 case 1: fprintf(fp,
"<td>%.4f</td>", p[j]);
break;
1123 default: fprintf(fp,
"<td>%.4E</td>", p[j]);
break;
1124 }
else fprintf(fp,
"<td></td>");
1126 fprintf(fp,
"</tr>\n");
1129 p=res->
voi[i].
cl1;
for(j=n=0; j<res->
parNr; j++)
if(!isnan(p[j])) n++;
1131 fprintf(fp,
"<tr class=\"cl1\">");
1132 fprintf(fp,
"<th>CL95%%L</th>");
1133 for(j=0; j<res->
parNr; j++) {
1134 if(!isnan(p[j]))
switch(partype[j]) {
1135 case 0: fprintf(fp,
"<td>%.0f</td>", p[j]);
break;
1136 case 1: fprintf(fp,
"<td>%.4f</td>", p[j]);
break;
1137 default: fprintf(fp,
"<td>%.4E</td>", p[j]);
break;
1138 }
else fprintf(fp,
"<td></td>");
1140 fprintf(fp,
"</tr>\n");
1143 p=res->
voi[i].
cl2;
for(j=n=0; j<res->
parNr; j++)
if(!isnan(p[j])) n++;
1145 fprintf(fp,
"<tr class=\"cl2\">");
1146 fprintf(fp,
"<th>CL95%%U</th>");
1147 for(j=0; j<res->
parNr; j++) {
1148 if(!isnan(p[j]))
switch(partype[j]) {
1149 case 0: fprintf(fp,
"<td>%.0f</td>", p[j]);
break;
1150 case 1: fprintf(fp,
"<td>%.4f</td>", p[j]);
break;
1151 default: fprintf(fp,
"<td>%.4E</td>", p[j]);
break;
1152 }
else fprintf(fp,
"<td></td>");
1154 fprintf(fp,
"</tr>\n");
1158 fprintf(fp,
"</tbody></table>\n");
1199 if(data==NULL)
return(1);
1202 qsort(data, nr,
sizeof(
double), resQSortComp);
1204 if(min!=NULL) *min=data[0];
1205 if(max!=NULL) *max=data[nr-1];
1208 if(nr%2) *median=data[(nr-1)/2];
1209 else *median=0.5*(data[(nr/2)-1]+data[nr/2]);
1233 double sum, ssum, v;
1236 if(data==NULL)
return(1);
1239 for(i=0, sum=ssum=0.0; i<nr; i++) {
1240 sum+=data[i]; ssum+=data[i]*data[i];
1242 if(
mean!=NULL) *
mean=sum/(double)nr;
1244 if(nr>1) v=(ssum-sum*sum/(double)nr)/(
double)(nr-1);
else v=0.0;
1245 if(v>0.0) *sd=sqrt(v);
else *sd=0.0;
1253int resQSortComp(
const void *f1,
const void *f2)
1255 if(*(
double*)f1<*(
double*)f2)
return(-1);
1256 else if(*(
double*)f1>*(
double*)f2)
return(1);
1270 if(res==NULL || res->
voiNr<=1)
return;
1278int resQSortName(
const void *voi1,
const void *voi2)
1282 res=strcasecmp( ((
const ResVOI*)voi1)->voiname, ((
const ResVOI*)voi2)->voiname );
1283 if(res!=0)
return(res);
1284 res=strcasecmp( ((
const ResVOI*)voi1)->hemisphere, ((
const ResVOI*)voi2)->hemisphere );
1285 if(res!=0)
return(res);
1286 res=strcasecmp( ((
const ResVOI*)voi1)->place, ((
const ResVOI*)voi2)->place );
1305 if(res1==NULL || res2==NULL)
return(1);
1327 for(i=0; i<res1->
parNr; i++) {
1351 if(res==NULL || voi>res->
voiNr-1 || voi<0)
return(1);
1353 if(voi==res->
voiNr) {res->
voiNr--;
return(0);}
1355 for(i=voi+1; i<res->
voiNr; i++)
1375 unsigned int i, j, n;
1376 char *p, n1[128], n2[128], n3[128], tmp[128], sname[1024], *lptr;
1378 if(data==NULL)
return(-1);
1380 if(name==NULL || strlen(name)==0) {
1381 for(i=0; i<(
unsigned int)data->
voiNr; i++) data->
voi[i].
sw=1;
1382 return(data->
voiNr);
1385 strcpy(sname, name); lptr=sname;
1387 n1[0]=n2[0]=n3[0]=(char)0;
1388 p=strtok(lptr,
" ,;\n\t|");
if(p!=NULL) strcpy(n1, p);
else return(-1);
1389 p=strtok(NULL,
" ,;\n\t|");
if(p!=NULL) {
1390 strcpy(n2, p); p=strtok(NULL,
" ,;\n\t|");
if(p!=NULL) strcpy(n3, p);}
1392 for(i=0; i<strlen(n1); i++) n1[i]=tolower(n1[i]);
1393 for(i=0; i<strlen(n2); i++) n2[i]=tolower(n2[i]);
1394 for(i=0; i<strlen(n3); i++) n3[i]=tolower(n3[i]);
1396 for(i=0, n=0; i<(
unsigned int)data->
voiNr; i++) {
1400 for(j=0; j<strlen(tmp); j++) tmp[j]=tolower(tmp[j]);
1401 if(strstr(tmp, n1)==NULL)
continue;
1402 if(n2[0] && strstr(tmp, n2)==NULL)
continue;
1403 if(n3[0] && strstr(tmp, n3)==NULL)
continue;
1404 data->
voi[i].
sw=1; n++;
1428 if(res==NULL || res->
voiNr<1 || strlen(region_name)<1)
return(-1);
1430 if(reset!=0)
for(ri=0; ri<res->
voiNr; ri++) res->
voi[ri].
sw=0;
1432 for(ri=0; ri<res->
voiNr; ri++) {
1434 res->
voi[ri].
sw=1; match_nr++;
1454 double x, m=0.0, pint;
1456 if(res==NULL || res->
voiNr<1 || parIndex<0 || parIndex>=res->
parNr)
1458 for(vi=0; vi<res->
voiNr; vi++) {
1460 if(modf(x, &pint)!=0.0) partype=1;
1461 x=fabs(x);
if(x>m) m=x;
1463 if(partype==1 && (m>=10.0 || m<0.1)) partype=2;
1479 if(res==NULL)
return(-1);
1480 if(res->
voiNr<2)
return(0);
1481 for(ri=0; ri<res->
voiNr-1; ri++)
for(rj=ri+1; rj<res->
voiNr; rj++)
1482 if(strcasecmp(res->
voi[ri].
name, res->
voi[rj].
name)==0)
return(1);
1500 if(res1==NULL || res2==NULL)
return(1);
1508 if(strcasecmp(res1->
refroi, res2->
refroi)!=0)
return(11);
1512 if(res1->
lc!=res2->
lc)
return(15);
1513 if(res1->
beta!=res2->
beta)
return(16);
1515 if(res1->
Vb!=res2->
Vb)
return(18);
1518 if(res1->
fA!=res2->
fA)
return(21);
1519 if(res1->
E!=res2->
E)
return(22);
1539 if(res1==NULL || res2==NULL || res1->
voiNr!=res2->
voiNr)
return(1);
1540 for(ri=0; ri<res1->
voiNr; ri++) {
1572 if(res1==NULL || res2==NULL || res1->
parNr!=res2->
parNr)
return(1);
1577 for(i=0; i<res1->
parNr; i++) {
1580 printf(
" Parameter names '%s' and '%s' do not match\n",
1586 printf(
" Parameter units '%s' and '%s' do not match\n",
1615 if(res1==NULL || res2==NULL || res1->
voiNr!=res2->
voiNr)
return(1);
1617 if(test_par<0)
return(1);
1618 if(test_par+1>res1->
parNr || test_par+1>res2->
parNr)
return(1);
1620 for(ri=0; ri<res1->
voiNr; ri++) {
1621 for(pi=0; pi<res1->
parNr; pi++) {
1622 if(test_par>=0 && test_par!=pi)
continue;
1624 if(isnan(v1) && isnan(v2))
continue;
1626 if(
RESULT_TEST>5) printf(
"pi=%d ri=%d\n", pi, ri);
1628 s=fabs(v1+v2);
if(isnan(s))
return(2);
1629 if(test_limit<=0.0) {
1630 if(v1!=v2)
return(2);
1631 }
if(s==0.0 || v1==0.0 || v2==0.0) {
1632 if(fabs(v1-v2)>test_limit)
return(2);
1634 if(fabs((v1-v2)/s)>test_limit)
return(2);
1638 v1=res1->
voi[ri].
sd[pi]; v2=res2->
voi[ri].
sd[pi];
1639 if(
RESULT_TEST>5) printf(
" SD: %g vs %g\n", v1, v2);
1640 if(isnan(v1) && isnan(v2)) {
1642 }
else if(isnan(v1) || isnan(v2)) {
1645 }
else if(test_limit<=0.0) {
1646 if(v1!=v2)
return(3);
1648 if(fabs(v1-v2)>test_limit)
return(3);
1650 if(fabs((v1-v2)/s)>test_limit)
return(3);
1654 if(
RESULT_TEST>5) printf(
" CL1: %g vs %g\n", v1, v2);
1655 if(isnan(v1) && isnan(v2)) {
1657 }
else if(isnan(v1) || isnan(v2)) {
1660 }
else if(test_limit<=0.0) {
1661 if(v1!=v2)
return(4);
1663 if(fabs(v1-v2)>test_limit)
return(4);
1665 if(fabs((v1-v2)/s)>test_limit)
return(4);
1669 if(
RESULT_TEST>5) printf(
" CL2: %g vs %g\n", v1, v2);
1670 if(isnan(v1) && isnan(v2)) {
1672 }
else if(isnan(v1) || isnan(v2)) {
1675 }
else if(test_limit<=0.0) {
1676 if(v1!=v2)
return(5);
1678 if(fabs(v1-v2)>test_limit)
return(5);
1680 if(fabs((v1-v2)/s)>test_limit)
return(5);
1709 if(res1==NULL || res2==NULL || res1->
voiNr!=res2->
voiNr)
return(1);
1711 if(test_par<0)
return(1);
1712 if(test_par+1>res1->
parNr || test_par+1>res2->
parNr)
return(1);
1714 if(test_limit<0.0)
return(1);
1715 for(ri=0; ri<res1->
voiNr; ri++) {
1716 for(pi=0; pi<res1->
parNr; pi++) {
1717 if(test_par>=0 && test_par!=pi)
continue;
1719 if(isnan(v1) && isnan(v2))
continue;
1721 if(
RESULT_TEST>5) printf(
"pi=%d ri=%d\n", pi, ri);
1724 if(isnan(s) || s>test_limit)
return(2);
1727 v1=res1->
voi[ri].
sd[pi]; v2=res2->
voi[ri].
sd[pi];
1728 if(isnan(v1) && !isnan(v2))
return(3);
1729 if(!isnan(v1) && isnan(v2))
return(3);
1730 if(!isnan(v1) && !isnan(v2)) {
1731 if(
RESULT_TEST>8) printf(
" SD: %g vs %g\n", v1, v2);
1732 s=fabs(v1-v2);
if(s>test_limit)
return(3);
1736 if(isnan(v1) && !isnan(v2))
return(4);
1737 if(!isnan(v1) && isnan(v2))
return(4);
1738 if(!isnan(v1) && !isnan(v2)) {
1739 if(
RESULT_TEST>8) printf(
" CL1: %g vs %g\n", v1, v2);
1740 s=fabs(v1-v2);
if(s>test_limit)
return(4);
1744 if(isnan(v1) && !isnan(v2))
return(5);
1745 if(!isnan(v1) && isnan(v2))
return(5);
1746 if(!isnan(v1) && !isnan(v2)) {
1747 if(
RESULT_TEST>8) printf(
" CL2: %g vs %g\n", v1, v2);
1748 s=fabs(v1-v2);
if(s>test_limit)
return(5);
1769 if(res==NULL)
return(-1);
1770 if(res->
voiNr<1)
return(-1);
1771 for(ri=0; ri<res->
voiNr; ri++) {
1776 strcmp(res->
voi[ri].
place,
".")!=0)
1779 ri=0;
if(m>0) ri+=1;
if(n>0) ri+=2;
int backupExistingFile(char *filename, char *backup_ext, char *status)
int get_datetime(char *str, struct tm *date, int verbose)
char * ctime_r_int(const time_t *t, char *buf)
Convert calendard time t into a null-terminated string of the form YYYY-MM-DD hh:mm:ss,...
time_t timegm(struct tm *tm)
Inverse of gmtime, converting struct tm to time_t.
int get_date(char *str, struct tm *date)
double atof_dpi(char *str)
Header file for libtpccurveio.
#define MAX_RESPARNAME_LEN
int rnameCatenate(char *rname, int max_rname_len, char *name1, char *name2, char *name3, char space)
int rnameMatch(char *rname, int rnr, char *test_str)
int rnameSplit(char *rname, char *name1, char *name2, char *name3, int max_name_len)
#define MAX_REGIONNAME_LEN
char * strEncodeForXML(const char *s)
int strTokenNCpy(const char *str1, const char *str2, int i, char *str3, int count)
int strTokenNr(const char *str1, const char *str2)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
char * strcasestr(const char *haystack, const char *needle)
int studynr_from_fname(char *fname, char *studynr)
#define MAX_REGIONSUBNAME_LEN
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
int resSetmem(RES *res, int voiNr)
int resMatchRegions(RES *res1, RES *res2)
int resMean(double *data, int nr, double *mean, double *sd)
int resSelectRegions(RES *res, char *region_name, int reset)
void resSortByName(RES *res)
int resCopyMHeader(RES *res1, RES *res2)
int resWriteXHTML11_head(FILE *fp, char *author_name)
int resFName2study(char *fname, char *studyNumber)
int resParameterPrintType(RES *res, int parIndex)
int resWriteXHTML11_doctype(FILE *fp)
void resFixParnames(RES *res)
int resMatchParameternames(RES *res1, RES *res2)
int resIsDuplicateNames(RES *res)
int resWrite(RES *res, char *filename, int verbose)
int resSelect(RES *data, char *name)
int resDelete(RES *res, int voi)
int resRNameSubfieldExists(RES *res)
int resRead(char *filename, RES *res, int verbose)
int resMatchParameters(RES *res1, RES *res2, int test_par, double test_limit, int test_sd)
int resWriteHTML_table(RES *res, FILE *fp)
int resWriteHTML(RES *res, char *fname, int verbose)
int resMatchHeader(RES *res1, RES *res2)
int resMatchParametersAbs(RES *res1, RES *res2, int test_par, double test_limit, int test_sd)
int resMedian(double *data, int nr, double *median, double *min, double *max)
char plasmafile2[FILENAME_MAX]
char studynr[MAX_STUDYNR_LEN+1]
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
char plasmafile[FILENAME_MAX]
char datafile[FILENAME_MAX]
char reffile[FILENAME_MAX]
char parunit[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
char bloodfile[FILENAME_MAX]
double parameter[MAX_RESPARAMS]
double cl2[MAX_RESPARAMS]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]
double cl1[MAX_RESPARAMS]
char name[MAX_REGIONNAME_LEN+1]
char voiname[MAX_REGIONSUBNAME_LEN+1]