TPCCLIB
Loading...
Searching...
No Matches
rescoll.c File Reference

Collects results from separate PET studies. More...

Go to the source code of this file.

Functions

ResVOIresGetNextResVOI (RES *reslist, int resNr, ResVOI *lastResVOI, int *resIndex)
 
int rescoll_tabulate (FILE *fp, RES *coll, int collNr)
 

Detailed Description

Collects results from separate PET studies.

Author
Vesa Oikonen
Todo
Add option to save as CSV table.

Definition in file rescoll.c.

Function Documentation

◆ rescoll_tabulate()

int rescoll_tabulate ( FILE * fp,
RES * coll,
int collNr )

Tabulate the collected results of a single region. Calculates and tabulates also the statistics.

Returns
Returns zero if successful, otherwise non-zero.
Parameters
fpPointer to an opened file, where XHTML headers etc have already been written
collPointer to the structure that contains the collected data
collNrNumber of regions collected this far, including this one

Definition at line 602 of file rescoll.c.

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}
int resMean(double *data, int nr, double *mean, double *sd)
Definition result.c:1222
int resParameterPrintType(RES *res, int parIndex)
Definition result.c:1447
#define MAX_RESPARAMS
int resMedian(double *data, int nr, double *median, double *min, double *max)
Definition result.c:1186
int parNr
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
int voiNr
ResVOI * voi
char datafile[FILENAME_MAX]
double parameter[MAX_RESPARAMS]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char name[MAX_REGIONNAME_LEN+1]
char voiname[MAX_REGIONSUBNAME_LEN+1]

◆ resGetNextResVOI()

ResVOI * resGetNextResVOI ( RES * reslist,
int resNr,
ResVOI * lastResVOI,
int * resIndex )

Get the next study region from a list of study results. This function depends on sw2 in result structures.

Returns
Returns NULL in case of error, or if there are no more regions.
Parameters
reslistInput: pointer to the list of RES structures
resNrInput: Nr of RES structures
lastResVOIInput: pointer to the last VOI
resIndexOutput: index [0..resNr-1] of results containing the returned VOI

Definition at line 556 of file rescoll.c.

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}