TPCCLIB
Loading...
Searching...
No Matches
tpctacmod.h File Reference

Header file for libtpctacmod. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "tpcextensions.h"
#include "tpcli.h"
#include "tpctac.h"
#include "tpcmodels.h"
#include "tpcpar.h"
#include "tpcfunc.h"

Go to the source code of this file.

Data Structures

struct  DELAYCMFITDATA

Functions

int tacIntegrate (TAC *inp, TAC *out, TPCSTATUS *status)
 Integrate TACs from one TAC structure into a new TAC structure.
int tacIntegrateFE (TAC *inp, TAC *out, TAC *out2, TPCSTATUS *status)
 Integrate TACs from one TAC structure into a new TAC structure. Integrals are calculated at frame end times.
int tacInterpolate (TAC *inp, TAC *xinp, TAC *tac, TAC *itac, TAC *iitac, TPCSTATUS *status)
 Interpolate and/or integrate TACs from one TAC structure into a new TAC structure, using sample times from another TAC structure which is not changed.
int tacInterpolateInto (TAC *inp, TAC *tac, TAC *itac, TAC *iitac, TPCSTATUS *status)
 Add TACs from one TAC structure into another TAC structure, interpolating the input TACs and allocating space if necessary.
double tacAUC (TAC *tac, int ti, double t1, double t2, TPCSTATUS *status)
 Calculates TAC AUC from t1 to t2.
int tacInput2sim (TAC *itac, TAC *ttac, TAC *stac, TPCSTATUS *status)
 Modify input TAC based on tissue TAC, for use in simulations.
int tacVb (TAC *ttac, const int i, TAC *btac, double Vb, const int simVb, const int petVolume, TPCSTATUS *status)
 Correct TTACs for vascular blood, or simulate its effect.
int tacInterpolateToEqualLengthFrames (TAC *inp, double minfdur, double maxfdur, TAC *tac, TPCSTATUS *status)
int tacFittime (TAC *d, double *startTime, double *endTime, int *first, int *last, TPCSTATUS *status)
int tacReadModelingData (const char *tissuefile, const char *inputfile1, const char *inputfile2, const char *inputfile3, double *fitdur, int cutInput, int *fitSampleNr, TAC *tis, TAC *inp, TPCSTATUS *status)
 Read tissue and input data for modelling.
int tacReadReference (TAC *tis, const char *reference, TAC *ref, int *refIndex, TPCSTATUS *status)
 Read reference tissue TAC.
int tacReadModelingInput (const char *inputfile1, const char *inputfile2, const char *inputfile3, TAC *inp, TPCSTATUS *status)
 Read arterial input data for modelling.
int tacPlotFitSVG (TAC *tac1, TAC *tac2, const char *main_title, const double x1, const double x2, const double y1, const double y2, const char *fname, TPCSTATUS *status)
int tacPlotLineSVG (TAC *tac, const char *main_title, const double x1, const double x2, const double y1, const double y2, const char *fname, TPCSTATUS *status)
int mtgaPlotSVG (MTAC *mtac, const char *main_title, const char *fname, TPCSTATUS *status)
int tacPlotHistogramSVG (TAC *d, const char *main_title, const double x1, const double x2, const double y1, const double y2, const char *fname, TPCSTATUS *status)
int tacAllocateWithPAR (TAC *tac, PAR *par, int sampleNr, TPCSTATUS *status)
 Allocate TAC based on data in PAR.
int parAllocateWithTAC (PAR *par, TAC *tac, int parNr, TPCSTATUS *status)
 Allocate PAR based on data in TAC.
int tacToPAR (TAC *tac, PAR *par, TPCSTATUS *status)
 Copy the contents of TAC struct into PAR struct.
int tacDelay (TAC *tac, double dt, int ti, TPCSTATUS *status)
 Move TAC y values (concentrations) in time, keeping sample times (x values) intact.
void initDelayCMFitData (DELAYCMFITDATA *d)
 Before first use, initiate the data structure for delay time estimation.
void freeDelayCMFitData (DELAYCMFITDATA *d)
 After last use, free memory in the data structure for delay time estimation.
int tacDelayCMFit (TAC *btac, TAC *ttac, int ci, double dtmin, double dtmax, double fitend, double dtstep, double *dt, int mode, int model, DELAYCMFITDATA *tdata, TPCSTATUS *status)
 Fit time delay between PET tissue and plasma or blood curve.
int mfCreateTAC (PAR *par, double endx, double dx, TAC *tac, TPCSTATUS *status)
 Make TAC(s) based on mathematical functions in PAR format.

Detailed Description

Header file for libtpctacmod.

libtpctacmod contains functions needed in reading and processing PET TAC data for modelling and fitting.

Author
Vesa Oikonen

Definition in file tpctacmod.h.

Function Documentation

◆ freeDelayCMFitData()

void freeDelayCMFitData ( DELAYCMFITDATA * d)
extern

After last use, free memory in the data structure for delay time estimation.

See also
tacDelayCMFit, initDelayCMFitData
Parameters
dPointer to the data structure to be initialized.

Definition at line 150 of file delay.c.

153 {
154 if(d==NULL) return;
155 d->iNr=d->tNr=d->moveNr=0;
156 tacFree(&d->dtac); tacFree(&d->ditac); tacFree(&d->diitac); tacFree(&d->ddtac); tacFree(&d->dddtac);
157 d->mode=0; d->model=0;
158 d->llsq_n=d->llsq_m=0;
159 free(d->llsq_a); free(d->llsq_mat);
160 free(d->llsq_b); free(d->llsq_x); free(d->llsq_wp); free(d->llsq_zz);
161 free(d->llsq_i);
162 return;
163}
unsigned int iNr
Definition tpctacmod.h:33
unsigned int moveNr
Definition tpctacmod.h:53
double ** llsq_a
Definition tpctacmod.h:80
double * llsq_b
Definition tpctacmod.h:82
unsigned int tNr
Definition tpctacmod.h:35
double * llsq_mat
Definition tpctacmod.h:78
double * llsq_zz
Definition tpctacmod.h:88
double * llsq_x
Definition tpctacmod.h:84
double * llsq_wp
Definition tpctacmod.h:86
void tacFree(TAC *tac)
Definition tac.c:106

Referenced by tacDelayCMFit().

◆ initDelayCMFitData()

void initDelayCMFitData ( DELAYCMFITDATA * d)
extern

Before first use, initiate the data structure for delay time estimation.

See also
tacDelayCMFit, freeDelayCMFitData
Parameters
dPointer to the data structure to be initialized.

Definition at line 131 of file delay.c.

134 {
135 if(d==NULL) return;
136 d->iNr=d->tNr=d->moveNr=0;
137 tacInit(&d->dtac); tacInit(&d->ditac); tacInit(&d->diitac); tacInit(&d->ddtac); tacInit(&d->dddtac);
138 d->mode=0; d->model=0;
139 d->llsq_n=d->llsq_m=0;
140 d->llsq_mat=NULL;
141 d->llsq_a=NULL;
142 d->llsq_b=d->llsq_x=d->llsq_wp=d->llsq_zz=NULL;
143 d->llsq_i=NULL;
144 return;
145}
void tacInit(TAC *tac)
Definition tac.c:24

Referenced by tacDelayCMFit().

◆ mfCreateTAC()

int mfCreateTAC ( PAR * par,
double endx,
double dx,
TAC * tac,
TPCSTATUS * status )
extern

Make TAC(s) based on mathematical functions in PAR format.

See also
mfEvalY, parExampleTTACs
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
parPointer to PAR structure containing functions for TACs.
endxEnd time (x) of created TAC data. TAC will always start at zero.
dxStep size (delta x).
tacPointer to initiated TAC structure. Any previous contents are deleted.
statusPointer to status data; enter NULL if not needed.

Definition at line 26 of file mftac.c.

37 {
38 int verbose=0; if(status!=NULL) verbose=status->verbose;
39 if(verbose>2) {
40 printf("%s(par, %g, %g, tac, status)\n", __func__, endx, dx);
41 fflush(stdout);
42 }
43
44 /* Check provided data */
45 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
46 if(par==NULL || tac==NULL || !(endx>0.0) || !(dx>0.0)) return(status->error);
47 if(par->tacNr<1) {
48 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
49 return(status->error);
50 }
51
52 /* Make sure that TAC is empty */
53 tacFree(tac);
54
55 /* Allocate memory for TAC(s) */
56 int xNr=1+endx/dx;
57 int ret=tacAllocate(tac, xNr, par->tacNr);
58 if(ret!=TPCERROR_OK) {
59 statusSet(status, __func__, __FILE__, __LINE__, ret);
60 return(status->error);
61 }
62 tac->sampleNr=xNr;
63 tac->tacNr=par->tacNr;
64
65 /* Fill x (times) */
66 tac->isframe=0;
67 for(int i=0; i<xNr; i++) tac->x[i]=(double)i*dx;
68
69 /* Calculate curves */
70 for(int ci=0; ci<par->tacNr; ci++) {
71 strcpy(tac->c[ci].name, par->r[ci].name);
72 if(verbose>6)
73 printf("'%s' model=%u code=%s\n", par->r[ci].name, par->r[ci].model, modelCode(par->r[ci].model));
74 if(mfEvalY(modelCode(par->r[ci].model), modelParNr(par->r[ci].model), par->r[ci].p,
75 tac->sampleNr, tac->x, tac->c[ci].y, verbose-3))
76 {
77 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_DATA);
78 tacFree(tac); return(status->error);
79 }
80 }
81
82 /* Try to find units */
83 int i;
84 i=iftFindKey(&par->h, "unit", 0); if(i<0) i=iftFindKey(&par->h, "calibration_unit", 0);
85 if(i>=0) tac->cunit=unitIdentify(par->h.item[i].value);
86 i=iftFindKey(&par->h, "timeunit", 0); if(i<0) i=iftFindKey(&par->h, "time_unit", 0);
87 if(i>=0) tac->tunit=unitIdentify(par->h.item[i].value);
88
89 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
90 return(TPCERROR_OK);
91}
int mfEvalY(const char *fid, const int parNr, const double *p, const int sampleNr, const double *x, double *y, const int verbose)
Definition func.c:26
int iftFindKey(IFT *ift, const char *key, int start_index)
Definition iftfind.c:30
char * modelCode(const unsigned int i)
Definition modell.c:176
unsigned int modelParNr(const unsigned int code)
Definition modell.c:256
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
char * value
Definition tpcift.h:37
IFT_ITEM * item
Definition tpcift.h:57
IFT h
Optional (but often useful) header information.
Definition tpcpar.h:147
int tacNr
Definition tpcpar.h:104
PARR * r
Definition tpcpar.h:114
char name[MAX_TACNAME_LEN+1]
Definition tpcpar.h:50
unsigned int model
Definition tpcpar.h:48
double * p
Definition tpcpar.h:64
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
double * x
Definition tpctac.h:97
unit cunit
Definition tpctac.h:105
int sampleNr
Definition tpctac.h:89
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
unit tunit
Definition tpctac.h:109
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
@ TPCERROR_FAIL
General error.
@ TPCERROR_OK
No error.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_INCOMPATIBLE_DATA
Incompatible data.
int unitIdentify(const char *s)
Definition units.c:162

◆ mtgaPlotSVG()

int mtgaPlotSVG ( MTAC * mtac,
const char * main_title,
const char * fname,
TPCSTATUS * status )
extern

MTGA plots in SVG format.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacPlotLineSVG, tacPlotFitSVG
Author
Vesa Oikonen
Parameters
mtacPointer to MTAC structure, which contains plot data of tissue regions, each in its own TAC structure. TAC must contain the plot x axis values, and three y columns: points included in regression, points not included, and points representing the fitted line.
main_titleString for plot main title, or "".
fnameSVG file name.
statusPointer to status data; enter NULL if not needed.

Definition at line 489 of file tacfitplot.c.

