TPCCLIB
Loading...
Searching...
No Matches
rescoll.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 <unistd.h>
14#include <string.h>
15#include <math.h>
16#include <time.h>
17/*****************************************************************************/
18#include "libtpcmisc.h"
19#include "libtpccurveio.h"
20/*****************************************************************************/
21
22/*****************************************************************************/
23/* Local functions */
24void print_usage();
25void print_build();
27 RES *reslist, int resNr, ResVOI *lastResVOI, int *resIndex);
28int rescoll_tabulate(FILE *fp, RES *coll, int collNr);
29/*****************************************************************************/
30
31/*****************************************************************************/
32static char *info[] = {
33 "Collects the model analysis results from a set of PET studies, and",
34 "by default tabulates regional results and means with standard deviations;",
35 "then results of only one model analysis program can be used at a time.",
36 " ",
37 "Usage: @P [Options] collection_file result_files",
38 " ",
39 "Options:",
40 " -sort",
41 " Results will be sorted by study number.",
42 " -strict",
43 " Quits with error when normally a warning would be displayed.",
44 " -list",
45 " Regional results are not collected but result files are just",
46 " tabulated into one HTML file.",
47 " -par[ameter]",
48 " Regional and individual results are collected for each parameter.",
49 " -stdoptions", // List standard options like --help, -v, etc
50 " ",
51 "Example:",
52 " rescoll patlak_means.html ua4???ki.res",
53 " ",
54 "The collected data is saved in tables in XHTML format, therefore the",
55 "collection filename extension has to be .htm(l).",
56 "File can then be viewed and printed with a web browser or Excel.",
57 "In Excel the data can be also be processed further and saved in Excel",
58 "format.",
59 " ",
60 "See also: reslist, pardiff, dft2res, fit2res, resmatch, resdel, paradd",
61 " ",
62 "Keywords: results, tabulation, reporting, modelling, simulation, tool",
63 0};
64/*****************************************************************************/
65
66/*****************************************************************************/
67/* Turn on the globbing of the command line, since it is disabled by default in
68 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
69 In Unix&Linux wildcard command line processing is enabled by default. */
70/*
71#undef _CRT_glob
72#define _CRT_glob -1
73*/
74int _dowildcard = -1;
75/*****************************************************************************/
76
77/*****************************************************************************/
81int main(int argc, char **argv)
82{
83 int ai, help=0, version=0, verbose=1;
84 int ri, rj, vi, pi, ret, len;
85 int resNr=0;
86 int doSort=0, beStrict=0;
87 int doMode=0; /* 0=regional results collected, 1=studies simply listed,
88 2=parametric results collected */
89 int first_res=-1;
90 int saveSD=0; /* 0=SD and CLs are not included; 1=included, if available */
91 RES *res, coll, tres;
92 char colfile[FILENAME_MAX], resfile[FILENAME_MAX], *cptr, tmp[1024];
93 struct tm *st;
94 FILE *fp;
95 ResVOI *resvoi1, *resvoi2;
96
97
98 /*
99 * Get arguments
100 */
101 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
102 colfile[0]=resfile[0]=(char)0;
103 resInit(&coll); resInit(&tres);
104 /* Options */
105 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
106 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
107 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
108 if(strcasecmp(cptr, "STRICT")==0) {
109 beStrict=1; continue;
110 } else if(strncasecmp(cptr, "SORT", 2)==0) {
111 doSort=1; continue;
112 } else if(strncasecmp(cptr, "LIST", 2)==0) {
113 doMode=1; continue;
114 } else if(strncasecmp(cptr, "PARAMETER", 3)==0) {
115 doMode=2; continue;
116 }
117 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
118 return(1);
119 } else break;
120
121 /* Print help or version? */
122 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
123 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
124 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
125
126 /* Process other arguments, starting from the first non-option */
127 for(; ai<argc; ai++) {
128 if(!colfile[0]) {
129 strlcpy(colfile, argv[ai], FILENAME_MAX);
130 /* Check the output file extension */
131 cptr=strrchr(colfile, '.');
132 if(strcasecmp(cptr, ".HTM")!=0 && strcasecmp(cptr, ".HTML")!=0) {
133 fprintf(stderr, "Error: collection file extension must be .htm or .html\n");
134 return(1);
135 }
136 continue;
137 }
138 /* this must be a input result file. Check that it exists */
139 if(access(argv[ai], 0) == -1) {
140 fprintf(stderr, "Error: result file %s does not exist.\n", argv[ai]);
141 return(1);
142 }
143 if(first_res<0) first_res=ai;
144 resNr++; /* calculate how many result files there will be */
145 }
146
147 /* Is something missing? */
148 if(resNr<1) {
149 fprintf(stderr, "Error: no result files to process.\n");
150 return(1);
151 } else if(resNr<2 && doMode!=1) {
152 fprintf(stderr, "Error: at least two result files must be given.\n");
153 return(1);
154 }
155
156 /* In verbose mode print arguments and options */
157 if(verbose>0) {
158 printf("colfile := %s\n", colfile);
159 printf("resNr := %d\n", resNr);
160 printf("doSort := %d\n", doSort);
161 printf("doMode := %d\n", doMode);
162 printf("saveSD := %d\n", saveSD);
163 printf("first_res := %d\n", first_res);
164 }
165 if(verbose>25) RESULT_TEST=verbose-25; else RESULT_TEST=0;
166
167
168 /*
169 * Read result files
170 */
171 if(verbose>1) printf("reading result files\n");
172 /* Allocate memory for separate study results */
173 res=(RES*)calloc(resNr, sizeof(RES));
174 if(res==NULL) {fprintf(stderr, "Error: out of memory.\n"); return(2);}
175 /* Initiate study results */
176 for(ri=0; ri<resNr; ri++) resInit(res+ri);
177 /* Read result files */
178 for(ai=first_res, vi=0; ai<argc; ai++) {
179 strcpy(resfile, argv[ai]);
180 if(verbose>0) fprintf(stdout, "file[%d] := %s\n", vi+1, resfile);
181 /* read this result file */
182 ret=resRead(resfile, res+vi, verbose-3);
183 if(ret) {
184 if(beStrict==0) {
185 fprintf(stderr, "Warning: '%s' not read: %s\n", resfile, reserrmsg);
186 resEmpty(res+vi); continue;
187 } else {
188 fprintf(stderr, "Error in reading '%s': %s\n", resfile, reserrmsg);
189 for(ri=0; ri<vi; ri++) resEmpty(res+ri);
190 return(3);
191 }
192 }
193 if(verbose>2) printf("res.voiNr := %d\n", res[vi].voiNr);
194 /* Make sure that TAC names do not need encoding in XML */
195 for(int i=0; i<res[vi].voiNr; i++) {
196 strCleanForXML(res[vi].voi[i].name);
197 strCleanForXML(res[vi].voi[i].voiname);
198 strCleanForXML(res[vi].voi[i].hemisphere);
199 strCleanForXML(res[vi].voi[i].place);
200 }
201 /* sort rois */
202 if(doMode!=1) resSortByName(res+vi);
203 /* make sure that there are no duplicate rois */
204 if(doMode!=1 && resIsDuplicateNames(res+vi)>0) {
205 fprintf(stderr, "Error: %s contains duplicate region names.\n", resfile);
206 for(ri=0; ri<vi; ri++) resEmpty(res+ri);
207 return(3);
208 }
209 /* make sure that result contains some sort of study number */
210 if(strlen(res[vi].studynr)<1 || strcmp(res[vi].studynr, ".")==0) {
211 cptr=strrchr(resfile, '/'); if(cptr==NULL) cptr=strrchr(resfile, '\\');
212 if(cptr==NULL) cptr=resfile; else cptr++;
213 strlcpy(res[vi].studynr, cptr, MAX_STUDYNR_LEN);
214 cptr=strrchr(res[vi].studynr, '.'); if(cptr!=NULL) *cptr=(char)0;
215 }
216 /* prepare for the next result file */
217 vi++;
218 }
219 if(verbose>0) fflush(stdout);
220 resNr=vi;
221 if(resNr<1) {
222 fprintf(stderr, "Error: no result file(s) could be read.\n");
223 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
224 return(3);
225 } else if(resNr<2 && doMode!=1) {
226 fprintf(stderr, "Error: only one result file could be read.\n");
227 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
228 return(3);
229 }
230 if(verbose>0) printf("%d result files read.\n", resNr);
231 if(verbose>20) for(ri=0; ri<resNr; ri++) resPrint(res+ri);
232 /* Sort the files by study number, if required */
233 if(doSort) {
234 if(verbose>1) printf("sorting results by study number\n");
235 for(ri=0; ri<resNr-1; ri++) for(rj=ri+1; rj<resNr; rj++)
236 if(strcmp(res[ri].studynr, res[rj].studynr)>0) {
237 memcpy(&tres, res+ri, sizeof(RES));
238 memcpy(res+ri, res+rj, sizeof(RES));
239 memcpy(res+rj, &tres, sizeof(RES));
240 }
241 }
242 if(verbose>19) for(ri=0; ri<resNr; ri++) resPrint(res+ri);
243 /* Print the study numbers */
244 if(verbose>0) {
245 for(ri=0; ri<resNr; ri++)
246 printf("study_number[%d] := %s\n", ri+1, res[ri].studynr);
247 fflush(stdout);
248 }
249
250 /*
251 * Check that results are of one kind only
252 */
253 if(doMode!=1) {
254 if(verbose>1) printf("checking that results can be combined\n");
255 strcpy(tmp, res[0].program); cptr=strtok(tmp, " \t\n\r(");
256 if(cptr==NULL) len=strlen(res[0].program); else len=strlen(cptr);
257 for(ri=1; ri<resNr; ri++) {
258 if(strncasecmp(res[0].program, res[ri].program, len)==0) continue;
259 fprintf(stderr, "Error: different software used in result files.\n");
260 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
261 return(4);
262 }
263 for(ri=1, ret=0; ri<resNr; ri++) {
264 /* parNr */
265 if(res[ri].parNr!=res[0].parNr) {
266 fprintf(stderr, "Error: different parameter nr in result files.\n");
267 ret=1; break;
268 }
269 /* Parameter names and units */
270 if(resMatchParameternames(&res[ri], &res[0])!=0) {
271 fprintf(stderr, "Error: different parameters in result files.\n");
272 ret=2; break;
273 }
274 }
275 if(ret>0) {
276 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
277 return(4);
278 }
279 }
280
281 /*
282 * Check that result file nr is not too big in parameter table mode
283 * (including median, mean and sd)
284 */
285 if(doMode==2) {
286 if(resNr>=MAX_RESPARAMS-3) {
287 fprintf(stderr, "Error: too many result files; %d allowed.\n", MAX_RESPARAMS);
288 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
289 return(1);
290 }
291 }
292
293 /*
294 * Check that the same regions exist in all result files in parameter table
295 * mode
296 */
297 if(doMode==2) {
298 ret=0;
299 for(ri=1; ri<resNr; ri++) {
300 if(res[0].voiNr!=res[ri].voiNr) {ret=1; break;}
301 if(resMatchRegions(res+0, res+ri)) {ret=2; break;}
302 }
303 if(ret>0) {
304 if(ret==1) fprintf(stderr, "Error: in this mode region nr must match.\n");
305 else fprintf(stderr, "Error: in this mode regions must match.\n");
306 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
307 return(1);
308 }
309 }
310
311 if(verbose>0) printf("collecting results...\n");
312
313 /*
314 * Open the collection file
315 */
316 if(verbose>1) printf("writing %s\n", colfile);
317
318 /* Check if the collection file exists; backup, if necessary */
319 (void)backupExistingFile(colfile, NULL, NULL);
320
321 /* Open the collection file for writing */
322 if((fp=fopen(colfile, "w"))==NULL) {
323 fprintf(stderr, "Error: cannot open file '%s' for write.\n", colfile);
324 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
325 return(11);
326 }
327
328 /* Write XHTML 1.1 doctype and head */
329 tpcProgramName(argv[0], 1, 1, tmp, 128);
331 fprintf(stderr, "Error: cannot write in file '%s'.\n", colfile);
332 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
333 fclose(fp); remove(colfile); return(11);
334 }
335
336 /* Start writing the body of the HTML file */
337 fprintf(fp, "\n<body>\n");
338
339 /* Write a title */
340 fprintf(fp, "\n<div id=\"title\">\n");
341 strcpy(tmp, res[0].program); cptr=strtok(tmp, " \t\n\r(");
342 if(cptr==NULL) cptr=res[0].program;
343 if(doMode!=1 && strlen(cptr)>1)
344 fprintf(fp, " <h1>Results of %s</h1>\n", cptr);
345 else
346 fprintf(fp, " <h1>Results</h1>\n");
347 fprintf(fp, "</div>\n");
348
349 /*
350 * Start with a list of links
351 */
352 if(doMode==0) {
353 /* Make a list of rois with links */
354 fprintf(fp, "\n<div id=\"regcontainer\">\n");
355 fprintf(fp, "<ul id=\"reglist\">\n");
356 resvoi2=NULL; resvoi1=resGetNextResVOI(res, resNr, NULL, NULL);
357 if(resvoi1==NULL) {
358 fprintf(stderr, "Error: cannot get result file contents.\n");
359 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
360 fclose(fp); remove(colfile); return(9);
361 }
362 while(resvoi1!=NULL) {
363 if(resvoi2==NULL || strcasecmp(resvoi1->name, resvoi2->name)) {
364 strcpy(tmp, resvoi1->name);
365 if(verbose>10) printf("NEW name := %s\n", resvoi1->name);
366 /* replace dots and spaces with underscores */
367 while((cptr=strpbrk(tmp, " ."))!=NULL) *cptr='_';
368 fprintf(fp, " <li><a href=\"#%s\">%s</a></li>\n", tmp, resvoi1->name);
369 }
370 resvoi2=resvoi1; if(verbose>11) printf("name := %s\n", resvoi2->name);
371 resvoi1=resGetNextResVOI(res, resNr, resvoi2, NULL);
372 }
373 fprintf(fp, "</ul>\n");
374 fprintf(fp, "</div>\n");
375 } else if(doMode==2) {
376 /* Make a list of parameters with links */
377 fprintf(fp, "\n<div id=\"parcontainer\">\n");
378 fprintf(fp, "<ol id=\"parlist\">\n");
379 for(pi=0; pi<res[0].parNr; pi++) {
380 sprintf(tmp, "par%d", pi+1);
381 fprintf(fp, " <li><a href=\"#%s\">%s</a></li>\n", tmp, res[0].parname[pi]);
382 }
383 fprintf(fp, "</ol>\n");
384 fprintf(fp, "</div>\n");
385 }
386
387 /* Start the div for tables */
388 fprintf(fp, "\n<div id=\"tables\">\n");
389
390 ret=0;
391 if(doMode==0) {
392 /*
393 * Collect and process each region, one at a time
394 */
395 if(verbose>1) printf("collecting results of one region at a time\n");
396 /* Allocate memory for results of one region */
397 if(resSetmem(&coll, resNr)) {
398 fprintf(stderr, "Error: out of memory.\n");
399 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
400 return(5);
401 }
402 /* Search through results for each region */
403 resvoi2=NULL; resvoi1=resGetNextResVOI(res, resNr, NULL, &ri);
404 if(resvoi1==NULL) {
405 fprintf(stderr, "Error: cannot get result file contents.\n");
406 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
407 fclose(fp); remove(colfile); return(9);
408 }
409 coll.voiNr=0; vi=0; ret=0;
410 while(resvoi1!=NULL && ret==0) {
411 if(resvoi2==NULL || strcasecmp(resvoi1->name, resvoi2->name)) {
412 vi++;
413 /* This is a new (or the first) region */
414 if(coll.voiNr>0) { // tabulate the previous region, if this is not 1st
415 ret=rescoll_tabulate(fp, &coll, vi);
416 }
417 /* Copy region information into collection data */
418 coll.voiNr=1;
419 if(verbose>0) printf("region_name[%d] := %s\n", vi, resvoi1->name);
420 strcpy(coll.datafile, resvoi1->name);
421 char *cptr=strstr(coll.datafile, " . ."); if(cptr!=NULL) *cptr=(char)0;
422 coll.parNr=res[ri].parNr;
423 for(pi=0; pi<coll.parNr; pi++) {
424 strcpy(coll.parname[pi], res[ri].parname[pi]);
425 strcpy(coll.parunit[pi], res[ri].parunit[pi]);
426 }
427 } else {
428 /* the same region, just a new study */
429 coll.voiNr++;
430 }
431 if(verbose>2) printf("studynr := %s\n", res[ri].studynr);
432 /* Copy study information into collection data */
433 /* Set the study name */
434 strcpy(coll.voi[coll.voiNr-1].name, res[ri].studynr);
435 /* set the calculation date */
436 st=localtime(&res[ri].time);
437 if(st!=NULL) strftime(tmp, 256, "%Y-%m-%d", st); else strcpy(tmp, " ");
438 strlcpy(coll.voi[coll.voiNr-1].voiname, tmp, 7);
439 strlcpy(coll.voi[coll.voiNr-1].hemisphere, tmp+6, 7);
440 /* parameter values */
441 for(pi=0; pi<res[ri].parNr; pi++)
442 coll.voi[coll.voiNr-1].parameter[pi]=resvoi1->parameter[pi];
443 /* Prepare for the next one */
444 resvoi2=resvoi1; resvoi1=resGetNextResVOI(res, resNr, resvoi2, &ri);
445 } // while
446 /* tabulate the last region */
447 if(coll.voiNr>0) {
448 ret=rescoll_tabulate(fp, &coll, vi);
449 }
450
451 } else if (doMode==1) {
452 /*
453 * Write one result file as one HTML table
454 */
455 if(verbose>1) printf("writing result files as HTML tables\n");
456 for(ri=0, ret=0; ri<resNr; ri++) {
457 /* Remove SDs and CLs if required */
458 if(saveSD==0) {
459 for(vi=0; vi<res[ri].voiNr; vi++) for(pi=0; pi<res[ri].parNr; pi++)
460 res[ri].voi[vi].cl1[pi]=res[ri].voi[vi].cl2[pi]=
461 res[ri].voi[vi].sd[pi]=nan("");
462 }
463 /* Add empty line to HTML */
464 if(ri>0) fprintf(fp, "\n<br />\n");
465 /* Write table */
466 ret=resWriteHTML_table(res+ri, fp);
467 if(ret!=0) break;
468 }
469 } else if(doMode==2) {
470 /*
471 * Collect and process each parameter, one at a time
472 */
473 if(verbose>1) printf("collecting results of one parameter at a time\n");
474 /* SDs and CLs are not used */
475 for(ri=0, ret=0; ri<resNr; ri++) {
476 for(vi=0; vi<res[ri].voiNr; vi++) for(pi=0; pi<res[ri].parNr; pi++)
477 res[ri].voi[vi].cl1[pi]=res[ri].voi[vi].cl2[pi]=
478 res[ri].voi[vi].sd[pi]=nan("");
479 }
480 /* Allocate memory for results of one parameter */
481 if(resSetmem(&coll, res[0].voiNr)) {
482 fprintf(stderr, "Error: out of memory.\n");
483 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
484 return(5);
485 }
486 /* Set common result header information */
487 strcpy(coll.program, "");
488 coll.voiNr=res[0].voiNr;
489 coll.parNr=resNr+3;
490 coll.isweight=res[0].isweight;
491 coll.time=time(NULL);
492 for(pi=0; pi<resNr; pi++) {
493 strcpy(coll.parname[pi], res[pi].studynr);
494 }
495 strcpy(coll.parname[pi++], "Median");
496 strcpy(coll.parname[pi++], "Mean");
497 strcpy(coll.parname[pi++], "SD");
498 for(ri=0; ri<res[0].voiNr; ri++) {
499 strcpy(coll.voi[ri].name, res[0].voi[ri].name);
500 strcpy(coll.voi[ri].voiname, res[0].voi[ri].voiname);
501 strcpy(coll.voi[ri].hemisphere, res[0].voi[ri].hemisphere);
502 strcpy(coll.voi[ri].place, res[0].voi[ri].place);
503 }
504 /* One parameter at a time */
505 double tdata[MAX_RESPARAMS];
506 for(pi=0; pi<res[0].parNr; pi++) {
507 strcpy(coll.program, res[0].parname[pi]);
508 /* Fill the table for this parameter */
509 for(ri=0; ri<res[0].voiNr; ri++) {
510 for(vi=0; vi<resNr; vi++) {
511 coll.voi[ri].parameter[vi]=tdata[vi]=res[vi].voi[ri].parameter[pi];
512 }
513 /* Calculate Median, Mean and SD */
514 resMedian(tdata, resNr, &coll.voi[ri].parameter[resNr], NULL, NULL);
515 resMean(tdata, resNr, &coll.voi[ri].parameter[resNr+1],
516 &coll.voi[ri].parameter[resNr+2]);
517 }
518 /* Add empty line to HTML */
519 if(pi>0) fprintf(fp, "\n<br />\n");
520 /* Write the anchor */
521 fprintf(fp, "\n<a id=\"par%d\"></a>\n", pi+1);
522 /* Write table */
523 ret=resWriteHTML_table(&coll, fp);
524 if(ret!=0) break;
525 } // next res parameter
526 }
527 if(ret!=0) {
528 fprintf(stderr, "Error: cannot tabulate result files.\n");
529 resEmpty(&coll); for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
530 fclose(fp); remove(colfile); return(9);
531 }
532
533
534 if(verbose>0) fprintf(fp, "\n");
535 /* Close collection file, writing HTLM end code */
536 if(verbose>1) printf("closing collection file.\n");
537 fprintf(fp, "</div>\n");
538 fprintf(fp, "</body></html>\n");
539 fclose(fp);
540
541 if(verbose>0) printf("%s written.\n", colfile);
542
543 /* Free up memory */
544 resEmpty(&coll);
545 for(ri=0; ri<resNr; ri++) resEmpty(res+ri);
546
547 return(0);
548}
549/*****************************************************************************/
551/*****************************************************************************/
558 RES *reslist,
560 int resNr,
562 ResVOI *lastResVOI,
564 int *resIndex
565) {
566 int ri, vi;
567
568 /* Check the input */
569 if(resIndex!=NULL) *resIndex=0;
570 if(reslist==NULL || resNr<1) return(NULL);
571 if(reslist[0].voiNr==0) return(NULL);
572 /* If lastResVOI is NULL, that means that first one is required */
573 if(lastResVOI==NULL) {
574 for(ri=0; ri<resNr; ri++) for(vi=0; vi<reslist[ri].voiNr; vi++)
575 reslist[ri].voi[vi].sw2=0;
576 reslist[0].voi[0].sw2=1;
577 return(reslist[0].voi);
578 }
579 /* Search the next study with the same region name */
580 for(ri=0; ri<resNr; ri++)
581 for(vi=0; vi<reslist[ri].voiNr; vi++) if(reslist[ri].voi[vi].sw2==0)
582 if(strcasecmp(reslist[ri].voi[vi].name, lastResVOI->name)==0) {
583 reslist[ri].voi[vi].sw2=1; if(resIndex!=NULL) *resIndex=ri;
584 return(reslist[ri].voi+vi);
585 }
586 /* If not found, then proceed to the next region name */
587 for(ri=0; ri<resNr; ri++)
588 for(vi=0; vi<reslist[ri].voiNr; vi++) if(reslist[ri].voi[vi].sw2==0) {
589 reslist[ri].voi[vi].sw2=1; if(resIndex!=NULL) *resIndex=ri;
590 return(reslist[ri].voi+vi);
591 }
592 /* If not found, then the previous one must have been the last one */
593 return(NULL);
594}
595/*****************************************************************************/
596
597/*****************************************************************************/
604 FILE *fp,
606 RES *coll,
608 int collNr
609) {
610 char *cptr, tmp[1024];
611 int si, pi, partype[MAX_RESPARAMS], n;
612 double resstat[5][MAX_RESPARAMS], *data;
613
614
615 /* Check the input */
616 if(fp==NULL || coll==NULL || coll->voiNr<0 || collNr<1) return(1);
617 if(coll->voiNr<1) return(0);
618
619 /* Calculate the statistics if more than one study */
620 if(coll->voiNr>1) {
621 data=(double*)malloc(coll->voiNr*sizeof(double));
622 for(pi=0; pi<coll->parNr; pi++) {
623 /* Copy data to a temp array */
624 for(si=0; si<coll->voiNr; si++) data[si]=coll->voi[si].parameter[pi];
625 /* Calculate median, min and max */
626 resMedian(data, coll->voiNr, &resstat[2][pi], &resstat[0][pi],
627 &resstat[1][pi]);
628 /* Calculate avg and sd */
629 resMean(data, coll->voiNr, &resstat[3][pi], &resstat[4][pi]);
630 }
631 free(data);
632 }
633
634 /* Put some space in between tables, if this is not the first table */
635 if(collNr>1) {
636 fprintf(fp, "\n<br />\n");
637 }
638
639 /* Write the anchor */
640 strcpy(tmp, coll->datafile);
641 /* replace dots and spaces with underscores */
642 while((cptr=strpbrk(tmp, " ."))!=NULL) *cptr='_';
643 fprintf(fp, "\n<a id=\"%s\"></a>\n", tmp);
644
645 /* Start the table */
646 fprintf(fp, "<table>\n");
647 fprintf(fp, " <thead>\n");
648
649 /* Write the region name */
650 fprintf(fp, " <tr><th colspan=\"%d\">", 3+coll->parNr);
651 fprintf(fp, "%s", coll->datafile);
652 fprintf(fp, "</th></tr>\n");
653
654 /* Write the titles */
655 fprintf(fp, " <tr>\n <td>Nr</td><td>Study</td><td>Date</td>\n");
656 /* continue with the parameter names */
657 for(pi=0; pi<coll->parNr; pi++)
658 fprintf(fp, " <td>%s</td>\n", coll->parname[pi]);
659 fprintf(fp, " </tr>\n");
660 fprintf(fp, " </thead>\n");
661
662 /* Determine the best print format for each of the parameters */
663 for(pi=0; pi<coll->parNr; pi++)
664 partype[pi]=resParameterPrintType(coll, pi);
665
666 /* Save all study results from this region */
667 fprintf(fp, " <tbody>\n");
668 for(si=0; si<coll->voiNr; si++) {
669 if(si%2) strcpy(tmp, "evenstudy"); else strcpy(tmp, "oddstudy");
670 fprintf(fp, " <tr class=\"%s\">\n", tmp);
671 fprintf(fp, " <td>%-3d</td>\n", si+1);
672 fprintf(fp, " <td>%s</td>\n", coll->voi[si].name);
673 fprintf(fp, " <td>%s%s</td>\n", coll->voi[si].voiname, coll->voi[si].hemisphere);
674 for(pi=0; pi<coll->parNr; pi++) {
675 if(coll->voi[si].parameter[pi]>=0) n=4; else n=3;
676 switch(partype[pi]) {
677 case 0: sprintf(tmp, "%.0f", coll->voi[si].parameter[pi]); break;
678 case 1: sprintf(tmp, "%.*f", n, coll->voi[si].parameter[pi]); break;
679 case 2:
680 default: sprintf(tmp, "%.*e", n, coll->voi[si].parameter[pi]); break;
681 }
682 fprintf(fp, " <td>%s</td>\n", tmp);
683 }
684 fprintf(fp, " </tr>\n");
685 }
686 fprintf(fp, " </tbody>\n");
687
688 /* Continue with the next region, if only one study was found */
689 if(coll->voiNr==1) {
690 fprintf(fp, "</table>\n");
691 return(0);
692 }
693
694 /* Write the statistics */
695 fprintf(fp, " <tbody>\n");
696 /* min */
697 fprintf(fp, " <tr class=\"oddsum\">\n");
698 fprintf(fp, " <td colspan=\"3\">Min</td>\n");
699 for(pi=0; pi<coll->parNr; pi++) {
700 if(resstat[0][pi]>=0) n=4; else n=3;
701 switch(partype[pi]) {
702 case 0: sprintf(tmp, "%.0f", resstat[0][pi]); break;
703 case 1: sprintf(tmp, "%.*f", n, resstat[0][pi]); break;
704 case 2:
705 default: sprintf(tmp, "%.*e", n, resstat[0][pi]); break;
706 }
707 fprintf(fp, " <td>%s</td>\n", tmp);
708 }
709 fprintf(fp, " </tr>\n");
710 /* max */
711 fprintf(fp, " <tr class=\"evensum\">\n");
712 fprintf(fp, " <td colspan=\"3\">Max</td>\n");
713 for(pi=0; pi<coll->parNr; pi++) {
714 if(resstat[1][pi]>=0) n=4; else n=3;
715 switch(partype[pi]) {
716 case 0: sprintf(tmp, "%.0f", resstat[1][pi]); break;
717 case 1: sprintf(tmp, "%.*f", n, resstat[1][pi]); break;
718 case 2:
719 default: sprintf(tmp, "%.*e", n, resstat[1][pi]); break;
720 }
721 fprintf(fp, " <td>%s</td>\n", tmp);
722 }
723 fprintf(fp, " </tr>\n");
724 /* median */
725 fprintf(fp, " <tr class=\"oddsum\">\n");
726 fprintf(fp, " <td colspan=\"3\">Median</td>\n");
727 for(pi=0; pi<coll->parNr; pi++) {
728 if(resstat[2][pi]>=0) n=6; else n=5;
729 switch(partype[pi]) {
730 case 0: sprintf(tmp, "%.2f", resstat[2][pi]); break;
731 case 1: sprintf(tmp, "%.*f", n, resstat[2][pi]); break;
732 case 2:
733 default: sprintf(tmp, "%.*e", n, resstat[2][pi]); break;
734 }
735 fprintf(fp, " <td>%s</td>\n", tmp);
736 }
737 fprintf(fp, " </tr>\n");
738 /* mean */
739 fprintf(fp, " <tr class=\"evensum\">\n");
740 fprintf(fp, " <td colspan=\"2\">Mean</td>\n");
741 fprintf(fp, " <td>n=%d</td>\n", coll->voiNr);
742 for(pi=0; pi<coll->parNr; pi++) {
743 if(resstat[3][pi]>=0) n=6; else n=5;
744 switch(partype[pi]) {
745 case 0: sprintf(tmp, "%.2f", resstat[3][pi]); break;
746 case 1: sprintf(tmp, "%.*f", n, resstat[3][pi]); break;
747 case 2:
748 default: sprintf(tmp, "%.*e", n, resstat[3][pi]); break;
749 }
750 fprintf(fp, " <td>%s</td>\n", tmp);
751 }
752 fprintf(fp, " </tr>\n");
753 /* sd */
754 fprintf(fp, " <tr class=\"oddsum\">\n");
755 fprintf(fp, " <td colspan=\"3\">SD</td>\n");
756 for(pi=0; pi<coll->parNr; pi++) {
757 if(resstat[4][pi]>=0) n=6; else n=5;
758 switch(partype[pi]) {
759 case 0: sprintf(tmp, "%.2f", resstat[4][pi]); break;
760 case 1: sprintf(tmp, "%.*f", n, resstat[4][pi]); break;
761 case 2:
762 default: sprintf(tmp, "%.*e", n, resstat[4][pi]); break;
763 }
764 fprintf(fp, " <td>%s</td>\n", tmp);
765 }
766 fprintf(fp, " </tr>\n");
767 fprintf(fp, " </tbody>\n");
768
769 /* End the table */
770 fprintf(fp, "</table>\n");
771
772 return(0);
773}
774/*****************************************************************************/
775
776/*****************************************************************************/
int backupExistingFile(char *filename, char *backup_ext, char *status)
Definition backup.c:14
Header file for libtpccurveio.
char reserrmsg[64]
Definition result.c:6
void resInit(RES *res)
Definition result.c:52
int resSetmem(RES *res, int voiNr)
Definition result.c:70
int resMatchRegions(RES *res1, RES *res2)
Definition result.c:1531
int resMean(double *data, int nr, double *mean, double *sd)
Definition result.c:1222
void resSortByName(RES *res)
Definition result.c:1266
void resPrint(RES *res)
Definition result.c:186
int resWriteXHTML11_head(FILE *fp, char *author_name)
Definition result.c:960
int resParameterPrintType(RES *res, int parIndex)
Definition result.c:1447
int resWriteXHTML11_doctype(FILE *fp)
Definition result.c:941
int resMatchParameternames(RES *res1, RES *res2)
Definition result.c:1564
int resIsDuplicateNames(RES *res)
Definition result.c:1473
#define MAX_RESPARAMS
int resRead(char *filename, RES *res, int verbose)
Definition result.c:199
int resWriteHTML_table(RES *res, FILE *fp)
Definition result.c:1013
void resEmpty(RES *res)
Definition result.c:22
int RESULT_TEST
Definition result.c:5
int resMedian(double *data, int nr, double *median, double *min, double *max)
Definition result.c:1186
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
void strCleanForXML(char *s)
Definition strext.c:402
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
void tpcProgramName(const char *program, int version, int copyright, char *prname, int n)
Definition proginfo.c:101
#define MAX_STUDYNR_LEN
Definition libtpcmisc.h:163
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
ResVOI * resGetNextResVOI(RES *reslist, int resNr, ResVOI *lastResVOI, int *resIndex)
Definition rescoll.c:556
int rescoll_tabulate(FILE *fp, RES *coll, int collNr)
Definition rescoll.c:602
int parNr
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
int voiNr
ResVOI * voi
char program[1024]
int isweight
char datafile[FILENAME_MAX]
char parunit[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
time_t time
double parameter[MAX_RESPARAMS]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]
char name[MAX_REGIONNAME_LEN+1]
char voiname[MAX_REGIONSUBNAME_LEN+1]