501 {
502 int verbose=0; if(status!=NULL) verbose=status->verbose;
503 if(verbose>0) {printf("%s(MTAC, '%s', '%s')\n", __func__, main_title, fname); fflush(stdout);}
504 /* Check data */
505 if(mtac==NULL || mtac->nr<1) {
506 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
507 return TPCERROR_NO_DATA;
508 }
509 if(fname==NULL || strnlen(fname, 1)<1) {
510 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
512 }
513 if(status!=NULL && status->forgiving==0) {
514 // any strict tests in here
515 }
516 if(verbose>1) {printf("%d plot(s)\n", mtac->nr); fflush(stdout);}
517
518 /* Do we show plot legends? */
519 int is_label=0; if(mtac->nr>1) is_label=1;
520
521 /* Get the plot x and y range */
522 double minx=nan(""), maxx=nan(""), miny=nan(""), maxy=nan(""), maxly=nan("");
523 for(int i=0; i<mtac->nr; i++) {
524 if(mtac->tac[i].tacNr<3) continue;
525 double x1, x2, y1, y2;
526 if(tacSampleXRange(&mtac->tac[i], &x1, &x2)!=0) continue;
527 if(isfinite(x1) && !(x1>minx)) minx=x1;
528 if(isfinite(x2) && !(x2<maxx)) maxx=x2;
529 if(tacYRange(mtac->tac+i, -1, &y1, &y2, NULL, NULL, NULL, NULL)!=0) continue;
530 if(isfinite(y1) && !(y1>miny)) miny=y1;
531 if(isfinite(y2) && !(y2<maxy)) maxy=y2;
532 /* Get the y maximum from fitted line alone */
533 if(tacYRange(mtac->tac+i, 2, &y1, &y2, NULL, NULL, NULL, NULL)!=0) continue;
534 if(isfinite(y2) && !(y2<maxly)) maxly=y2;
535 }
536 if(verbose>1) {
537 printf("x-range := %g - %g\n", minx, maxx);
538 printf("y-range := %g - %g (%g for the line)\n", miny, maxy, maxly);
539 }
540 if(!(maxx>minx) || !(maxy>miny)) {
541 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
542 return TPCERROR_NO_DATA;
543 }
544 /* Limit the y range to maximal line value plus 1/40 of y range */
545 {
546 double yrange=maxy-miny;
547 double ylim=maxly+0.025*yrange;
548 if(maxy>ylim) maxy=ylim;
549 if(verbose>2) printf(" yrange := %g\n ylim := %g\n maxy := %g\n", yrange, ylim, maxy);
550 }
551
552 /* Start setting viewports */
553 struct svg_viewports viewports; svg_init_viewports(&viewports);
554 viewports.x.min=minx; viewports.x.max=maxx;
555 viewports.y.min=miny; viewports.y.max=maxy;
556 viewports.label_area_viewport.is=is_label; // needed for x axis ticks
557
558 /* Calculate the axis ticks */
559 if(svg_calculate_axes(&viewports, verbose-3)) {
560 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
562 }
563
564 /* Set x and y axis titles based on activity and time units */
565 char x_title[64], y_title[64];
566 strcpy(x_title, ""); strcpy(y_title, "");
567
568 /* Set the plot window and window area sizes; ticks should be set before this */
569 if(svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
570 strlen(x_title), is_label, &viewports, verbose-3))
571 {
572 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
574 }
575
576 /* Initiate graphics file */
577 FILE *fp=svg_initiate(fname, 0, 0, &viewports, NULL, verbose-3);
578 if(fp==NULL) {
579 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
581 }
582
583
584 /* Put the graph titles into their own viewports */
585 if(svg_create_main_title(fp, main_title, "", &viewports, NULL,verbose-3)) {
586 fclose(fp);
587 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
589 }
590 if(svg_create_yaxis_title(fp, y_title, &viewports, NULL, verbose-3)) {
591 fclose(fp);
592 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
594 }
595 if(svg_create_xaxis_title(fp, x_title, &viewports, NULL, verbose-3)) {
596 fclose(fp);
597 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
599 }
600
601 /* Put the plot into its own viewport */
602 if(svg_start_plot_viewport(fp, &viewports, NULL, verbose-3)) {
603 fclose(fp);
604 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
606 }
607
608 /* Start coordinate area viewport */
609 if(svg_start_coordinate_viewport(fp, &viewports, NULL, verbose-3)) {
610 fclose(fp);
611 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
613 }
614
615 /* Write plot axes */
616 if(svg_write_axes(fp, &viewports, NULL, verbose-3)) {
617 fclose(fp);
618 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
620 }
621
622
623 /*
624 * Draw the plots
625 */
626 SVG_LEGENDS legends; svg_init_legends(&legends);
627
628 int max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
629 if(verbose>3) {printf("max_color_nr := %d\n", max_color_nr); fflush(stdout);}
630 int color_nr; if(mtac->nr==1) color_nr=0; else color_nr=1;
631 int max_symbol_nr=0; while(svgSymbolName(max_symbol_nr)!=NULL) max_symbol_nr++;
632 if(verbose>3) printf("max_symbol_nr := %d\n", max_symbol_nr);
633 int n=0, symbol_nr=0;
634 for(int ri=0; ri<mtac->nr; ri++) {
635 if(mtac->tac[ri].tacNr<3) continue;
636 char tac_id[32], tac_title[64];
637 sprintf(tac_id, "plot_%d", n);
638 strcpy(tac_title, mtac->tac[ri].c[0].name);
639
640
641 /* Draw the measured points */
642 int ret=svg_write_tac(fp, &viewports, 2, tac_id, tac_title,
643 mtac->tac[ri].x, mtac->tac[ri].c[1].y, mtac->tac[ri].sampleNr,
644 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLOPEN,
645 NULL, verbose-3);
646 if(!ret) ret=svg_write_tac(fp, &viewports, 2, tac_id, tac_title,
647 mtac->tac[ri].x, mtac->tac[ri].c[0].y, mtac->tac[ri].sampleNr,
648 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLFILLED,
649 NULL, verbose-3);
650 /* Draw the regression line */
651 if(!ret) ret=svg_write_tac(fp, &viewports, 1, tac_id, tac_title,
652 mtac->tac[ri].x, mtac->tac[ri].c[2].y, mtac->tac[ri].sampleNr,
653 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLOPEN,
654 NULL, verbose-3);
655 if(ret) {
656 svg_legend_empty(&legends); fclose(fp);
657 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
659 }
660
661
662 /* Set legend too, if requested */
663 if(is_label!=0) {
664 unsigned int ci, si; // remainder works only if 2nd operator > 0
665 if(max_color_nr<1) ci=0; else ci=color_nr % max_color_nr;
666 if(max_symbol_nr<1) si=0; else si=symbol_nr % max_symbol_nr;
667 svg_legend_add(&legends, 0, si, SYMBOLFILLED, ci, tac_title);
668 }
669 /* Prepare for the next plot */
670 color_nr++; n++;
671 if(color_nr==max_color_nr) color_nr=0;
672 }
673
674
675
676 /* Close the coordinate viewport */
677 if(svg_end_coordinate_viewport(fp, NULL, verbose-3)) {
678 fclose(fp); svg_legend_empty(&legends);
679 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
681 }
682
683 /* Write the axis ticks */
684 if(svg_write_xticks(fp, &viewports, NULL, verbose-3)!=0 ||
685 svg_write_yticks(fp, &viewports, NULL, verbose-3)!=0)
686 {
687 fclose(fp); svg_legend_empty(&legends);
688 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
690 }
691
692 /* Close the plot viewport */
693 if(svg_end_plot_viewport(fp, NULL, verbose-3)) {
694 fclose(fp); svg_legend_empty(&legends);
695 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
697 }
698
699 /* Make the plot legends into their own viewport */
700 if(viewports.label_area_viewport.is!=0) {
701 if(verbose>2) {printf("creating plot legends\n"); fflush(stdout);}
702 int ret=svg_create_legends(fp, &viewports, &legends, NULL, verbose-3);
703 if(ret) {
704 fclose(fp); svg_legend_empty(&legends);
705 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
707 }
708 }
709 svg_legend_empty(&legends);
710
711 /* Close the SVG file */
712 if(svg_close(fp, NULL, verbose-3)) {
713 fclose(fp);
714 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
716 }
717
718 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
719 return(TPCERROR_OK);
720}
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
TAC * tac
Definition tpctac.h:151
int nr
Definition tpctac.h:153
int forgiving
Force level, 0 for strict tests for data units etc.
int tacSampleXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:162
int tacYRange(TAC *d, int i, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct.
Definition tacy.c:26
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_INVALID_FILENAME
Invalid file name.
@ TPCERROR_CANNOT_WRITE
Cannot write file.

◆ parAllocateWithTAC()

int parAllocateWithTAC ( PAR * par,
TAC * tac,
int parNr,
TPCSTATUS * status )
extern

Allocate PAR based on data in TAC.

Region number, names, etc are copied from given TAC.

See also
parAllocate, parAllocateMore, parInit, tacToPar
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
parPointer to initiated PAR struct; any old contents are deleted. PAR tacNr and parNr will be set, although contents will be empty.
Precondition
Struct must be initiated with parInit.
Parameters
tacPointer to TAC struct which contains at least the TAC number and names.
parNrNr of parameters to allocate.
statusPointer to status data; enter NULL if not needed.

Definition at line 90 of file partac.c.

101 {
102 int verbose=0; if(status!=NULL) verbose=status->verbose;
103 if(verbose>0) printf("%s(par, tac, %d)\n", __func__, parNr);
104
105 /* Check the input */
106 if(tac==NULL || par==NULL) {
107 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
108 return TPCERROR_FAIL;
109 }
110 if(parNr<1 || tac->tacNr<1) {
111 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
112 return TPCERROR_NO_DATA;
113 }
114
115 int i, ret;
116
117 /* Allocate memory */
118 if(verbose>2) printf("allocate memory for PAR\n");
119 ret=parAllocate(par, parNr, tac->tacNr);
120 if(ret!=TPCERROR_OK) {statusSet(status, __func__, __FILE__, __LINE__, ret); return ret;}
121 par->tacNr=tac->tacNr;
122 par->parNr=parNr;
123
124 /* Copy TAC names */
125 if(verbose>3) printf("copy TAC names\n");
126 for(int i=0; i<par->tacNr; i++) strcpy(par->r[i].name, tac->c[i].name);
127
128 /* Copy header information */
129 if(verbose>3) printf("copy header\n");
130
131 i=iftFindKey(&tac->h, "studynr", 0);
132 if(i<0) i=iftFindKey(&tac->h, "study_number", 0);
133 if(i>=0) iftPut(&par->h, tac->h.item[i].key, tac->h.item[i].value, 0, NULL);
134
135 i=iftFindKey(&tac->h, "injection_time", 0);
136 if(i<0) i=iftFindKey(&tac->h, "injection time", 0);
137 if(i>=0) iftPut(&par->h, tac->h.item[i].key, tac->h.item[i].value, 0, NULL);
138
139 i=iftFindKey(&tac->h, "isotope", 0);
140 if(i>=0) iftPut(&par->h, tac->h.item[i].key, tac->h.item[i].value, 0, NULL);
141
142 i=iftFindKey(&tac->h, "radiopharmaceutical", 0);
143 if(i>=0) iftPut(&par->h, tac->h.item[i].key, tac->h.item[i].value, 0, NULL);
144
145 i=iftFindKey(&tac->h, "scan_start_time", 0);
146 if(i>=0) iftPut(&par->h, tac->h.item[i].key, tac->h.item[i].value, 0, NULL);
147
148 if(tacIsWeighted(tac)) iftPut(&par->h, "weighting", "yes", 0, NULL);
149 else iftPut(&par->h, "weighting", "no", 0, NULL);
150
151 if(tac->tunit!=UNIT_UNKNOWN)
152 iftPut(&par->h, "timeunit", unitName(tac->tunit), 0, NULL);
153 if(tac->cunit!=UNIT_UNKNOWN)
154 iftPut(&par->h, "unit", unitName(tac->cunit), 0, NULL);
155
156 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
157 return(TPCERROR_OK);
158}
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
Definition ift.c:63
int parAllocate(PAR *par, int parNr, int tacNr)
Definition par.c:108
char * key
Definition tpcift.h:32
int parNr
Definition tpcpar.h:108
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
int tacIsWeighted(TAC *tac)
Definition tacw.c:24
@ UNIT_UNKNOWN
Unknown unit.
char * unitName(int unit_code)
Definition units.c:143

Referenced by tacToPAR().

◆ tacAllocateWithPAR()

int tacAllocateWithPAR ( TAC * tac,
PAR * par,
int sampleNr,
TPCSTATUS * status )
extern

Allocate TAC based on data in PAR.

TAC region number, names, and units are copied from given PAR.

See also
tacAllocate, tacAllocateMore, tacDuplicate, tacAllocateWithIMG
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
tacPointer to initiated TAC structure; any old contents are deleted. TAC sampleNr and tacNr will be set, although contents will be empty.
Precondition
Structure must be initiated with tacInit.
Parameters
parPointer to PAR structure which contains at least the TAC number and names.
sampleNrNr of samples (time frames) to allocate.
statusPointer to status data; enter NULL if not needed.

Definition at line 28 of file partac.c.

39 {
40 int verbose=0; if(status!=NULL) verbose=status->verbose;
41 if(verbose>0) printf("%s(tac, par, %d)\n", __func__, sampleNr);
42
43 /* Check the input */
44 if(tac==NULL || par==NULL) {
45 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
46 return TPCERROR_FAIL;
47 }
48 if(sampleNr<1 || par->tacNr<1) {
49 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
50 return TPCERROR_NO_DATA;
51 }
52
53 int ret, i;
54
55 /* Allocate */
56 ret=tacAllocate(tac, sampleNr, par->tacNr);
57 statusSet(status, __func__, __FILE__, __LINE__, ret);
58 if(ret!=TPCERROR_OK) return(ret);
59 tac->sampleNr=sampleNr; tac->tacNr=par->tacNr;
60
61 /* Copy TAC names */
62 for(int i=0; i<par->tacNr; i++) strcpy(tac->c[i].name, par->r[i].name);
63
64 /* Try to find the data units */
65 i=iftFindKey(&par->h, "unit", 0);
66 if(i<0) i=iftFindKey(&par->h, "calibration_unit", 0);
67 if(i>0) tac->cunit=unitIdentify(par->h.item[i].value);
68 i=iftFindKey(&par->h, "timeunit", 0);
69 if(i<0) i=iftFindKey(&par->h, "time_unit", 0);
70 if(i>0) tac->tunit=unitIdentify(par->h.item[i].value);
71 /* Try to find study number */
72 i=iftFindKey(&par->h, "studynr", 0);
73 if(i<0) i=iftFindKey(&par->h, "study", 0);
74 if(i>=0) {
75 iftPut(&tac->h, par->h.item[i].key, par->h.item[i].value, 1, NULL);
76 }
77
78 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
79 return(TPCERROR_OK);
80}

◆ tacAUC()

double tacAUC ( TAC * tac,
int ti,
double t1,
double t2,
TPCSTATUS * status )
extern

Calculates TAC AUC from t1 to t2.

See also
tacInterpolate, liInterpolate, liIntegrate
Returns
AUC, or NaN in case of an error.
Parameters
tacPointer to TAC structure.
Precondition
Data must be sorted by increasing x. No gaps or overlap between frames allowed.
See also
tacSortByTime, tacSetXContiguous
Parameters
tiIndex [0..tacNr-1] of the TAC to calculate AUC from.
t1AUC start time.
t2AUC end time.
statusPointer to status data; enter NULL if not needed.

Definition at line 486 of file litac.c.

500 {
501 int verbose=0; if(status!=NULL) verbose=status->verbose;
502 if(verbose>0) printf("%s(tac, %d, %g, %g)\n", __func__, ti, t1, t2);
503 /* Check the function input */
504 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1) {
505 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
506 return(nan(""));
507 }
508 if(ti<0 || ti>=tac->tacNr) {
509 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
510 return(nan(""));
511 }
512 if(t1>=t2) {
513 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
514 return(nan(""));
515 }
516
517 /* Get and check the x range */
518 double xmin=nan(""), xmax=nan("");
519 if(tacXRange(tac, &xmin, &xmax)!=0 || t1>=xmax || t2<=xmin) {
520 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
521 return(nan(""));
522 }
523
524 /* Make temporary x and yi array */
525 double tx[2]; tx[0]=t1; tx[1]=t2;
526 double tyi[2];
527
528 /* If TAC contains just frame mid times, then simple dot-to-dot integration */
529 if(tac->isframe==0) {
530 if(liInterpolate(tac->x, tac->c[ti].y, tac->sampleNr, tx, NULL, tyi, NULL, 2, 3, 1, verbose-10))
531 {
532 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
533 return(nan(""));
534 }
535 /* That's it then */
536 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
537 return(tyi[1]-tyi[0]);
538 }
539
540 /* We have frame start and end times */
541 /* Convert the data into stepwise dot-to-dot data */
542 TAC stac; tacInit(&stac);
543 {
544 int ret=tacFramesToSteps(tac, &stac, NULL);
545 if(ret!=TPCERROR_OK) {
546 tacFree(&stac);
547 statusSet(status, __func__, __FILE__, __LINE__, ret);
548 return(nan(""));
549 }
550 }
551 /* Then simple dot-to-dot integration */
552 if(liInterpolate(stac.x, stac.c[ti].y, stac.sampleNr, tx, NULL, tyi, NULL, 2, 3, 1, verbose-10))
553 {
554 tacFree(&stac);
555 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
556 return(nan(""));
557 }
558 tacFree(&stac);
559
560 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
561 return(tyi[1]-tyi[0]);
562}
int liInterpolate(double *x, double *y, const int nr, double *newx, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear interpolation and/or integration with trapezoidal method.
Definition tpctac.h:87
int tacFramesToSteps(TAC *inp, TAC *out, TPCSTATUS *status)
Transform TAC with frames into TAC with frames represented with stepwise changing dot-to-dot data.
Definition tacx.c:942
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:124
@ TPCERROR_INVALID_XRANGE
Invalid sample time range.

◆ tacDelay()

int tacDelay ( TAC * tac,
double dt,
int ti,
TPCSTATUS * status )
extern

Move TAC y values (concentrations) in time, keeping sample times (x values) intact.

If TAC has frame start and end times, this function tries to retain the AUC with stepwise frame interpretation. If you wish to prevent this, then set tac->isframe=0 before calling this function and after it set back tac->isframe=1.

See also
tacDelayCMFit, tacInterpolate, tacFramesToSteps, simDispersion, liInterpolate, tacVb
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
tacPointer to TAC structure.
Precondition
Data must be sorted by increasing x. No gaps or overlap between frames allowed.
See also
tacSortByTime, tacSetXContiguous
Postcondition
Data y values are modified, x values will stay the same.
Parameters
dtTime (in TAC tunit's) to move the TAC forward (negative time moves TAC backward).
tiIndex [0..tacNr-1] of the TAC to move, or <0 to move all TACs.
statusPointer to status data; enter NULL if not needed.

Definition at line 29 of file delay.c.

41 {
42 int verbose=0; if(status!=NULL) verbose=status->verbose;
43 if(verbose>0) printf("%s(tac, %g, %d)\n", __func__, dt, ti);
44 /* Check the function input */
45 if(tac==NULL || tac->sampleNr<1 || tac->tacNr<1) {
46 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
47 return TPCERROR_NO_DATA;
48 }
49 if(ti>=tac->tacNr) {
50 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
51 return TPCERROR_FAIL;
52 }
53 if(fabs(dt)<1.0E-12) {
54 if(verbose>1) printf(" requested delay time is zero; nothing done.\n");
55 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
56 return(TPCERROR_OK);
57 }
58 /* Check that input does not have any missing values */
59 if(tacXNaNs(tac)>0 || tacYNaNs(tac, ti)>0) {
60 if(verbose>1) printf(" data contains NaN(s).\n");
61 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
63 }
64
65 /* Get and check the x range */
66 double xmin=nan(""), xmax=nan("");
67 if(tacXRange(tac, &xmin, &xmax)!=0 || dt>=xmax || dt<=-xmax) {
68 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
70 }
71 if(verbose>2) printf(" xrange: %g - %g\n", xmin, xmax);
72
73
74 /* If TAC contains just frame mid times, then simple dot-to-dot interpolation */
75 if(tac->isframe==0) {
76 /* Make temporary x array */
77 double tx[tac->sampleNr];
78 for(int i=0; i<tac->sampleNr; i++) tx[i]=tac->x[i]+dt;
79 /* One TAC at a time */
80 for(int j=0; j<tac->tacNr; j++) if(ti<0 || ti==j) {
81 /* Make temporary y array */
82 double ty[tac->sampleNr];
83 for(int i=0; i<tac->sampleNr; i++) ty[i]=tac->c[j].y[i];
84 /* Interpolate temporary data to original times */
85 if(liInterpolate(tx, ty, tac->sampleNr, tac->x, tac->c[j].y, NULL, NULL, tac->sampleNr, 0, 1,
86 verbose-10)!=0)
87 {
88 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
90 }
91 }
92 /* That's it then */
93 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
94 return(TPCERROR_OK);
95 }
96
97 /* We have frame start and end times */
98 /* Convert the data into stepwise dot-to-dot data */
99 TAC stac; tacInit(&stac);
100 {
101 int ret=tacFramesToSteps(tac, &stac, NULL);
102 if(ret!=TPCERROR_OK) {
103 tacFree(&stac);
104 statusSet(status, __func__, __FILE__, __LINE__, ret);
105 return(ret);
106 }
107 }
108 /* Change times of the stepwise data */
109 for(int i=0; i<stac.sampleNr; i++) stac.x[i]+=dt;
110 /* Interpolate stepwise data into original frame times, one TAC at a time */
111 for(int j=0; j<tac->tacNr; j++) if(ti<0 || ti==j) {
112 if(liInterpolateForPET(stac.x, stac.c[j].y, stac.sampleNr, tac->x1, tac->x2, tac->c[j].y,
113 NULL, NULL, tac->sampleNr, 0, 1, verbose-10))
114 {
115 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
117 }
118 }
119 tacFree(&stac);
120
121
122 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
123 return(TPCERROR_OK);
124}
int liInterpolateForPET(double *x, double *y, const int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear TAC interpolation and/or integration to PET frames.
double * x2
Definition tpctac.h:101
double * x1
Definition tpctac.h:99
int tacYNaNs(TAC *tac, const int i)
Definition tacnan.c:47
int tacXNaNs(TAC *tac)
Definition tacnan.c:23
@ TPCERROR_MISSING_DATA
File contains missing values.

◆ tacDelayCMFit()

int tacDelayCMFit ( TAC * btac,
TAC * ttac,
int ci,
double dtmin,
double dtmax,
double fitend,
double dtstep,
double * dt,
int mode,
int model,
DELAYCMFITDATA * tdata,
TPCSTATUS * status )
extern

Fit time delay between PET tissue and plasma or blood curve.

Initial part of tissue curve is fitted with a range of input curves moved in time, using linearised one or two-tissue compartment model with blood volume term. The time that provides the best fit is selected. It is assumed that tissue heterogeneity, dispersion of the blood curve, metabolites, and variable plasma-to-blood ratio will only minimally impact the time delay estimate, since only the initial part of the data is fitted, especially if reversible two-tissue model (R2tCM) is used.

See also
tacDelay, simDispersion
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
btacPointer to input data (blood or plasma curve). Units of input and tissue TAC must match. All but first curve in TAC are ignored. Enter NULL in subsequent runs
ttacPointer to tissue data. Units of input and tissue TAC must match. All but first curve in TAC are ignored.
ciIndex [0..ttac->tacNr-1] of tissue tac to use.
dtminMinimum delay to be tested, for example -10 s, in the same units as in TACs. Not used in subsequent runs with tdata.
dtmaxMaximum delay to be tested, for example +50 s, in the same units as in TACs. Not used in subsequent runs with tdata.
fitendFitting uses data from 0 to end time, for example 120 s, in the same units as in TACs. In case of short PET scan, end time may need to be reduced so that input TAC with negative delay extends to the fit end. Not used in subsequent runs with tdata.
dtstepThe step length for moving the input curve, for example 1 s, in the same units as in TACs. Not used in subsequent runs with tdata.
dtPointer for the time delay estimate. Positive delay time means that tissue curve is delayed as compared to the input curve, and vice versa. Thus, input curve needs to be moved by the delay time to match the tissue curve.
modeMode for multilinear equations: 0=integrals and 2nd integrals, 1=derivates and 2nd derivates (experimental), 2=integrals and derivates (experimental).
modelModel: 0=R1TCM, 1=I2TCM, 2=R2TCM.
tdataPointer to temporary data structure, which quickens subsequent runs with other tissue TACs; enter NULL if not needed.
See also
initDelayCMFitData, freeDelayCMFitData
Parameters
statusPointer to status data; enter NULL if not needed.

Definition at line 179 of file delay.c.

219 {
220 int verbose=0; if(status!=NULL) verbose=status->verbose;
221 if(verbose>2) {
222 printf("%s(inp, tis, %d, %g, %g, %g, %g, %d, ...)\n", __func__, ci, dtmin, dtmax, fitend, dtstep, mode);
223 fflush(stdout);
224 }
225
226
227 /* Check provided data */
228 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
229 if(ttac==NULL || (btac==NULL && tdata==NULL)) return(TPCERROR_FAIL);
230 if(btac!=NULL && (btac->tacNr<1 || btac->sampleNr<4)) return(TPCERROR_FAIL);
231 if(ci<0 || ci>=ttac->tacNr || ttac->sampleNr<4) return(TPCERROR_FAIL);
232 if(model<0 || model>2) return(TPCERROR_FAIL);
233 if(dt!=NULL) *dt=nan("");
234
235 /* Initiate (possibly reused) data structure */
236 DELAYCMFITDATA *b, ltdata; initDelayCMFitData(&ltdata);
237 if(tdata!=NULL) {
238 b=tdata;
239 if(verbose>3) {
240 if(b->moveNr==0) printf(" given temp data will be filled\n");
241 else printf(" filled temp data will be used\n");
242 fflush(stdout);
243 }
244 } else {
245 b=&ltdata;
246 if(verbose>4) {printf(" local temp data created\n"); fflush(stdout);}
247 }
248
249 /* Check and set temp data when run first time with the given TTAC */
250 if(btac!=NULL || b->moveNr==0) {
251 /* Delay range and steps*/
252 if(!(dtmax>dtmin) || !(dtstep>0.001)) {
253 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
255 }
256 b->dtmin=dtmin; b->dtmax=dtmax; b->dtstep=dtstep;
257 /* How many delayed curves needed */
258 b->moveNr=1+(b->dtmax-b->dtmin)/b->dtstep;
259 if(verbose>3) printf(" moveNr := %d\n", b->moveNr);
260 if(b->moveNr<5 || b->moveNr>5000) {
261 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
263 }
264 /* Get x range */
265 if(tacXRange(ttac, &b->ttac_xmin, &b->ttac_xmax)!=0 || tacXRange(btac, &b->btac_xmin, &b->btac_xmax)!=0) {
266 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
268 }
269 if(verbose>3) printf(" TTAC range := %g - %g\n BTAC range := %g - %g\n",
270 b->ttac_xmin, b->btac_xmax, b->ttac_xmin, b->btac_xmax);
271 /* Check that time units do match */
272 if(btac->tunit!=ttac->tunit) {
273 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
274 return(TPCERROR_INVALID_X);
275 }
276 /* Check that input curve is long enough to fit duration */
277 if(!(fitend>0.0)) {
278 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
280 }
281 b->fitend=fitend;
282 if(b->fitend>b->ttac_xmax) b->fitend=b->ttac_xmax;
283 if(b->fitend>b->btac_xmax) b->fitend=b->btac_xmax;
284 if(b->dtmin<0.0 && b->btac_xmax<(b->fitend+b->dtmin))
285 b->fitend+=b->dtmin;
286 if(verbose>3) printf("fitend=%g -> %g\n", fitend, b->fitend);
287 b->iNr=0; for(unsigned int i=0; i<(unsigned int)btac->sampleNr; i++) if(btac->x[i]<=b->fitend) b->iNr++; else break;
288 b->tNr=0; for(unsigned int i=0; i<(unsigned int)ttac->sampleNr; i++) if(ttac->x[i]<=b->fitend) b->tNr++; else break;
289 //printf("iNr=%u tNr=%u\n", b->iNr, b->tNr);
290 if(b->iNr<5 || b->tNr<5) {
291 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
293 }
294
295 /* Further, when run the first time, make input TACs moved in time, interpolated and integrated
296 to tissue times */
297 if(verbose>5) {printf(" preparing delayed input data\n"); fflush(stdout);}
298 b->mode=mode;
299 b->model=model;
300 int ret;
301 ret=tacAllocate(&b->dtac, b->tNr, b->moveNr+1); // additional place for tissue curve
302 if(ret!=TPCERROR_OK) {
303 freeDelayCMFitData(&ltdata);
304 statusSet(status, __func__, __FILE__, __LINE__, ret);
306 }
307 b->dtac.sampleNr=b->tNr;
308 b->dtac.tacNr=b->moveNr+1; // tissue as the last curve
309 b->dtac.isframe=ttac->isframe;
310 for(int i=0; i<b->dtac.sampleNr; i++) {
311 b->dtac.x1[i]=ttac->x1[i]; b->dtac.x[i]=ttac->x[i]; b->dtac.x2[i]=ttac->x2[i];}
312 ret=tacDuplicate(&b->dtac, &b->ditac);
313 if(ret==TPCERROR_OK) ret=tacDuplicate(&b->dtac, &b->diitac);
314 if(ret==TPCERROR_OK) ret=tacDuplicate(&b->dtac, &b->ddtac);
315 if(ret==TPCERROR_OK) ret=tacDuplicate(&b->dtac, &b->dddtac);
316 if(ret!=TPCERROR_OK) {
317 freeDelayCMFitData(&ltdata);
318 statusSet(status, __func__, __FILE__, __LINE__, ret);
319 return(ret);
320 }
321 /* Integrate/derivate input data, change times, and interpolate to tissue data */
322 double bd[btac->sampleNr], bdd[btac->sampleNr];
323 double bi[btac->sampleNr], bii[btac->sampleNr];
324 if(liDerivate3(btac->x, btac->c[0].y, btac->sampleNr, bd, bdd, 0)) {
325 freeDelayCMFitData(&ltdata);
326 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
328 }
329 if(btac->isframe==0) {
330 if(liIntegrate(btac->x, btac->c[0].y, btac->sampleNr, bi, 3, 0) ||
331 liIntegrate(btac->x, bi, btac->sampleNr, bii, 3, 0))
333 } else {
334 if(liIntegrateFE(btac->x1, btac->x2, btac->c[0].y, btac->sampleNr, bi, bii, 0))
336 }
337 if(ret) {
338 freeDelayCMFitData(&ltdata);
339 statusSet(status, __func__, __FILE__, __LINE__, ret);
340 return(ret);
341 }
342 double dx[btac->sampleNr], dx2[btac->sampleNr], *dxp;
343 if(btac->isframe==0) dxp=dx; else dxp=dx2;
344 for(int di=0; di<b->dtac.tacNr-1; di++) {
345 for(int i=0; i<btac->sampleNr; i++) {
346 dx[i]=btac->x[i]+b->dtmin+di*b->dtstep;
347 dx2[i]=btac->x2[i]+b->dtmin+di*b->dtstep;
348 }
349 if(b->dtac.isframe==0) {
350 ret=liInterpolate(dx, btac->c[0].y, btac->sampleNr, b->dtac.x, b->dtac.c[di].y,
351 NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
352
353 if(!ret) ret=liInterpolate(dxp, bi, btac->sampleNr, b->dtac.x, b->ditac.c[di].y,
354 NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
355 if(!ret) ret=liInterpolate(dxp, bii, btac->sampleNr, b->dtac.x, b->diitac.c[di].y,
356 NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
357 if(!ret) ret=liInterpolate(dx, bd, btac->sampleNr, b->dtac.x, b->ddtac.c[di].y,
358 NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
359 if(!ret) ret=liInterpolate(dx, bdd, btac->sampleNr, b->dtac.x, b->dddtac.c[di].y,
360 NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
361 } else {
362 ret=liInterpolateForPET(dx, btac->c[0].y, btac->sampleNr, b->dtac.x1, b->dtac.x2,
363 b->dtac.c[di].y, NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
364 if(!ret) ret=liInterpolateForPET(dxp, bi, btac->sampleNr, b->dtac.x1, b->dtac.x2,
365 b->ditac.c[di].y, NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
366 if(!ret) ret=liInterpolateForPET(dxp, bii, btac->sampleNr, b->dtac.x1, b->dtac.x2,
367 b->diitac.c[di].y, NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
368 if(!ret) ret=liInterpolateForPET(dx, bd, btac->sampleNr, b->dtac.x1, b->dtac.x2,
369 b->ddtac.c[di].y, NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
370 if(!ret) ret=liInterpolateForPET(dx, bdd, btac->sampleNr, b->dtac.x1, b->dtac.x2,
371 b->dddtac.c[di].y, NULL, NULL, b->dtac.sampleNr, 3, 1, 0);
372 }
373 if(ret) {
374 freeDelayCMFitData(&ltdata);
375 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
377 }
378 }
379 if(verbose>6) {
380 printf("integrated input curve 1:\n");
381 for(int i=0; i<b->dtac.sampleNr; i++)
382 printf("%g %g %g %g\n", b->dtac.x[i], b->dtac.c[0].y[i], b->ditac.c[0].y[i], b->diitac.c[0].y[i]);
383 fflush(stdout);
384 }
385
386
387 /* Allocate memory for linear LSQ */
388 if(verbose>5) {printf(" preparing data for LLSQ\n"); fflush(stdout);}
389 b->llsq_n=3+b->model;
390 b->llsq_m=b->dtac.sampleNr;
391 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
392 b->llsq_mat=(double*)malloc((b->llsq_n*b->llsq_m)*sizeof(double));
393 if(b->llsq_mat==NULL) {freeDelayCMFitData(&ltdata); return(TPCERROR_OUT_OF_MEMORY);}
394 b->llsq_a=(double**)malloc(b->llsq_n*sizeof(double*));
395 if(b->llsq_a==NULL) {freeDelayCMFitData(&ltdata); return(TPCERROR_OUT_OF_MEMORY);}
396 for(int ni=0; ni<b->llsq_n; ni++) b->llsq_a[ni]=b->llsq_mat+ni*b->llsq_m;
397 b->llsq_b=(double*)malloc(b->llsq_m*sizeof(double));
398 b->llsq_x=(double*)malloc(b->llsq_n*sizeof(double));
399 b->llsq_wp=(double*)malloc(b->llsq_n*sizeof(double));
400 b->llsq_zz=(double*)malloc(b->llsq_m*sizeof(double));
401 b->llsq_i=(int*)malloc(b->llsq_n*sizeof(int));
402 if(b->llsq_b==NULL || b->llsq_x==NULL || b->llsq_wp==NULL || b->llsq_zz==NULL || b->llsq_i==NULL) {
403 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
405 }
406
407 /* Integrate tissue curve */
408 {
409 if(verbose>5) {printf(" preparing tissue data\n"); fflush(stdout);}
410 int ti=b->dtac.tacNr-1; // index of tissue curve after the input curves
411 for(int i=0; i<b->dtac.sampleNr; i++) b->dtac.c[ti].y[i]=ttac->c[ci].y[i];
412
413 int ret=liDerivate(b->dtac.x, b->dtac.c[ti].y, b->dtac.sampleNr, b->ddtac.c[ti].y, b->dddtac.c[ti].y, 0);
414 if(b->dtac.isframe==0) {
415 if(!ret) ret=liIntegrate(b->dtac.x, b->dtac.c[ti].y, b->dtac.sampleNr, b->ditac.c[ti].y, 3, 0);
416 if(!ret) ret=liIntegrate(b->dtac.x, b->ditac.c[ti].y, b->dtac.sampleNr, b->diitac.c[ti].y, 3, 0);
417 } else {
418 if(!ret) ret=liIntegrateFE(b->dtac.x1, b->dtac.x2, b->dtac.c[ti].y, b->dtac.sampleNr,
419 b->ditac.c[ti].y, b->diitac.c[ti].y, 0);
420 }
421 if(ret) {
422 freeDelayCMFitData(&ltdata);
423 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
425 }
426
427 if(verbose>10) {
428 printf("integrated tissue curves:\n");
429 for(int i=0; i<b->dtac.sampleNr; i++)
430 printf("%g %g %g %g\n", b->dtac.x[i], b->dtac.c[ti].y[i], b->ditac.c[ti].y[i], b->diitac.c[ti].y[i]);
431 fflush(stdout);
432 }
433 }
434
435
436 /* Multilinear fitting with each delayed input */
437 if(verbose>5) {printf(" LLSQ\n"); fflush(stdout);}
438 double ss, ssmin=nan("");
439 int mini=-1;
440 for(int di=0; di<b->dtac.tacNr-1; di++) {
441 /* Setup data matrix A and vector B */
442 for(int mi=0; mi<b->llsq_m; mi++) {
443 b->llsq_b[mi]=b->dtac.c[b->dtac.tacNr-1].y[mi]; // TTAC
444 b->llsq_mat[mi]=b->dtac.c[di].y[mi]; // BTAC
445 if(mode==1) {
446 b->llsq_mat[mi+1*b->llsq_m]=b->ddtac.c[di].y[mi]; // BTAC derivate
447 b->llsq_mat[mi+2*b->llsq_m]=-b->ddtac.c[b->dtac.tacNr-1].y[mi]; // TTAC derivate
448 if(b->llsq_n>3) b->llsq_mat[mi+3*b->llsq_m]=b->dddtac.c[di].y[mi]; // BTAC derivate
449 if(b->llsq_n>4) b->llsq_mat[mi+4*b->llsq_m]=-b->dddtac.c[b->dtac.tacNr-1].y[mi]; // TTAC derivate
450 } else if(mode==2) {
451 b->llsq_mat[mi+1*b->llsq_m]=b->ditac.c[di].y[mi]; // BTAC integral
452 b->llsq_mat[mi+2*b->llsq_m]=-b->ditac.c[b->dtac.tacNr-1].y[mi]; // TTAC integral
453 if(b->llsq_n>3) b->llsq_mat[mi+3*b->llsq_m]=b->ddtac.c[di].y[mi]; // BTAC derivate
454 if(b->llsq_n>4) b->llsq_mat[mi+4*b->llsq_m]=-b->ddtac.c[b->dtac.tacNr-1].y[mi]; // TTAC derivate
455 } else { // mode 0
456 b->llsq_mat[mi+1*b->llsq_m]=b->ditac.c[di].y[mi]; // BTAC integral
457 b->llsq_mat[mi+2*b->llsq_m]=-b->ditac.c[b->dtac.tacNr-1].y[mi]; // TTAC integral
458 if(b->llsq_n>3) b->llsq_mat[mi+3*b->llsq_m]=b->diitac.c[di].y[mi]; // BTAC 2nd integral
459 if(b->llsq_n>4) b->llsq_mat[mi+4*b->llsq_m]=-b->diitac.c[b->dtac.tacNr-1].y[mi]; // TTAC 2nd integral
460 }
461 b->llsq_mat[mi]=b->dtac.c[di].y[mi]; // BTAC
462 b->llsq_mat[mi+1*b->llsq_m]=b->ditac.c[di].y[mi]; // BTAC integral
463 b->llsq_mat[mi+2*b->llsq_m]=-b->ditac.c[b->dtac.tacNr-1].y[mi]; // TTAC integral
464 if(b->llsq_n>3) b->llsq_mat[mi+3*b->llsq_m]=b->diitac.c[di].y[mi]; // BTAC 2nd integral
465 if(b->llsq_n>4) b->llsq_mat[mi+4*b->llsq_m]=-b->diitac.c[b->dtac.tacNr-1].y[mi]; // TTAC 2nd integral
466 }
467 if(verbose>3) {
468 int failnr=0;
469 for(int mi=0; mi<b->llsq_m; mi++) {
470 if(!isfinite(b->llsq_b[mi])) failnr++;
471 if(!isfinite(b->llsq_mat[mi])) failnr++;
472 if(!isfinite(b->llsq_mat[mi+1*b->llsq_m])) failnr++;
473 if(!isfinite(b->llsq_mat[mi+2*b->llsq_m])) failnr++;
474 if(!isfinite(b->llsq_mat[mi+3*b->llsq_m])) failnr++;
475 if(!isfinite(b->llsq_mat[mi+4*b->llsq_m])) failnr++;
476 }
477 if(failnr>0) printf("%d bad values\n", failnr);
478 }
479 if(verbose>9 && b->llsq_m<100) {
480 printf("---- B x A ----\n");
481 for(int mi=0; mi<b->llsq_m; mi++) {
482 printf(" %g ", b->llsq_b[mi]);
483 for(int ni=0; ni<b->llsq_n; ni++)
484 printf(" %g", b->llsq_mat[mi+ni*b->llsq_m]);
485 printf("\n");
486 }
487 }
488
489 int ret=nnls(b->llsq_a, b->llsq_m, b->llsq_n, b->llsq_b, b->llsq_x, &ss, b->llsq_wp, b->llsq_zz, b->llsq_i);
490 if(ret<2 && isfinite(ss)) {
491 if(!isfinite(ssmin) || ssmin>ss) {ssmin=ss; mini=di;}
492 if(verbose>2) printf(" %d %d %g %g\n", di, mini, ss, ssmin);
493 } else {
494 if(verbose>1) printf(" failed NNLS\n");
495 }
496 }
497 if(mini<0) {
498 if(verbose>1) fprintf(stderr, "Error: all fits failed.\n");
499 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_BAD_FIT);
500 freeDelayCMFitData(&ltdata); return(TPCERROR_BAD_FIT);
501 }
502 if(dt!=NULL && mini>=0) *dt=b->dtmin+mini*b->dtstep;
503
504 freeDelayCMFitData(&ltdata); // the local one, not the one possibly given by caller
505 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
506 return(TPCERROR_OK);
507}
void freeDelayCMFitData(DELAYCMFITDATA *d)
After last use, free memory in the data structure for delay time estimation.
Definition delay.c:150
void initDelayCMFitData(DELAYCMFITDATA *d)
Before first use, initiate the data structure for delay time estimation.
Definition delay.c:131
int liDerivate3(double *x, double *y, const int nr, double *d, double *dd, const int verbose)
Simplistic derivation of PET TAC using regression line over three points.
Definition integrate.c:493
int liIntegrateFE(double *x1, double *x2, double *y, int nr, double *ie, double *iie, const int verbose)
Linear integration of PET TAC to frame end times.
Definition integrate.c:219
int liIntegrate(double *x, double *y, const int nr, double *yi, const int se, const int verbose)
Linear integration of TAC with trapezoidal method.
Definition integrate.c:33
int liDerivate(double *x, double *y, const int nr, double *d, double *dd, const int verbose)
Simplistic derivation of TAC as Δy divided by Δx, in relation to the previous point.
Definition integrate.c:444
int nnls(double **a, int m, int n, double *b, double *x, double *rnorm, double *wp, double *zzp, int *indexp)
Definition nnls.c:43
double ttac_xmax
Definition tpctacmod.h:39
double dtstep
Definition tpctacmod.h:51
double ttac_xmin
Definition tpctacmod.h:37
double btac_xmax
Definition tpctacmod.h:43
double btac_xmin
Definition tpctacmod.h:41
double fitend
Definition tpctacmod.h:45
int tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
Definition tac.c:356
@ TPCERROR_BAD_FIT
Fitting not successful.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_INVALID_X
Invalid sample time.

◆ tacFittime()

int tacFittime ( TAC * d,
double * startTime,
double * endTime,
int * first,
int * last,
TPCSTATUS * status )
extern

Reset user-defined fit time range to comply with TAC data.

Returns
Returns the number of samples included in the fit range, or <0 in case of an error.
See also
tacReadModelingData, tacVerifyTimeOrder, tacSortByTime
Parameters
dPointer to TAC containing (regional tissue) data; times can be in minutes or seconds, as long as units are defined. TAC sampleNr is not changed in this function.
startTimePointer containing originally the requested fit start time (min). This is changed to contain the time of the first included frame. Unit must be minutes. Initially, set to <0 to start from the beginning of the data.
endTimePointer containing originally the requested fit end time (min). This is changed to contain the time of the last included frame. Unit must be minutes. Initially, set to <0 or to a very large value to reach to the end of data.
firstFunction writes the index of the first included sample (frame) here; enter NULL if not needed.
lastFunction writes the index of the last included sample (frame) here; enter NULL if not needed.
statusPointer to status data; enter NULL if not needed.

Definition at line 25 of file tacmodelinput.c.

49 {
50 int verbose=0; if(status!=NULL) verbose=status->verbose;
51 if(verbose>0) printf("%s()\n", __func__);
52 if(first!=NULL) *first=0;
53 if(last!=NULL) *last=0;
54 if(d==NULL || startTime==NULL || endTime==NULL) {
55 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
56 return(-1);
57 }
58
59 if(d->sampleNr<=0) {
60 *startTime=*endTime=0.0;
61 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
62 return(0);
63 }
64 if(*endTime<0.0) *endTime=1.0E+100;
65
66 /* Change start and end times to seconds if necessary */
67 double cf;
69 if(!isnan(cf)) {*startTime*=cf; *endTime*=cf;}
70 if(verbose>1) {
71 printf("startTime := %g\n", *startTime);
72 printf("endTime := %g\n", *endTime);
73 }
74
75#if(0)
76 /* Check that data range is not outside required range */
77 {
78 double s, e;
79 if(tacXRange(d, &s, &e) || e<*startTime || s>*endTime) {
80 *startTime=*endTime=0.0;
81 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X_RANGE);
82 return(0);
83 }
84 }
85#endif
86
87 /* Get first and last data point inside the range */
88 int s, e;
89 {
90 double f;
91 s=e=-1;
92 for(int i=0; i<d->sampleNr; i++) {
93 if(d->isframe) f=0.5*(d->x1[i]+d->x2[i]); else f=d->x[i];
94 if(verbose>3) printf(" f := %g\n", f);
95 if(s<0 && f>=*startTime) s=i;
96 if(f<=*endTime) e=i; else break;
97 }
98 if(s<0 || e<0) {
99 *startTime=*endTime=0.0;
100 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
101 return(0);
102 }
103 if(first!=NULL) *first=s;
104 if(last!=NULL) *last=e;
105 }
106
107 /* Correct fit range to frame start and end times */
108 *startTime=(d->isframe ? d->x1[s] : d->x[s]);
109 *endTime= (d->isframe ? d->x2[e] : d->x[e]);
110 /* Change start and end times back to minutes if necessary */
111 if(!isnan(cf)) {*startTime/=cf; *endTime/=cf;}
112 /* Return the sample number in the fit range */
113 return(1+e-s);
114}
@ UNIT_MIN
minutes
double unitConversionFactor(const int u1, const int u2)
Definition units.c:487

Referenced by tacReadModelingData().

◆ tacInput2sim()

int tacInput2sim ( TAC * itac,
TAC * ttac,
TAC * stac,
TPCSTATUS * status )
extern

Modify input TAC based on tissue TAC, for use in simulations.

Note
NOT FUNCTIONAL/TESTED YET!
See also
tacReadModelingInput, tacReadModelingData, tacInterpolateInto, tacInterpolateToEqualLengthFrames
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
itacPointer to original input TAC structure. Not modified. Data must not have missing values.
ttacPointer to tissue TAC structure. Not modified. Data must not have missing values.
stacPointer to the new input data, containing input data with new sample times.
statusPointer to status data; obligatory.

Definition at line 29 of file lisim.c.

38 {
39 if(status==NULL) return TPCERROR_FAIL;
40 int verbose=status->verbose;
41 if(verbose>0) printf("%s(itac, ttac, ...)\n", __func__);
42
43 /* Check the input */
44 if(itac==NULL || ttac==NULL || stac==NULL) {
45 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
46 return TPCERROR_FAIL;
47 }
48 if(itac->sampleNr<1 || ttac->sampleNr<1 || itac->tacNr<1) {
49 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
50 return TPCERROR_NO_DATA;
51 }
52
53 /* Delete any previous data */
54 tacFree(stac);
55
56 /* Make a working copy of input data */
57 TAC inp; tacInit(&inp);
58 status->error=tacDuplicate(itac, &inp); if(status->error!=TPCERROR_OK) return(status->error);
59 /* Make sure that input data contains also frame mid times */
60 if(inp.isframe) tacSetX(&inp, NULL);
61 /* Convert time units to TTAC units */
62 tacXUnitConvert(&inp, ttac->tunit, status);
63 if(status->error!=TPCERROR_OK) {tacFree(&inp); return(status->error);}
64
65 /* Sort the input data by sample times */
66 tacSortByTime(&inp, status); if(status->error!=TPCERROR_OK) {tacFree(&inp); return(status->error);}
67 /* Add zero sample if necessary */
68 tacAddZeroSample(&inp, status);
69 if(status->error!=TPCERROR_OK) {tacFree(&inp); return(status->error);}
70
71 /* Make a combined list of sample times based on input and tissue TACs */
72 unsigned int maxn=inp.sampleNr+ttac->sampleNr;
73 if(inp.isframe) maxn+=2*inp.sampleNr;
74 if(ttac->isframe) maxn+=ttac->sampleNr;
75 double x[maxn];
76
77 int n=0;
78 for(int i=0; i<inp.sampleNr; i++) if(isfinite(inp.x[i])) {
79 int j; for(j=0; j<n; j++) if(fabs(x[j]-inp.x[i])<1.0E-20) break;
80 if(j==n) x[n++]=inp.x[i];
81 }
82 if(inp.isframe) {
83 for(int i=0; i<inp.sampleNr; i++) if(isfinite(inp.x1[i])) {
84 int j; for(j=0; j<n; j++) if(fabs(x[j]-inp.x1[i])<1.0E-20) break;
85 if(j==n) x[n++]=inp.x1[i];
86 }
87 for(int i=0; i<inp.sampleNr; i++) if(isfinite(inp.x2[i])) {
88 int j; for(j=0; j<n; j++) if(fabs(x[j]-inp.x2[i])<1.0E-20) break;
89 if(j==n) x[n++]=inp.x2[i];
90 }
91 }
92 if(ttac->isframe) {
93 for(int i=0; i<ttac->sampleNr; i++) if(isfinite(ttac->x2[i])) {
94 int j; for(j=0; j<n; j++) if(fabs(x[j]-ttac->x2[i])<1.0E-20) break;
95 if(j==n) x[n++]=ttac->x2[i];
96 }
97 for(int i=0; i<ttac->sampleNr; i++) if(isfinite(ttac->x2[i])) {
98 int j; for(j=0; j<n; j++) if(fabs(x[j]-ttac->x2[i])<1.0E-20) break;
99 if(j==n) x[n++]=ttac->x2[i];
100 }
101 } else {
102 for(int i=0; i<ttac->sampleNr; i++) if(isfinite(ttac->x[i])) {
103 int j; for(j=0; j<n; j++) if(fabs(x[j]-ttac->x[i])<1.0E-20) break;
104 if(j==n) x[n++]=ttac->x[i];
105 }
106 }
107 if(verbose>2) printf("n=%d\n", n);
108 statSortDouble(x, n, 0);
109
110 /* Put new sample times into output data */
111 status->error=tacDuplicate(itac, stac);
112 if(status->error!=TPCERROR_OK) {tacFree(&inp); return(status->error);}
113 status->error=tacAllocateMoreSamples(stac, n-stac->sampleNr);
114 if(status->error!=TPCERROR_OK) {tacFree(&inp); return(status->error);}
115 stac->sampleNr=n; stac->tunit=inp.tunit; stac->isframe=0;
116 for(int i=0; i<n; i++) stac->x[i]=x[i];
117
118 /* Interpolate input data into the new sample times */
119 for(int i=0; i<inp.tacNr; i++) {
120 status->error=liInterpolate(inp.x, inp.c[i].y, inp.sampleNr,
121 stac->x, stac->c[i].y, NULL, NULL, stac->sampleNr, 4, 1, verbose-10);
122 if(status->error!=TPCERROR_OK) break;
123 }
124 if(status->error!=TPCERROR_OK) {tacFree(&inp); tacFree(stac); return(status->error);}
125
126 tacFree(&inp);
127
128 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
129 return(TPCERROR_OK);
130}
void statSortDouble(double *data, unsigned int n, int order)
Definition sort.c:99
int tacAllocateMoreSamples(TAC *tac, int addNr)
Allocate memory for more samples in TAC data.
Definition tac.c:435
int tacSortByTime(TAC *d, TPCSTATUS *status)
Definition tacorder.c:74
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
int tacAddZeroSample(TAC *d, TPCSTATUS *status)
Add an initial sample to TAC(s) with zero time and concentration.
Definition tacx.c:366
int tacSetX(TAC *d, TPCSTATUS *status)
Set TAC x values based on x1 and x2 values, or guess x1 and x2 values based on x values.
Definition tacx.c:653

Referenced by bfm1TCM().

◆ tacIntegrate()

int tacIntegrate ( TAC * inp,
TAC * out,
TPCSTATUS * status )
extern

Integrate TACs from one TAC structure into a new TAC structure.

PET frame lengths are taken into account, if available.

See also
liIntegrate, liIntegratePET, tacInterpolate, tacInterpolateInto
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
inpPointer to source TAC structure.
Precondition
Data must be sorted by increasing x.
Parameters
outPointer to target TAC structure into which the integrated TAC(s) are written. Structure must be initiated; any previous contents are deleted.
statusPointer to status data; enter NULL if not needed.

Definition at line 27 of file litac.c.

36 {
37 int verbose=0; if(status!=NULL) verbose=status->verbose;
38 if(verbose>0) printf("%s()\n", __func__);
39 if(inp==NULL || out==NULL) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
41 return TPCERROR_FAIL;
42 }
43 tacFree(out);
44 int ret=TPCERROR_OK;
45 ret=tacDuplicate(inp, out);
46 if(ret!=TPCERROR_OK) {
47 statusSet(status, __func__, __FILE__, __LINE__, ret);
48 return(ret);
49 }
50 if(inp->isframe==0) {
51 for(int i=0; i<inp->tacNr; i++) {
52 ret=liIntegrate(inp->x, inp->c[i].y, inp->sampleNr, out->c[i].y, 3, 0);
53 if(ret!=TPCERROR_OK) break;
54 }
55 } else {
56 for(int i=0; i<inp->tacNr; i++) {
57 ret=liIntegratePET(inp->x1, inp->x2, inp->c[i].y, inp->sampleNr, out->c[i].y, NULL, 0);
58 if(ret!=TPCERROR_OK) break;
59 }
60 }
61 if(ret!=TPCERROR_OK) tacFree(out);
62 statusSet(status, __func__, __FILE__, __LINE__, ret);
63 return(ret);
64}
int liIntegratePET(double *x1, double *x2, double *y, int nr, double *ie, double *iie, const int verbose)
Calculate PET TAC AUC from start to each time frame, as averages during each frame.
Definition integrate.c:120

◆ tacIntegrateFE()

int tacIntegrateFE ( TAC * inp,
TAC * out,
TAC * out2,
TPCSTATUS * status )
extern

Integrate TACs from one TAC structure into a new TAC structure. Integrals are calculated at frame end times.

TAC must contain frame start and end times.

See also
tacIntegrate, liIntegrateFE, tacIsXContiguous, tacSetXContiguous, tacMultipleSamples
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
inpPointer to source TAC structure.
Precondition
Data must be sorted by increasing x. Frames must not overlap.
Parameters
outPointer to target TAC structure into which the integrated TAC(s) are written. Structure must be initiated; any previous contents are deleted.
out2Pointer to target TAC structure into which the 2nd integrals are written. Structure must be initiated; any previous contents are deleted. Enter NULL if not needed.
statusPointer to status data; enter NULL if not needed.

Definition at line 75 of file litac.c.

88 {
89 int verbose=0; if(status!=NULL) verbose=status->verbose;
90 if(verbose>0) printf("%s()\n", __func__);
91 if(inp==NULL || out==NULL) {
92 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
93 return TPCERROR_FAIL;
94 }
95 if(inp->isframe==0) {
96 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
97 return(TPCERROR_INVALID_X);
98 }
99
100 /* Make space */
101 tacFree(out); if(out2!=NULL) tacFree(out2);
102 int ret=TPCERROR_OK;
103 ret=tacDuplicate(inp, out);
104 if(ret!=TPCERROR_OK) {
105 statusSet(status, __func__, __FILE__, __LINE__, ret);
106 return(ret);
107 }
108 if(out2!=NULL) {
109 ret=tacDuplicate(inp, out2);
110 if(ret!=TPCERROR_OK) {
111 tacFree(out);
112 statusSet(status, __func__, __FILE__, __LINE__, ret);
113 return(ret);
114 }
115 }
116
117 for(int i=0; i<inp->tacNr; i++) {
118 if(out2==NULL)
119 ret=liIntegrateFE(inp->x1, inp->x2, inp->c[i].y, inp->sampleNr, out->c[i].y, NULL, 0);
120 else
121 ret=liIntegrateFE(inp->x1, inp->x2, inp->c[i].y, inp->sampleNr, out->c[i].y, out2->c[i].y, 0);
122 if(ret!=TPCERROR_OK) break;
123 }
124 if(ret!=TPCERROR_OK) {tacFree(out); if(out2!=NULL) tacFree(out2);}
125
126 statusSet(status, __func__, __FILE__, __LINE__, ret);
127 return(ret);
128}

◆ tacInterpolate()

int tacInterpolate ( TAC * inp,
TAC * xinp,
TAC * tac,
TAC * itac,
TAC * iitac,
TPCSTATUS * status )
extern

Interpolate and/or integrate TACs from one TAC structure into a new TAC structure, using sample times from another TAC structure which is not changed.

PET frame lengths of output TACs are taken into account in interpolation, if available. Input frame lengths are taken into account if the framing is same as with output TACs, otherwise frame middle times are used.

See also
tacInterpolateInto, tacAUC, tacFramesToSteps, tacXCopy, liInterpolate
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
inpPointer to source TAC structure; make sure that x (time) and y (concentration) units are the same as in output TAC structure, because input time range is verified to cover the output data range. Detailed verification of suitability of TAC for interpolation must be done elsewhere.
Precondition
Data must be sorted by increasing x.
Parameters
xinpPointer to TAC structure which contains the x values (sample times) for the interpolation and integration. Data in this TAC structure is not modified.
Precondition
Data must be sorted by increasing x.
Parameters
tacPointer to target TAC structure into which the interpolated input TAC(s) are added. Structure must be initiated; any previous contents are deleted. Enter NULL if not needed.
itacPointer to target TAC structure into which the integrated input TAC(s) are added. Structure must be initiated; any previous contents are deleted. Enter NULL if not needed.
iitacPointer to target TAC structure into which 2nd integrals of input TAC(s) are added. Structure must be initiated; any previous contents are deleted. Enter NULL if not needed.
statusPointer to status data; enter NULL if not needed.

Definition at line 141 of file litac.c.

163 {
164 int verbose=0; if(status!=NULL) verbose=status->verbose;
165 if(verbose>0) printf("%s()\n", __func__);
166 if(inp==NULL || xinp==NULL || xinp==tac || xinp==itac || xinp==iitac) {
167 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
168 return TPCERROR_FAIL;
169 }
170 if(tac==NULL && itac==NULL && iitac==NULL) { // there's nothing to do
171 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
172 return TPCERROR_OK;
173 }
174 /* Check the function input */
175 if(inp->sampleNr<1 || inp->tacNr<1 || xinp->sampleNr<1) {
176 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
177 return TPCERROR_NO_DATA;
178 }
179
180 /* Check that input does not have any missing values */
181 if(tacNaNs(inp)>0 || tacXNaNs(xinp)>0) {
182 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
184 }
185
186
187 /* If input data have similar x values as requested already, then
188 copy x1 and x2 into input if available */
189 if(xinp->isframe && tacXMatch(inp, xinp, verbose-2) && inp->sampleNr<=xinp->sampleNr) {
190 for(int i=0; i<inp->sampleNr; i++) {
191 inp->x[i]=xinp->x[i]; inp->x1[i]=xinp->x1[i]; inp->x2[i]=xinp->x2[i];
192 }
193 inp->isframe=xinp->isframe;
194 }
195
196
197 /* Check that there is no need for excess extrapolation */
198 {
199 double start1, end1, start2, end2, range2;
200 if(tacXRange(inp, &start1, &end1) || tacXRange(xinp, &start2, &end2)) {
201 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
202 return TPCERROR_INVALID_X;
203 }
204 range2=end2-start2;
205 if(verbose>2) printf("time ranges: %g - %g vs %g - %g\n", start1, end1, start2, end2);
206 if(start1>start2+0.2*range2 || end1<end2-0.3*range2) {
207 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
209 }
210 }
211
212 /* Delete any previous contents in output structs */
213 if(tac!=NULL) tacFree(tac);
214 if(itac!=NULL) tacFree(itac);
215 if(iitac!=NULL) tacFree(iitac);
216
217 /* Allocate memory for output data */
218 int ret=TPCERROR_OK;
219 if(tac!=NULL) ret=tacAllocate(tac, xinp->sampleNr, inp->tacNr);
220 if(ret==TPCERROR_OK && itac!=NULL)
221 ret=tacAllocate(itac, xinp->sampleNr, inp->tacNr);
222 if(ret==TPCERROR_OK && iitac!=NULL)
223 ret=tacAllocate(iitac, xinp->sampleNr, inp->tacNr);
224 if(ret!=TPCERROR_OK) {
225 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
227 }
228 if(tac!=NULL) {tac->tacNr=inp->tacNr; tac->sampleNr=xinp->sampleNr;}
229 if(itac!=NULL) {itac->tacNr=inp->tacNr; itac->sampleNr=xinp->sampleNr;}
230 if(iitac!=NULL) {iitac->tacNr=inp->tacNr; iitac->sampleNr=xinp->sampleNr;}
231
232
233 /* Copy header information */
234 if(tac!=NULL) {
235 tacCopyHdr(inp, tac);
236 for(int i=0; i<inp->tacNr; i++) tacCopyTacchdr(inp->c+i, tac->c+i);
237 }
238 if(itac!=NULL) {
239 tacCopyHdr(inp, itac);
240 for(int i=0; i<inp->tacNr; i++) tacCopyTacchdr(inp->c+i, itac->c+i);
241 }
242 if(iitac!=NULL) {
243 tacCopyHdr(inp, iitac);
244 for(int i=0; i<inp->tacNr; i++) tacCopyTacchdr(inp->c+i, iitac->c+i);
245 }
246 /* Copy X (time) information */
247 if(tac!=NULL) {
248 tac->isframe=xinp->isframe; tacXCopy(xinp, tac, 0, tac->sampleNr-1);
249 }
250 if(itac!=NULL) {
251 itac->isframe=xinp->isframe; tacXCopy(xinp, itac, 0, itac->sampleNr-1);
252 }
253 if(iitac!=NULL) {
254 iitac->isframe=xinp->isframe; tacXCopy(xinp, iitac, 0, iitac->sampleNr-1);
255 }
256
257 /* Check if TACs have the same frame times already */
258 if(tacXMatch(inp, tac, verbose-2) && inp->sampleNr>=xinp->sampleNr) {
259 if(verbose>2) printf(" same frame times\n");
260 int ret=0, ri, fi;
261 double *i1, *i2;
262 /* copy the values directly and integrate in place, if requested */
263 for(ri=0; ri<inp->tacNr && ret==0; ri++) {
264 if(tac!=NULL)
265 for(fi=0; fi<tac->sampleNr; fi++)
266 tac->c[ri].y[fi]=inp->c[ri].y[fi];
267 /* If integrals not requested then that's it for this TAC */
268 if(itac==NULL && iitac==NULL) continue;
269 /* otherwise set pointers for integrals and then integrate */
270 if(itac!=NULL) i1=itac->c[ri].y; else i1=NULL;
271 if(iitac!=NULL) i2=iitac->c[ri].y; else i2=NULL;
272 if(inp->isframe)
273 ret=liIntegratePET(inp->x1, inp->x2, inp->c[ri].y,
274 xinp->sampleNr, i1, i2, verbose-2);
275 else
276 ret=liInterpolate(inp->x, inp->c[ri].y, inp->sampleNr,
277 xinp->x, NULL, i1, i2, xinp->sampleNr, 4, 1, verbose-2);
278 }
279 if(ret) {
280 if(tac!=NULL) tacFree(tac);
281 if(itac!=NULL) tacFree(itac);
282 if(iitac!=NULL) tacFree(iitac);
283 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
285 }
286 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
287 return(TPCERROR_OK); // that's it then
288 }
289
290 /* Interpolate and/or integrate inp data to tac sample times,
291 taking into account tac frame lengths if available */
292 if(verbose>2) printf(" different frame times\n");
293 ret=0;
294 double *i0, *i1, *i2;
295 for(int ri=0; ri<inp->tacNr && ret==0; ri++) {
296 /* set pointers for output y arrays */
297 if(tac!=NULL) i0=tac->c[ri].y; else i0=NULL;
298 if(itac!=NULL) i1=itac->c[ri].y; else i1=NULL;
299 if(iitac!=NULL) i2=iitac->c[ri].y; else i2=NULL;
300 if(xinp->isframe)
301 ret=liInterpolateForPET(inp->x, inp->c[ri].y, inp->sampleNr,
302 xinp->x1, xinp->x2, i0, i1, i2, xinp->sampleNr, 4, 1, verbose-2);
303 else
304 ret=liInterpolate(inp->x, inp->c[ri].y, inp->sampleNr,
305 xinp->x, i0, i1, i2, xinp->sampleNr, 4, 1, verbose-2);
306 }
307 if(ret) {
308 if(tac!=NULL) tacFree(tac);
309 if(itac!=NULL) tacFree(itac);
310 if(iitac!=NULL) tacFree(iitac);
311 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
313 }
314
315 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
316 return(TPCERROR_OK);
317}
int tacCopyTacchdr(TACC *d1, TACC *d2)
Definition tac.c:282
int tacCopyHdr(TAC *tac1, TAC *tac2)
Copy TAC header data from tac1 to tac2.
Definition tac.c:310
int tacNaNs(TAC *tac)
Definition tacnan.c:71
int tacXMatch(TAC *d1, TAC *d2, const int verbose)
Check whether sample (frame) times are the same (or very close to) in two TAC structures.
Definition tacx.c:249
int tacXCopy(TAC *tac1, TAC *tac2, int i1, int i2)
Definition tacx.c:24

◆ tacInterpolateInto()

int tacInterpolateInto ( TAC * inp,
TAC * tac,
TAC * itac,
TAC * iitac,
TPCSTATUS * status )
extern

Add TACs from one TAC structure into another TAC structure, interpolating the input TACs and allocating space if necessary.

PET frame lengths of output TACs are taken into account in interpolation, if available. Input frame lengths are taken into account if the framing is same as with output TACs, otherwise frame middle times are used.

See also
tacInterpolate, tacAUC, tacInterpolateToEqualLengthFrames, liInterpolateForPET
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
inpPointer to source TAC struct; make sure that x (time) and y (concentration) units are the same as in output TAC struct, because input time range is verified to cover the output data range. Detailed verification of suitability of TAC for interpolation must be done elsewhere.
Precondition
Data must be sorted by increasing x.
Parameters
tacPointer to target TAC struct into which the input TAC(s) are added. Struct must contain at least one TAC, and the x or x1 and x2 values.
Precondition
Data must be sorted by increasing x.
Parameters
itacPointer to target TAC struct into which integrated input TAC(s) are added; enter NULL if not needed.
iitacPointer to target TAC struct into which 2nd integrals of input TAC(s) are added; enter NULL if not needed.
statusPointer to status data; enter NULL if not needed.

Definition at line 330 of file litac.c.

348 {
349 int verbose=0; if(status!=NULL) verbose=status->verbose;
350 if(verbose>0) printf("%s()\n", __func__);
351 if(tac==NULL || inp==NULL) {
352 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
353 return TPCERROR_FAIL;
354 }
355
356 /* Check the function input */
357 if(tac->sampleNr<1 || inp->sampleNr<1 || inp->tacNr<1) {
358 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
359 return TPCERROR_NO_DATA;
360 }
361 if(itac!=NULL && itac->sampleNr!=tac->sampleNr) {
362 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
363 return TPCERROR_INVALID_X;
364 }
365 if(iitac!=NULL && iitac->sampleNr!=tac->sampleNr) {
366 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
367 return TPCERROR_INVALID_X;
368 }
369
370
371 /* Check that input does not have any missing values */
372 /* Check that there are no missing sample times in output TACs */
373 if(tacNaNs(inp)>0 || tacXNaNs(tac)>0) {
374 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
376 }
377
378 /* Check that there is no need for excess extrapolation */
379 {
380 double start1, end1, start2, end2, range2;
381 if(tacXRange(inp, &start1, &end1) || tacXRange(tac, &start2, &end2)) {
382 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
383 return TPCERROR_INVALID_X;
384 }
385 range2=end2-start2;
386 if(verbose>2)
387 printf("time ranges: %g - %g vs %g - %g\n", start1, end1, start2, end2);
388 if(start1>(start2+0.2*range2) || end1<(end2-0.3*range2)) {
389 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
391 }
392 }
393
394 /* Allocate memory for interpolated data */
395 if(tacAllocateMore(tac, inp->tacNr)) {
396 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
398 }
399 /* Copy header information */
400 for(int i=0; i<inp->tacNr; i++) tacCopyTacchdr(inp->c+i, tac->c+tac->tacNr+i);
401 /* Same for the integrals */
402 if(itac!=NULL) {
403 if(tacAllocateMore(itac, inp->tacNr)) {
404 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
406 }
407 for(int i=0; i<inp->tacNr; i++)
408 tacCopyTacchdr(inp->c+i, itac->c+itac->tacNr+i);
409 }
410 if(iitac!=NULL) {
411 if(tacAllocateMore(iitac, inp->tacNr)) {
412 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
414 }
415 for(int i=0; i<inp->tacNr; i++) tacCopyTacchdr(inp->c+i, iitac->c+iitac->tacNr+i);
416 }
417
418 /* Check if TACs have the same frame times already */
419 if(tacXMatch(inp, tac, verbose-2) && inp->sampleNr>=tac->sampleNr) {
420 if(verbose>2) printf("same frame times\n");
421 int ret=0, ri, fi;
422 double *i1, *i2;
423 /* copy the values directly and integrate in place, if requested */
424 for(ri=0; ri<inp->tacNr && ret==0; ri++) {
425 for(fi=0; fi<tac->sampleNr; fi++)
426 tac->c[tac->tacNr+ri].y[fi]=inp->c[ri].y[fi];
427 /* If integrals not requested then that's it for this TAC */
428 if(itac==NULL && iitac==NULL) continue;
429 /* otherwise set pointers for integrals and then integrate */
430 if(itac!=NULL) i1=itac->c[itac->tacNr+ri].y; else i1=NULL;
431 if(iitac!=NULL) i2=iitac->c[iitac->tacNr+ri].y; else i2=NULL;
432 if(tac->isframe)
433 ret=liIntegratePET(tac->x1, tac->x2, tac->c[tac->tacNr+ri].y,
434 tac->sampleNr, i1, i2, verbose-2);
435 else
436 ret=liInterpolate(tac->x, tac->c[tac->tacNr+ri].y, tac->sampleNr,
437 tac->x, NULL, i1, i2, tac->sampleNr, 4, 1, verbose-2);
438 }
439 if(ret) {
440 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
442 }
443 tac->tacNr+=inp->tacNr;
444 if(itac!=NULL) itac->tacNr+=inp->tacNr;
445 if(iitac!=NULL) iitac->tacNr+=inp->tacNr;
446 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
447 return(TPCERROR_OK); // that's it then
448 }
449
450 /* Interpolate and, if requested, integrate inp data to tac sample times,
451 taking into account tac frame lengths if available */
452 int ret=0;
453 double *i1, *i2;
454 for(int ri=0; ri<inp->tacNr && ret==0; ri++) {
455 /* set pointers for integrals */
456 if(itac!=NULL) i1=itac->c[itac->tacNr+ri].y; else i1=NULL;
457 if(iitac!=NULL) i2=iitac->c[iitac->tacNr+ri].y; else i2=NULL;
458 if(tac->isframe)
459 ret=liInterpolateForPET(inp->x, inp->c[ri].y, inp->sampleNr,
460 tac->x1, tac->x2, tac->c[tac->tacNr+ri].y,
461 i1, i2, tac->sampleNr, 4, 1, verbose-2);
462 else
463 ret=liInterpolate(inp->x, inp->c[ri].y, inp->sampleNr,
464 tac->x, tac->c[tac->tacNr+ri].y,
465 i1, i2, tac->sampleNr, 4, 1, verbose-2);
466 }
467 if(ret) {
468 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
470 }
471 tac->tacNr+=inp->tacNr;
472 if(itac!=NULL) itac->tacNr+=inp->tacNr;
473 if(iitac!=NULL) iitac->tacNr+=inp->tacNr;
474
475 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
476 return(TPCERROR_OK);
477}
int tacAllocateMore(TAC *tac, int tacNr)
Definition tac.c:178

Referenced by tacReadModelingData(), and tacReadModelingInput().

◆ tacInterpolateToEqualLengthFrames()

int tacInterpolateToEqualLengthFrames ( TAC * inp,
double minfdur,
double maxfdur,
TAC * tac,
TPCSTATUS * status )
extern

Interpolate TAC data into data with equal frame lengths, starting from zero.

By default, the shortest frame length or sampling interval in the input data is used.

Remarks
This is needed for TAC convolution.
See also
tacInterpolate, liInterpolateForPET, tacGetSampleInterval, simIsSteadyInterval
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
inpPointer to source TAC struct. Missing values are not allowed.
Precondition
Data must be sorted by increasing x.
Parameters
minfdurMinimum frame length; if NaN or <=0 then not applied, otherwise frame lengths are not allowed to be lower.
maxfdurMaximum frame length; if NaN or <=0 then not applied, otherwise frame lengths are not allowed to be higher.
tacPointer to target TAC struct into which the interpolated TACs are written.
Precondition
Struct must be initiated.
Parameters
statusPointer to status data; enter NULL if not needed.

Definition at line 214 of file lisim.c.

229 {
230 int verbose=0; if(status!=NULL) verbose=status->verbose;
231 if(verbose>0) {printf("%s(tac1, %g, %g, ...)\n", __func__, minfdur, maxfdur); fflush(stdout);}
232 if(tac==NULL || inp==NULL || inp->sampleNr<1 || inp->tacNr<1) {
233 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
234 return TPCERROR_FAIL;
235 }
236 if(minfdur>0.0 && maxfdur>0.0 && minfdur>maxfdur) {
237 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
238 return TPCERROR_INVALID_X;
239 }
240 if(!tacIsX(inp)) {
241 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
242 return TPCERROR_INVALID_X;
243 }
244
245 /* Get the minimum sample interval (that is higher than 0) */
246 double freq=nan("");
247 int ret=tacGetSampleInterval(inp, 1.0E-08, &freq, NULL);
248 //printf("dataset based freq: %g\n", freq);
249 if(ret!=TPCERROR_OK) {statusSet(status, __func__, __FILE__, __LINE__, ret); return(ret);}
250 if(minfdur>0.0 && freq<minfdur) freq=minfdur;
251 if(maxfdur>0.0 && freq>maxfdur) freq=maxfdur;
252 //printf("refined freq: %g\n", freq);
253
254 /* Get the x range */
255 double xmax=nan("");
256 if(tacXRange(inp, NULL, &xmax)!=0) {
257 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
259 }
260 //printf("xmax: %g\n", xmax);
261 if(freq>0.5*xmax) {
262 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
264 }
265
266
267 /* Calculate the number of required interpolated samples */
268 int nreq=ceil(xmax/freq); //printf("required_n := %d\n", nreq);
269 /* Check that it is not totally stupid */
270 if(nreq<1 || nreq>2E+06) {
271 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_BIG);
272 return TPCERROR_TOO_BIG;
273 }
274
275 /* Setup the output TAC */
276 if(tacAllocate(tac, nreq, inp->tacNr)!=TPCERROR_OK) {
277 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
279 }
280 tac->tacNr=inp->tacNr; tac->sampleNr=nreq;
281 /* Copy header information */
282 tacCopyHdr(inp, tac);
283 for(int i=0; i<inp->tacNr; i++) tacCopyTacchdr(inp->c+i, tac->c+i);
284
285 /* Set X (sample time) information */
286 tac->isframe=1;
287 for(int i=0; i<nreq; i++) tac->x1[i]=(double)i*freq;
288 for(int i=0; i<nreq; i++) tac->x2[i]=(double)(i+1)*freq;
289 for(int i=0; i<nreq; i++) tac->x[i]=0.5*(tac->x1[i]+tac->x2[i]);
290
291 /* Calculate mean value during each interval */
292 if(verbose>2) {printf(" interpolating...\n"); fflush(stdout);}
293 for(int i=0; i<inp->tacNr; i++) {
294 if(liInterpolateForPET(inp->x, inp->c[i].y, inp->sampleNr, tac->x1, tac->x2,
295 tac->c[i].y, NULL, NULL, tac->sampleNr, 2, 1, 0)!=0) {
296 tacFree(tac);
297 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
299 }
300 }
301 if(verbose>2) {printf(" ... done.\n"); fflush(stdout);}
302
303 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
304 return(TPCERROR_OK);
305}
int tacGetSampleInterval(TAC *d, double ilimit, double *minfdur, double *maxfdur)
Get the shortest and longest sampling intervals or frame lengths in TAC structure.
Definition tacx.c:832
int tacIsX(TAC *d)
Verify if TAC structure contains reasonable x values (times).
Definition tacx.c:226
@ TPCERROR_TOO_BIG
File is too big.

◆ tacPlotFitSVG()

int tacPlotFitSVG ( TAC * tac1,
TAC * tac2,
const char * main_title,
const double x1,
const double x2,
const double y1,
const double y2,
const char * fname,
TPCSTATUS * status )
extern

Writes specified range of plots of original and fitted TACs in SVG format.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacPlotLineSVG, mtgaPlotSVG
Author
Vesa Oikonen
Parameters
tac1Measured data points. Frame mid times must be set.
tac2Fitted data points. Times can be different but unit must be the same as in tac1.
main_titleString for plot main title, or "".
x1Start time; NaN if determined from data.
x2End time; NaN if determined from data.
y1Minimum y value; NaN if determined from data.
y2Maximum y value; NaN if determined from data.
fnameSVG file name.
statusPointer to status data; enter NULL if not needed.

Definition at line 27 of file tacfitplot.c.

46 {
47 int verbose=0; if(status!=NULL) verbose=status->verbose;
48 if(verbose>0) printf("%s()\n", __func__);
49 /* Check data */
50 if(tac1==NULL || tac2==NULL || tac1->tacNr<1 || tac2->tacNr<1 ||
51 tac1->sampleNr<1 || tac2->sampleNr<1)
52 {
53 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
54 return TPCERROR_NO_DATA;
55 }
56 if(fname==NULL || strnlen(fname, 1)<1) {
57 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
59 }
60 if(tac1->tacNr!=tac2->tacNr) {
61 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_DATA);
63 }
64 if(status!=NULL && status->forgiving==0) {
65 // any strict tests in here
66 }
67
68 int ret, n, ri, si, ei;
69 char x_title[64], y_title[64], tac_id[32], tac_title[64];
70 double minx, maxx, miny, maxy, tx1, tx2, ty1, ty2, f;
71 struct svg_viewports viewports; svg_init_viewports(&viewports);
72 int max_color_nr=0, color_nr=0;
73 int max_symbol_nr=0, symbol_nr=0;
74 SVG_LEGENDS legends; svg_init_legends(&legends);
75 FILE *fp_svg=NULL;
76
77 int is_label=0; if(tac1->tacNr>1) is_label=1;
78
79 /* Determine the plot min and max x values */
80 if(tacSampleXRange(tac1, &tx1, &tx2)) {
81 if(verbose>0) {printf(" tac1 failed\n"); fflush(stdout);}
82 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
84 }
85 minx=tx1; maxx=tx2;
86 if(tacSampleXRange(tac2, &tx1, &tx2)) {
87 if(verbose>0) {printf(" tac2 failed\n"); fflush(stdout);}
88 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
90 }
91 if(minx>tx1) minx=tx1;
92 if(maxx<tx2) maxx=tx2;
93 if(minx>0.0) {double f=maxx-minx; minx-=0.05*f; if(minx<0.0) minx=0.0;}
94 if(!isnan(x1)) minx=x1;
95 if(!isnan(x2)) maxx=x2;
96 if(verbose>10) printf(" minx := %g\n maxx:=%g\n", minx, maxx);
97
98 /* Determine the plot min and max y values inside the x range */
99 if(tacYRangeInXRange(tac1, -1, minx, maxx, &ty1, &ty2, NULL, NULL, NULL, NULL)) {
100 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
102 }
103 miny=ty1; maxy=ty2;
104 if(tacYRangeInXRange(tac2, -1, minx, maxx, &ty1, &ty2, NULL, NULL, NULL, NULL)) {
105 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
107 }
108 if(miny>ty1) miny=ty1;
109 if(maxy<ty2) maxy=ty2;
110 if(miny>0.0) {f=maxy-miny; miny-=0.05*f; if(miny<0.0) miny=0.0;}
111 if(!isnan(y1)) miny=y1;
112 if(!isnan(y2)) maxy=y2;
113 if(verbose>1) printf(" miny := %g\n maxy:=%g\n", miny, maxy);
114
115 /* Calculate the axis ticks */
116 viewports.x.min=minx; viewports.x.max=maxx;
117 viewports.y.min=miny; viewports.y.max=maxy;
118 viewports.label_area_viewport.is=is_label; // needed for x axis ticks
119 ret=svg_calculate_axes(&viewports, verbose-11);
120 if(ret) {
121 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
123 }
124
125 /* Set x and y axis titles based on activity and time units */
126 strcpy(x_title, "");
127 if(unitIsTime(tac1->tunit))
128 sprintf(x_title, "Time (%s)", unitName(tac1->tunit));
129 else if(tac1->tunit!=UNIT_UNKNOWN)
130 strcpy(x_title, unitName(tac1->tunit));
131 strcpy(y_title, "");
132 if(tac1->cunit!=UNIT_UNKNOWN) strcpy(y_title, unitName(tac1->cunit));
133
134 /* Set the plot window and window area sizes */
135 ret=svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
136 strlen(x_title), is_label, &viewports, verbose-13);
137 if(ret) {
138 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
140 }
141
142 /* Initiate graphics file */
143 fp_svg=svg_initiate(fname, 0, 0, &viewports, NULL, verbose-13);
144 if(fp_svg==NULL) {
145 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
147 }
148
149 /* Put the graph titles into their own viewports */
150 ret=svg_create_main_title(fp_svg, main_title, "", &viewports, NULL,verbose-13);
151 if(!ret)
152 ret=svg_create_yaxis_title(fp_svg, y_title, &viewports, NULL, verbose-13);
153 if(!ret)
154 ret=svg_create_xaxis_title(fp_svg, x_title, &viewports, NULL, verbose-13);
155
156 /* Put the plot into its own viewport */
157 if(!ret)
158 ret=svg_start_plot_viewport(fp_svg, &viewports, NULL, verbose-13);
159
160 /* Start coordinate area viewport */
161 if(!ret)
162 ret=svg_start_coordinate_viewport(fp_svg, &viewports, NULL, verbose-13);
163
164 /* Write plot axes */
165 if(!ret) ret=svg_write_axes(fp_svg, &viewports, NULL, verbose-13);
166
167 if(ret) {
168 fclose(fp_svg);
169 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
171 }
172
173 /*
174 * Draw the plots
175 */
176 max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
177 if(verbose>3) printf("max_color_nr := %d\n", max_color_nr);
178 max_symbol_nr=0; while(svgSymbolName(max_symbol_nr)!=NULL) max_symbol_nr++;
179 if(verbose>3) printf("max_symbol_nr := %d\n", max_symbol_nr);
180 if(tac1->tacNr==1) color_nr=0; else color_nr=1;
181 symbol_nr=0;
182 for(ri=0, n=0; ri<tac1->tacNr; ri++) {
183 sprintf(tac_id, "plot_%d", n);
184 strcpy(tac_title, tac1->c[ri].name);
185 /* Draw the fitted line */
186 for(si=0; si<tac2->sampleNr; si++) if(!isnan(tac2->c[ri].y[si])) break;
187 for(ei=tac2->sampleNr-1; ei>=si; ei--) if(!isnan(tac2->c[ri].y[ei])) break;
188 if((ei-si)>0) {
189 ret=svg_write_tac(fp_svg, &viewports, 1, tac_id, tac_title,
190 tac2->x+si, tac2->c[ri].y+si, 1+ei-si,
191 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLOPEN,
192 NULL, verbose-13);
193 if(ret) {
194 svg_legend_empty(&legends); fclose(fp_svg);
195 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
197 }
198 }
199 /* Draw the measured points */
200 ret=svg_write_tac(fp_svg, &viewports, 2, tac_id, tac_title,
201 tac1->x, tac1->c[ri].y, tac1->sampleNr,
202 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLFILLED,
203 NULL, verbose-13);
204 if(ret) {
205 svg_legend_empty(&legends); fclose(fp_svg);
206 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
208 }
209 /* Set legend too, if requested */
210 if(is_label!=0) {
211 int si=0, ci=0; // remainder works only if 2nd operator > 0
212 if(max_symbol_nr>0) si=symbol_nr%max_symbol_nr;
213 if(max_color_nr>0) ci=color_nr%max_color_nr;
214
215 svg_legend_add(&legends, 0, si, SYMBOLFILLED, ci, tac_title);
216 }
217 /* Prepare for the next plot */
218 color_nr++; n++;
219 if(color_nr==max_color_nr) {symbol_nr++; color_nr=0;}
220 if(symbol_nr==max_symbol_nr) symbol_nr=0;
221 }
222
223 /* Close the coordinate viewport */
224 ret=svg_end_coordinate_viewport(fp_svg, NULL, verbose-13);
225
226 /* Write the axis ticks */
227 if(!ret) {
228 if(svg_write_xticks(fp_svg, &viewports, NULL, verbose-13)!=0) ret=1;}
229 if(!ret) {
230 if(svg_write_yticks(fp_svg, &viewports, NULL, verbose-13)!=0) ret=1;}
231
232 /* Close the plot viewport */
233 if(!ret) ret=svg_end_plot_viewport(fp_svg, NULL, verbose-13);
234
235 if(ret) {
236 fclose(fp_svg); svg_legend_empty(&legends);
237 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
239 }
240
241 /* Make the plot legends into their own viewport */
242 ret=0;
243 if(viewports.label_area_viewport.is!=0) {
244 if(verbose>2) printf("creating plot legends\n");
245 ret=svg_create_legends(fp_svg, &viewports, &legends, NULL, verbose-13);
246 }
247 svg_legend_empty(&legends);
248 if(ret) {
249 fclose(fp_svg);
250 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
252 }
253
254 /* Close the SVG file */
255 ret=svg_close(fp_svg, NULL, verbose-13);
256 if(ret) {
257 fclose(fp_svg);
258 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
260 }
261
262 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
263 return(TPCERROR_OK);
264}
int tacYRangeInXRange(TAC *d, int i, const double xmin, const double xmax, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct, including only samples with x (times) insid...
Definition tacy.c:99
int unitIsTime(int u)
Definition units.c:359

◆ tacPlotHistogramSVG()

int tacPlotHistogramSVG ( TAC * d,
const char * main_title,
const double x1,
const double x2,
const double y1,
const double y2,
const char * fname,
TPCSTATUS * status )
extern

SVG plot of histogram from data given in TAC data structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacPlotLineSVG, tacPlotFitSVG, mtgaPlotSVG
Author
Vesa Oikonen
Parameters
dPointer to TAC structure. Only the first dataset is used.
main_titleString for plot main title, or "".
x1Start x value; NaN if determined from data.
x2End x value; NaN if determined from data.
y1Minimum y value; NaN if determined from data.
y2Maximum y value; NaN if determined from data.
fnameSVG file name.
statusPointer to status data; obligatory.

Definition at line 30 of file histplot.c.

47 {
48 if(status==NULL) return TPCERROR_FAIL;
49 if(status->verbose>1)
50 printf("%s(tac, '%s', %g, %g, %g, %g, '%s')\n", __func__, main_title, x1, x2, y1, y2, fname);
51 if(d==NULL || d->sampleNr<1 || d->tacNr<1) {
52 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA); return(status->error);}
53 if(fname==NULL || strnlen(fname, 1)<1) {
54 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME); return(status->error);}
55
56 /* Determine the plot min and max x and y values */
57 double minx, maxx, miny, maxy, tx1, tx2, ty1, ty2;
58 if(tacSampleXRange(d, &tx1, &tx2)) {
59 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE); return(status->error);}
60 minx=tx1; maxx=tx2;
61 if(minx>0.0) {double f=maxx-minx; minx-=0.05*f; if(minx<0.0) minx=0.0;}
62 if(isfinite(x1)) minx=x1;
63 if(isfinite(x2)) maxx=x2;
64 if(status->verbose>1) {printf(" minx := %g\n maxx := %g\n", minx, maxx); fflush(stdout);}
65 /* Determine the plot min and max y values inside the x range */
66 if(tacYRangeInXRange(d, 0, minx, maxx, &ty1, &ty2, NULL, NULL, NULL, NULL)) {
67 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE); return(status->error);}
68// if(ty1>0.0) ty1=0.0;
69// if(ty2<0.0) ty2=0.0;
70 miny=ty1; maxy=ty2;
71 if(miny>0.0) {double f=maxy-miny; miny-=0.05*f; if(miny<0.0) miny=0.0;}
72 else if(maxy<0.0) maxy=0.0;
73 if(isfinite(y1)) miny=y1;
74 if(isfinite(y2)) maxy=y2;
75 if(status->verbose>1) {printf(" miny := %g\n maxy := %g\n", miny, maxy); fflush(stdout);}
76
77 /* Calculate the axis ticks */
78 struct svg_viewports viewports; svg_init_viewports(&viewports);
79 viewports.x.min=minx; viewports.x.max=maxx;
80 viewports.y.min=miny; viewports.y.max=maxy;
81 viewports.label_area_viewport.is=0; // no plot legends
82 if(svg_calculate_axes(&viewports, status->verbose-1)) {
83 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE); return(status->error);}
84
85 /* Set the plot window and window area sizes */
86 if(svg_define_viewports(0, 0, strlen(main_title), 0, 0, 0, &viewports, status->verbose-1)) {
87 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE); return(status->error);}
88
89 /* Initiate graphics file */
90 FILE *fp=svg_initiate(fname, 0, 0, &viewports, NULL, status->verbose-1);
91 if(fp==NULL) {
92 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_OPEN); return(status->error);}
93
94 /* Put the graph titles into their own viewports */
95 if(svg_create_main_title(fp, main_title, "", &viewports, NULL, status->verbose-2)) {
96 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
97 fclose(fp); return(status->error);
98 }
99 /* Put the plot into its own viewport */
100 if(svg_start_plot_viewport(fp, &viewports, NULL, status->verbose-2)) {
101 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
102 fclose(fp); return(status->error);
103 }
104 /* Start coordinate area viewport */
105 if(svg_start_coordinate_viewport(fp, &viewports, NULL, status->verbose-3)) {
106 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
107 fclose(fp); return(status->error);
108 }
109 /* Write plot axes */
110 if(svg_write_axes(fp, &viewports, NULL, status->verbose-3)) {
111 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
112 fclose(fp); return(status->error);
113 }
114
115 /*
116 * Draw the data
117 */
118 char ilc[9], tmp[1024];
119 if(SVG_INLINE) strcpy(ilc, "svg:"); else strcpy(ilc, "");
120 /* Initiate the data object group */
121 sprintf(tmp, "\n<%sg stroke=\"black\" stroke-width=\"25\" fill=\"black\">\n", ilc);
122 if(svg_write(fp, tmp, NULL, status->verbose-5)!=0) {
123 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
124 fclose(fp); return(status->error);
125 }
126 if(d->isframe==0) { // vertical lines
127 /* Open the path */
128 sprintf(tmp, "<%spath fill=\"none\" d=\"", ilc);
129 svg_write(fp, tmp, NULL, status->verbose-5);
130 for(int i=0; i<d->sampleNr; i++) {
131 if(!isfinite(d->x[i]) || !isfinite(d->c[0].y[i])) continue;
132 double nx1, ny1, nx2, ny2;
133 nx1=nx2=viewports.x.origo+d->x[i]*viewports.x.scale;
134 ny1=viewports.coordinate_area_viewport.h-(viewports.y.origo+viewports.y.scale*0.0);
135 ny2=viewports.coordinate_area_viewport.h-(viewports.y.origo+viewports.y.scale*d->c[0].y[i]);
136 /* Do not plot if x is outside viewport */
137 if(nx1<0 && nx2<=0) continue;
138 if(nx1>viewports.coordinate_area_viewport.w+1 || nx1>viewports.coordinate_area_viewport.w+1)
139 continue;
140 /* Do not plot if both y's are outside viewport */
141 if((ny1<0 || ny2>viewports.coordinate_area_viewport.h+1) &&
142 (ny2<0 || ny1>viewports.coordinate_area_viewport.h+1)) continue;
143 /* Set y limit to the viewport border */
144 if(ny1<0) ny1=0.0; else if(ny2<0) ny2=0.0;
145 if(ny1>viewports.coordinate_area_viewport.h+1) ny1=viewports.coordinate_area_viewport.h+1;
146 else if(ny2>viewports.coordinate_area_viewport.h+1) ny2=viewports.coordinate_area_viewport.h+1;
147 /* Draw */
148 sprintf(tmp, " M%.0f %.0f L%.0f %.0f", nx1, ny1, nx2, ny2);
149 svg_write(fp, tmp, NULL, status->verbose-5);
150 }
151 /* Close the path */
152 strcpy(tmp, "\" />\n");
153 svg_write(fp, tmp, NULL, status->verbose-5);
154 } else { // rectangles
155 for(int i=0; i<d->sampleNr; i++) {
156 if(!isfinite(d->x[i]) || !isfinite(d->c[0].y[i])) continue;
157 double nx1, ny1, nx2, ny2;
158 nx1=viewports.x.origo+d->x1[i]*viewports.x.scale;
159 nx2=viewports.x.origo+d->x2[i]*viewports.x.scale;
160 ny1=viewports.coordinate_area_viewport.h-(viewports.y.origo+viewports.y.scale*0.0);
161 ny2=viewports.coordinate_area_viewport.h-(viewports.y.origo+viewports.y.scale*d->c[0].y[i]);
162 /* Do not plot if x is outside viewport */
163 if(nx1<0 && nx2<=0) continue;
164 if(nx1>viewports.coordinate_area_viewport.w+1 || nx1>viewports.coordinate_area_viewport.w+1)
165 continue;
166 /* Do not plot if both y's are outside viewport */
167 if((ny1<0 || ny2>viewports.coordinate_area_viewport.h+1) &&
168 (ny2<0 || ny1>viewports.coordinate_area_viewport.h+1)) continue;
169 /* Set y limit to the viewport border */
170 if(ny1<0) ny1=0.0; else if(ny2<0) ny2=0.0;
171 if(ny1>viewports.coordinate_area_viewport.h+1) ny1=viewports.coordinate_area_viewport.h+1;
172 else if(ny2>viewports.coordinate_area_viewport.h+1) ny2=viewports.coordinate_area_viewport.h+1;
173 if(ny1>ny2) {double f=ny1; ny1=ny2; ny2=f;}
174 /* Draw */
175 sprintf(tmp, " <rect x=\"%.0f\" y=\"%.0f\" width=\"%.0f\" height=\"%.0f\" />\n",
176 nx1, ny1, nx2-nx1, fabs(ny2-ny1));
177 svg_write(fp, tmp, NULL, status->verbose-5);
178 }
179 }
180 /* Close the data object group */
181 sprintf(tmp, "</%sg>\n", ilc);
182 if(svg_write(fp, tmp, NULL, status->verbose-5)!=0) {
183 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
184 fclose(fp); return(status->error);
185 }
186
187 /* Close the coordinate viewport */
188 if(svg_end_coordinate_viewport(fp, NULL, status->verbose-1)) {
189 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
190 fclose(fp); return(status->error);
191 }
192
193 /* Write the axis ticks */
194 if(svg_write_xticks(fp, &viewports, NULL, status->verbose-3)!=0 ||
195 svg_write_yticks(fp, &viewports, NULL, status->verbose-3)!=0) {
196 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
197 fclose(fp); return(status->error);
198 }
199
200 /* Close the plot viewport */
201 if(svg_end_plot_viewport(fp, NULL, status->verbose-2)) {
202 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
203 fclose(fp); return(status->error);
204 }
205
206 /* Close the SVG file */
207 if(svg_close(fp, NULL, status->verbose-1)) {
208 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
209 fclose(fp); return(status->error);
210 }
211
212 if(status->verbose>0) fprintf(stdout, " written file %s\n", fname);
213
214 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
215 return(TPCERROR_OK);
216}
int SVG_INLINE
@ TPCERROR_CANNOT_OPEN
Cannot open file.

◆ tacPlotLineSVG()

int tacPlotLineSVG ( TAC * tac,
const char * main_title,
const double x1,
const double x2,
const double y1,
const double y2,
const char * fname,
TPCSTATUS * status )
extern

Writes specified range of line plots of TACs in SVG format.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
tacPlotFitSVG, mtgaPlotSVG
Author
Vesa Oikonen
Parameters
tacTAC data points.
main_titleString for plot main title, or "".
x1Start time; NaN if determined from data.
x2End time; NaN if determined from data.
y1Minimum y value; NaN if determined from data.
y2Maximum y value; NaN if determined from data.
fnameSVG file name.
statusPointer to status data; enter NULL if not needed.

Definition at line 273 of file tacfitplot.c.

290 {
291 int verbose=0; if(status!=NULL) verbose=status->verbose;
292 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
293 /* Check data */
294 if(tac==NULL || tac->tacNr<1 || tac->sampleNr<1) {
295 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
296 return TPCERROR_NO_DATA;
297 }
298 if(fname==NULL || strnlen(fname, 1)<1) {
299 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FILENAME);
301 }
302 if(status!=NULL && status->forgiving==0) {
303 // any strict tests in here
304 }
305
306 int ret, n, ri, si, ei;
307 char x_title[64], y_title[64], tac_id[32], tac_title[64];
308 double minx, maxx, miny, maxy, tx1, tx2, ty1, ty2, f;
309 struct svg_viewports viewports; svg_init_viewports(&viewports);
310 unsigned int max_color_nr=0, color_nr=0;
311 unsigned int max_symbol_nr=0, symbol_nr=0;
312 SVG_LEGENDS legends; svg_init_legends(&legends);
313 FILE *fp_svg=NULL;
314
315
316 int is_label=0; if(tac->tacNr>1) is_label=1;
317
318 /* Determine the plot min and max x values */
319 if(tacSampleXRange(tac, &tx1, &tx2)) {
320 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
322 }
323 minx=tx1; maxx=tx2;
324 if(minx>0.0) {double f=maxx-minx; minx-=0.05*f; if(minx<0.0) minx=0.0;}
325 if(!isnan(x1)) minx=x1;
326 if(!isnan(x2)) maxx=x2;
327 if(verbose>1) {
328 printf(" minx := %g\n maxx := %g\n", minx, maxx); fflush(stdout);}
329
330 /* Determine the plot min and max y values inside the x range */
331 if(tacYRangeInXRange(tac, -1, minx, maxx, &ty1, &ty2, NULL, NULL, NULL, NULL)) {
332 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
334 }
335 miny=ty1; maxy=ty2;
336 if(miny>0.0) {f=maxy-miny; miny-=0.05*f; if(miny<0.0) miny=0.0;}
337 if(!isnan(y1)) miny=y1;
338 if(!isnan(y2)) maxy=y2;
339 if(verbose>1) {
340 printf(" miny := %g\n maxy := %g\n", miny, maxy); fflush(stdout);}
341
342 /* Calculate the axis ticks */
343 viewports.x.min=minx; viewports.x.max=maxx;
344 viewports.y.min=miny; viewports.y.max=maxy;
345 viewports.label_area_viewport.is=is_label; // needed for x axis ticks
346 ret=svg_calculate_axes(&viewports, verbose-3);
347 if(ret) {
348 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
350 }
351
352 /* Set x and y axis titles based on activity and time units */
353 strcpy(x_title, "");
354 if(unitIsTime(tac->tunit))
355 sprintf(x_title, "Time (%s)", unitName(tac->tunit));
356 else if(tac->tunit!=UNIT_UNKNOWN)
357 strcpy(x_title, unitName(tac->tunit));
358 strcpy(y_title, "");
359 if(tac->cunit!=UNIT_UNKNOWN) strcpy(y_title, unitName(tac->cunit));
360
361 /* Set the plot window and window area sizes */
362 ret=svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
363 strlen(x_title), is_label, &viewports, verbose-3);
364 if(ret) {
365 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
367 }
368
369 /* Initiate graphics file */
370 fp_svg=svg_initiate(fname, 0, 0, &viewports, NULL, verbose-3);
371 if(fp_svg==NULL) {
372 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
374 }
375
376 /* Put the graph titles into their own viewports */
377 ret=svg_create_main_title(fp_svg, main_title, "", &viewports, NULL,verbose-3);
378 if(!ret)
379 ret=svg_create_yaxis_title(fp_svg, y_title, &viewports, NULL, verbose-3);
380 if(!ret)
381 ret=svg_create_xaxis_title(fp_svg, x_title, &viewports, NULL, verbose-3);
382
383 /* Put the plot into its own viewport */
384 if(!ret)
385 ret=svg_start_plot_viewport(fp_svg, &viewports, NULL, verbose-3);
386
387 /* Start coordinate area viewport */
388 if(!ret)
389 ret=svg_start_coordinate_viewport(fp_svg, &viewports, NULL, verbose-3);
390
391 /* Write plot axes */
392 if(!ret) ret=svg_write_axes(fp_svg, &viewports, NULL, verbose-3);
393
394 if(ret) {
395 fclose(fp_svg);
396 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
398 }
399
400 /*
401 * Draw the plots
402 */
403 max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
404 if(verbose>3) {printf("max_color_nr := %d\n", max_color_nr); fflush(stdout);}
405 if(tac->tacNr==1) color_nr=0; else color_nr=1;
406 symbol_nr=0;
407 for(ri=0, n=0; ri<tac->tacNr; ri++) {
408 sprintf(tac_id, "plot_%d", n);
409 strcpy(tac_title, tac->c[ri].name);
410 /* Draw the line */
411 for(si=0; si<tac->sampleNr; si++) if(!isnan(tac->c[ri].y[si])) break;
412 for(ei=tac->sampleNr-1; ei>=si; ei--) if(!isnan(tac->c[ri].y[ei])) break;
413 if((ei-si)>0) {
414 unsigned int ci, si; // remainder works only if 2nd operator > 0
415 if(max_color_nr<1) ci=0; else ci=color_nr % max_color_nr;
416 if(max_symbol_nr<1) si=0; else si=symbol_nr % max_symbol_nr;
417 ret=svg_write_tac(fp_svg, &viewports, 1, tac_id, tac_title,
418 tac->x+si, tac->c[ri].y+si, 1+ei-si,
419 svgColorName(ci), si, SYMBOLFILLED,
420 NULL, verbose-3);
421 if(ret) {
422 svg_legend_empty(&legends); fclose(fp_svg);
423 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
425 }
426 }
427 /* Set legend too, if requested */
428 if(is_label!=0) {
429 unsigned int ci, si; // remainder works only if 2nd operator > 0
430 if(max_color_nr<1) ci=0; else ci=color_nr % max_color_nr;
431 if(max_symbol_nr<1) si=0; else si=symbol_nr % max_symbol_nr;
432 svg_legend_add(&legends, 0, si, SYMBOLFILLED, ci, tac_title);
433 }
434 /* Prepare for the next plot */
435 color_nr++; n++;
436 if(color_nr==max_color_nr) color_nr=0;
437 }
438
439 /* Close the coordinate viewport */
440 ret=svg_end_coordinate_viewport(fp_svg, NULL, verbose-3);
441
442 /* Write the axis ticks */
443 if(!ret) {
444 if(svg_write_xticks(fp_svg, &viewports, NULL, verbose-3)!=0) ret=1;}
445 if(!ret) {
446 if(svg_write_yticks(fp_svg, &viewports, NULL, verbose-3)!=0) ret=1;}
447
448 /* Close the plot viewport */
449 if(!ret) ret=svg_end_plot_viewport(fp_svg, NULL, verbose-3);
450
451 if(ret) {
452 fclose(fp_svg); svg_legend_empty(&legends);
453 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
455 }
456
457 /* Make the plot legends into their own viewport */
458 ret=0;
459 if(viewports.label_area_viewport.is!=0) {
460 if(verbose>2) {printf("creating plot legends\n"); fflush(stdout);}
461 ret=svg_create_legends(fp_svg, &viewports, &legends, NULL, verbose-3);
462 }
463 svg_legend_empty(&legends);
464 if(ret) {
465 fclose(fp_svg);
466 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
468 }
469
470 /* Close the SVG file */
471 ret=svg_close(fp_svg, NULL, verbose-3);
472 if(ret) {
473 fclose(fp_svg);
474 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
476 }
477
478 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
479 return(TPCERROR_OK);
480}

◆ tacReadModelingData()

int tacReadModelingData ( const char * tissuefile,
const char * inputfile1,
const char * inputfile2,
const char * inputfile3,
double * fitdur,
int cutInput,
int * fitSampleNr,
TAC * tis,
TAC * inp,
TPCSTATUS * status )
extern

Read tissue and input data for modelling.

Time units are converted to min and input calibration units to the units of tissue data. Input data is NOT interpolated to tissue times, but original sample times are kept. If input data extends much further than fit duration, the last part is removed to save computation time in simulations. Input data ranges or TAC shapes are NOT verified.

See also
tacReadReference, tacReadModelingInput, tacFittime, tacRead, tacInit, tacInterpolate
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
tissuefileTissue data file name; one time sample is sufficient here; required.
inputfile11st input data file name; required.
inputfile22nd input data file name (or NULL or empty string if not needed); required, if inputfile3 is given.
inputfile33rd input data file name (or NULL or empty string if not needed).
fitdurFit duration (in minutes); shortened if longer than tissue data; input data is cut (if requested) so that it will not be much longer. Tissue TACs are NOT cut to this time.
cutInputCut off too many input samples to make calculation faster by entering <>0 here, or 0 to keep all input samples (which may be needed for delay correction).
fitSampleNrNr of time frames (samples) in tissue data that are inside fitdur will be written here; enter NULL if not needed.
tisPointer to initiated TAC struct into which tissue data will be written; required.
inpPointer to initiated TAC struct into which input data (plasma and/or blood) TACs will be written; required.
statusPointer to status data; enter NULL if not needed.

Definition at line 130 of file tacmodelinput.c.

157 {
158 int verbose=0; if(status!=NULL) verbose=status->verbose;
159 if(verbose>0) printf("%s()\n", __func__);
160 if(tis==NULL || inp==NULL) {
161 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
162 return TPCERROR_FAIL;
163 }
164 if(tissuefile==NULL || inputfile1==NULL || strnlen(inputfile1, 1)<1) {
165 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
166 return TPCERROR_NO_DATA;
167 }
168
169 /* Check the function input */
170 int input_nr=1;
171 if(inputfile2!=NULL && strnlen(inputfile2, 1)>0) input_nr++;
172 if(inputfile3!=NULL && strnlen(inputfile3, 1)>0) {
173 if(input_nr<2) {
174 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
175 return TPCERROR_NO_DATA;
176 }
177 input_nr++;
178 }
179 if(verbose>2) printf("input_nr := %d\n", input_nr);
180
181 /* Delete any previous data */
182 tacFree(tis); tacFree(inp);
183 if(fitSampleNr!=NULL) *fitSampleNr=0;
184
185 int ret;
186 /*
187 * Read tissue data
188 */
189 if(verbose>1) printf("reading tissue data in %s\n", tissuefile);
190 ret=tacRead(tis, tissuefile, status);
191 if(ret!=TPCERROR_OK) return(ret);
192
193 /* Do not check frame number; static scan is fine here */
194
195 /* Check for NaN's */
196 if(tacNaNs(tis)>0) {
197 tacFree(tis);
198 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
200 }
201
202 /* Sort the tissue data by increasing sample times */
203 ret=tacSortByTime(tis, status);
204 if(ret!=TPCERROR_OK) {
205 tacFree(tis);
206 statusSet(status, __func__, __FILE__, __LINE__, ret);
207 return ret;
208 }
209
210 /* Make sure that there is no overlap in sample frame times; samples must
211 be sorted before this */
212 ret=tacCorrectFrameOverlap(tis, status);
213 if(ret!=TPCERROR_OK) {tacFree(tis); return ret;}
214
215 /*
216 * Read first input data
217 */
218 if(verbose>1) printf("reading input data 1 in %s\n", inputfile1);
219 ret=tacRead(inp, inputfile1, status);
220 if(ret!=TPCERROR_OK) {tacFree(tis); return ret;}
221 /* Check and correct the sample time unit */
222 if(tis->tunit==UNIT_UNKNOWN) tis->tunit=inp->tunit;
223 else if(inp->tunit==UNIT_UNKNOWN) inp->tunit=tis->tunit;
224 if(inp->tunit==UNIT_UNKNOWN && verbose>0) {
225 fprintf(stderr, "Warning: input sample time units not known.\n");}
226 if(tis->tunit!=inp->tunit && tacXUnitConvert(inp, tis->tunit, status)) {
227 tacFree(tis); tacFree(inp); return ret;
228 }
229 /* Check TAC nr */
230 if(inp->tacNr>1) {
231 if(verbose>0)
232 fprintf(stderr, "Warning: using only first TAC in %s\n", inputfile1);
233 inp->tacNr=1;
234 }
235 /* Check sample nr */
236 if(inp->sampleNr<4) {
237 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
238 tacFree(tis); tacFree(inp); return TPCERROR_TOO_FEW;
239 }
240 /* Sort the data by increasing sample times */
241 tacSortByTime(inp, NULL);
242 /* If inp contains isotope and tis does not, then copy it */
244 int isotope=tacGetIsotope(inp);
246 }
247
248 /*
249 * Read following input files, if available
250 */
251 char *fname;
252 TAC tmptac; tacInit(&tmptac);
253 for(int ii=2; ii<=input_nr; ii++) {
254 if(ii==2) fname=(char*)inputfile2; else fname=(char*)inputfile3;
255 if(verbose>1) printf("reading input data %d in %s\n", ii, fname);
256 ret=tacRead(&tmptac, fname, status);
257 if(ret!=TPCERROR_OK) {
258 tacFree(tis); tacFree(inp); tacFree(&tmptac); return ret;}
259 /* Check TAC nr */
260 if(tmptac.tacNr>1) {
261 if(verbose>0)
262 fprintf(stderr, "Warning: using only first TAC in %s\n", fname);
263 tmptac.tacNr=1;
264 }
265 /* Check sample nr */
266 if(tmptac.sampleNr<4) {
267 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
268 tacFree(tis); tacFree(inp); tacFree(&tmptac); return TPCERROR_TOO_FEW;
269 }
270 /* Sort the data by increasing sample times */
271 tacSortByTime(&tmptac, NULL);
272
273 /* Check and correct the sample time unit */
274 if(tis->tunit==UNIT_UNKNOWN) tis->tunit=tmptac.tunit;
275 else if(tmptac.tunit==UNIT_UNKNOWN) tmptac.tunit=tis->tunit;
276 if(inp->tunit!=tmptac.tunit && tacXUnitConvert(&tmptac, inp->tunit, status))
277 {
278 tacFree(tis); tacFree(inp); tacFree(&tmptac); return ret;
279 }
280
281 /* Check and correct the sample concentration unit */
282 if(inp->cunit==UNIT_UNKNOWN) inp->cunit=tmptac.cunit;
283 else if(tmptac.cunit==UNIT_UNKNOWN) tmptac.cunit=inp->cunit;
284 if(inp->cunit!=tmptac.cunit && tacYUnitConvert(&tmptac, inp->cunit, status))
285 {
286 tacFree(tis); tacFree(inp); tacFree(&tmptac); return ret;
287 }
288
289 /* Copy to input data */
290 if(tacInterpolateInto(&tmptac, inp, NULL, NULL, status)!=TPCERROR_OK) {
291 tacFree(tis); tacFree(inp); tacFree(&tmptac); return ret;
292 }
293
294 tacFree(&tmptac);
295 } // next input file
296
297 /* Set time unit to min */
298 ret=tacXUnitConvert(tis, UNIT_MIN, status);
299 if(ret && verbose>0) {
300 fprintf(stderr, "Warning: check that regional data times are in minutes.\n");
301 }
302 ret=tacXUnitConvert(inp, UNIT_MIN, status);
303 if(ret && verbose>0) {
304 fprintf(stderr, "Warning: check that input data times are in minutes.\n");
305 }
306 /* Check that input and tissue time ranges are about the same */
307 double iend, tend;
308 {
309 ret=tacXRange(inp, NULL, &iend); if(ret==0) ret=tacXRange(tis, NULL, &tend);
310 if(ret || iend<=0.0 || tend<=0.0) {
311 tacFree(tis); tacFree(inp);
312 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
314 }
315 if(tend>10.0*iend || tend<0.10*iend) {
316 if(verbose>0) fprintf(stderr, "Warning: check the sample time units.\n");
317 }
318 }
319 ret=tacYUnitConvert(inp, tis->cunit, status);
320 if(ret && verbose>0) {
321 fprintf(stderr, "Warning: check the calibration units.\n");
322 }
323
324 /*
325 * Check and set fit time length
326 */
327 if(verbose>1) printf("checking and setting fit time length\n");
328 /* Set fit duration */
329 double starttime=0, endtime=*fitdur;
330 int fnr=tacFittime(tis, &starttime, &endtime, NULL, NULL, status);
331 if(verbose>3) {
332 fprintf(stdout, "tis.sampleNr := %d\n", tis->sampleNr);
333 fprintf(stdout, "starttime := %g\n", starttime);
334 fprintf(stdout, "endtime := %g\n", endtime);
335 //fprintf(stdout, "first := %d\n", first);
336 //fprintf(stdout, "last := %d\n", last);
337 fprintf(stdout, "fitSampleNr := %d\n", fnr);
338 }
339 *fitdur=endtime;
340 if(fitSampleNr!=NULL) *fitSampleNr=fnr;
341
342 /* Check that input data does not end much before fitdur */
343 if(*fitdur>1.2*iend) {
344 tacFree(tis); tacFree(inp);
345 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
346 return TPCERROR_TOO_FEW;
347 }
348
349 /* Cut off too many input samples to make calculation faster */
350 if(cutInput && iend>*fitdur) {
351 if(verbose>1) printf("cut off too many input samples\n");
352 int i; double f;
353 for(i=0; i<inp->sampleNr; i++) {
354 if(inp->isframe) f=0.5*(inp->x1[i]+inp->x2[i]); else f=inp->x[i];
355 if(f>(*fitdur)) break;
356 }
357 if(i<inp->sampleNr) i++;
358 inp->sampleNr=i;
359 if(inp->sampleNr<4) {
360 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
361 tacFree(tis); tacFree(inp); return TPCERROR_TOO_FEW;
362 }
363 }
364 if(verbose>2) fprintf(stdout, "inp.sampleNr := %d\n", inp->sampleNr);
365
366 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
367 return(TPCERROR_OK);
368}
int tacInterpolateInto(TAC *inp, TAC *tac, TAC *itac, TAC *iitac, TPCSTATUS *status)
Add TACs from one TAC structure into another TAC structure, interpolating the input TACs and allocati...
Definition litac.c:330
int tacGetIsotope(TAC *tac)
Definition tacdc.c:25
void tacSetIsotope(TAC *tac, int isotope)
Definition tacdc.c:41
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
int tacFittime(TAC *d, double *startTime, double *endTime, int *first, int *last, TPCSTATUS *status)
int tacYUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:72
int tacCorrectFrameOverlap(TAC *d, TPCSTATUS *status)
Correct PET frame start and end times if frames are slightly overlapping or have small gaps in betwee...
Definition tacx.c:65
@ TPCERROR_TOO_FEW
File contains too few samples.
isotope
Definition tpcisotope.h:50
@ ISOTOPE_UNKNOWN
Unknown.
Definition tpcisotope.h:51

◆ tacReadModelingInput()

int tacReadModelingInput ( const char * inputfile1,
const char * inputfile2,
const char * inputfile3,
TAC * inp,
TPCSTATUS * status )
extern

Read arterial input data for modelling.

Time and calibration units to the units of the first data. Input data ranges or TAC shapes are NOT verified.

See also
tacReadModelingData, tacReadReference, tacFittime, tacInterpolate
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
inputfile11st input data file name; required.
inputfile22nd input data file name (or NULL or empty string if not needed); required, if inputfile3 is given.
inputfile33rd input data file name (or NULL or empty string if not needed).
inpPointer to initiated TAC data structure into which input data (plasma and/or blood) TACs will be written; required.
See also
tacInit, tacFree
Parameters
statusPointer to status data; enter NULL if not needed.

Definition at line 560 of file tacmodelinput.c.

575 {
576 int verbose=0; if(status!=NULL) verbose=status->verbose;
577 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
578 if(inp==NULL) {
579 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
580 return TPCERROR_FAIL;
581 }
582 if(inputfile1==NULL || strnlen(inputfile1, 1)<1) {
583 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
584 return TPCERROR_NO_DATA;
585 }
586
587 /* Check the function input */
588 int input_nr=1;
589 if(inputfile2!=NULL && strnlen(inputfile2, 1)>0) input_nr++;
590 if(inputfile3!=NULL && strnlen(inputfile3, 1)>0) {
591 if(input_nr<2) {
592 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
593 return TPCERROR_NO_DATA;
594 }
595 input_nr++;
596 }
597 if(verbose>2) {printf("input_nr := %d\n", input_nr); fflush(stdout);}
598
599 /* Delete any previous data */
600 tacFree(inp);
601
602 int ret;
603 /*
604 * Read first input data
605 */
606 if(verbose>1) {
607 printf("reading input data 1 in %s\n", inputfile1); fflush(stdout);
608 }
609 ret=tacRead(inp, inputfile1, status);
610 if(ret!=TPCERROR_OK) {return ret;}
611 /* Check for NaN's */
612 if(tacNaNs(inp)>0) {
613 tacFree(inp);
614 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
616 }
617 /* Sort the data by increasing sample times */
618 ret=tacSortByTime(inp, status);
619 if(ret!=TPCERROR_OK) {
620 tacFree(inp); return ret;
621 }
622 /* Check TAC nr */
623 if(inp->tacNr>1) {
624 if(verbose>0)
625 fprintf(stderr, "Warning: using only first TAC in %s\n", inputfile1);
626 inp->tacNr=1;
627 }
628 /* Check sample nr */
629 if(inp->sampleNr<4) {
630 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
631 tacFree(inp); return TPCERROR_TOO_FEW;
632 }
633
634 /*
635 * Read following input files, if available
636 */
637 char *fname;
638 TAC tmptac; tacInit(&tmptac);
639 for(int ii=2; ii<=input_nr; ii++) {
640 if(ii==2) fname=(char*)inputfile2; else fname=(char*)inputfile3;
641 if(verbose>1) {
642 printf("reading input data %d in %s\n", ii, fname);
643 fflush(stdout);
644 }
645 ret=tacRead(&tmptac, fname, status);
646 if(ret!=TPCERROR_OK) {
647 tacFree(inp); tacFree(&tmptac); return ret;}
648 /* Check TAC nr */
649 if(tmptac.tacNr>1) {
650 if(verbose>0)
651 fprintf(stderr, "Warning: using only first TAC in %s\n", fname);
652 tmptac.tacNr=1;
653 }
654 /* Check sample nr */
655 if(tmptac.sampleNr<4) {
656 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
657 tacFree(inp); tacFree(&tmptac); return TPCERROR_TOO_FEW;
658 }
659 /* Sort the data by increasing sample times */
660 tacSortByTime(&tmptac, status);
661 if(ret!=TPCERROR_OK) {
662 tacFree(inp); tacFree(&tmptac); return ret;
663 }
664 /* Check and correct the sample time unit */
665 if(inp->tunit==UNIT_UNKNOWN) inp->tunit=tmptac.tunit;
666 else if(tmptac.tunit==UNIT_UNKNOWN) tmptac.tunit=inp->tunit;
667 if(inp->tunit!=tmptac.tunit && tacXUnitConvert(&tmptac, inp->tunit, status))
668 {
669 tacFree(inp); tacFree(&tmptac); return ret;
670 }
671 /* Check and correct the sample concentration unit */
672 if(inp->cunit==UNIT_UNKNOWN) inp->cunit=tmptac.cunit;
673 else if(tmptac.cunit==UNIT_UNKNOWN) tmptac.cunit=inp->cunit;
674 if(inp->cunit!=tmptac.cunit && tacYUnitConvert(&tmptac, inp->cunit, status))
675 {
676 tacFree(inp); tacFree(&tmptac); return ret;
677 }
678 /* Copy to input data */
679 if(tacInterpolateInto(&tmptac, inp, NULL, NULL, status)!=TPCERROR_OK) {
680 tacFree(inp); tacFree(&tmptac); return ret;
681 }
682 tacFree(&tmptac);
683 } // next input file
684
685 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
686 return(TPCERROR_OK);
687}

◆ tacReadReference()

int tacReadReference ( TAC * tis,
const char * reference,
TAC * ref,
int * refIndex,
TPCSTATUS * status )
extern

Read reference tissue TAC.

Reference tissue TAC is read either from a TAC file or from TAC structure containing all regional TACs based on its name. Reference tissue TACs are then either placed in a separate TAC structure, if provided by the user, or added/marked inside the existing TAC structure. Reference TAC(s) are marked with sw=2 (best or only match) or sw=1; if reference region file contains several TACs then the one which contains name 'mean' or 'avg' or has shortest total name length is assumed to be the best guess of true reference region and marked with value sw=2. When necessary, reference data units are converted to match the existing tissue TAC. If reference TAC(s) are read from a file, then this function verifies that the sample times do match the existing TACs. Reference TAC shapes are NOT verified.

See also
tacReadModelingData, tacFittime, tacRead, tacInit, tacInterpolate, tacSelectedTACs, tacSelectBestReference, tacReadModelingInput.
Returns
The number of reference TACs, and 0 in case of an error.
Author
Vesa Oikonen
Parameters
tisPointer to TAC structure containing the regional tissue TACs, possibly also the reference TAC(s). If pointer to reference TAC structure is not given (below), then the reference TAC(s) are marked/added in this TAC structure; otherwise reference TAC(s) may be moved from this structure into the reference TAC structure.
referenceString containing either the name of reference TAC file, or reference region name or number in the TAC structure (above).
refPointer to output TAC structure into which the reference tissue TACs are placed. Enter NULL, if reference TACs are to be placed/kept in the TAC structure with all tissue TACs. TACs in this structure will be marked with either sw=2 (best guess of true reference region) or sw=1 (less probable reference TACs). Any previous contents are deleted.
Precondition
Struct must be initiated before calling this function.
Parameters
refIndexIndex of the best reference region; enter NULL if not needed.
statusPointer to status data; enter NULL if not needed.

Definition at line 390 of file tacmodelinput.c.

411 {
412 int verbose=0; if(status!=NULL) verbose=status->verbose;
413 if(verbose>0) printf("%s()\n", __func__);
414 if(tis==NULL || reference==NULL) {
415 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
416 return 0;
417 }
418 if(strnlen(reference, 1)<1 || tis->sampleNr<1 || !tacIsX(tis)) {
419 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
420 return 0;
421 }
422
423 /* First, try to read reference from file */
424 TAC temp; tacInit(&temp);
425 if(verbose>1) printf("trying to read file %s\n", reference);
426 if(tacRead(&temp, reference, status)==TPCERROR_OK) {
427 /* Check sample nr */
428 if(temp.sampleNr<tis->sampleNr) {
429 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
430 tacFree(&temp); return 0;
431 }
432 int n, ret=0, refi=0;
433 /* Convert units */
434 if(tacXUnitConvert(&temp, tis->tunit, status)) ret++;
435 if(tacYUnitConvert(&temp, tis->cunit, status)) ret++;
436 if(verbose>0 && ret>0)
437 fprintf(stderr, "Warning: check the units of reference and tissue data.\n");
438 /* Check that sample times do match */
439 if(!tacXMatch(tis, &temp, verbose-1)) {
440 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_X);
441 tacFree(&temp); return 0;
442 } else if(tis->isframe && !temp.isframe) {
443 /* Copy frame start and end times, in case those had been lost */
444 tacXCopy(tis, &temp, 0, tis->sampleNr-1);
445 temp.isframe=1;
446 }
447 /* Select the best reference region */
448 if(temp.tacNr==1) {
449 temp.c[0].sw=2; refi=0; // just one
450 } else {
451 for(int i=0; i<temp.tacNr; i++) temp.c[i].sw=1;
452 refi=tacSelectBestReference(&temp); if(refi<0) refi=0;
453 temp.c[refi].sw=2;
454 }
455 if(verbose>1) printf("selected ref region := %s\n", temp.c[refi].name);
456 /* If ref contains isotope and tis does not, then copy it */
458 int isotope=tacGetIsotope(&temp);
460 }
461 /* Copy to output struct, if pointer is given; otherwise copy to tis */
462 if(ref!=NULL) {
463 if(verbose>2) printf("adding %d ref tacs to ref struct\n", temp.tacNr);
464 ret=tacDuplicate(&temp, ref);
465 if(ret!=TPCERROR_OK) {
466 statusSet(status, __func__, __FILE__, __LINE__, ret);
467 tacFree(&temp); return 0;
468 }
469 if(refIndex!=NULL) *refIndex=refi;
470 } else {
471 if(verbose>2) printf("adding %d ref tacs to tis struct\n", temp.tacNr);
472 for(int i=0; i<tis->tacNr; i++) tis->c[i].sw=0;
473 ret=tacAllocateMore(tis, temp.tacNr);
474 for(int i=0; i<temp.tacNr && ret==TPCERROR_OK; i++)
475 ret=tacCopyTacc(&temp.c[i], &tis->c[tis->tacNr+i], tis->sampleNr);
476 if(ret!=TPCERROR_OK) {
477 statusSet(status, __func__, __FILE__, __LINE__, ret);
478 tacFree(&temp); return 0;
479 }
480 if(refIndex!=NULL) *refIndex=tis->tacNr+refi;
481 tis->tacNr+=temp.tacNr;
482 }
483 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
484 n=temp.tacNr; tacFree(&temp);
485 if(verbose>1) printf("%d ref region(s) found in file.\n", n);
486 return(n);
487 // reference file was read and processed
488 } else if(verbose>1) {
489 printf(" '%s' was not a file\n", reference); fflush(stdout);
490 }
491
492 /* So 'reference' did not contain valid, accessible filename,
493 but is it a region name or number? */
494 if(verbose>1) printf("trying to find reference in TAC struct\n");
495 int n, refi;
496 n=tacSelectTACs(tis, reference, 1, status);
497 if(verbose>1) {printf("%d region(s) matched.\n", n); fflush(stdout);}
498 if(n<1) {
499 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_REFERENCE);
500 return(0);
501 }
502 if(n==tis->tacNr) {
503 if(verbose>2) {printf("... which means all region(s) matched.\n"); fflush(stdout);}
504 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
505 return(0);
506 }
507 refi=tacSelectBestReference(tis);
508 if(refi<0) {
509 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
510 return(0);
511 }
512 tis->c[refi].sw=2; if(refIndex!=NULL) *refIndex=refi;
513
514 /* If output struct was not given, then we are ready */
515 if(ref==NULL) {
516 if(verbose>1) {printf("reference TAC tagged.\n"); fflush(stdout);}
517 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
518 return(n);
519 }
520
521 /* Move reference TACs to output struct */
522 if(verbose>1) printf("moving reference TAC(s) to output TAC struct\n");
523 int ret;
524 ret=tacDuplicate(tis, ref);
525 if(ret!=TPCERROR_OK) {
526 statusSet(status, __func__, __FILE__, __LINE__, ret);
527 return 0;
528 }
529 int i=ref->tacNr-1; ret=0;
530 while(i>=0 && !ret) {
531 if(ref->c[i].sw==0) ret=tacDeleteTACC(ref, i);
532 i--;
533 }
534 i=tis->tacNr-1;
535 while(i>=0 && !ret) {
536 if(tis->c[i].sw) ret=tacDeleteTACC(tis, i);
537 i--;
538 }
539 if(ret) {
540 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
541 return 0;
542 }
543 if(refIndex!=NULL) { // set reference index to index inside ref struct
544 *refIndex=-1;
545 for(i=0; i<ref->tacNr; i++) if(ref->c[i].sw==2) {*refIndex=i; break;}
546 }
547 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
548 return(n);
549}
char sw
Definition tpctac.h:77
int tacCopyTacc(TACC *d1, TACC *d2, int sampleNr)
Definition tac.c:233
int tacDeleteTACC(TAC *d, int i)
Definition tacorder.c:310
int tacSelectTACs(TAC *d, const char *region_name, int reset, TPCSTATUS *status)
Definition tacselect.c:24
int tacSelectBestReference(TAC *d)
Definition tacselect.c:139
@ TPCERROR_NO_REFERENCE
Reference not found.

◆ tacToPAR()

int tacToPAR ( TAC * tac,
PAR * par,
TPCSTATUS * status )
extern

Copy the contents of TAC struct into PAR struct.

In addition to data, the header contents such as region names and units are copied if possible.

See also
parInit, parFree, parAllocateWithTAC, parWrite
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
tacPointer to the TAC struct to be copied.
parPointer to PAR struct; any old contents are deleted.
Precondition
Struct must be initiated with parInit.
Parameters
statusPointer to status data; enter NULL if not needed

Definition at line 169 of file partac.c.

177 {
178 int verbose=0; if(status!=NULL) verbose=status->verbose;
179 if(verbose>0) printf("%s(par, tac)\n", __func__);
180
181 int ret;
182
183 /* Check the input */
184 if(tac==NULL || par==NULL) {
185 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
186 return TPCERROR_FAIL;
187 }
188 if(tac->sampleNr<1 || tac->tacNr<1) {
189 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
190 return TPCERROR_NO_DATA;
191 }
192
193 /* Allocate memory and copy most of headers */
194 ret=parAllocateWithTAC(par, tac, tac->sampleNr, status);
195 if(ret!=TPCERROR_OK) return(ret);
196
197 /* Copy the values */
198 for(int i=0; i<tac->tacNr; i++)
199 for(int j=0; j<par->parNr; j++)
200 par->r[i].p[j]=tac->c[i].y[j];
201
202 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
203 return TPCERROR_OK;
204}
int parAllocateWithTAC(PAR *par, TAC *tac, int parNr, TPCSTATUS *status)
Allocate PAR based on data in TAC.
Definition partac.c:90

◆ tacVb()

int tacVb ( TAC * ttac,
const int i,
TAC * btac,
double Vb,
const int simVb,
const int petVolume,
TPCSTATUS * status )
extern

Correct TTACs for vascular blood, or simulate its effect.

See also
tacDelay, tacReadModelingInput, tacInterpolate, imgVb
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
ttacPointer to TAC data to process.
iIndex of TAC to be processed; enter <0 to process all.
btacPointer to BTAC data to subtract or add; must contain exactly same sample times as TTAC and y values must be in the same units.
VbVb fraction [0,1].
simVbSwitch to either subtract vascular volume (0) or to simulate it (1).
petVolumeSwitch to model vascular volume as either 0 : Cpet = (1-Vb)*Ct + Vb*Cb, or 1 : Cpet = Ct + Vb*Cb
statusPointer to status data; obligatory.

Definition at line 138 of file lisim.c.

156 {
157 int verbose=0; if(status!=NULL) verbose=status->verbose;
158 if(verbose>0) printf("%s(ttac, %d, btac, %g, %d, %d)\n", __func__, i, Vb, simVb, petVolume);
159 if(ttac==NULL || btac==NULL) {
160 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
161 return TPCERROR_FAIL;
162 }
163 if(ttac->tacNr<1 || btac->tacNr<1 || ttac->sampleNr<1) {
164 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
165 return TPCERROR_NO_DATA;
166 }
167 if(ttac->sampleNr>btac->sampleNr) {
168 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INCOMPATIBLE_DATA);
170 }
171 if(!(Vb>=0.0) || !(Vb<=1.0)) {
172 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
174 }
175 if(Vb==1.0 && petVolume==0 && simVb==0) { // combination would lead to divide by zero
176 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
178 }
179 if(i>=ttac->tacNr) {
180 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
182 }
183
184
185 if(simVb==0) {
186 if(verbose>1) printf("subtracting blood\n");
187 for(int ri=0; ri<ttac->tacNr; ri++) if(i<0 || i==ri) {
188 for(int fi=0; fi<ttac->sampleNr; fi++) {
189 ttac->c[ri].y[fi]-=Vb*btac->c[0].y[fi];
190 if(petVolume==0) ttac->c[ri].y[fi]/=(1.0-Vb);
191 }
192 }
193 } else {
194 if(verbose>1) printf("adding blood\n");
195 for(int ri=0; ri<ttac->tacNr; ri++) if(i<0 || i==ri) {
196 for(int fi=0; fi<ttac->sampleNr; fi++) {
197 if(petVolume==0) ttac->c[ri].y[fi]*=(1.0-Vb);
198 ttac->c[ri].y[fi]+=Vb*btac->c[0].y[fi];
199 }
200 }
201 }
202
203 return(TPCERROR_OK);
204}