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

Header file for libtpcmodext. More...

#include "tpcclibConfig.h"
#include "libtpcmisc.h"
#include "libtpcmodel.h"
#include "libtpcsvg.h"
#include "libtpccurveio.h"
#include "libtpcimgio.h"
#include "libtpcimgp.h"

Go to the source code of this file.

Functions

int bf_srtm (double *t, double *cr, int n, int bfNr, double t3min, double t3max, DFT *bf)
 
int bfRadiowater (DFT *input, DFT *tissue, DFT *bf, int bfNr, double k2min, double k2max, char *status, int verbose)
 
int bfIrr2TCM (DFT *input, DFT *tissue, DFT *bf, int bfNr, double thetamin, double thetamax, char *status, int verbose)
 
int dftReadinput (DFT *input, DFT *tissue, char *filename, int *filetype, double *ti1, double *ti2, int verifypeak, char *status, int verbose)
 
int dftReadReference (DFT *tissue, char *filename, int *filetype, int *ref_index, char *status, int verbose)
 
int dftReadModelingData (char *tissuefile, char *inputfile1, char *inputfile2, char *inputfile3, double *fitdur, int *fitframeNr, DFT *tis, DFT *inp, FILE *loginfo, int verbose, char *status)
 
int dftRobustMinMaxTAC (DFT *dft, int tacindex, double *minx, double *maxx, double *miny, double *maxy, int *mini, int *maxi, int *mins, int *maxs, int verbose)
 
int dftVerifyPeak (DFT *dft, int index, int verbose, char *status)
 
int imgReadModelingData (char *petfile, char *siffile, char *inputfile1, char *inputfile2, char *inputfile3, double *fitdur, int *fitframeNr, IMG *img, DFT *inp, DFT *iinp, int verifypeak, FILE *loginfo, int verbose, char *status)
 
int extrapolate_monoexp (DFT *dft, double *fittime, int *min_nr, int max_nr, double mintime, double extr_to, DFT *ext, FILE *loginfo, char *status)
 
int dftAutointerpolate (DFT *dft, DFT *dft2, double endtime, int verbose)
 
int dftDoubleFrames (DFT *dft, DFT *dft2)
 
int dftDivideFrames (DFT *dft, int voi_index, int add_nr, DFT *dft2, int verbose)
 
int dft_end_line (DFT *dft, double *fittime, int *min_nr, int max_nr, double mintime, int check_impr, FIT *fit, FILE *loginfo, char *status)
 
int dft_ln (DFT *dft1, DFT *dft2)
 
int fittime_from_dft (DFT *dft, double *startTime, double *endTime, int *first, int *last, int verbose)
 
int fittime_from_img (IMG *img, double *fittime, int verbose)
 
int check_times_dft_vs_img (IMG *img, DFT *dft, int verbose)
 
int check_times_dft_vs_dft (DFT *dft1, DFT *dft2, int verbose)
 
int copy_times_from_img_to_dft (IMG *img, DFT *dft, int verbose)
 
int getActualSamplenr (DFT *dft, int ri)
 
double dftEndtime (DFT *dft)
 
double imgEndtime (IMG *img)
 
int dftMatchTimeunits (DFT *dft1, DFT *dft2, int *tunit2, int verbose)
 
int img_patlak (DFT *input, IMG *dyn_img, int start, int end, linefit_range fit_range, float thrs, IMG *ki_img, IMG *ic_img, IMG *nr_img, char *status, int verbose)
 
int img_logan (DFT *input, IMG *dyn_img, int start, int end, linefit_range fit_range, float thrs, double k2, IMG *vt_img, IMG *ic_img, IMG *nr_img, char *status, int verbose)
 
int img_k1_using_ki (DFT *input, IMG *dyn_img, int frame_nr, IMG *ki_img, IMG *k1_img, IMG *k2k3_img, char *status, int verbose)
 
int dftInterpolateCheckStart (DFT *input, DFT *output, char *status, int verbose)
 
int dftInterpolateCheckEnd (DFT *input, DFT *output, char *status, int verbose)
 
int dftInterpolate (DFT *input, DFT *tissue, DFT *output, char *status, int verbose)
 
int dftInterpolateInto (DFT *inp, DFT *tis, char *status, int verbose)
 
int dftTimeIntegral (DFT *dft, double t1, double t2, DFT *idft, int calc_mode, char *status, int verbose)
 
int dftDerivative (DFT *dft, DFT *deriv, char *status)
 
int dftDerivative_old (DFT *dft, DFT *deriv, char *status)
 
int dftInterpolateForIMG (DFT *input, IMG *img, int frame_nr, DFT *output, double *ti1, double *ti2, int verbose, char *status)
 
int imgTimeIntegral (IMG *img, float t1, float t2, IMG *iimg, int calc_mode, char *status, int verbose)
 
int dftAllocateWithIMG (DFT *dft, int tacNr, IMG *img)
 
int sif2dft (SIF *sif, DFT *dft)
 
int sifAllocateWithIMG (SIF *sif, IMG *img, int doCounts, int verbose)
 
int mrl_between_tacs (double *y1, double *y2, int n)
 
int noiseSD4Simulation (double y, double t1, double dt, double hl, double a, double *sd, char *status, int verbose)
 
int noiseSD4SimulationFromDFT (DFT *dft, int index, double pc, double *sd, char *status, int verbose)
 
int plot_svg (DFT *dft, RES *res, int first, int last, char *main_title, char *x_title, char *y_title, int color_scale, char *fname, int verbose)
 
int plotdata (DFT *dft, RES *res, int first, int last, char *mtitle, char *xtitle, char *ytitle, char *fname)
 
int plotdata_as_dft (DFT *dft, char *fname)
 
int plot_fit_svg (DFT *dft1, DFT *dft2, char *main_title, char *fname, int verbose)
 
int plot_fitrange_svg (DFT *dft1, DFT *dft2, char *main_title, double x1, double x2, double y1, double y2, char *fname, int verbose)
 
int cunit_check_dft_vs_img (DFT *dft, IMG *img, char *errmsg, int verbose)
 
int dftWeightByFreq (DFT *dft)
 
int imgSetWeights (IMG *img, int wmet, int verbose)
 
int dftWSampleNr (DFT *tac)
 
int clusterTACs (IMG *dimg, IMG *cimg, int nr, DFT *tac, int verbose)
 

Detailed Description

Header file for libtpcmodext.

Author
Vesa Oikonen

Definition in file libtpcmodext.h.

Function Documentation

◆ bf_srtm()

int bf_srtm ( double * t,
double * cr,
int n,
int bfNr,
double t3min,
double t3max,
DFT * bf )

Calculates set of basis functions for SRTM.

Returns
Returns 0 if successful, otherwise non-zero.
See also
bfRadiowater, bfIrr2TCM
Parameters
tPET frame mid times.
crNon-decay corrected Cr(t).
nNr of PET frames.
bfNrNr of basis functions to calculate.
t3mintheta3 min.
t3maxtheta3 max.
bfdata for basis functions is allocated and filled here.

Definition at line 16 of file bf_model.c.

31 {
32 int bi, fi, ret;
33 double a, b, c;
34
35 // printf("\n%s(*t, *cr, %d, %d, %g, %g, *bf)\n", __func__, n, bfNr, t3min, t3max);
36
37 /* Check the parameters */
38 if(t==NULL || cr==NULL || n<2 || bfNr<1 || t3min<1.0E-10 || t3min>=t3max) return(1);
39 if(bf==NULL || bf->voiNr>0) return(1);
40
41 /* Allocate meory for basis functions */
42 ret=dftSetmem(bf, n, bfNr); if(ret) return(2);
43
44 /* Copy and set information fields */
45 bf->voiNr=bfNr; bf->frameNr=n;
47 for(bi=0; bi<bf->voiNr; bi++) {
48 snprintf(bf->voi[bi].voiname, 6, "B%5.5d", bi+1);
49 strcpy(bf->voi[bi].hemisphere, ".");
50 strcpy(bf->voi[bi].place, ".");
51 strcpy(bf->voi[bi].name, bf->voi[bi].voiname);
52 }
53 for(fi=0; fi<bf->frameNr; fi++) bf->x[fi]=t[fi];
54
55 /* Compute theta3 values to size fields */
56 a=log10(t3min); b=log10(t3max); c=(b-a)/(double)(bfNr-1);
57 for(bi=0; bi<bf->voiNr; bi++) {
58 bf->voi[bi].size=pow(10.0, (double)bi*c+a);
59 }
60
61 /* Calculate the functions */
62 for(bi=0; bi<bf->voiNr; bi++) {
63 a=bf->voi[bi].size;
64 ret=simC1(t, cr, n, 1.0, a, bf->voi[bi].y);
65 if(ret) return(4);
66 }
67
68 return(0);
69}
int dftSetmem(DFT *data, int frameNr, int voiNr)
Definition dft.c:57
#define DFT_FORMAT_STANDARD
int simC1(double *t, double *ca, int nr, double k1, double k2, double *ct)
Definition simulate.c:1317
int _type
Voi * voi
int voiNr
int frameNr
double * x
double size
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]

◆ bfIrr2TCM()

int bfIrr2TCM ( DFT * input,
DFT * tissue,
DFT * bf,
int bfNr,
double thetamin,
double thetamax,
char * status,
int verbose )

Calculates set of basis functions for irreversible 2TCM.

Returns
Returns 0 if successful, otherwise non-zero.
See also
bf_srtm, bfRadiowater
Parameters
inputArterial PTAC (not modified).
tissuePET TTAC (not modified, just to get frame times).
bfPlace for basis functions (initiated DFT struct, allocated and filled here).
bfNrNr of basis functions to calculate.
thetaminMinimum of theta=k2+k3 (sec-1 or min-1, corresponding to TAC time units).
thetamaxMaximum of theta=k2+k3 (sec-1 or min-1, corresponding to TAC time units).
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 217 of file bf_model.c.

235 {
236 int bi, fi, ret;
237 double a, b, c;
238
239 if(verbose>0)
240 printf("\n%s(*inp, *tis, *bf, %d, %g, %g, status, %d)\n", __func__,
241 bfNr, thetamin, thetamax, verbose);
242
243 /* Check the parameters */
244 if(input==NULL || tissue==NULL || bf==NULL) {
245 if(status!=NULL) strcpy(status, "program error");
246 else if(verbose>0) fprintf(stderr, "invalid function parameters\n");
247 return(1);
248 }
249 if(input->frameNr<3 || input->voiNr<1) {
250 if(status!=NULL) strcpy(status, "no input data");
251 else if(verbose>0) fprintf(stderr, "invalid input data\n");
252 return(2);
253 }
254 if(tissue->frameNr<1) {
255 if(status!=NULL) strcpy(status, "no pet data");
256 else if(verbose>0) fprintf(stderr, "invalid PET data\n");
257 return(3);
258 }
259 if(input->timeunit!=tissue->timeunit) {
260 if(status!=NULL) strcpy(status, "invalid time units");
261 else if(verbose>0) fprintf(stderr, "invalid time units\n");
262 return(4);
263 }
264 if(bfNr<2) {
265 if(status!=NULL) strcpy(status, "invalid nr of basis functions");
266 else if(verbose>0) fprintf(stderr, "invalid number of basis functions\n");
267 return(5);
268 }
269 if(thetamin<0.0) thetamin=0.0;
270 if(thetamin>=thetamax) {
271 if(status!=NULL) strcpy(status, "invalid theta range");
272 else if(verbose>0) fprintf(stderr, "invalid theta range\n");
273 return(6);
274 }
275 if(verbose>1) {
276 printf("input timerange: %g - %g\n", input->x[0], input->x[input->frameNr-1]);
277 printf("tissue timerange: %g - %g\n", tissue->x[0], tissue->x[tissue->frameNr-1]);
278 }
279
280 /* Allocate memory for basis functions */
281 if(verbose>1) printf("allocating memory for basis functions\n");
282 ret=dftSetmem(bf, tissue->frameNr, bfNr);
283 if(ret) {
284 if(status!=NULL) strcpy(status, "out of memory");
285 else if(verbose>0) fprintf(stderr, "out of memory\n");
286 return(10);
287 }
288
289 /* Copy and set information fields */
290 bf->voiNr=bfNr; bf->frameNr=tissue->frameNr;
291 bf->_type=tissue->_type;
292 dftCopymainhdr2(tissue, bf, 1);
293 for(bi=0; bi<bf->voiNr; bi++) {
294 snprintf(bf->voi[bi].voiname, 6, "B%5.5d", bi+1);
295 strcpy(bf->voi[bi].hemisphere, ".");
296 strcpy(bf->voi[bi].place, ".");
297 strcpy(bf->voi[bi].name, bf->voi[bi].voiname);
298 }
299 for(fi=0; fi<bf->frameNr; fi++) {
300 bf->x[fi]=tissue->x[fi];
301 bf->x1[fi]=tissue->x1[fi];
302 bf->x2[fi]=tissue->x2[fi];
303 }
304
305 /* Compute the range of theta values to size fields */
306 if(verbose>1) printf("computing theta values\n");
307 a=thetamin; b=thetamax; c=(b-a)/(double)(bfNr-1);
308 if(verbose>20) printf("a=%g b=%g, c=%g\n", a, b, c);
309 for(bi=0; bi<bf->voiNr; bi++) bf->voi[bi].size=(double)bi*c+a;
310 if(verbose>2) {
311 printf("final BF theta range: %g - %g\n", bf->voi[0].size, bf->voi[bf->voiNr-1].size);
312 printf("theta step size: %g\n", c);
313 }
314
315 /* Allocate memory for simulated TAC */
316 double *sim;
317 sim=(double*)malloc(input->frameNr*sizeof(double));
318 if(sim==NULL) {
319 if(status!=NULL) strcpy(status, "out of memory");
320 else if(verbose>0) fprintf(stderr, "out of memory\n");
321 dftEmpty(bf); return(11);
322 }
323
324 /* Calculate the basis functions at input time points */
325 if(verbose>1) printf("computing basis functions at input sample times\n");
326 for(bi=0; bi<bf->voiNr; bi++) {
327 a=bf->voi[bi].size;
328 ret=simC1(input->x, input->voi[0].y, input->frameNr, 1.0, a, sim);
329 if(ret) {
330 if(status!=NULL) strcpy(status, "simulation problem");
331 else if(verbose>0) fprintf(stderr, "simulation problem\n");
332 free(sim); dftEmpty(bf); return(20);
333 }
334 if(verbose>100) {
335 printf("\ntheta := %g\n", a);
336 printf("simulated TAC:\n");
337 for(fi=0; fi<input->frameNr; fi++)
338 printf(" %12.6f %12.3f\n", input->x[fi], sim[fi]);
339 }
340 /* interpolate to PET time frames */
341 if(tissue->timetype==DFT_TIME_STARTEND)
342 ret=interpolate4pet(input->x, sim, input->frameNr, tissue->x1, tissue->x2,
343 bf->voi[bi].y, NULL, NULL, bf->frameNr);
344 else
345 ret=interpolate(input->x, sim, input->frameNr, tissue->x,
346 bf->voi[bi].y, NULL, NULL, bf->frameNr);
347 if(ret) {
348 if(status!=NULL) strcpy(status, "simulation problem");
349 else if(verbose>0) fprintf(stderr, "simulation problem\n");
350 free(sim); dftEmpty(bf); return(20);
351 }
352
353 } // next basis function
354
355 free(sim);
356 if(verbose>1) printf("%s() done.\n\n", __func__);
357 if(status!=NULL) strcpy(status, "ok");
358 return(0);
359}
int dftCopymainhdr2(DFT *dft1, DFT *dft2, int ow)
Definition dft.c:587
void dftEmpty(DFT *data)
Definition dft.c:20
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
Definition integr.c:28
int interpolate4pet(double *x, double *y, int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, int newnr)
Interpolate and integrate TAC to PET frames.
Definition integr.c:510
#define DFT_TIME_STARTEND
int timetype
int timeunit
double * x1
double * x2

◆ bfRadiowater()

int bfRadiowater ( DFT * input,
DFT * tissue,
DFT * bf,
int bfNr,
double k2min,
double k2max,
char * status,
int verbose )

Calculates set of basis functions for generic radiowater model.

Returns
Returns 0 if successful, otherwise non-zero.
See also
bf_srtm, bfIrr2TCM
Parameters
inputArterial blood input TAC (not modified).
tissuePET TACs (not modified, just to get frame times).
bfPlace for basis functions (initiated DFT struct, allocated and filled here).
bfNrNr of basis functions to calculate.
k2minMinimum of k2 (sec-1 or min-1, corresponding to TAC time units).
k2maxMaximum of k2 (sec-1 or min-1, corresponding to TAC time units).
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 77 of file bf_model.c.

95 {
96 if(verbose>0)
97 printf("\n%s(*inp, *tis, *bf, %d, %g, %g, status, %d)\n", __func__,
98 bfNr, k2min, k2max, verbose);
99
100 /* Check the parameters */
101 if(input==NULL || tissue==NULL || bf==NULL) {
102 if(status!=NULL) strcpy(status, "program error");
103 return 1;
104 }
105 if(input->frameNr<3 || input->voiNr<1) {
106 if(status!=NULL) strcpy(status, "no input data");
107 return 2;
108 }
109 if(tissue->frameNr<1) {
110 if(status!=NULL) strcpy(status, "no pet data");
111 return 3;
112 }
113 if(input->timeunit!=tissue->timeunit) {
114 if(status!=NULL) strcpy(status, "invalid time units");
115 return 4;
116 }
117 if(bfNr<2) {
118 if(status!=NULL) strcpy(status, "invalid nr of basis functions");
119 return 5;
120 }
121 if(k2min<1.0E-10) k2min=1.0E-10; // range calculation does not work otherwise
122 if(k2min>=k2max || k2min<0.0) {
123 if(status!=NULL) strcpy(status, "invalid k2 range");
124 return 6;
125 }
126 if(verbose>1) {
127 printf("input timerange: %g - %g\n", input->x[0], input->x[input->frameNr-1]);
128 printf("tissue timerange: %g - %g\n", tissue->x[0], tissue->x[tissue->frameNr-1]);
129 }
130
131 /* Allocate memory for basis functions */
132 if(verbose>1) printf("allocating memory for basis functions\n");
133 if(dftSetmem(bf, tissue->frameNr, bfNr)) {
134 if(status!=NULL) strcpy(status, "out of memory");
135 return 10;
136 }
137
138 /* Copy and set information fields */
139 bf->voiNr=bfNr; bf->frameNr=tissue->frameNr;
140 bf->_type=tissue->_type;
141 dftCopymainhdr2(tissue, bf, 1);
142 for(int bi=0; bi<bf->voiNr; bi++) {
143 snprintf(bf->voi[bi].voiname, 6, "B%5.5d", bi+1);
144 strcpy(bf->voi[bi].hemisphere, ".");
145 strcpy(bf->voi[bi].place, ".");
146 strcpy(bf->voi[bi].name, bf->voi[bi].voiname);
147 }
148 for(int fi=0; fi<bf->frameNr; fi++) {
149 bf->x[fi]=tissue->x[fi];
150 bf->x1[fi]=tissue->x1[fi];
151 bf->x2[fi]=tissue->x2[fi];
152 }
153
154 /* Compute the range of k2 values to size fields */
155 if(verbose>1) printf("computing k2 values\n");
156 double a, b, c;
157 a=log10(k2min); b=log10(k2max); c=(b-a)/(double)(bfNr-1);
158 if(verbose>20) printf("a=%g b=%g, c=%g\n", a, b, c);
159 for(int bi=0; bi<bf->voiNr; bi++) {
160 bf->voi[bi].size=pow(10.0, (double)bi*c+a);
161 }
162 if(verbose>2) {
163 printf("final BF k2 range: %g - %g\n", bf->voi[0].size, bf->voi[bf->voiNr-1].size);
164 }
165
166 /* Allocate memory for simulated TAC */
167 double *sim;
168 sim=(double*)malloc(input->frameNr*sizeof(double));
169 if(sim==NULL) {
170 if(status!=NULL) strcpy(status, "out of memory");
171 dftEmpty(bf); return 11;
172 }
173
174 /* Calculate the basis functions at input time points */
175 if(verbose>1) printf("computing basis functions at input sample times\n");
176 for(int bi=0; bi<bf->voiNr; bi++) {
177 a=bf->voi[bi].size;
178 if(simC1(input->x, input->voi[0].y, input->frameNr, 1.0, a, sim)) {
179 if(status!=NULL) strcpy(status, "simulation problem");
180 free(sim); dftEmpty(bf);
181 return(20);
182 }
183 if(verbose>100) {
184 printf("\nk2 := %g\n", a);
185 printf("simulated TAC:\n");
186 for(int fi=0; fi<input->frameNr; fi++)
187 printf(" %12.6f %12.3f\n", input->x[fi], sim[fi]);
188 }
189 /* interpolate to PET time frames */
190 int ret=0;
191 if(tissue->timetype==DFT_TIME_STARTEND)
192 ret=interpolate4pet(input->x, sim, input->frameNr, tissue->x1, tissue->x2,
193 bf->voi[bi].y, NULL, NULL, bf->frameNr);
194 else
195 ret=interpolate(input->x, sim, input->frameNr, tissue->x,
196 bf->voi[bi].y, NULL, NULL, bf->frameNr);
197 if(ret) {
198 if(status!=NULL) strcpy(status, "simulation problem");
199 free(sim); dftEmpty(bf);
200 return(20);
201 }
202
203 } // next basis function
204
205 free(sim);
206 if(verbose>1) printf("%s() done.\n\n", __func__);
207 if(status!=NULL) strcpy(status, "ok");
208 return(0);
209}

◆ check_times_dft_vs_dft()

int check_times_dft_vs_dft ( DFT * dft1,
DFT * dft2,
int verbose )

Check whether sample times are the same (or very close to) in two DFT structs. Data sets are not edited. If DFT structs contain different sample number, then only common nr of samples are compared.

See also
check_times_dft_vs_img, copy_times_from_img_to_dft
Returns
Returns 0 in case of no match, 1 if times do match, and <1 in case of an error.
Parameters
dft1Pointer to first DFT data; times can be both seconds or minutes, if unit is correctly set.
dft2Pointer to second DFT data; times can be both seconds or minutes, if unit is correctly set; sample nr may be different than in dft1.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 169 of file fittime.c.

177 {
178 int fi, n, smaller_frameNr=0;
179 double f, ts1, ts2;
180 double accepted_timedif=2.2; // sec
181
182 if(verbose>0) printf("%s(*img, *dft)\n", __func__);
183 if(dft1==NULL || dft2==NULL) return -1;
184 if(dft1->frameNr<=0 || dft2->frameNr<=0) return 0;
185
186 /* Which has less samples? */
187 if(dft1->frameNr<dft2->frameNr) smaller_frameNr=dft1->frameNr;
188 else smaller_frameNr=dft2->frameNr;
189
190 /* Convert times to sec if necessary (and possible) */
191 ts1=ts2=1.0;
192 if(dft1->timeunit!=TUNIT_UNKNOWN && dft1->timeunit!=TUNIT_UNKNOWN) {
193 if(dft1->timeunit==TUNIT_MIN) ts1=60.0;
194 if(dft2->timeunit==TUNIT_MIN) ts2=60.0;
195 }
196 if(verbose>1) {
197 printf("dft1->timetype := %d\n", dft1->timetype);
198 printf("dft2->timetype := %d\n", dft2->timetype);
199 if(verbose>2) {
200 printf("time range 1 := %g - %g %s\n", dft1->x[0],
201 dft1->x[dft1->frameNr-1], petTunit(dft1->timeunit));
202 printf("time range 2 := %g - %g %s\n", dft2->x[0],
203 dft2->x[dft2->frameNr-1], petTunit(dft2->timeunit));
204 }
205 }
206
207 /* With short study the accepted time difference must be shorter */
208 f=0.01*dft1->x2[dft1->frameNr-1]*ts1;
209 if(accepted_timedif>f) accepted_timedif=f;
210 if(verbose>1) printf("accepted_timedif := %g [s]\n", accepted_timedif);
211
212 /* Compare sample times frame-by-frame */
213 for(fi=0, n=0; fi<smaller_frameNr; fi++) {
214 if(dft1->timetype==DFT_TIME_MIDDLE) { // check frame mid times
215 f=fabs(dft1->x[fi]*ts1-dft2->x[fi]*ts2);
216 if(verbose>10) printf("timedif[%d] := %g\n", fi, f);
217 if(verbose>12) printf(" %g vs %g\n", ts1*dft1->x[fi], ts2*dft2->x[fi]);
218 if(f>accepted_timedif) n++;
219 continue;
220 }
222 f=fabs(dft1->x1[fi]*ts1-dft2->x1[fi]*ts2);
223 if(verbose>10) printf("timedif[%d] := %g\n", fi, f);
224 if(verbose>12) printf(" %g vs %g\n", ts1*dft1->x1[fi], ts2*dft2->x1[fi]);
225 if(f>accepted_timedif) {n++; continue;}
226 }
227 if(dft1->timetype==DFT_TIME_END || dft1->timetype==DFT_TIME_STARTEND) {
228 f=fabs(dft1->x2[fi]*ts1-dft2->x2[fi]*ts2);
229 if(verbose>10) printf("timedif[%d] := %g\n", fi, f);
230 if(verbose>12) printf(" %g vs %g\n", ts1*dft1->x2[fi], ts2*dft2->x2[fi]);
231 if(f>accepted_timedif) n++;
232 }
233 }
234 if(verbose>2) printf("nr of different frame times := %d\n", n);
235
236 if(n==0) return 1; else return 0;
237}
#define DFT_TIME_MIDDLE
#define DFT_TIME_END
#define DFT_TIME_START
char * petTunit(int tunit)
Definition petunits.c:226

Referenced by dftInterpolate(), dftInterpolateForIMG(), and dftInterpolateInto().

◆ check_times_dft_vs_img()

int check_times_dft_vs_img ( IMG * img,
DFT * dft,
int verbose )

Check whether DFT sample times are the same (or very close to) as the frame times in IMG. This would suggest that DFT data originates from the same or similar PET scan. Specified data sets are not edited. If frame nr is different, then only the common frames are compared.

See also
check_times_dft_vs_dft, copy_times_from_img_to_dft, dftEndtime, imgEndtime
Returns
Returns 0 in case of no match, 1 if times do match, and <1 in case of an error.
Parameters
imgPointer to IMG data; times must be in sec as usual.
dftPointer to DFT data; times can be both seconds or minutes, if unit is correctly set; sample nr may be different than in IMG.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 109 of file fittime.c.

117 {
118 int smaller_dimt=0;
119 double f, ts;
120 double accepted_timedif=2.2; // sec
121
122 if(verbose>0) printf("%s(*img, *dft)\n", __func__);
123 if(img==NULL || dft==NULL) return -1;
124 if(img->dimt<=0 || dft->frameNr<=0) return 0;
125
126 /* Get the smaller frame nr */
127 if(img->dimt<dft->frameNr) smaller_dimt=img->dimt; else smaller_dimt=dft->frameNr;
128
129 /* With short study the accepted time difference must be shorter */
130 f=0.01*img->end[img->dimt-1]; if(accepted_timedif>f) accepted_timedif=f;
131 if(verbose>1) printf("accepted_timedif := %g [s]\n", accepted_timedif);
132
133 /* Convert DFT times to sec if necessary */
134 if(dft->timeunit==TUNIT_MIN) ts=60.0; else ts=1.0;
135
136 /* Compare sample times frame-by-frame */
137 int n=0;
138 for(int fi=0; fi<smaller_dimt; fi++) {
139 if(dft->timetype==DFT_TIME_MIDDLE) { // check frame mid times
140 f=fabs(img->mid[fi]-dft->x[fi]*ts);
141 if(verbose>10) printf("timedif[%d] := %g\n", fi, f);
142 if(f>accepted_timedif) n++;
143 continue;
144 }
146 f=fabs(img->start[fi]-dft->x1[fi]*ts);
147 if(verbose>10) printf("timedif[%d] := %g\n", fi, f);
148 if(f>accepted_timedif) {n++; continue;}
149 }
151 f=fabs(img->end[fi]-dft->x2[fi]*ts);
152 if(verbose>10) printf("timedif[%d] := %g\n", fi, f);
153 if(f>accepted_timedif) n++;
154 }
155 }
156 if(verbose>2) printf("nr of different frame times := %d\n", n);
157
158 if(n==0) return 1; else return 0;
159}
unsigned short int dimt
float * start
float * end
float * mid

Referenced by img_logan(), and img_patlak().

◆ clusterTACs()

int clusterTACs ( IMG * dimg,
IMG * cimg,
int nr,
DFT * tac,
int verbose )

Allocates memory and calculates the values for average TACs for clusters.

Returns
Returns 0 if ok, and >0 in case of an error.
Parameters
dimgDynamic image
cimgCluster image
nrHighest cluster ID
tacPointer to initiated but empty DFT data
verboseVerbose level; if zero, then only warnings are printed into stderr

Definition at line 15 of file cluster_tac.c.

26 {
27 if(verbose>0) printf("clusterTACs(dimg, cimg, %d, tac, %d)\n", nr, verbose);
28
29 /* Check the arguments */
30 if(dimg==NULL || cimg==NULL || nr<1 || tac==NULL) return(1);
31 if(dimg->dimt<1 || cimg->dimt<1) return(1);
32 if(cimg->dimx!=dimg->dimx || cimg->dimy!=dimg->dimy || cimg->dimz!=dimg->dimz)
33 return(2);
34
35 /* Allocate memory for the TACs */
36 dftEmpty(tac);
37 if(dftSetmem(tac, dimg->dimt, nr+1)) return(3);
38
39 /* Set TAC info */
40 tac->voiNr=0; tac->frameNr=dimg->dimt; tac->_type=1;
41 for(int fi=0; fi<tac->frameNr; fi++) {
42 tac->x1[fi]=dimg->start[fi];
43 tac->x2[fi]=dimg->end[fi];
44 tac->x[fi] =dimg->mid[fi];
45 }
47 tac->timeunit=TUNIT_SEC;
48 strcpy(tac->unit, imgUnit(dimg->unit));
49
50 /* Calculate one cluster at a time */
51 float y[dimg->dimt];
52 int clusterID;
53 for(clusterID=1; clusterID<=nr; clusterID++) {
54 char buf[128]; snprintf(buf, 128, "%06d", clusterID);
55 char *p=buf+strlen(buf)-6;
56 snprintf(tac->voi[clusterID-1].voiname, MAX_REGIONSUBNAME_LEN+1, "%s", p);
57 int n=imgsegmClusterMean(dimg, cimg, clusterID, y, verbose);
58 if(verbose>1) printf(" clusterID%d -> %d pixels\n", clusterID, n);
59 if(n<0) return(5); else if(n==0) return(6);
60 for(int fi=0; fi<tac->frameNr; fi++) tac->voi[clusterID-1].y[fi]=(double)y[fi];
61 tac->voi[clusterID-1].size=(double)n*dimg->sizex*dimg->sizey*dimg->sizez;
62 tac->voiNr++;
63 }
64 /* and once more for cluster 0, i.e. the thresholded pixels; */
65 /* note that it is possible that there is no cluster 0 at all */
66 clusterID=0;
67 sprintf(tac->voi[tac->voiNr].voiname, "%06d", clusterID);
68 strcpy(tac->voi[tac->voiNr].name, tac->voi[tac->voiNr].voiname);
69 int n=imgsegmClusterMean(dimg, cimg, clusterID, y, verbose);
70 if(n<0) return(7);
71 if(n>0) {
72 for(int fi=0; fi<tac->frameNr; fi++) tac->voi[tac->voiNr].y[fi]=(double)y[fi];
73 tac->voi[tac->voiNr].size=(double)n*dimg->sizex*dimg->sizey*dimg->sizez;
74 tac->voiNr++;
75 }
76
77 return(0);
78}
int imgsegmClusterMean(IMG *dimg, IMG *cimg, int clusterID, float *avg, int verbose)
Definition imgsegm.c:357
char * imgUnit(int dunit)
Definition imgunits.c:315
#define MAX_REGIONSUBNAME_LEN
Definition libtpcmisc.h:158
char unit[MAX_UNITS_LEN+1]
float sizex
unsigned short int dimx
char unit
float sizey
unsigned short int dimz
unsigned short int dimy
float sizez

◆ copy_times_from_img_to_dft()

int copy_times_from_img_to_dft ( IMG * img,
DFT * dft,
int verbose )

Copies frame times (especially start and end times, but also mid times) from an IMG data into DFT data, and sets DFT 'header' to indicate that frame start and end times are present.

See also
check_times_dft_vs_img, dftEndtime, imgEndtime, dftMatchTimeunits
Returns
Returns 0 if successful and <>0 in case of an error.
Parameters
imgPointer to IMG data; times must be in sec as usual.
dftPointer to DFT data; times can be both seconds or minutes, if unit is correctly set; sample nr may be smaller than in IMG.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 246 of file fittime.c.

254 {
255 int times_changed=0;
256
257 if(verbose>0) printf("%s(*img, *dft)\n", __func__);
258 if(img==NULL || dft==NULL) return 1;
259 if(img->dimt<=0 || dft->frameNr<=0) return 0;
260
261 /* If more DFT samples, then that is an error */
262 if(img->dimt<dft->frameNr) return 2;
263
264 /* Convert DFT times to sec if necessary */
265 if(dft->timeunit==TUNIT_MIN) {dftMin2sec(dft); times_changed=1;}
266
267 /* Copy the frame times frame-by-frame */
268 for(int fi=0; fi<dft->frameNr; fi++) {
269 dft->x1[fi]=img->start[fi];
270 dft->x2[fi]=img->end[fi];
271 dft->x[fi]=img->mid[fi];
272 }
274
275 /* Convert DFT times back to min if necessary */
276 if(times_changed!=0) dftSec2min(dft);
277
278 return 0;
279}
void dftSec2min(DFT *dft)
Definition dftunit.c:160
void dftMin2sec(DFT *dft)
Definition dftunit.c:145

Referenced by dftInterpolateForIMG(), img_logan(), and img_patlak().

◆ cunit_check_dft_vs_img()

int cunit_check_dft_vs_img ( DFT * dft,
IMG * img,
char * errmsg,
int verbose )

Check that calibration units in IMG (PET image) and DFT (input TAC) are the same, and if not, then try to convert DFT calibration unit to IMG unit. If input unit is unknown, then assume it is the same as the PET unit.

Returns
Returns 0 if successful, >0 in case of error, and <0 in case of a warning or error message to user is suggested.
Parameters
dftPointer to DFT.
imgPointer to IMG.
errmsgChar pointer to string (at least of length 128) where possible error description or warning is copied; set to NULL if not necessary.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 18 of file units_check.c.

28 {
29 int iunit, punit;
30
31 if(verbose>0) printf("calibration_unit_check_dft_vs_img()\n");
32 if(errmsg!=NULL) sprintf(errmsg, "program error");
33 if(dft==NULL || img==NULL) return 1;
34
35 iunit=petCunitId(dft->unit); // identify input file unit
36 punit=img->unit;
37
38 if(iunit==CUNIT_UNKNOWN) { // Input file unit is unknown
39 // If PET unit is not known either, give a warning
40 if(punit==CUNIT_UNKNOWN) {
41 if(errmsg!=NULL) sprintf(errmsg, "unknown concentration units");
42 return -1;
43 } else { // Set to PET unit, and give a warning
44 if(errmsg!=NULL)
45 sprintf(errmsg, "unknown input concentration unit, now set to PET unit");
46 strcpy(dft->unit, imgUnit(img->unit));
47 return -2;
48 }
49 }
50
51 // Input unit is known; if PET unit is not, then give a warning
52 if(punit==CUNIT_UNKNOWN) {
53 if(errmsg!=NULL) sprintf(errmsg, "unknown concentration units in PET data");
54 return -3;
55 }
56
57 // Both units are known, so convert input data if necessary/possible
58 if(iunit==CUNIT_KBQ_PER_ML) { // input is in units kBq/ml
59 // If PET unit is the same, then everything is fine
60 if(punit==CUNIT_KBQ_PER_ML) {
61 if(errmsg!=NULL)
62 sprintf(errmsg, "input and PET data have the same concentration units.\n");
63 return 0;
64 } else if(punit==CUNIT_BQ_PER_ML) { // image is in Bq/ml, convert input
65 dftUnitConversion(dft, CUNIT_BQ_PER_ML);
66 if(errmsg!=NULL)
67 sprintf(errmsg, "input units converted to %s\n", dft->unit);
68 return 0;
69 } else { // image is in some other units, just give a warning for now
70 if(errmsg!=NULL)
71 sprintf(errmsg, "different concentration units in input and PET data");
72 return -4;
73 }
74 } else if(iunit==CUNIT_BQ_PER_ML) { // input is in units Bq/ml
75 // If PET unit is the same, then everything is fine
76 if(punit==CUNIT_BQ_PER_ML) {
77 if(errmsg!=NULL)
78 sprintf(errmsg, "input and PET data have the same concentration units.\n");
79 return 0;
80 } else if(punit==CUNIT_KBQ_PER_ML) { // image is in kBq/ml, convert input
81 dftUnitConversion(dft, CUNIT_KBQ_PER_ML);
82 if(errmsg!=NULL)
83 sprintf(errmsg, "input units converted to %s\n", dft->unit);
84 return 0;
85 } else { // image is in some other units, just give a warning for now
86 if(errmsg!=NULL)
87 sprintf(errmsg, "different concentration units in input and PET data");
88 return -4;
89 }
90 } else { // input unit is known, but not kBq/ml or Bq/ml
91 if(errmsg!=NULL)
92 sprintf(errmsg, "check the concentration units in input and PET data");
93 return -5;
94 }
95
96 return 0;
97}
int dftUnitConversion(DFT *dft, int dunit)
Definition dftunit.c:25
int petCunitId(const char *unit)
Definition petunits.c:74

Referenced by imgReadModelingData().

◆ dft_end_line()

int dft_end_line ( DFT * dft,
double * fittime,
int * min_nr,
int max_nr,
double mintime,
int check_impr,
FIT * fit,
FILE * loginfo,
char * status )

Fits line to the end-part of TACs. By default, the included data points are determined based on maximum adjusted R^2 from at least three points; regression to the larger number of points is used in case difference in adjusted R^2 values is not larger than 0.0001.

Returns
Returns 0 when successful, otherwise <>0.
Parameters
dftPointer to original TAC data
fittimeBy default, the search for the best line fit is started from the last sample towards the first sample; set fit time to -1 to use this default. However, if the end phase is unreliable or very noisy, you may want to set fittime to include only certain time range from the beginning. Function will write here the fittime that was actually used.
min_nrThe minimum number of samples used in searching the best fit; at least 2, but 3 is recommended. If data is very noisy, then this number may need to be increased. Function will write here the nr of samples that was actually used. This can be used as an alternative to mintime or in addition to it.
max_nrThe maximum number of samples used in searching the best fit; must be higher than min_nr, or set to -1 to not to limit the number.
mintimeMinimum time range used in searching the best fit. If data is very noisy, then this may need to be set, otherwise setting mintime to -1 will use the default. This can be used as an alternative to min_nr or in addition to it.
check_imprLinear fitting can be applied to all data subsets in the fit time range (check_impr=0), or fitting is stopped when increasing n does not improve the adjusted R^2 (check_impr=1); the latter mode is for compatibility with WinNonlin.
fitPointer to data for fitted parameters. Struct must be initiated. Any existing data is deleted. Additionally, adjusted R^2 is written as 3rd (non-documented) parameter.
loginfoGive file pointer (for example stdout) where log information is printed; NULL if not needed.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 514 of file extrapolate.c.

552 {
553 int fi, ret, n, to, from, to_min, from_min, orig_max_nr;
554 int fitNr, snr;
555 double *cx, *cy;
556 double adj_r2, slope, slope_sd, ic, ic_sd, r, f, ySD_min;
557 double adj_r2_max, adj_r2_prev=-10.0, ic_min, slope_min;
558
559
560 /* Check the input */
561 if(status!=NULL) sprintf(status, "program error");
562 if(dft==NULL || fit==NULL) return -1;
563 if(*min_nr<2) *min_nr=3; // Setting erroneous value to a recommended value
564 if(max_nr>-1 && max_nr<*min_nr) return -2;
565 orig_max_nr=max_nr;
566
567 /* Set the last sample to be fitted */
568 fitNr=dft->frameNr;
569 if(*fittime>0.0) {
570 while(dft->x[fitNr-1]>*fittime && fitNr>0) fitNr--;
571 if(loginfo!=NULL) fprintf(loginfo, "fitNr := %d\nTime range := %g - %g\n",
572 fitNr, dft->x[0], dft->x[fitNr-1]);
573 }
574 *fittime=dft->x[fitNr-1];
575 /* Check that there are at least 3 samples */
576 if(fitNr<3) { /* min_nr is checked later */
577 if(status!=NULL) sprintf(status, "too few samples for linear fit");
578 return(2);
579 }
580
581 /* If mintime was set, then get min_nr based on that */
582 if(mintime>0.0) {
583 fi=0; while(dft->x[fi]<(*fittime-mintime) && fi<fitNr) fi++;
584 if(--fi<=0) {
585 if(status!=NULL) sprintf(status, "required minimum fit range too large");
586 return(2);
587 }
588 *min_nr=((fitNr-fi)>*min_nr?fitNr-fi:*min_nr);
589 }
590 if(loginfo!=NULL) fprintf(loginfo, "final_min_nr := %d\n", *min_nr);
591
592 /* Allocate data for fits */
593 if((ret=fit_allocate_with_dft(fit, dft))!=0) {
594 if(loginfo!=NULL) fprintf(loginfo, "Error %d: cannot allocate memory for fits.\n", ret);
595 if(status!=NULL) sprintf(status, "cannot allocate memory for fits");
596 return 4;
597 }
598 /* and for x,y data to be fitted */
599 cx=(double*)malloc(2*fitNr*sizeof(double)); if(cx==NULL) {
600 if(status!=NULL) sprintf(status, "out of memory");
601 return(6);
602 }
603 cy=cx+fitNr;
604
605 /* Fit each TAC */
606 if(loginfo!=NULL) fprintf(loginfo, "linear fitting\n");
607 for(int ri=0; ri<dft->voiNr; ri++) {
608 max_nr=orig_max_nr;
609 /* Print TAC name, if more than one was found */
610 if(dft->voiNr>1 && loginfo!=NULL)
611 fprintf(loginfo, "%s :\n", dft->voi[ri].name);
612 /* Set header */
613 fit->voi[ri].parNr=2;
614 fit->voi[ri].type=101;
615 /* Copy appropriate TAC data */
616 for(fi=n=0; fi<fitNr; fi++)
617 if(dft->x[fi]>0.0 && !isnan(dft->voi[ri].y[fi])) {
618 cx[n]=dft->x[fi]; cy[n++]=dft->voi[ri].y[fi];}
619 if(n<*min_nr) {
620 if(status!=NULL) sprintf(status, "check the datafile (%d<%d)", n, *min_nr);
621 free(cx); return(7);
622 }
623 if(max_nr<=0) max_nr=n;
624 /* Search the plot range that gives the max adjusted R^2 */
625 from_min=to_min=-1; adj_r2_max=-9.99E+99; ic_min=slope_min=0.0; ySD_min=0.0;
626 for(from=n-*min_nr, to=n-1; from>=n-max_nr; from--) {
627 snr=(to-from)+1;
628 /* Calculation of linear regression using pearson() */
629 ret=pearson(
630 cx+from, cy+from, snr, &slope, &slope_sd, &ic, &ic_sd, &r, &f
631 );
632 if(ret==0) {
633 adj_r2= 1.0 - ((1.0-r*r)*(double)(snr-1)) / (double)(snr-2);
634 if(adj_r2<0.0 && loginfo!=NULL)
635 fprintf(loginfo, " r=%g; snr=%d\n", r, snr);
636 } else {
637 adj_r2=-9.99E+99;
638 }
639 if(adj_r2>adj_r2_max-0.0001) {
640 adj_r2_max=adj_r2; from_min=from; to_min=to;
641 ic_min=ic; slope_min=slope; ySD_min=f;
642 }
643 if(loginfo!=NULL)
644 fprintf(loginfo, " adj_r2=%g from=%d (%g)\n",
645 adj_r2, from, *(cx+from) );
646 /* check for improvement, if required */
647 if(check_impr!=0 && adj_r2_prev>-1.0 && adj_r2>0.0 && adj_r2<adj_r2_prev)
648 break;
649
650 adj_r2_prev=adj_r2;
651 }
652 if(from_min<0) {
653 if(status!=NULL) sprintf(status, "check the datafile");
654 free(cx); return(7);
655 }
656 if(loginfo!=NULL) fprintf(loginfo, " adj_r2_max=%g.\n", adj_r2_max );
657 /* Set fit line parameters */
658 fit->voi[ri].p[0]=ic_min;
659 fit->voi[ri].p[1]=slope_min;
660 fit->voi[ri].p[2]=adj_r2_max;
661 fit->voi[ri].wss=ySD_min;
662 fit->voi[ri].start=cx[from_min]; fit->voi[ri].end=cx[to_min];
663 fit->voi[ri].dataNr=(to_min-from_min)+1;
664 } // next curve
665
666
667 free(cx);
668 if(status!=NULL) sprintf(status, "ok");
669 return 0;
670}
int fit_allocate_with_dft(FIT *fit, DFT *dft)
Definition fitres.c:14
int pearson(double *x, double *y, int nr, double *k, double *kSD, double *b, double *bSD, double *r, double *ySD)
Definition pearson.c:14
FitVOI * voi
double wss
double end
double start
double p[MAX_FITPARAMS]

◆ dft_ln()

int dft_ln ( DFT * dft1,
DFT * dft2 )

Natural logarithm (ln) transformation for TAC concentrations.

Returns
Returns 0 when successful, otherwise <>0.
Parameters
dft1Pointer to original TAC data.
dft2Pointer to allocated memory for ln transformed TAC data; enter NULL, if original data is to be overwritten by ln transformed values.

Definition at line 677 of file extrapolate.c.

683 {
684 DFT *out;
685
686 if(dft1==NULL || dft1->voiNr<1 || dft1->frameNr<1) return 1;
687 if(dft2!=NULL) out=dft2; else out=dft1;
688
689 int ok_nr=0;
690 for(int ri=0; ri<dft1->voiNr; ri++) for(int fi=0; fi<dft1->frameNr; fi++) {
691 if(!isnan(dft1->voi[ri].y[fi]) && dft1->voi[ri].y[fi]>0.0) {
692 out->voi[ri].y[fi]=log(dft1->voi[ri].y[fi]); ok_nr++;
693 } else {
694 out->voi[ri].y[fi]=nan("");
695 }
696 }
697 if(ok_nr>0) return 0; else return 2;
698}

◆ dftAllocateWithIMG()

int dftAllocateWithIMG ( DFT * dft,
int tacNr,
IMG * img )

Allocate memory for DFT based on information in IMG.

See also
sifAllocateWithIMG
Returns
Returns 0 if successful, otherwise <>0.
Parameters
dftPointer to initiated DFT struct which will be allocated here.
tacNrNr of TACs to be allocated in DFT; if zero, then TACs for all IMG pixels is allocated, but it may lead to out of memory error.
imgPointer to IMG struct from where necessary information is read.

Definition at line 296 of file misc_model.c.

304 {
305 int ri, fi, ret;
306
307 // Check the input data
308 if(dft==NULL || img==NULL) return 1;
309 if(img->status!=IMG_STATUS_OCCUPIED) return 2;
310 if(img->dimt<1) return 3;
311
312 // Get tacNr from image dimensions if necessary
313 if(tacNr<1) {
314 tacNr=img->dimz*img->dimx*img->dimy;
315 if(tacNr<1) return 4;
316 }
317
318 // Allocate memory
319 ret=dftSetmem(dft, img->dimt, tacNr);
320 if(ret) return(100+ret);
321 dft->voiNr=tacNr;
322 dft->frameNr=img->dimt;
323
324 // Set header contents
326 for(fi=0; fi<dft->frameNr; fi++) {
327 dft->x[fi]=img->mid[fi];
328 dft->x1[fi]=img->start[fi];
329 dft->x2[fi]=img->end[fi];
330 }
331 dft->isweight=0;
332 strncpy(dft->unit, imgUnit(img->unit), MAX_UNITS_LEN);
333 dft->timeunit=TUNIT_SEC;
335 for(ri=0; ri<dft->voiNr; ri++) {
336 snprintf(dft->voi[ri].voiname, 6, "%06d", ri+1);
337 strcpy(dft->voi[ri].name, dft->voi[ri].voiname);
338 }
340
341 return 0;
342}
#define IMG_STATUS_OCCUPIED
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
#define MAX_STUDYNR_LEN
Definition libtpcmisc.h:163
#define MAX_UNITS_LEN
Definition libtpcmisc.h:95
char studynr[MAX_STUDYNR_LEN+1]
int isweight
char status
char studyNr[MAX_STUDYNR_LEN+1]

Referenced by imgMaskPixelTACs().

◆ dftAutointerpolate()

int dftAutointerpolate ( DFT * dft,
DFT * dft2,
double endtime,
int verbose )

Interpolates TACs to automatically determined sample times with smaller intervals in the beginning. Only data in y arrays are interpolated; data in y2 and y3 are not used.

Returns
Function returns 0 when succesful, else a value >= 1.
Parameters
dftData to be interpolated is read from this structure.
dft2Interpolated data is written in this struct; must be initiated; any previous content is deleted.
endtimeThe length of interpolated/extrapolated data.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 243 of file extrapolate.c.

253 {
254 int i, newnr, maxNr=10000;
255 double t, dt;
256
257
258 if(verbose>0) printf("dftAutointerpolate(dft1, dft2, %g)\n", endtime);
259 /* Check the arguments */
260 if(dft->frameNr<1 || dft->voiNr<1) return 1;
261 if(endtime<1.0 || endtime>1.0E12) return 2;
263 return 10;
264
265 /* Calculate the number of interpolated data points */
266 t=0.0; dt=0.02; newnr=1;
267 while(t+dt<endtime && newnr<maxNr-1) {
268 t+=dt; dt*=1.05; newnr++;
269 }
270 dt=endtime-t; t=endtime; newnr++;
271 if(verbose>1) printf("newnr := %d\n", newnr);
272
273 /* Allocate memory for interpolated data */
274 dftEmpty(dft2); if(dftSetmem(dft2, newnr, dft->voiNr)) return 3;
275 /* Copy header info */
276 (void)dftCopymainhdr(dft, dft2); dft2->voiNr=dft->voiNr;
277 for(i=0; i<dft->voiNr; i++) if(dftCopyvoihdr(dft, i, dft2, i)) return 4;
278
279 /* Set times */
280 if(dft->timetype==DFT_TIME_STARTEND) {
281
283 t=0.0; dt=0.02; i=0;
284 if(verbose>1) printf("%05d: %12.5f %10.5f\n", i, t, dt);
285 dft2->x1[i]=t; dft2->x2[i]=t+dt; dft2->x[i]=0.5*(dft2->x1[i]+dft2->x2[i]);
286 i++;
287 while((t+2.5*dt)<endtime && newnr<maxNr-2) {
288 t+=dt; dt*=1.05;
289 if(verbose>1) printf("%05d: %12.5f %10.5f\n", i, t, dt);
290 dft2->x1[i]=t; dft2->x2[i]=t+dt; dft2->x[i]=0.5*(dft2->x1[i]+dft2->x2[i]);
291 i++;
292 }
293 t+=dt; dt=endtime-t;
294 if(verbose>1) printf("%05d: %12.5f %10.5f\n", i, t, dt);
295 dft2->x1[i]=t; dft2->x2[i]=t+dt; dft2->x[i]=0.5*(dft2->x1[i]+dft2->x2[i]);
296 i++; dft2->frameNr=i;
297
298 /* Interpolate */
299 for(i=0; i<dft->voiNr; i++)
300 if(interpolate4pet(dft->x, dft->voi[i].y, dft->frameNr,
301 dft2->x1, dft2->x2, dft2->voi[i].y, NULL, NULL, dft2->frameNr)) {
302 dftEmpty(dft2); return 5;
303 }
304
305 } else if(dft->timetype==DFT_TIME_MIDDLE) {
306
308 t=0.0; dt=0.02; i=0;
309 if(verbose>1) printf("%05d: %12.5f %10.5f\n", i, t, dt);
310 dft2->x1[i]=t; dft2->x2[i]=t+dt; dft2->x[i]=0.5*(dft2->x1[i]+dft2->x2[i]);
311 i++;
312 while((t+2.5*dt)<endtime && newnr<maxNr-2) {
313 t+=dt; dt*=1.05;
314 if(verbose>1) printf("%05d: %12.5f %10.5f\n", i, t, dt);
315 dft2->x1[i]=t; dft2->x2[i]=t+dt; dft2->x[i]=0.5*(dft2->x1[i]+dft2->x2[i]);
316 i++;
317 }
318 t+=dt; dt=endtime-t;
319 if(verbose>1) printf("%05d: %12.5f %10.5f\n", i, t, dt);
320 dft2->x1[i]=t; dft2->x2[i]=t+2.0*dt;
321 dft2->x[i]=0.5*(dft2->x1[i]+dft2->x2[i]);
322 i++; dft2->frameNr=i;
323
324 /* Interpolate */
325 for(i=0; i<dft->voiNr; i++)
326 if(interpolate4pet(dft->x, dft->voi[i].y, dft->frameNr,
327 dft2->x1, dft2->x2, dft2->voi[i].y, NULL, NULL, dft2->frameNr)) {
328 dftEmpty(dft2); return 5;
329 }
330
331 }
332
333 return 0;
334}
int dftCopyvoihdr(DFT *dft1, int from, DFT *dft2, int to)
Definition dft.c:623
int dftCopymainhdr(DFT *dft1, DFT *dft2)
Definition dft.c:561

◆ dftDerivative()

int dftDerivative ( DFT * dft,
DFT * deriv,
char * status )

Calculate simple derivatives from regional PET TACs. This must not be used for any quantitative purpose.

Returns
Returns 0 if successul.
Parameters
dftDFT struct containing the regional tissue TACs
derivAllocated DFT struct for derivatives
statusPointer to allocated string where the status or error message is written; set to NULL if not needed

Definition at line 635 of file dftint.c.

643 {
644 int ri, fi;
645 double fdur;
646
647 /* check input */
648 if(status!=NULL) sprintf(status, "invalid input for dftDerivative()");
649 if(dft==NULL || dft->frameNr<1 || dft->voiNr<1) return 1;
650 if(deriv==NULL || deriv->frameNr<dft->frameNr || deriv->voiNr<dft->voiNr)
651 return 2;
653 if(status!=NULL)
654 sprintf(status, "frame start and end times or mid times are required");
655 return 3;
656 }
657
658 /* calculate frame mid times if necessary */
660 for(fi=0; fi<dft->frameNr; fi++)
661 dft->x[fi]=0.5*(dft->x1[fi]+dft->x2[fi]);
662
663 /* calculate derivative */
664 if(dft->x[0]<=1.0E-20) for(ri=0; ri<dft->voiNr; ri++)
665 deriv->voi[ri].y[0]=0.0;
666 else for(ri=0; ri<dft->voiNr; ri++)
667 deriv->voi[ri].y[0]=dft->voi[ri].y[0]/dft->x[0];
668 for(fi=1; fi<dft->frameNr; fi++) {
669 fdur=dft->x[fi]-dft->x[fi-1];
670 if(fdur<=1.0E-20) for(ri=0; ri<dft->voiNr; ri++)
671 deriv->voi[ri].y[fi]=0.0;
672 else for(ri=0; ri<dft->voiNr; ri++)
673 deriv->voi[ri].y[fi]=(dft->voi[ri].y[fi]-dft->voi[ri].y[fi-1])/fdur;
674 }
675 for(ri=0; ri<dft->voiNr; ri++) for(fi=0; fi<dft->frameNr-1; fi++) {
676 deriv->voi[ri].y[fi]+=deriv->voi[ri].y[fi+1];
677 deriv->voi[ri].y[fi]*=0.5;
678 }
679
680 return 0;
681}

◆ dftDerivative_old()

int dftDerivative_old ( DFT * dft,
DFT * deriv,
char * status )

Calculate simple derivatives from regional PET TACs. Old version. Requires that frame start and end times are known.

Returns
Returns 0 if successul.
Parameters
dftDFT struct containing the regional tissue TACs
derivAllocated DFT struct for derivatives
statusPointer to allocated string where the status or error message is written; set to NULL if not needed

Definition at line 591 of file dftint.c.

599 {
600 int ri, fi;
601 double fdur;
602
603 /* check input */
604 if(status!=NULL) sprintf(status, "invalid input for dftDerivative()");
605 if(dft==NULL || dft->frameNr<1 || dft->voiNr<1) return 1;
606 if(deriv==NULL || deriv->frameNr<dft->frameNr || deriv->voiNr<dft->voiNr)
607 return 2;
608 if(dft->timetype!=3) {
609 if(status!=NULL) sprintf(status, "frame start and end times are required");
610 return 3;
611 }
612
613 /* calculate derivative */
614 for(fi=0; fi<dft->frameNr; fi++) {
615 fdur=dft->x2[fi]-dft->x1[fi];
616 if(fdur<=1.0E-10) {
617 for(ri=0; ri<dft->voiNr; ri++) deriv->voi[ri].y[fi]=0.0;
618 continue;
619 }
620 for(ri=0; ri<dft->voiNr; ri++) {
621 deriv->voi[ri].y[fi]=dft->voi[ri].y[fi];
622 if(fi>0) deriv->voi[ri].y[fi]-=dft->voi[ri].y[fi-1];
623 deriv->voi[ri].y[fi]/=fdur;
624 }
625 }
626 return 0;
627}

◆ dftDivideFrames()

int dftDivideFrames ( DFT * dft,
int voi_index,
int add_nr,
DFT * dft2,
int verbose )

Interpolates TACs to automatically determined sample times with smaller intervals in the beginning. Only data in y arrays are interpolated; data in y2 and y3 are not used.

Returns
Function returns 0 when succesful, else a value >= 1.
Parameters
dftData to be interpolated into more time frames is read from this struct.
voi_indexRegion index [0..voiNr-1] that is interpolated; <0 means all VOIs.
add_nrNr of extra time frames that are created from each original frame; valid numers are 1-100; 1 doubles the frame number.
dft2Interpolated data is written in this struct; must be initiated, may be allocated but do not need to be; any previous content is deleted.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 406 of file extrapolate.c.

420 {
421 int ret, fi, fj, i, new_frameNr=0, new_voiNr=0;
422 double fdur;
423
424 if(verbose>0) {
425 printf("dftDivideFrames(*dft, %d, %d, *dft2)\n", voi_index, add_nr);
426 fflush(stdout);
427 }
428 /* Check the arguments */
429 if(dft==NULL || dft2==NULL) return 1;
430 if(dft->frameNr<1 || dft->voiNr<1) return 2;
431 if(add_nr<1 || add_nr>100) return 3;
432 if(voi_index>=dft->voiNr) return 4;
433
434 /* Calculate how many frames and TACs will be needed */
435 if(dft->timetype==DFT_TIME_STARTEND) new_frameNr=(add_nr+1)*dft->frameNr;
436 else new_frameNr=(add_nr+1)*dft->frameNr-1;
437 if(voi_index<0) new_voiNr=dft->voiNr; else new_voiNr=1;
438 if(verbose>1) {
439 printf("new_frameNr := %d\n", new_frameNr);
440 printf("new_voiNr := %d\n", new_voiNr);
441 fflush(stdout);
442 }
443
444 /* Allocate memory for interpolated data if necessary */
445 if(new_frameNr>dft2->frameNr || new_voiNr>dft2->_voidataNr) {
446 if(verbose>1) {
447 printf("deleting old data and allocating new\n"); fflush(stdout);}
448 dftEmpty(dft2);
449 if(dftSetmem(dft2, new_frameNr, dft->voiNr)) return 11;
450 }
451
452 /* Copy header info */
453 ret=dftCopymainhdr(dft, dft2); if(ret!=0) return 12;
454 dft2->voiNr=new_voiNr; dft2->frameNr=new_frameNr;
455 if(voi_index>=0) ret=dftCopyvoihdr(dft, voi_index, dft2, 0);
456 else {
457 for(int ri=0; ri<dft->voiNr; ri++) {
458 ret=dftCopyvoihdr(dft, ri, dft2, ri); if(ret!=0) break;}
459 }
460 if(ret!=0) return 13;
461
462 /* Set new frame times and interpolate */
463 ret=0;
464 if(dft->timetype==DFT_TIME_STARTEND) {
465 for(fi=0, fj=0; fi<dft->frameNr; fi++) {
466 fdur=(dft->x2[fi]-dft->x1[fi])/(double)(add_nr+1);
467 for(i=0; i<add_nr+1; i++) {
468 fj=fi*(add_nr+1)+i;
469 dft2->x1[fj]=dft->x1[fi]+fdur*(double)i;
470 dft2->x2[fj]=dft2->x1[fj]+fdur;
471 dft2->x[fj]=0.5*(dft2->x1[fj]+dft2->x2[fj]);
472 if(voi_index>=0)
473 dft2->voi[0].y[fj]=dft->voi[voi_index].y[fi];
474 else
475 for(int ri=0; ri<dft->voiNr; ri++) dft2->voi[ri].y[fj]=dft->voi[ri].y[fi];
476 }
477 }
478 dft2->frameNr=fj+1;
479 } else {
480 dft2->x[0]=dft->x[0];
481 for(fi=1, fj=0; fi<dft->frameNr; fi++) {
482 fdur=(dft->x[fi]-dft->x[fi-1])/(double)(add_nr+1);
483 for(i=0; i<add_nr+1; i++) {
484 fj=(fi-1)*(add_nr+1) + i + 1;
485 dft2->x[fj]=dft->x[fi-1]+fdur*(double)(i+1);
486 }
487 }
488 dft2->frameNr=fj+1;
489 if(voi_index>=0) {
490 ret=interpolate(dft->x, dft->voi[voi_index].y, dft->frameNr,
491 dft2->x, dft2->voi[0].y, NULL, NULL, dft2->frameNr);
492 } else {
493 for(int ri=0; ri<dft->voiNr; ri++) {
494 ret=interpolate(dft->x, dft->voi[ri].y, dft->frameNr,
495 dft2->x, dft2->voi[ri].y, NULL, NULL, dft2->frameNr);
496 if(ret) break;
497 }
498 }
499 }
500 if(ret!=0) return 21;
501
502 return 0;
503}

◆ dftDoubleFrames()

int dftDoubleFrames ( DFT * dft,
DFT * dft2 )

Doubles the TAC sample number by making each sample/frame into two by linear interpolation. Only data in y arrays are interpolated; data in y2 and y3 are not used.

Returns
Function returns 0 when succesful, else a value >= 1.
Parameters
dftData to be interpolated is read from this structure.
dft2Interpolated data is written in this struct; must be initiated; any previous content is deleted.

Definition at line 343 of file extrapolate.c.

349 {
350 int ri, fi, fj, ret;
351 double f;
352
353
354 /* Check the arguments */
355 if(dft==NULL || dft2==NULL) return 1;
356 if(dft->frameNr<1 || dft->voiNr<1) return 2;
357 if(dft->timetype!=DFT_TIME_STARTEND && dft->x[0]<0.0) return 3;
358
359 /* Allocate memory for interpolated data */
360 dftEmpty(dft2); if(dftSetmem(dft2, 2*dft->frameNr, dft->voiNr)) return 11;
361 /* Copy header info */
362 (void)dftCopymainhdr(dft, dft2);
363 dft2->voiNr=dft->voiNr; dft2->frameNr=2*dft->frameNr;
364 for(ri=0; ri<dft->voiNr; ri++) if(dftCopyvoihdr(dft, ri, dft2, ri)) return 12;
365
366 /* Set new time frames and interpolate */
367 if(dft->timetype==DFT_TIME_STARTEND) {
368 for(fi=fj=0; fi<dft->frameNr; fi++, fj+=2) {
369 f=0.5*(dft->x1[fi]+dft->x2[fi]);
370 dft2->x1[fj]=dft->x1[fi]; dft2->x2[fj]=f;
371 dft2->x[fj]=0.5*(dft2->x1[fj]+dft2->x2[fj]);
372 dft2->x1[fj+1]=f; dft2->x2[fj+1]=dft->x2[fi];
373 dft2->x[fj+1]=0.5*(dft2->x1[fj+1]+dft2->x2[fj+1]);
374 for(ri=0; ri<dft->voiNr; ri++)
375 dft2->voi[ri].y[fj]=dft2->voi[ri].y[fj+1]=dft->voi[ri].y[fi];
376 }
377 ret=0;
378 } else {
379 for(fi=fj=0; fi<dft->frameNr; fi++) {
380 if(dft->x[fi]<=0.0) {
381 /* just copy, no doubles */
382 dft2->x[fj++]=dft->x[fi]; continue;
383 }
384 if(fi==0) f=0.5*dft->x[fi];
385 else f=0.5*(dft->x[fi-1]+dft->x[fi]);
386 dft2->x[fj++]=f; dft2->x[fj++]=dft->x[fi];
387 }
388 dft2->frameNr=fj;
389 for(ri=0, ret=0; ri<dft->voiNr; ri++) {
390 ret=interpolate(dft->x, dft->voi[ri].y, dft->frameNr,
391 dft2->x, dft2->voi[ri].y, NULL, NULL, dft2->frameNr);
392 if(ret) break;
393 }
394 }
395 if(ret) return 20+ret;
396 return 0;
397}

◆ dftEndtime()

double dftEndtime ( DFT * dft)

Get TAC end time. Sample times are assumed to be sorted to increasing order.

See also
imgEndtime, fittime_from_dft, getActualSamplenr
Returns
Returns the TAC end time, not converting the time units.
Parameters
dftPointer to DFT TAC structure.

Definition at line 315 of file fittime.c.

318 {
319 if(dft==NULL || dft->frameNr<1) return(0.0);
320 for(int fi=dft->frameNr-1; fi>=0; fi--) {
321 if(dft->timetype==DFT_TIME_MIDDLE) {
322 if(!isnan(dft->x[fi])) return(dft->x[fi]);
323 } else if(dft->timetype==DFT_TIME_STARTEND) {
324 if(!isnan(dft->x2[fi])) return(dft->x2[fi]);
325 } else if(dft->timetype==DFT_TIME_START) {
326 if(!isnan(dft->x[fi])) return(dft->x[fi]);
327 } else if(dft->timetype==DFT_TIME_END) {
328 if(!isnan(dft->x[fi])) return(dft->x[fi]);
329 } else
330 return(0.0);
331 }
332 return(0.0);
333}

Referenced by imgReadModelingData().

◆ dftInterpolate()

int dftInterpolate ( DFT * input,
DFT * tissue,
DFT * output,
char * status,
int verbose )

Interpolate (and integrate) TAC data to sample times that are given with another TAC data. PET frame lengths are taken into account if available in tissue DFT struct.

Input frame lengths are taken into account if the framing is same as with tissue data.

See also
dftInterpolateInto, dftTimeIntegral
Returns
Returns 0 if successful, and <>0 in case of an error.
Parameters
inputData which is interpolated; make sure that time unit is the same as in tissue data; time range is checked to cover the tissue data
tissueData to which (sample times) the interpolation is done
outputPointer to initiated DFT into which interpolated values and integrals will be written
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 162 of file dftint.c.

176 {
177 int fi, ri, ret;
178
179 if(verbose>0) printf("dftInterpolate()");
180
181 // Check the input
182 if(input==NULL || tissue==NULL || output==NULL) {
183 if(status!=NULL) sprintf(status, "program error");
184 return 1;
185 }
186
187 // If input and tissue data have the same frame times already, then
188 // copy frame times and timetype into input
189 if(tissue->timetype==DFT_TIME_STARTEND &&
190 check_times_dft_vs_dft(tissue, input, verbose)==1 &&
191 input->frameNr<=tissue->frameNr)
192 {
193 for(fi=0; fi<input->frameNr; fi++) {
194 input->x[fi]=tissue->x[fi];
195 input->x1[fi]=tissue->x1[fi]; input->x2[fi]=tissue->x2[fi];
196 }
197 input->timetype=tissue->timetype;
198 }
199
200 // Check that there is no need for excess extrapolation
201 ret=dftInterpolateCheckEnd(input, tissue, status, verbose);
202 if(ret<0) return 2;
203 ret=dftInterpolateCheckStart(input, tissue, status, verbose);
204 if(ret<0) return 2;
205
206 // Delete any previous output data
207 dftEmpty(output);
208
209 // Allocate memory for interpolated data
210 if(dftSetmem(output, tissue->frameNr, input->voiNr)) {
211 if(status!=NULL) strcpy(status, "memory allocation error");
212 return 3;
213 }
214 output->voiNr=input->voiNr; output->frameNr=tissue->frameNr;
215
216 // Copy header information
217 dftCopymainhdr(input, output);
218 for(ri=0; ri<input->voiNr; ri++) dftCopyvoihdr(input, ri, output, ri);
219
220 // Copy frame information
221 output->isweight=tissue->isweight;
222 for(fi=0; fi<tissue->frameNr; fi++) {
223 output->x[fi]=tissue->x[fi];
224 output->x1[fi]=tissue->x1[fi]; output->x2[fi]=tissue->x2[fi];
225 output->w[fi]=tissue->w[fi];
226 }
227 output->timetype=tissue->timetype;
228
229 // Check if input and tissue data do have the same frame times already
230 if(check_times_dft_vs_dft(tissue, input, verbose)==1 &&
231 input->frameNr>=tissue->frameNr)
232 {
233 // copy the values directly and integrate in place
234 for(ri=0, ret=0; ri<output->voiNr && ret==0; ri++) {
235 for(fi=0; fi<tissue->frameNr; fi++)
236 output->voi[ri].y[fi]=input->voi[ri].y[fi];
237 if(output->timetype==3)
238 ret=petintegral(output->x1, output->x2, output->voi[ri].y,
239 output->frameNr, output->voi[ri].y2, output->voi[ri].y3);
240 else
241 ret=interpolate(output->x, output->voi[ri].y, output->frameNr,
242 output->x, output->voi[ri].y, output->voi[ri].y2,
243 output->voi[ri].y3, output->frameNr);
244 }
245 if(ret) {
246 if(status!=NULL) sprintf(status, "cannot interpolate (%d)", ret);
247 dftEmpty(output); return 5;
248 }
249 return 0; // that's it then
250 }
251
252 // Interpolate and integrate input data to tissue sample times,
253 // taking into account tissue frame lengths if available
254 for(ri=0, ret=0; ri<output->voiNr && ret==0; ri++) {
255 if(output->timetype==DFT_TIME_STARTEND)
256 ret=interpolate4pet(input->x, input->voi[ri].y, input->frameNr,
257 output->x1, output->x2, output->voi[ri].y, output->voi[ri].y2,
258 output->voi[ri].y3, output->frameNr);
259 else
260 ret=interpolate(input->x, input->voi[ri].y, input->frameNr,
261 output->x, output->voi[ri].y, output->voi[ri].y2,
262 output->voi[ri].y3, output->frameNr);
263 }
264 if(ret) {
265 if(status!=NULL) sprintf(status, "cannot interpolate (%d)", ret);
266 dftEmpty(output); return 6;
267 }
268
269 return 0;
270}
int dftInterpolateCheckStart(DFT *input, DFT *output, char *status, int verbose)
Definition dftint.c:17
int dftInterpolateCheckEnd(DFT *input, DFT *output, char *status, int verbose)
Definition dftint.c:82
int check_times_dft_vs_dft(DFT *dft1, DFT *dft2, int verbose)
Definition fittime.c:169
int petintegral(double *x1, double *x2, double *y, int nr, double *ie, double *iie)
Integrate PET TAC data to frame mid times.
Definition integr.c:771
double * w
double * y2
double * y3

Referenced by dftReadinput().

◆ dftInterpolateCheckEnd()

int dftInterpolateCheckEnd ( DFT * input,
DFT * output,
char * status,
int verbose )

Verify that data to-be-interpolated does not need too much extrapolation in the end, and that samples are not too sparse.

Time units in DFTs can be different, if specified.

See also
dftInterpolateCheckStart, dftInterpolateInto, dftInterpolate
Returns
Returns 0 if data is fine, 1 if extrapolation can be done, but there may be too few samples, and -1 if extrapolation in the end is impossible.
Parameters
inputData that will be verified for reliable interpolation
outputData containing sample times for interpolated data
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 82 of file dftint.c.

92 {
93 int fi, n, itunit;
94 double t1, t2;
95
96 if(verbose>0) printf("dftInterpolateCheckEnd()\n");
97
98 // Check the input
99 if(status!=NULL) sprintf(status, "program error");
100 if(input==NULL || output==NULL) return -1;
101 if(input->frameNr<1 || output->frameNr<1) return -1;
102 if(input->frameNr==1 && output->frameNr>1) {
103 if(status!=NULL) sprintf(status, "too short data for interpolation");
104 return -1;
105 }
106 if(status!=NULL) sprintf(status, "ok");
107
108 /* Try to make sure that time units are the same */
109 dftMatchTimeunits(output, input, &itunit, verbose);
110
111 /* Check that input data extends almost to the end of output range */
112 if(input->timetype==DFT_TIME_STARTEND && output->timetype==DFT_TIME_STARTEND) {
113 t1=input->x2[input->frameNr-1]; t2=output->x2[output->frameNr-1];
114 } else {
115 t1=input->x[input->frameNr-1]; t2=output->x[output->frameNr-1];
116 }
117 if(t1<0.95*t2) {
118 if(status!=NULL) strcpy(status, "too short data for interpolation");
119 if(verbose>1) printf("t1 := %g\nt2 := %g\n", t1, t2);
120 dftTimeunitConversion(input, itunit); // back to original time units
121 return -1;
122 }
123
124 /* Check that input sample frequency is not too low in the end */
125 if(output->frameNr>3) {
126 if(output->timetype==DFT_TIME_STARTEND) {
127 t1=output->x1[output->frameNr-3];
128 t2=output->x2[output->frameNr-1];
129 } else {
130 t1=output->x[output->frameNr-3];
131 t2=output->x[output->frameNr-1];
132 }
133 for(fi=n=0; fi<input->frameNr; fi++)
134 if(input->x[fi]>=t1 && input->x[fi]<=t2) n++;
135 if(n<1 || (n<2 && t2>input->x[input->frameNr-1])) {
136 if(status!=NULL) strcpy(status, "too sparse sampling for interpolation");
137 if(verbose>1) printf("n=%d t1=%g t2=%g\n", n, t1, t2);
138 dftTimeunitConversion(input, itunit); // back to original time units
139 return -1; // Error
140 }
141 if(n<2 || (n<3 && t2>input->x[input->frameNr-1])) {
142 if(status!=NULL) strcpy(status, "too sparse sampling for interpolation");
143 if(verbose>1) printf("n=%d t1=%g t2=%g\n", n, t1, t2);
144 dftTimeunitConversion(input, itunit); // back to original time units
145 return 1; // Warning
146 }
147 }
148 dftTimeunitConversion(input, itunit); // back to original time units
149 return 0;
150}
int dftTimeunitConversion(DFT *dft, int tunit)
Definition dftunit.c:119
int dftMatchTimeunits(DFT *dft1, DFT *dft2, int *tunit2, int verbose)
Definition fittime.c:358

Referenced by dftInterpolate(), dftInterpolateForIMG(), and dftInterpolateInto().

◆ dftInterpolateCheckStart()

int dftInterpolateCheckStart ( DFT * input,
DFT * output,
char * status,
int verbose )

Verify that data to-be-interpolated does not need too much extrapolation in the beginning.

See also
dftInterpolateCheckEnd, dftInterpolate, dftInterpolateInto, dftTimeIntegral
Returns
Returns 0 if data is fine, 1 if it starts late but extrapolation can be done reliably, and -1 if extrapolation in the beginning would be too risky.
Parameters
inputData that will be verified for reliable interpolation
outputData containing sample times for interpolated data
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 17 of file dftint.c.

27 {
28 int ri, itunit;
29 double t1, t2, f;
30
31 if(verbose>0) printf("dftInterpolateCheckStart()\n");
32
33 // Check the input
34 if(status!=NULL) sprintf(status, "program error");
35 if(input==NULL || output==NULL) return -1;
36 if(input->frameNr<1 || output->frameNr<1) return -1;
37 if(input->frameNr==1 && output->frameNr>1) {
38 if(status!=NULL) sprintf(status, "too short data for interpolation");
39 return -1;
40 }
41 if(status!=NULL) sprintf(status, "ok");
42
43 /* Try to make sure that time units are the same */
44 dftMatchTimeunits(output, input, &itunit, verbose);
45
46 /* Check the start */
48 t1=input->x1[0]; t2=output->x1[0];
49 } else {
50 t1=input->x[0]; t2=output->x[0];
51 }
52 if(0.95*t1>t2) {
53 if(verbose>1) printf("t1 := %g\nt2 := %g\n", t1, t2);
54 /* Check that first value is relatively low, so that there will not be any
55 error when the initial part is assumed to be a straight line from
56 (0,0) to the first sample point */
57 f=0.25*dft_kBqMax(input);
58 for(ri=0; ri<input->voiNr; ri++) if(input->voi[ri].y[0] > f) {
59 if(status!=NULL) strcpy(status, "data starts too late");
60 dftTimeunitConversion(input, itunit); // back to original time units
61 return -1;
62 }
63 if(status!=NULL) strcpy(status, "data starts late");
64 dftTimeunitConversion(input, itunit); // back to original time units
65 return 1;
66 }
67 dftTimeunitConversion(input, itunit); // back to original time units
68 return 0;
69}
double dft_kBqMax(DFT *data)
Definition dft.c:1148

Referenced by dftInterpolate(), dftInterpolateForIMG(), and dftInterpolateInto().

◆ dftInterpolateForIMG()

int dftInterpolateForIMG ( DFT * input,
IMG * img,
int frame_nr,
DFT * output,
double * ti1,
double * ti2,
int verbose,
char * status )

Interpolate (and integrate) TAC data to sample times that are given with IMG data. Input frame lengths are taken into account if they are available in DFT or if the framing is the same as in IMG data.

Returns
Returns 0 if successful, and <>0 in case of an error.
Parameters
inputData which is interpolated.
imgData to which (sample times) the interpolation is done.
frame_nrNumber of IMG frames that are needed; can be set to 0 if all frames can be included.
outputPointer to initiated DFT into which interpolated values and integrals will be written at input sample times and units.
ti1First time of input data before interpolation (in input time units); use this to check that required time range was measured; NULL if not needed.
ti2Last time of input data before interpolation (in input time units); use this to check that required time range was measured; NULL if not needed.
verboseVerbose level; set to zero to not to print any comments.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 17 of file misc_model.c.

38 {
39 /* Check input */
40 if(verbose>0) {
41 printf("%s(*inp, *img, %d, *out, *ti1, *ti2, %d, status)\n", __func__, frame_nr, verbose);
42 fflush(stdout);
43 }
44 if(input==NULL || img==NULL || output==NULL) {
45 if(status!=NULL) strcpy(status, "program error");
46 return 1;
47 }
48 if(input->frameNr<1 || input->voiNr<1 || img->dimt<1) {
49 if(status!=NULL) strcpy(status, "no pet data");
50 return 2;
51 }
52 if(input->timeunit!=TUNIT_MIN && input->timeunit!=TUNIT_SEC) {
53 if(status!=NULL) strcpy(status, "unknown time units");
54 return 3;
55 }
56 if(frame_nr<1 || frame_nr>img->dimt) frame_nr=img->dimt;
57 /* Set ti1 and ti2 */
58 if(ti1!=NULL) {
59 if(input->timetype==DFT_TIME_STARTEND)
60 *ti1=input->x1[0]; else *ti1=input->x[0];
61 }
62 if(ti2!=NULL) {
63 if(input->timetype==DFT_TIME_STARTEND) *ti2=input->x2[input->frameNr-1];
64 else *ti2=input->x[input->frameNr-1];
65 }
66
67 /* Delete any previous data */
68 dftEmpty(output);
69
70 /* Allocate memory for interpolated data */
71 if(verbose>10) printf("allocating memory for interpolated data\n");
72 if(dftAllocateWithHeader(output, frame_nr, input->voiNr, input)) {
73 if(status!=NULL) strcpy(status, "memory allocation error");
74 return 11;
75 }
76 output->voiNr=input->voiNr; output->frameNr=frame_nr;
77
78 /* Set output times */
79 if(copy_times_from_img_to_dft(img, output, verbose)!=0) {
80 if(status!=NULL) strcpy(status, "frame time error");
81 dftEmpty(output); return 12;
82 }
83 if(verbose>10) {
84 printf("time range := %g - %g %s\n", output->x[0],
85 output->x[output->frameNr-1], petTunit(output->timeunit));
86 printf(" timetype := %d\n", output->timetype);
87 }
88
89 // Check if input and output data do have the same frame times already
90 if(check_times_dft_vs_dft(input, output, verbose)==1 && input->frameNr>=output->frameNr) {
91 // copy the values directly and integrate in place
92 if(verbose>10) printf("frame times are assumed to be the same\n");
93 int ret=0;
94 for(int ri=0; ri<output->voiNr && ret==0; ri++) {
95 for(int fi=0; fi<output->frameNr; fi++)
96 output->voi[ri].y[fi]=input->voi[ri].y[fi];
97 ret=petintegral(output->x1, output->x2, output->voi[ri].y,
98 output->frameNr, output->voi[ri].y2, output->voi[ri].y3);
99 }
100 if(ret) {
101 if(status!=NULL) sprintf(status, "cannot interpolate (%d)", ret);
102 dftEmpty(output); return 15;
103 }
104 return 0; // that's it then
105 }
106 if(verbose>10) printf("frame times are not the same\n");
107
108 // Check that there is no need for extrapolation in the start
109 if(dftInterpolateCheckStart(input, output, status, verbose)<0) {
110 dftEmpty(output); return 16;
111 }
112 // Check that there is no need for excess extrapolation in the end either
113 if(dftInterpolateCheckEnd(input, output, status, verbose)<0) {
114 dftEmpty(output); return 17;
115 }
116
117 // Interpolate and integrate input data to tissue sample times,
118 // taking into account tissue frame lengths
119 {
120 int ret=0;
121 for(int ri=0; ri<output->voiNr && ret==0; ri++) {
122 ret=interpolate4pet(input->x, input->voi[ri].y, input->frameNr,
123 output->x1, output->x2, output->voi[ri].y, output->voi[ri].y2,
124 output->voi[ri].y3, output->frameNr);
125 }
126 if(ret) {
127 if(status!=NULL) sprintf(status, "cannot interpolate (%d)", ret);
128 dftEmpty(output); return 18;
129 }
130 }
131
132 return 0;
133}
int dftAllocateWithHeader(DFT *dft, int frameNr, int voiNr, DFT *dft_from)
Definition dft.c:702
int copy_times_from_img_to_dft(IMG *img, DFT *dft, int verbose)
Definition fittime.c:246

Referenced by imgReadModelingData().

◆ dftInterpolateInto()

int dftInterpolateInto ( DFT * inp,
DFT * tis,
char * status,
int verbose )

Interpolate (and integrate) TAC data to sample times that are given with another TAC data. New TAC is written into existing TAC data. PET frame lengths are taken into account if available in tissue DFT struct. Input frame lengths are taken into account if the framing is same as with tissue data.

See also
dftTimeIntegral, dftInterpolate, dftInterpolateCheckStart, dftInterpolateCheckEnd
Returns
Returns 0 if successful, and <>0 in case of an error.
Parameters
inpData which is interpolated; make sure that time unit is the same as in tissue data; time range is checked to cover the tissue data
tisData into which the interpolation is done
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 281 of file dftint.c.

292 {
293 int fi, ri, ret;
294
295 if(verbose>0) printf("dftInterpolateInto()\n");
296
297 // Check the input
298 if(inp==NULL || tis==NULL) {
299 if(status!=NULL) sprintf(status, "program error");
300 return 1;
301 }
302 ret=dft_nr_of_NA(inp); if(ret>0) {
303 if(status!=NULL) sprintf(status, "missing sample(s)");
304 return 2;
305 }
306
307 // Check that there is no need for excess extrapolation
308 ret=dftInterpolateCheckEnd(inp, tis, status, verbose);
309 if(ret<0) return 3;
310 ret=dftInterpolateCheckStart(inp, tis, status, verbose);
311 if(ret<0) return 4;
312
313 // Allocate memory for interpolated data
314 if(dftAddmem(tis, inp->voiNr)) {
315 if(status!=NULL) strcpy(status, "memory allocation error");
316 return 5;
317 }
318
319 // Copy header information
320 for(ri=0; ri<inp->voiNr; ri++)
321 dftCopyvoihdr(inp, ri, tis, tis->voiNr+ri);
322
323 // Check if input and tissue data do have the same frame times already
324 if(check_times_dft_vs_dft(inp, tis, verbose)==1 &&
325 inp->frameNr>=tis->frameNr)
326 {
327 // copy the values directly and integrate in place
328 for(ri=0, ret=0; ri<inp->voiNr && ret==0; ri++) {
329 for(fi=0; fi<tis->frameNr; fi++)
330 tis->voi[tis->voiNr+ri].y[fi]=inp->voi[ri].y[fi];
332 ret=petintegral(tis->x1, tis->x2, tis->voi[tis->voiNr+ri].y,
333 tis->frameNr, tis->voi[tis->voiNr+ri].y2,
334 tis->voi[tis->voiNr+ri].y3);
335 else
336 ret=interpolate(tis->x, tis->voi[tis->voiNr+ri].y, tis->frameNr,
337 tis->x, tis->voi[tis->voiNr+ri].y,
338 tis->voi[tis->voiNr+ri].y2,
339 tis->voi[tis->voiNr+ri].y3, tis->frameNr);
340 }
341 if(ret) {
342 if(status!=NULL) sprintf(status, "cannot interpolate (%d)", ret);
343 dftEmpty(tis); return 7;
344 }
345 tis->voiNr+=inp->voiNr;
346 return 0; // that's it then
347 }
348
349 // Interpolate and integrate input data to tissue sample times,
350 // taking into account tissue frame lengths if available
351 for(ri=0, ret=0; ri<inp->voiNr && ret==0; ri++) {
353 ret=interpolate4pet(inp->x, inp->voi[ri].y, inp->frameNr,
354 tis->x1, tis->x2, tis->voi[tis->voiNr+ri].y,
355 tis->voi[tis->voiNr+ri].y2,
356 tis->voi[tis->voiNr+ri].y3, tis->frameNr);
357 else
358 ret=interpolate(inp->x, inp->voi[ri].y, inp->frameNr,
359 tis->x, tis->voi[tis->voiNr+ri].y,
360 tis->voi[tis->voiNr+ri].y2,
361 tis->voi[tis->voiNr+ri].y3, tis->frameNr);
362 }
363 if(ret) {
364 if(status!=NULL) sprintf(status, "cannot interpolate (%d)", ret);
365 return 9;
366 }
367 tis->voiNr+=inp->voiNr;
368
369 return 0;
370}
int dftAddmem(DFT *dft, int voiNr)
Definition dft.c:107
int dft_nr_of_NA(DFT *dft)
Definition dft.c:905

Referenced by dftReadModelingData(), dftReadReference(), and imgReadModelingData().

◆ dftMatchTimeunits()

int dftMatchTimeunits ( DFT * dft1,
DFT * dft2,
int * tunit2,
int verbose )

Make sure that time units in two DFT structs are the same, converting units when necessary, optionally saving original units so that units can be converted back to what they were using dftTimeunitConversion().

See also
dftTimeunitConversion, dftEndtime, fittime_from_dft
Returns
Returns 0 if the was no need for time unit conversion, 1 if time units in dft2 were converted, and <0 if units were not identified or in case of an error.
Parameters
dft1Pointer to DFT struct 1.
dft2Pointer to DFT struct 2; sample time units are changed to match the data in dft1.
tunit2Pointer for original time unit in DFT 2; enter NULL if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 358 of file fittime.c.

367 {
368 if(verbose>0) printf("%s()\n", __func__);
369 if(dft1==NULL || dft2==NULL) return(-1);
370 /* Save original units if required */
371 if(tunit2!=NULL) *tunit2=dft2->timeunit;
372 /* Check that time units are available */
373 if(dft1->timeunit!=TUNIT_MIN && dft1->timeunit!=TUNIT_SEC) {
374 if(verbose>0) printf(" unknown time units in dft1\n");
375 return(-2);
376 }
377 if(dft2->timeunit!=TUNIT_MIN && dft2->timeunit!=TUNIT_SEC) {
378 if(verbose>0) printf(" unknown time units in dft2\n");
379 return(-3);
380 }
381 /* Check if they are the same */
382 if(dft1->timeunit==dft2->timeunit) {
383 if(verbose>1) printf(" time units are the same in dft1 and dft2.\n");
384 return(0);
385 }
386 /* Conversion to dft2 */
387 if(verbose>1) printf(" time units in dft2 converted from %s to %s\n",
388 petTunit(dft2->timeunit), petTunit(dft1->timeunit));
389 int ret=dftTimeunitConversion(dft2, dft1->timeunit);
390 if(ret) {
391 if(verbose>0) printf(" time unit conversion failed\n");
392 return(-10-ret);
393 }
394 return(1);
395}

Referenced by dftInterpolateCheckEnd(), and dftInterpolateCheckStart().

◆ dftReadinput()

int dftReadinput ( DFT * input,
DFT * tissue,
char * filename,
int * filetype,
double * ti1,
double * ti2,
int verifypeak,
char * status,
int verbose )

Read DFT format input TAC data to match the time frames in the specified tissue DFT file. Instead of input filename, a reference region name can be given: then all the matching tacs (based on roi names) are moved from the roi data to the input data, with the best match as first tac. Input data is interpolated (if necessary) and also integrated to y2[]. Input time and concentration units are tried to be converted to be the same as in tissue data.

Returns
Returns 0 if successful, and >0 in case of an error, and specifically 101 in case input TAC is not valid.
See also
dftReadReference, dftRead, dftReadModelingData, dftVerifyPeak, imgReadModelingData
Parameters
inputInput data, previous contents are cleared.
tissuePET data containing frames and possible input regions.
filenameInput data filename, or region name in PET data.
filetypeType of input, as found out here; 1 and 2 =tac, 3=fit, 5=region name; enter NULL, if not needed.
ti1First time of input data before interpolation (in tissue time units); use this to check that required time range was measured; NULL if not needed.
ti2Last time of input data before interpolation (in tissue time units); use this to check that required time range was measured; NULL if not needed.
verifypeakSet to <>0 to verify that input TAC does not start too late and has decent peak to provide reliable AUC0-T.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 25 of file dftinput.c.

49 {
50 int ri, n, ret, ftype=0;
51 DFT temp;
52 FILE *fp;
53
54 if(verbose>0) printf("dftReadinput(inp, tis, %s, type, ti1, ti2, %d, status, %d)\n",
55 filename, verifypeak, verbose);
56 if(filetype!=NULL) *filetype=0;
57
58 /* Check that PET data is ok */
59 if(input==NULL || tissue==NULL || filename==NULL) {
60 if(status!=NULL) strcpy(status, "program error");
61 return 1;
62 }
63 if(tissue->frameNr<1 || tissue->voiNr<1) {
64 if(status!=NULL) strcpy(status, "no pet data");
65 return 2;
66 }
67
68 /* Delete any previous input data and initiate temp data */
69 dftEmpty(input); dftInit(&temp);
70
71 /* Try to figure out what is the 'filename' */
72 ftype=0;
73 /* Can we open it as a file? */
74 fp=fopen(filename, "r");
75 if(fp!=NULL) {
76 /* File can be opened for read; close it for now */
77 if(verbose>1) printf(" file can be opened for reading.\n");
78 if(filetype!=NULL) *filetype=1;
79 fclose(fp);
80
81 /* Try to identify the file format */
82 ftype=dftFormat(filename);
83 if(ftype==DFT_FORMAT_UNKNOWN) {
84 if(filetype!=NULL) *filetype=0;
85 if(status!=NULL) strcpy(status, "unknown file format");
86 return 3;
87 } else if(ftype==DFT_FORMAT_FIT) {
88 if(filetype!=NULL) *filetype=3;
89 if(status!=NULL) strcpy(status, "cannot read fit file");
90 return 3;
91 }
92 if(verbose>2) printf(" fileformat=%d\n", ftype);
93
94 /* Try to read it */
95 if((ret=dftRead(filename, &temp))!=0) {
96 if(filetype!=NULL) *filetype=0;
97 if(status!=NULL) sprintf(status, "cannot read file (%d)", ret);
98 return(2);
99 }
100 /* Convert input time units to the same as in tissue data */
101 (void)dftTimeunitConversion(&temp, tissue->timeunit);
102 /* Check the tissue and plasma TAC concentration units */
103 ret=dftUnitConversion(&temp, petCunitId(tissue->unit));
104 if(ret!=0) {sprintf(status, "check the units of input and tissue data");}
105 /* Tell user what was the original input time range */
106 if(temp.timetype==DFT_TIME_STARTEND) {
107 if(ti1!=NULL) *ti1=temp.x1[0];
108 if(ti2!=NULL) *ti2=temp.x2[temp.frameNr-1];
109 } else {
110 if(ti1!=NULL) *ti1=temp.x[0];
111 if(ti2!=NULL) *ti2=temp.x[temp.frameNr-1];
112 }
113 /* Verify the peak if requested */
114 if(verifypeak!=0) {
115 ret=dftVerifyPeak(&temp, 0, verbose-2, status);
116 //if(ret!=0) sprintf(status, "input TAC should start at time zero");
117 if(ret>0) {dftEmpty(&temp); return 101;}
118 }
119 /* Interpolate and integrate data to pet times */
120 ret=dftInterpolate(&temp, tissue, input, status, verbose);
121 dftEmpty(&temp);
122 if(ret!=0) return 4;
123
124 } else {
125
126 /* it's not a file, at least an accessible file, but is it a region name? */
127 if(filetype!=NULL) *filetype=5;
128 /* Select ROIs that match the specified input name */
129 n=dftSelectRegions(tissue, filename, 1);
130 if(n<=0) {
131 if(status!=NULL) sprintf(status, "cannot find region");
132 return 7;
133 }
134 if(n==tissue->voiNr) {
135 if(status!=NULL) sprintf(status, "all regions do match");
136 return 8;
137 }
138 /* one or more regions was found ; move them to input data */
139 ret=dftdup(tissue, input); if(ret==0) {
140 ri=0; ret=0; while(ri<input->voiNr && ret==0) {
141 if(input->voi[ri].sw==0) ret=dftDelete(input, ri); else ri++;
142 }
143 if(ret==0) {
144 ri=0; ret=0; while(ri<tissue->voiNr && ret==0) {
145 if(tissue->voi[ri].sw!=0) ret=dftDelete(tissue, ri); else ri++;
146 }
147 }
148 }
149 if(ret!=0) {
150 if(status!=NULL) sprintf(status, "cannot separate input regions");
151 dftEmpty(input); return 9;
152 }
153 /* Try to select the best reference ROI */
154 ri=dftSelectBestReference(input); if(ri<0) {
155 if(status!=NULL) sprintf(status, "cannot separate input regions");
156 dftEmpty(input); return 10;
157 }
158 /* And move it to the first place */
159 if(ri>0) {dftMovevoi(input, ri, 0); ri=0;}
160 if(verbose>1) printf("selected ref region := %s\n", input->voi[0].name);
161 /* Verify the peak if requested */
162 if(verifypeak!=0) {
163 ret=dftVerifyPeak(input, 0, verbose-2, status);
164 //if(ret!=0) sprintf(status, "input TAC should start at time zero");
165 if(ret>0) {dftEmpty(input); return 101;}
166 }
167
168 /* Calculate integrals */
169 for(ri=0; ri<input->voiNr; ri++) {
170 if(input->timetype==DFT_TIME_STARTEND) {
171 ret=petintegral(input->x1, input->x2, input->voi[ri].y, input->frameNr,
172 input->voi[ri].y2, input->voi[ri].y3);
173 if(ti1!=NULL) *ti1=input->x1[0];
174 if(ti2!=NULL) *ti2=input->x2[input->frameNr-1];
175 } else {
176 ret=interpolate(input->x, input->voi[ri].y, input->frameNr,
177 input->x, NULL, input->voi[ri].y2, input->voi[ri].y3, input->frameNr);
178 if(ti1!=NULL) *ti1=input->x[0];
179 if(ti2!=NULL) *ti2=input->x[input->frameNr-1];
180 }
181 if(ret) {
182 if(status!=NULL) sprintf(status, "cannot integrate input");
183 dftEmpty(input); return(11);
184 }
185 }
186 }
187
188 return(0);
189}
void dftInit(DFT *data)
Definition dft.c:38
int dftdup(DFT *dft1, DFT *dft2)
Definition dft.c:655
int dftMovevoi(DFT *dft, int from, int to)
Definition dft.c:508
int dftSelectBestReference(DFT *dft)
Definition dft.c:314
int dftDelete(DFT *dft, int voi)
Definition dft.c:538
int dftSelectRegions(DFT *dft, char *region_name, int reset)
Definition dft.c:285
int dftVerifyPeak(DFT *dft, int index, int verbose, char *status)
Definition dftinput.c:747
int dftInterpolate(DFT *input, DFT *tissue, DFT *output, char *status, int verbose)
Definition dftint.c:162
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
int dftFormat(char *fname)
Definition dftio.c:422
#define DFT_FORMAT_FIT
#define DFT_FORMAT_UNKNOWN
char sw

◆ dftReadModelingData()

int dftReadModelingData ( char * tissuefile,
char * inputfile1,
char * inputfile2,
char * inputfile3,
double * fitdur,
int * fitframeNr,
DFT * tis,
DFT * inp,
FILE * loginfo,
int verbose,
char * status )

Read tissue and input data for modeling. Time units are converted to min and input calibration units to units of tissue data. Input data is NOT interpolated to tissue times. If input data extends much further than fit duration, the last part is removed to save computation time in simulations. Input data is verified not to end too early, and not to start too late.

Returns
Returns 0 when successful, otherwise a non-zero value.
See also
dftReadReference, dftRead, dftReadinput, imgReadModelingData
Parameters
tissuefileTissue data filename; one time sample is sufficient here.
inputfile11st input data filename.
inputfile22nd input data filename (or NULL if only not needed).
inputfile33rd input data filename (or NULL if only not needed).
fitdurFit duration (in minutes); shortened if longer than tissue data.
fitframeNrNr of time frames (samples) in tissue data that are inside fitdur will be written here.
tisPointer to initiated DFT into which tissue data will be written.
inpPointer to initiated DFT into which input data (plasma and/or blood) will be written.
loginfoGive file pointer (for example stdout) where log information is printed; NULL if not needed; warnings will be printed in stderr anyway.
verboseVerbose level; if zero, then only warnings are printed into stderr.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 342 of file dftinput.c.

367 {
368 int ret, fi, n, first, last, ii, input_nr=0;
369 DFT tmpdft;
370 double f, starttime, endtime;
371 FILE *wfp;
372 char *fname;
373
374
375 if(loginfo!=NULL && verbose>0) {
376 fprintf(loginfo, "dftReadModelingData(\n");
377 fprintf(loginfo, " %s,\n", tissuefile);
378 fprintf(loginfo, " %s,\n", inputfile1);
379 fprintf(loginfo, " %s,\n", inputfile2);
380 fprintf(loginfo, " %s,\n", inputfile3);
381 fprintf(loginfo, " %g,\n", *fitdur);
382 fprintf(loginfo, " *fitframeNr, *tis, *inp, *loginfo, %d, *status\n", verbose);
383 fprintf(loginfo, ")\n");
384 }
385 /* Check the input */
386 if(status!=NULL) sprintf(status, "program error");
387 if(tis==NULL || inp==NULL) return -1;
388 if(tissuefile==NULL || strlen(tissuefile)<1) return -2;
389 ret=0;
390 if(inputfile1==NULL || strlen(inputfile1)<1) return -3; else input_nr++;
391 if(inputfile2!=NULL && strlen(inputfile2)>0) input_nr++;
392 if(inputfile3!=NULL && strlen(inputfile3)>0) {
393 if(input_nr<2) return -4;
394 input_nr++;
395 }
396 if(status!=NULL) sprintf(status, "arguments validated");
397 /* Warnings will be printed into stderr */
398 wfp=stderr;
399
400 /* Delete any previous data and initiate temp data */
401 dftEmpty(inp); dftEmpty(tis); dftInit(&tmpdft);
402
403 /*
404 * Read tissue data
405 */
406 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading tissue data in %s\n", tissuefile);
407 if(dftRead(tissuefile, tis)) {
408 if(status!=NULL) sprintf(status, "cannot read '%s': %s", tissuefile, dfterrmsg);
409 return(2);
410 }
411 /* Check for NaN's */
412 ret=dft_nr_of_NA(tis); if(ret>0) {
413 if(status!=NULL) sprintf(status, "missing sample(s) in %s", tissuefile);
414 dftEmpty(tis); return(2);
415 }
416 /* Sort the data by increasing sample times */
417 dftSortByFrame(tis);
418 /* Do not check frame number; static scan is fine here */
419 /* Make sure that there is no overlap in frame times */
420 if(tis->timetype==DFT_TIME_STARTEND) {
421 if(loginfo!=NULL && verbose>0)
422 fprintf(loginfo, "checking frame overlap in %s\n", tissuefile);
423 ret=dftDeleteFrameOverlap(tis);
424 if(ret) {
425 if(status!=NULL) sprintf(status, "%s has overlapping frame times", tissuefile);
426 dftEmpty(tis); return(2);
427 }
428 }
429 if(tis->timeunit==TUNIT_UNKNOWN) {
430 fprintf(wfp, "Warning: tissue sample time units not known.\n");
431 }
432
433 /*
434 * Read first input data
435 */
436 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading input data in %s\n", inputfile1);
437 if(dftRead(inputfile1, inp)) {
438 if(status!=NULL) sprintf(status, "cannot read '%s': %s", inputfile1, dfterrmsg);
439 dftEmpty(tis); return(3);
440 }
441 /* Check and correct the sample time unit */
442 if(tis->timeunit==TUNIT_UNKNOWN) tis->timeunit=inp->timeunit;
443 else if(inp->timeunit==TUNIT_UNKNOWN) inp->timeunit=tis->timeunit;
444 if(inp->timeunit==TUNIT_UNKNOWN) {
445 fprintf(wfp, "Warning: input sample time units not known.\n");
446 }
447 if(tis->timeunit!=inp->timeunit &&
448 dftTimeunitConversion(inp, tis->timeunit)!=0) {
449 if(status!=NULL) sprintf(status, "tissue and plasma do have different time units");
450 dftEmpty(tis); dftEmpty(inp);
451 return(3);
452 }
453 if(inp->voiNr>1) {
454 fprintf(wfp, "Warning: using only first TAC in %s\n", inputfile1);
455 inp->voiNr=1;
456 }
457 if(inp->frameNr<4) {
458 if(status!=NULL) sprintf(status, "%s contains too few samples", inputfile1);
459 dftEmpty(tis); dftEmpty(inp); return(3);
460 }
461 /* Sort the data by increasing sample times */
462 dftSortByFrame(inp);
463
464 /*
465 * Read following input files, if required
466 */
467 for(ii=2; ii<=input_nr; ii++) {
468 if(ii==2) fname=inputfile2;
469 else fname=inputfile3;
470
471 /* Make room for one more curve in input data */
472 ret=dftAddmem(inp, 1);
473 if(ret) {
474 if(status!=NULL) sprintf(status, "cannot allocate more memory");
475 dftEmpty(tis); dftEmpty(inp); return(4);
476 }
477
478 /* Read blood data */
479 dftInit(&tmpdft);
480 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading input data in %s\n", fname);
481 if(dftRead(fname, &tmpdft)) {
482 if(status!=NULL) sprintf(status, "cannot read '%s': %s", fname, dfterrmsg);
483 dftEmpty(tis); dftEmpty(inp); return(4);
484 }
485 if(tmpdft.frameNr<4) {
486 if(status!=NULL) sprintf(status, "%s contains too few samples", fname);
487 dftEmpty(tis); dftEmpty(inp); dftEmpty(&tmpdft); return(4);
488 }
489
490 /* Check and correct the sample time unit */
491 if(tis->timeunit==TUNIT_UNKNOWN) tis->timeunit=tmpdft.timeunit;
492 else if(tmpdft.timeunit==TUNIT_UNKNOWN) tmpdft.timeunit=tis->timeunit;
493 if(tmpdft.timeunit==TUNIT_UNKNOWN) {
494 fprintf(wfp, "Warning: blood sample time units not known.\n");
495 }
496 if(inp->timeunit!=tmpdft.timeunit &&
497 dftTimeunitConversion(&tmpdft, inp->timeunit)!=0) {
498 if(status!=NULL) sprintf(status, "two input data are in different time units");
499 dftEmpty(tis); dftEmpty(inp); dftEmpty(&tmpdft);
500 return(4);
501 }
502 /* Sort the data by increasing sample times */
503 dftSortByFrame(&tmpdft);
504
505 /* Copy to input data */
506 if(tmpdft.voiNr>1) {
507 fprintf(wfp, "Warning: using only first TAC in %s\n", fname);
508 tmpdft.voiNr=1;
509 }
510 if(loginfo!=NULL && verbose>1)
511 fprintf(loginfo, "interpolating %d samples into %d samples.\n",
512 tmpdft.frameNr, inp->frameNr);
513 ret=dftInterpolateInto(&tmpdft, inp, status, verbose);
514 if(ret) {
515 if(loginfo!=NULL && verbose>0)
516 fprintf(loginfo, "dftInterpolateInto() := %d\n", ret);
517 dftEmpty(tis); dftEmpty(inp); dftEmpty(&tmpdft); return(4);
518 }
519 /* Remove the originally read blood data */
520 dftEmpty(&tmpdft);
521
522 } // next input file
523
524 /* Set time unit to min */
525 if(loginfo!=NULL && verbose>1)fprintf(loginfo, "setting time units to min.\n");
526 ret=dftTimeunitConversion(tis, TUNIT_MIN); if(ret)
527 fprintf(wfp, "Warning: check that regional data times are in minutes.\n");
528 ret=dftTimeunitConversion(inp, TUNIT_MIN); if(ret)
529 fprintf(wfp, "Warning: check that input data times are in minutes.\n");
530
531 /*
532 * Check the input data
533 */
534 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "checking input data\n");
535 if(inp->frameNr<4) {
536 if(status!=NULL) sprintf(status, "%s contains too few samples", inputfile1);
537 dftEmpty(tis); dftEmpty(inp); return(4);
538 }
539 /* Check for NaN's */
540 ret=dft_nr_of_NA(inp); if(ret>0) {
541 if(status!=NULL) sprintf(status, "missing sample(s) in data");
542 dftEmpty(tis); dftEmpty(inp); return(4);
543 }
544 /* Check that input and tissue time ranges are about the same */
545 if(tis->x[tis->frameNr-1]>10.0*inp->x[inp->frameNr-1] ||
546 tis->x[tis->frameNr-1]<0.10*inp->x[inp->frameNr-1]) {
547 fprintf(wfp, "Warning: you might need to check the sample time units.\n");
548 }
549 /* Check and give a warning, if the first value is the highest */
550 for(fi=1, n=0, f=inp->voi[0].y[0]; fi<inp->frameNr; fi++)
551 if(inp->voi[0].y[fi]>=f) {f=inp->voi[0].y[fi]; n=fi;}
552 if(n<2) fprintf(wfp, "Warning: check the first input sample values.\n");
553
554 /* Check the tissue and blood TAC concentration units */
555 ret=dftUnitConversion(inp, petCunitId(tis->unit));
556 if(ret!=0) {fprintf(wfp, "Note: check the units of input and tissue data.\n");}
557
558 /*
559 * Check and set fit time length
560 */
561 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "checking and setting fit time length\n");
562 /* Set fit duration */
563 starttime=0; endtime=*fitdur;
564 *fitframeNr=fittime_from_dft(tis, &starttime, &endtime, &first, &last, verbose);
565 if(loginfo!=NULL && verbose>1) {
566 fprintf(loginfo, "tis.frameNr := %d\n", tis->frameNr);
567 fprintf(loginfo, "starttime := %g\n", starttime);
568 fprintf(loginfo, "endtime := %g\n", endtime);
569 fprintf(loginfo, "first := %d\n", first);
570 fprintf(loginfo, "last := %d\n", last);
571 fprintf(loginfo, "fitframeNr := %d\n", *fitframeNr);
572 }
573 *fitdur=endtime;
574 /* Check that input data does not end much_before fitdur */
575 if(inp->timetype==DFT_TIME_STARTEND) f=inp->x2[inp->frameNr-1];
576 else f=inp->x[inp->frameNr-1];
577 if(*fitdur>1.2*f) {
578 if(status!=NULL) sprintf(status, "input TAC is too short");
579 dftEmpty(inp); dftEmpty(tis); return(5);
580 }
581 /* Cut off too many input samples to make calculation faster */
582 f=*fitdur+1.0; // One minute extra to allow time delay correction
583 if(loginfo!=NULL && verbose>0) printf("Input TAC cutoff at %g min\n", f);
584 for(fi=0; fi<inp->frameNr; fi++) if(inp->x[fi]>f) break;
585 if(fi<inp->frameNr) fi++;
586 inp->frameNr=fi;
587 if(inp->frameNr<4) {
588 if(status!=NULL) sprintf(status, "too few samples in specified fit duration.\n");
589 dftEmpty(inp); dftEmpty(tis); return(5);
590 }
591 if(loginfo!=NULL && verbose>1) {
592 fprintf(loginfo, "dft.frameNr := %d\ninp.frameNr := %d\nfitdur := %g\n",
593 tis->frameNr, inp->frameNr, *fitdur);
594 fprintf(loginfo, "fitframeNr := %d\n", *fitframeNr);
595 }
596
597 if(status!=NULL) sprintf(status, "ok");
598 return 0;
599}
char dfterrmsg[64]
Definition dft.c:6
int dftDeleteFrameOverlap(DFT *dft)
Definition dft.c:1237
int dftSortByFrame(DFT *dft)
Definition dft.c:1169
int dftInterpolateInto(DFT *inp, DFT *tis, char *status, int verbose)
Definition dftint.c:281
int fittime_from_dft(DFT *dft, double *startTime, double *endTime, int *first, int *last, int verbose)
Definition fittime.c:16

◆ dftReadReference()

int dftReadReference ( DFT * tissue,
char * filename,
int * filetype,
int * ref_index,
char * status,
int verbose )

Read DFT format reference region TAC data and add it into DFT already containing other tissue TACs, if reference region TAC(s) are be given in a separate file. Alternatively the reference region name can be given, which will then be selected from existing tissue TACs. Reference TACs are marked in DFT with sw=2 (best name 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 given value sw=2. When necessary, reference data is interpolated and units converted to match the existing tissue DFT. Reference TAC is also integrated into y2[].

Returns
Returns the number of reference TACs, and <=0 in case of an error.
See also
dftReadinput, dftRead, dftReadModelingData, imgReadModelingData
Parameters
tissuePET data containing existing tissue TACs, possibly also ref regions.
filenameReference TAC filename, or region name in previous data.
filetypeType of input, as found out here; 1 and 2 =tac, 3=fit, 5=region name; enter NULL, if not needed.
ref_indexIndex of the best reference region; enter NULL if not needed.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 204 of file dftinput.c.

219 {
220 int ri, n, ret;
221 DFT temp;
222 FILE *fp;
223 int ftype=0;
224
225 if(verbose>0) printf("dftReadReference(tis, %s, type, i, status, %d)\n", filename, verbose);
226
227 /* Check that input is ok */
228 if(tissue==NULL || filename==NULL || strlen(filename)<1) {
229 if(status!=NULL) strcpy(status, "program error");
230 return -1;
231 }
232 if(tissue->frameNr<1 || tissue->voiNr<1) {
233 if(status!=NULL) strcpy(status, "no pet data");
234 return -2;
235 }
236
237 /* Check if we can identify the reference as an unsupported file */
238 ret=dftFormat(filename);
239 if(ret==DFT_FORMAT_FIT) {
240 if(filetype!=NULL) *filetype=3;
241 if(status!=NULL) strcpy(status, "cannot read fit file");
242 return -3;
243 }
244
245
246 /* Can we open it as a file? */
247 fp=fopen(filename, "r");
248 if(fp!=NULL) {
249 fclose(fp);
250 /* Try to read the reference as a TAC file */
251 dftInit(&temp);
252 if((ret=dftRead(filename, &temp))!=0) {
253 if(status!=NULL) sprintf(status, "cannot read file (%d)", ret);
254 return -4;
255 }
256 if(filetype!=NULL) *filetype=1;
257
258 /* Convert ref time units to the same as in tissue data */
259 (void)dftTimeunitConversion(&temp, tissue->timeunit);
260 /* Check the tissue and ref TAC concentration units */
261 if((ret=dftUnitConversion(&temp, petCunitId(tissue->unit)))!=0) {
262 sprintf(status, "check the units of reference and tissue data");
263 }
264 /* Interpolate and integrate data to pet times */
265 /* this also verifies that ref data does not need extensive extrapolation */
266 ret=dftInterpolateInto(&temp, tissue, status, verbose);
267 if(ret!=0) {dftEmpty(&temp); return -5;}
268 /* Set switches to define which are reference regions and which are not */
269 for(ri=0; ri<tissue->voiNr-temp.voiNr; ri++) tissue->voi[ri].sw=0;
270 for(; ri<tissue->voiNr; ri++) tissue->voi[ri].sw=1;
271 /* Find the best reference region */
272 n=temp.voiNr; dftEmpty(&temp);
273 if(n==1) {
274 ri=tissue->voiNr-n;
275 } else {
276 if((ri=dftSelectBestReference(tissue))<0) {
277 sprintf(status, "cannot select the best reference region");
278 dftEmpty(&temp); return -6;
279 }
280 }
281 tissue->voi[ri].sw=2; if(ref_index!=NULL) *ref_index=ri;
282 if(verbose>1) printf("selected ref region := %s\n", tissue->voi[ri].name);
283 if(status!=NULL) sprintf(status, "%d reference curve(s) read", n);
284
285 return n;
286
287 } // reference file was read and processed
288
289
290 /* So it's not a file, at least an accessible file, but is it region name? */
291 ftype=5; if(filetype!=NULL) *filetype=ftype;
292 /* Select ROIs that match the specified input name */
293 n=dftSelectRegions(tissue, filename, 1);
294 if(verbose>1) printf("nr of ref regions := %d/%d\n", n, tissue->voiNr);
295 if(n<=0) {
296 if(status!=NULL) sprintf(status, "cannot find region");
297 return -7;
298 }
299 if(n==tissue->voiNr && tissue->voiNr>1) {
300 if(status!=NULL) sprintf(status, "all regions do match");
301 return -8;
302 }
303
304 /* Try to select the best reference ROI */
305 ri=dftSelectBestReference(tissue); if(ri<0) {
306 if(status!=NULL) sprintf(status, "cannot select the best reference region");
307 return -9;
308 }
309 tissue->voi[ri].sw=2; if(ref_index!=NULL) *ref_index=ri;
310 if(verbose>1) printf("selected ref region := %s\n", tissue->voi[ri].name);
311
312 /* Calculate integrals */
313 for(ri=0; ri<tissue->voiNr; ri++) if(tissue->voi[ri].sw>0) {
314 if(tissue->timetype==DFT_TIME_STARTEND) {
315 ret=petintegrate(tissue->x1, tissue->x2, tissue->voi[ri].y,
316 tissue->frameNr, tissue->voi[ri].y2, NULL);
317 } else {
318 ret=integrate(tissue->x, tissue->voi[ri].y, tissue->frameNr, tissue->voi[ri].y2);
319 }
320 if(ret) {
321 if(status!=NULL) sprintf(status, "cannot integrate input");
322 return(-11);
323 }
324 }
325
326 if(status!=NULL) sprintf(status, "%d reference curve(s) read", n);
327 return(n);
328}
int petintegrate(double *x1, double *x2, double *y, int nr, double *newyi, double *newyii)
Definition integr.c:334
int integrate(double *x, double *y, int nr, double *yi)
Definition integr.c:271

◆ dftRobustMinMaxTAC()

int dftRobustMinMaxTAC ( DFT * dft,
int tacindex,
double * minx,
double * maxx,
double * miny,
double * maxy,
int * mini,
int * maxi,
int * mins,
int * maxs,
int verbose )

Robust search of the min and max values of DFT TAC data. Data may contain NaN's, and individual outliers are not taken as min or max.

See also
dftMinMaxTAC, dftMinMax
Returns
Returns 0 if successful.
Parameters
dftPointer to the DFT TAC data to search.
tacindexIndex of the only TAC which is searched for min and max; <0 if all.
minxPointer to X at TAC min; set to NULL if not needed.
maxxPointer to X at TAC max; set to NULL if not needed.
minyPointer to min Y; set to NULL if not needed.
maxyPointer to max Y; set to NULL if not needed.
miniIndex of min TAC; set to NULL if not needed.
maxiIndex of max TAC; set to NULL if not needed.
minsIndex of min sample; set to NULL if not needed.
maxsIndex of max sample; set to NULL if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 608 of file dftinput.c.

631 {
632 int ri, fi, i1, i2, s1, s2;
633 double x, x1, x2, y1, y2;
634 int n, runnh, maxrunnh, runns, maxrunns;
635 double ym;
636 int run1h, run2h, maxrun1h, maxrun2h, run1s, run2s, maxrun1s, maxrun2s;
637
638 if(verbose>0)
639 printf("dftRobustMinMaxTAC(dft, %d, minx, maxx, miny, maxy, mini, maxi, mins, maxs, %d)\n",
640 tacindex, verbose);
641
642 if(dft==NULL) return(1);
643 if(tacindex>=dft->voiNr) return(2);
644 if(dft->voiNr<1 || dft->frameNr<1) return(3);
645
646 /* One TAC at a time */
647 double list[dft->frameNr];
648 x1=x2=y1=y2=nan(""); i1=i2=s1=s2=0;
649 for(ri=0; ri<dft->voiNr; ri++) {
650 if(tacindex>=0 && ri!=tacindex) continue;
651 //fprintf(stderr, "Region: %s\n", dft->voi[ri].name);
652 /* Calculate median of y values */
653 for(fi=n=0; fi<dft->frameNr; fi++) {
654 if(isnan(dft->voi[ri].y[fi])) continue;
655 if(dft->timetype==DFT_TIME_STARTEND) {
656 if(isnan(dft->x1[fi]) || isnan(dft->x2[fi])) continue;}
657 else {if(isnan(dft->x[fi])) continue;}
658 list[n++]=dft->voi[ri].y[fi];
659 }
660 if(n<10) {
661 maxrunnh=maxrunns=dft->frameNr;
662 maxrun1h=maxrun1s=0;
663 maxrun2h=maxrun2s=dft->frameNr-1;
664 } else {
665 ym=dmedian(list, n);
666 //fprintf(stderr, "median := %g\n", ym);
667 /* Search the longest run of values which are larger/smaller than the median */
668 runnh=maxrunnh=run1h=run2h=maxrun1h=maxrun2h=0;
669 runns=maxrunns=run1s=run2s=maxrun1s=maxrun2s=0;
670 for(fi=0; fi<dft->frameNr; fi++) {
671 if(isnan(dft->voi[ri].y[fi])) continue;
672 if(dft->timetype==DFT_TIME_STARTEND) {
673 if(isnan(dft->x1[fi]) || isnan(dft->x2[fi])) continue;}
674 else {if(isnan(dft->x[fi])) continue;}
675 /* max */
676 if(dft->voi[ri].y[fi]>ym) {
677 runnh++; if(runnh==1) {run1h=run2h=fi;} else {run2h=fi;}
678 } else {
679 if(runnh>maxrunnh) {maxrunnh=runnh; maxrun1h=run1h; maxrun2h=run2h;}
680 runnh=0;
681 }
682 /* min */
683 if(dft->voi[ri].y[fi]<ym) {
684 runns++; if(runns==1) {run1s=run2s=fi;} else {run2s=fi;}
685 } else {
686 if(runns>maxrunns) {maxrunns=runns; maxrun1s=run1s; maxrun2s=run2s;}
687 runns=0;
688 }
689 }
690 /* Get range also from the end part */
691 if(runnh>maxrunnh) {maxrunnh=runnh; maxrun1h=run1h; maxrun2h=run2h;}
692 if(runns>maxrunns) {maxrunns=runns; maxrun1s=run1s; maxrun2s=run2s;}
693 /* If longest range includes just one sample, then take the whole range */
694 if(maxrunnh<2) {maxrunnh=dft->frameNr; maxrun1h=0; maxrun2h=dft->frameNr-1;}
695 if(maxrunns<2) {maxrunns=dft->frameNr; maxrun1s=0; maxrun2s=dft->frameNr-1;}
696 }
697 if(verbose>12) {
698 fprintf(stderr, "longest run for max: %g - %g\n", dft->x[maxrun1h], dft->x[maxrun2h]);
699 fprintf(stderr, "longest run for min: %g - %g\n", dft->x[maxrun1s], dft->x[maxrun2s]);
700 }
701 /* Inside the range, search for max */
702 for(fi=maxrun1h; fi<=maxrun2h; fi++) {
703 if(isnan(dft->voi[ri].y[fi])) continue;
704 if(dft->timetype==DFT_TIME_STARTEND) {
705 if(isnan(dft->x1[fi]) || isnan(dft->x2[fi])) continue;
706 x=0.5*(dft->x1[fi]+dft->x2[fi]);
707 } else {
708 if(isnan(dft->x[fi])) continue;
709 x=dft->x[fi];
710 }
711 if(isnan(y2) || y2<dft->voi[ri].y[fi]) {y2=dft->voi[ri].y[fi]; i2=ri; x2=x; s2=fi;}
712 }
713 /* Inside the range, search for min */
714 for(fi=maxrun1s; fi<=maxrun2s; fi++) {
715 if(isnan(dft->voi[ri].y[fi])) continue;
716 if(dft->timetype==DFT_TIME_STARTEND) {
717 if(isnan(dft->x1[fi]) || isnan(dft->x2[fi])) continue;
718 x=0.5*(dft->x1[fi]+dft->x2[fi]);
719 } else {
720 if(isnan(dft->x[fi])) continue;
721 x=dft->x[fi];
722 }
723 if(isnan(y1) || y1>dft->voi[ri].y[fi]) {y1=dft->voi[ri].y[fi]; i1=ri; x1=x; s1=fi;}
724 }
725
726 } /* next TAC */
727
728 if(minx!=NULL) {if(isnan(x1)) return(11); else *minx=x1;}
729 if(maxx!=NULL) {if(isnan(x2)) return(12); else *maxx=x2;}
730 if(miny!=NULL) {if(isnan(y1)) return(13); else *miny=y1;}
731 if(maxy!=NULL) {if(isnan(y2)) return(14); else *maxy=y2;}
732 if(mini!=NULL) {if(isnan(y1)) return(13); else *mini=i1;}
733 if(maxi!=NULL) {if(isnan(y2)) return(14); else *maxi=i2;}
734 if(mins!=NULL) {if(isnan(y1)) return(13); else *mins=s1;}
735 if(maxs!=NULL) {if(isnan(y2)) return(14); else *maxs=s2;}
736 return(0);
737}
double dmedian(double *data, int n)
Definition median.c:48

◆ dftTimeIntegral()

int dftTimeIntegral ( DFT * dft,
double t1,
double t2,
DFT * idft,
int calc_mode,
char * status,
int verbose )

Integration of regional TAC data from time1 to time2, i.e. AUC(t1,t2).

You may want to test the time range before applying this routine, because this function accepts relatively large extrapolation large.

See also
dftInterpolateInto, dftInterpolate, dftInterpolateCheckStart, dftInterpolateCheckEnd
Returns
Returns 0 when call was successful, and >0 in case of an error.
Parameters
dftRegional TAC data in DFT struct. Number of samples must be at least one. If only one sample, then the integration time range must match with the possible frame start and times. Frames do not have to be continuous in time.
t1Time where to start integration (same unit as in TACs)
t2Time to stop integration (same unit as in TACs); must be higher than t1, except that t1=t2 is acceptable when calc_mode=average
idftPointer to initiated but empty AUC DFT data (output)
calc_modeCalculate integral or average: 0=integral, 1=average
statusPointer to a string (allocated for at least 128 chars) where error message or other execution status will be written; enter NULL, if not needed
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 382 of file dftint.c.

402 {
403 int ri, fi, ret, f1, f2;
404 double fdur, aucroi, t[2], auc[2];
405 double accept_tdif=1.0; // in seconds
406
407 if(verbose>0)
408 printf("dftTimeIntegral(dft, %g, %g, idft, %d, status, %d)\n", t1, t2, calc_mode, verbose);
409
410 /* Check the arguments */
411 if(status!=NULL) sprintf(status, "program error");
412 if(dft==NULL || idft==NULL || t1<0.0 || t2<0.0) return STATUS_FAULT;
413 fdur=t2-t1; if(fdur<0.0) return STATUS_FAULT;
414 if(fdur==0.0 && (calc_mode!=1 || dft->frameNr>1)) return STATUS_FAULT;
415 if(dft->frameNr<1 || dft->voiNr<1) return STATUS_FAULT;
416
417 /* Set time unit based things */
418 if(dft->timeunit==TUNIT_MIN) accept_tdif/=60.0;
419
420 /* Create the DFT struct for AUC values */
421 ret=dftAllocateWithHeader(idft, 1, dft->voiNr, dft);
422 if(ret!=0) {
423 if(status!=NULL) sprintf(status, "cannot setup AUC data (%d)", ret);
424 return STATUS_FAULT;
425 }
426 /* 'frame' start and end time are taken from integration time */
428 if(calc_mode==1 && fdur==0.0) idft->timetype=DFT_TIME_MIDDLE;
430 /* Initially integral is zero */
431 for(ri=0; ri<idft->voiNr; ri++) idft->voi[ri].y[0]=0.0;
432 //dftPrint(dft);
433
434 /* Different paths if frame start and end times are taken into account or not */
435 if(dft->timetype==DFT_TIME_STARTEND) {
436
437 /* Check that time range matches with pet frame */
438 if(dft->frameNr==1) { // static data (one frame only)
439 /* check that specified times match with frame times, but
440 accept 1 s differences */
441 if(fabs(dft->x2[0]-t2)>accept_tdif || fabs(dft->x1[0]-t1)>accept_tdif) {
442 if(status!=NULL) {
443 strcpy(status, "for static data the integration time range must");
444 strcat(status, " be exactly as long as the scan");
445 }
446 return STATUS_FAULT;
447 }
448 /* Set the times, in case there was a small difference */
449 dft->x2[0]=t2; dft->x1[0]=t1;
450 } else { // Dynamic data (more than one frame)
451 /* First frame must start before 1/3 of the integration time */
452 /* Last frame must end after 2/3 of integration time */
453 if(dft->x1[0]>(0.66*t1+0.34*t2) ||
454 dft->x2[dft->frameNr-1]<(0.34*t1+0.66*t2)) {
455 if(status!=NULL)
456 strcpy(status, "integration time range oversteps data range");
457 return STATUS_FAULT;
458 }
459 }
460
461 /* Get the first and last frame index that resides inside integration time*/
462 if(dft->frameNr==1) {
463 f1=f2=0;
464 } else {
465 for(fi=0, f1=f2=-1; fi<dft->frameNr; fi++) {
466 if(f1<0) {if(dft->x1[fi]>=t1 && dft->x2[fi]<=t2) f1=f2=fi;}
467 if(f1>=0) {if(t2>=dft->x2[fi]) f2=fi;}
468 }
469 }
470 if(verbose>1) printf("f1=%d f2=%d\n", f1, f2);
471 if(f1>=0 && f2>=0) {
472 /* Integrate over the frames that are included in time range as a whole */
473 fi=f1;
474 for(ri=0; ri<dft->voiNr; ri++) {
475 idft->voi[ri].y[0]+=(dft->x2[fi]-dft->x1[fi])*dft->voi[ri].y[fi];
476 }
477 for(fi=f1+1; fi<=f2; fi++) {
478 for(ri=0; ri<dft->voiNr; ri++) {
479 idft->voi[ri].y[0]+=(dft->x2[fi]-dft->x1[fi])*dft->voi[ri].y[fi];
480 }
481 /* Check whether frames are contiguous */
482 if(dft->x1[fi]==dft->x2[fi-1]) continue;
483 /* When not, calculate the area of an imaginary frame */
484 double x, a;
485 x=(dft->x1[fi]+dft->x2[fi-1])/2.0;
486 for(ri=0; ri<dft->voiNr; ri++) {
487 a=(dft->x1[fi]-dft->x2[fi-1])*
488 (dft->voi[ri].y[fi]-(dft->voi[ri].y[fi]-dft->voi[ri].y[fi-1])
489 *(dft->x2[fi]+dft->x1[fi]-2.0*x)
490 /(dft->x2[fi]+dft->x1[fi]-dft->x2[fi-1]-dft->x1[fi-1]));
491 idft->voi[ri].y[0]+=a;
492 }
493 }
494
495 /* If necessary, add the partial integrals */
496 if(dft->x1[f1]>t1) {
497 t[0]=t1; t[1]=dft->x1[f1];
498 if(verbose>5) printf("t[0]=%g t[1]=%g\n", t[0], t[1]);
499 for(ri=0; ri<dft->voiNr; ri++) {
500 ret=interpolate(dft->x, dft->voi[ri].y, dft->frameNr, t, NULL, auc, NULL, 2);
501 if(ret) aucroi=0.0; else aucroi=auc[1]-auc[0];
502 idft->voi[ri].y[0]+=aucroi;
503 }
504 }
505 if(t2>dft->x2[f2]) {
506 t[0]=dft->x2[f2]; t[1]=t2;
507 if(verbose>5) printf("t[0]=%g t[1]=%g\n", t[0], t[1]);
508 for(ri=0; ri<dft->voiNr; ri++) {
509 ret=interpolate(dft->x, dft->voi[ri].y, dft->frameNr, t, NULL, auc, NULL, 2);
510 if(ret) aucroi=0.0; else aucroi=auc[1]-auc[0];
511 idft->voi[ri].y[0]+=aucroi;
512 }
513 }
514
515 } else { // no full frames inside integration range
516
517 t[0]=t1; t[1]=t2;
518 for(ri=0; ri<dft->voiNr; ri++) {
519 ret=interpolate(dft->x, dft->voi[ri].y, dft->frameNr, t, NULL, auc, NULL, 2);
520 if(ret) aucroi=0.0; else aucroi=auc[1]-auc[0];
521 idft->voi[ri].y[0]+=aucroi;
522 }
523
524 }
525
526 /* Set output image time frame */
527 idft->x2[0]=t2; idft->x1[0]=t1; idft->x[0]=0.5*(t1+t2);
528
529 } else if(dft->timetype==DFT_TIME_MIDDLE) { // do not consider frame lengths
530
531 /* If average calculation was required, and sample times match the required
532 time range, then directly take the values; otherwise, calculate AUC */
533 if(calc_mode==1 && dft->x[0]==t1 && dft->x[0]==t2 && dft->frameNr==1) {
534 for(ri=0; ri<dft->voiNr; ri++)
535 idft->voi[ri].y[0]=dft->voi[ri].y[0];
536 } else {
537
538 /* First sample time must be before 1/3 of the integration time */
539 /* Last sample time must end after 2/3 of integration time */
540 if(dft->x[0]>(0.66*t1+0.34*t2) ||
541 dft->x[dft->frameNr-1]<(0.34*t1+0.66*t2)) {
542 if(status!=NULL) sprintf(status, "integration time range oversteps data range");
543 return STATUS_FAULT;
544 }
545
546 t[0]=t1; t[1]=t2;
547 if(verbose>5) printf("t[0]=%g t[1]=%g\n", t[0], t[1]);
548 for(ri=0; ri<dft->voiNr; ri++) {
549 ret=interpolate(dft->x, dft->voi[ri].y, dft->frameNr, t, NULL, auc, NULL, 2);
550 if(ret) idft->voi[ri].y[0]=0.0; else idft->voi[ri].y[0]=auc[1]-auc[0];
551 }
552 }
553 /* Set output image time frame */
554 idft->x2[0]=t2; idft->x1[0]=t1; idft->x[0]=0.5*(t1+t2);
555
556 } else {
557 if(status!=NULL)
558 sprintf(status, "frame mid times or start and end times required");
559 return STATUS_FAULT;
560 }
561
562 /* If required, then calculate average by dividing integral with time */
563 /* Set units accordingly */
564 if(calc_mode!=0) { // average
565 if(fdur>0.0)
566 for(ri=fi=0; ri<idft->voiNr; ri++)
567 idft->voi[ri].y[fi]/=fdur;
568 if(status!=NULL) sprintf(status, "average TAC [%g,%g] calculated", t1, t2);
569 } else { // integral
570 int unit;
571 unit=petCunitId(idft->unit);
572 strcpy(idft->unit, dftUnit(CUNIT_UNKNOWN));
573 if(unit==CUNIT_KBQ_PER_ML) {
574 if(idft->timeunit==TUNIT_MIN)
575 strcpy(idft->unit, dftUnit(CUNIT_MIN_KBQ_PER_ML));
576 else if(idft->timeunit==TUNIT_SEC)
577 strcpy(idft->unit, dftUnit(CUNIT_SEC_KBQ_PER_ML));
578 }
579 if(status!=NULL) sprintf(status, "TAC integral [%g,%g] calculated", t1, t2);
580 }
581
582 return(0);
583}

◆ dftVerifyPeak()

int dftVerifyPeak ( DFT * dft,
int index,
int verbose,
char * status )

Verify that specified (input) TAC contains peak and that it does not start too late to get reliable estimate of AUC.

Returns
Returns 0 in case data is suitable, < 0 if there may be a problem, 1 in case of an error, and 2 if peak seems to be missed.
See also
dftReadModelingData, imgReadModelingData
Parameters
dftPointer to TAC data which is verified.
indexIndex of TAC to be verified; <0 in case all are (separately) verified.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 747 of file dftinput.c.

757 {
758 int ri, fi, ret, mini, maxi, starti, warn=0;
759 double minx, maxx, miny, maxy, startx, dif, lowesty;
760
761 if(verbose>0) printf("dftVerifyPeak(dft, %d, %d)\n", index, verbose);
762 /* Check the arguments */
763 if(status!=NULL) strcpy(status, "program error");
764 if(dft==NULL || dft->frameNr<1 || dft->voiNr<1) return 1;
765 if(index>=dft->voiNr) return 1;
766
767 /* If less than 3 samples, then this can not be suitable as input TAC */
768 if(dft->frameNr<3) {
769 if(status!=NULL) strcpy(status, "too few samples");
770 return 2;
771 }
772
773 /* Make sure data is sorted by increasing sample time */
774 dftSortByFrame(dft);
775
776 /* Go through all TACs that are requested */
777 for(ri=0; ri<dft->voiNr; ri++) {
778 if(index>=0 && index!=ri) continue;
779 if(verbose>1) printf("checking region %d: %s\n", 1+ri, dft->voi[ri].name);
780
781 /* Get the TAC min and max */
782 ret=dftMinMaxTAC(dft, ri, &minx, &maxx, &miny, &maxy, NULL, NULL, &mini, &maxi);
783 if(ret!=0) {
784 if(verbose>0) printf("Error %d in dftMinMaxTAC()\n", ret);
785 if(status!=NULL) strcpy(status, "invalid TAC");
786 return 1;
787 }
788
789 /* Check that there are no big negative values */
790 if(maxy<=0.0) {
791 if(verbose>0) printf("TAC has no positive values.\n");
792 if(status!=NULL) strcpy(status, "no positive TAC values");
793 return 2;
794 }
795 if(miny<0.0) {
796 if((-miny)>0.40*maxy) {
797 if(verbose>0) printf("TAC has high negative value(s).\n");
798 if(status!=NULL) strcpy(status, "too high negative TAC values");
799 return 2;
800 }
801 if((-miny)>0.02*maxy) {
802 if(verbose>1) printf("TAC has negative value(s).\n");
803 warn++;
804 }
805 }
806
807 /* Get the first sample time, considering missing values */
808 startx=1.0E+10; starti=dft->frameNr-1;
809 for(fi=0; fi<dft->frameNr; fi++) {
810 if(isnan(dft->voi[ri].y[fi])) continue;
811 if(dft->timetype==DFT_TIME_STARTEND) {
812 if(isnan(dft->x1[fi])) continue;
813 if(isnan(dft->x2[fi])) continue;
814 startx=dft->x1[fi]; starti=fi; break;
815 } else {
816 if(isnan(dft->x[fi])) continue;
817 startx=dft->x[fi]; starti=fi; break;
818 }
819 }
820 if(verbose>2) printf("first time sample at %g\n", startx);
821
822 /* If the first sample is the peak, then check that sample time is not too late */
823 if(maxi==starti) {
824 if(verbose>2) printf("Peak at the first sample.\n");
825 if(status!=NULL) strcpy(status, "input TAC should start at time zero");
826 /* Calculate peak time to initial sample frequency ratio */
827 if(dft->timetype==DFT_TIME_STARTEND) {
828 dif=dft->x1[maxi]/(dft->x2[maxi]-dft->x1[maxi]);
829 } else {
830 //dif=dft->x[maxi]/(dft->x[maxi+1]-dft->x[maxi]);
831 for(fi=maxi+1; fi<dft->frameNr; fi++)
832 if(!isnan(dft->x[fi]) && dft->x[fi]>dft->x[maxi]) break;
833 if(fi==dft->frameNr) dif=1.0E+10;
834 else dif=dft->x[maxi]/(dft->x[fi]-dft->x[maxi]);
835 }
836 if(dif>0.3) {
837 if(verbose>0) printf("Peak at the first sample which is not at zero.\n");
838 if(verbose>1) printf("dif := %g\n", dif);
839 }
840 if(dif>5.0) {
841 return 2;
842 } else if(dif>1.0) {
843 /* Not bad, if peak is still much higher than tale */
844 if(maxy>20.*miny) warn++; else return 2;
845 if(verbose>1) printf("good peak/tail -ratio\n");
846 } else if(dif>0.3) warn++;
847 }
848
849 /* Search the lowest value before the peak */
850 lowesty=dft->voi[ri].y[starti];
851 for(fi=starti+1; fi<maxi; fi++)
852 if(dft->voi[ri].y[fi]<lowesty) lowesty=dft->voi[ri].y[fi];
853 if(verbose>2) printf("lowest value before peak: %g\n", lowesty);
854
855 /* If first sample is closer to peak and relatively high, then that is or may be a problem */
856 if(maxi>starti && startx>0.001 && startx>0.75*maxx) {
857 if(dft->voi[ri].y[starti]>0.66*maxy && lowesty>0.05*maxy && mini>maxi) {
858 if(verbose>0) printf("The first sample is relatively late and high.\n");
859 if(status!=NULL) strcpy(status, "input TAC should start at time zero");
860 if(verbose>2) {
861 printf("startx=%g\n", startx);
862 printf("starty=%g\n", dft->voi[ri].y[starti]);
863 printf("maxx=%g\n", maxx);
864 printf("maxy=%g\n", maxy);
865 }
866 return 2;
867 }
868 }
869 if(maxi>starti && startx>0.001 && startx>0.5*maxx) {
870 if(dft->voi[ri].y[starti]>0.5*maxy && lowesty>0.05*maxy && mini>maxi) {
871 if(verbose>1) printf("The first sample is relatively late and high.\n");
872 warn++;
873 }
874 }
875 if(verbose>5) {
876 printf("startx=%g\n", startx);
877 printf("starty=%g\n", dft->voi[ri].y[starti]);
878 printf("maxx=%g\n", maxx);
879 printf("maxy=%g\n", maxy);
880 }
881
882 /* If peak is not much higher than lowest value, that may indicate
883 a problem */
884 if(maxy<1.5*miny) {
885 if(verbose>0) printf("TAC does not have a clear peak.\n");
886 if(status!=NULL) strcpy(status, "input TAC peak missing");
887 return 2;
888 }
889 if(maxy<5.0*miny) {
890 if(verbose>1) printf("TAC does not have a clear peak.\n");
891 warn++;
892 }
893
894 } // next TAC
895
896 if(verbose>0 && warn>0) printf("%d warning(s)\n", warn);
897 if(warn>0) {
898 if(status!=NULL) strcpy(status, "input TAC is not optimal");
899 return -1;
900 }
901 if(status!=NULL) strcpy(status, "input TAC ok");
902 return 0;
903}
int dftMinMaxTAC(DFT *dft, int tacindex, double *minx, double *maxx, double *miny, double *maxy, int *mini, int *maxi, int *mins, int *maxs)
Definition dft.c:1024

Referenced by dftFixPeak(), dftReadinput(), and imgReadModelingData().

◆ dftWeightByFreq()

int dftWeightByFreq ( DFT * dft)

Add weights based on sample frequency or frame length.

Existing weights are overwritten.

Returns
Returns 0 when successful, otherwise <>0.
See also
dftRead, dftSortByFrame, sifWeight, sifWeightByFrames, dftDecayCorrection, imgSetWeights, dftWSampleNr
Parameters
dftSamples/frames must be sorted by sample time, but duplicate samples are allowed

Definition at line 20 of file weight_model.c.

24 {
25 int fi, fi1, fi2;
26 double f, t, t1, t2, sumw=0.0;
27
28 if(dft==NULL || dft->frameNr<1) return 1;
29 if(dft->frameNr==1) {
30 dft->w[0]=1.0;
31 dft->isweight=1;
32 return 0;
33 }
34
35 if(dft->timetype==DFT_TIME_STARTEND) { /* weights by frame lengths */
36
37 for(fi=0; fi<dft->frameNr; fi++) {
38 dft->w[fi]=dft->x2[fi]-dft->x1[fi];
39 sumw+=dft->w[fi];
40 }
41 /* scale weights so that sum of weights equals sample number */
42 sumw/=(double)dft->frameNr;
43 for(fi=0; fi<dft->frameNr; fi++) dft->w[fi]/=sumw;
44
45 } else if(dft->timetype==DFT_TIME_MIDDLE) { /* weights by sample distance */
46
47 for(fi=0; fi<dft->frameNr; fi++) {
48 t=t1=t2=dft->x[fi]; //printf("fi=%d t=%g\n", fi, t);
49 /* Find the closest sample time before this one */
50 for(fi1=fi; fi1>=0; fi1--) {t1=dft->x[fi1]; if(t1<t) break;}
51 /* Find the closest sample time after this one */
52 for(fi2=fi; fi2<dft->frameNr; fi2++) {t2=dft->x[fi2]; if(t2>t) break;}
53 //printf(" t1=%g t2=%g\n", t1, t2);
54 /* Mean sample distance */
55 f=0.0;
56 if(t1<t) f+=t-t1; else f+=t2-t;
57 if(t2>t) f+=t2-t; else f+=t-t1;
58 f*=0.5; if(f<=0.0) f=1.0;
59 /* Set initial weight */
60 //printf(" f=%g\n", f);
61 dft->w[fi]=f; sumw+=f;
62 }
63 /* Scale weights */
64 sumw/=(double)dft->frameNr;
65 for(fi=0; fi<dft->frameNr; fi++) dft->w[fi]/=sumw;
66
67 } else
68 return 2;
69
70 dft->isweight=1;
71 return(0);
72}

◆ dftWSampleNr()

int dftWSampleNr ( DFT * tac)

Get the number of samples in DFT that have weight > 0. Missing (NaN) sample values are included as long as weight is not missing. If weights are not set, then nr of all samples is returned.

Returns
The number of samples with weight above zero.
See also
dftWeightByFreq, aicSS, parFreeNr
Parameters
tacPointer to the DFT struct.

Definition at line 147 of file weight_model.c.

150 {
151 if(tac==NULL || tac->voiNr<1 || tac->frameNr<1) return(0);
152 if(tac->isweight==0) return(tac->frameNr);
153 int n=0;
154 for(int i=0; i<tac->frameNr; i++) if(tac->w[i]>0.0) n++;
155 return(n);
156}

◆ extrapolate_monoexp()

int extrapolate_monoexp ( DFT * dft,
double * fittime,
int * min_nr,
int max_nr,
double mintime,
double extr_to,
DFT * ext,
FILE * loginfo,
char * status )

Extrapolation of exponentially decreasing tail of PET radiotracer plasma curves. This is accomplished by fitting line to the end-part of the plot of the natural logarithm of tracer concentration against time. By default, the included data points are determined based on maximum adjusted R^2 from at least three points; fit to the larger number of points is used in case difference in adjusted R^2 values is not larger than 0.0001. This function is used and tested with program extrapol.

Returns
Returns 0 when successful, otherwise <>0.
Parameters
dftPointer to original TAC data.
fittimeBy default, the search for the best line fit is started from the last sample towards the first sample; set fit time to -1 to use this default. However, if the end phase is unreliable or very noisy, you may want to set fittime to include only certain time range from the beginning. Function will write here the fittime that was actually used.
min_nrThe minimum number of samples used in searching the best fit; at least 2, but 3 is recommended. If data is very noisy, then this number may need to be increased. Function will write here the nr of samples that was actually used. This can be used as an alternative to mintime or in addition to it.
max_nrThe maximum number of samples used in searching the best fit; must be higher than min_nr, or set to -1 to not to limit the number.
mintimeMinimum time range used in searching the best fit. If data is very noisy, then this may need to be set, otherwise setting mintime to -1 will use the default. This can be used as an alternative to min_nr or in addition to it.
extr_toLast extrapolated sample time in same time units than in the data.
extPointer to data for extrapolated TACs. Struct must be initiated. Any existing data is deleted.
loginfoGive file pointer (for example stdout) where log information is printed; NULL if not needed.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 22 of file extrapolate.c.

56 {
57 int fi, ret, n, to, from, to_min, from_min, orig_max_nr;
58 int fitNr, snr;
59 double kel, c0=0.0, *cx, *cy;
60 double slope, slope_sd, ic, ic_sd, r, f, adj_r2, adj_r2_max;
61 double extr_sampl;
62
63
64 /* Check the input */
65 if(status!=NULL) sprintf(status, "program error");
66 if(dft==NULL || ext==NULL) return -1;
67 if(*min_nr<2) *min_nr=3; // Setting erroneous value to a recommended value
68 if(max_nr>-1 && max_nr<*min_nr) return -2;
69 orig_max_nr=max_nr;
70
71 /* Set the last sample to be fitted */
72 fitNr=dft->frameNr;
73 if(*fittime>0.0) {
74 while(dft->x[fitNr-1]>*fittime && fitNr>0) fitNr--;
75 if(loginfo!=NULL) fprintf(loginfo, "fitNr := %d\nTime range := %g - %g\n",
76 fitNr, dft->x[0], dft->x[fitNr-1]);
77 }
78 *fittime=dft->x[fitNr-1];
79 /* Check that there are at least 3 samples */
80 if(fitNr<3) { /* min_nr is checked later */
81 if(status!=NULL) sprintf(status, "too few samples for extrapolation");
82 return(2);
83 }
84
85 /* If mintime was set, then get min_nr based on that */
86 if(mintime>0.0) {
87 fi=0; while(dft->x[fi]<(*fittime-mintime) && fi<fitNr) fi++;
88 if(--fi<=0) {
89 if(status!=NULL) sprintf(status, "required minimum fit range too large");
90 return(2);
91 }
92 *min_nr=((fitNr-fi)>*min_nr?fitNr-fi:*min_nr);
93 }
94 if(loginfo!=NULL) fprintf(loginfo, "final_min_nr := %d\n", *min_nr);
95
96
97 /*
98 * Initiate data for extrapolated data
99 */
100 /* Determine the sampling time for extrapolated range */
101 extr_sampl=0.5*(dft->x[dft->frameNr-1]-dft->x[dft->frameNr-3]);
102 if(loginfo!=NULL) fprintf(loginfo, "extr_sampl=%g\n", extr_sampl);
103 if(extr_sampl<1.0E-8) {
104 if(status!=NULL) sprintf(status, "check sample times");
105 return(2);
106 }
107 /* Determine the nr of extrapolated samples */
108 f=extr_to-dft->x[dft->frameNr-1];
109 if(f<=0.0) {
110 if(status!=NULL) sprintf(status, "no extrapolation is needed");
111 return(2);
112 }
113 n=ceil(f/extr_sampl);
114 if(loginfo!=NULL) fprintf(loginfo, " extr_sampl=%g n=%d\n", extr_sampl, n);
115 /* Allocate memory */
116 dftEmpty(ext);
117 ret=dftSetmem(ext, dft->frameNr+n, dft->voiNr);
118 if(ret) {
119 if(status!=NULL) sprintf(status, "error in memory allocation.\n");
120 return(4);
121 }
122 ext->frameNr=dft->frameNr+n; ext->voiNr=dft->voiNr;
123 /* Set sample times */
124 for(fi=0; fi<dft->frameNr; fi++) {
125 ext->x[fi]=dft->x[fi]; ext->x1[fi]=dft->x1[fi]; ext->x2[fi]=dft->x2[fi];}
126 if(dft->timetype==DFT_TIME_MIDDLE) {
127 for(; fi<ext->frameNr; fi++) {
128 ext->x[fi]=ext->x[fi-1]+extr_sampl;
129 ext->x1[fi]=ext->x2[fi-1]; ext->x2[fi]=ext->x[fi]+0.5*extr_sampl;
130 }
131 } else {
132 for(; fi<ext->frameNr; fi++) {
133 ext->x1[fi]=ext->x2[fi-1]; ext->x2[fi]=ext->x1[fi]+extr_sampl;
134 ext->x[fi]=0.5*(ext->x1[fi]+ext->x2[fi]);
135 }
136 }
137 /* Copy "header" information */
138 dftCopymainhdr(dft, ext);
139 for(int ri=0; ri<dft->voiNr; ri++) dftCopyvoihdr(dft, ri, ext, ri);
140 /* Copy existing values */
141 for(int ri=0; ri<dft->voiNr; ri++)
142 for(int fi=0; fi<dft->frameNr; fi++)
143 ext->voi[ri].y[fi]=dft->voi[ri].y[fi];
144
145
146 /*
147 * Make ln transformation for TACs
148 */
149 if(loginfo!=NULL) fprintf(loginfo, "ln transformation\n");
150 for(int ri=0; ri<dft->voiNr; ri++)
151 for(int fi=0; fi<dft->frameNr; fi++) {
152 if(!isnan(dft->voi[ri].y[fi]) && dft->voi[ri].y[fi]>0.0)
153 dft->voi[ri].y2[fi]=log(dft->voi[ri].y[fi]);
154 else
155 dft->voi[ri].y2[fi]=nan("");
156 }
157
158
159 /*
160 * Compute best linear fit to the end of ln transformed TACs
161 */
162 if(loginfo!=NULL) fprintf(loginfo, "linear fitting\n");
163 cx=(double*)malloc(2*fitNr*sizeof(double)); if(cx==NULL) {
164 if(status!=NULL) sprintf(status, "out of memory");
165 return(6);
166 }
167 cy=cx+fitNr;
168 for(int ri=0; ri<dft->voiNr; ri++) {
169 kel=0.0; max_nr=orig_max_nr;
170 /* Print TAC name, if more than one was found */
171 if(dft->voiNr>1 && loginfo!=NULL)
172 fprintf(loginfo, "%s :\n", dft->voi[ri].name);
173
174 /* Copy appropriate TAC data */
175 for(fi=n=0; fi<fitNr; fi++)
176 if(dft->x[fi]>0.0 && !isnan(dft->voi[ri].y2[fi])) {
177 cx[n]=dft->x[fi]; cy[n++]=dft->voi[ri].y2[fi];}
178 if(n<*min_nr) {
179 if(status!=NULL) sprintf(status, "check the datafile (%d<%d)", n, *min_nr);
180 free(cx); return(7);
181 }
182 if(max_nr<=0) max_nr=n;
183 /* Search the plot range that gives the max adjusted R^2 */
184 from_min=to_min=-1; adj_r2_max=-9.99E+99;
185 for(from=n-max_nr, to=n-1; from<1+n-*min_nr; from++) {
186 snr=(to-from)+1;
187 /* Calculation of linear regression using pearson() */
188 ret=pearson(
189 cx+from, cy+from, snr, &slope, &slope_sd, &ic, &ic_sd, &r, &f
190 );
191 if(ret==0) {
192 adj_r2= 1.0 - ((1.0-r*r)*(double)(snr-1)) / (double)(snr-2);
193 } else {
194 adj_r2=-9.99E+99;
195 }
196 //if(cv<cv_min) {
197 if(adj_r2>adj_r2_max+0.0001) {
198 adj_r2_max=adj_r2; from_min=from; to_min=to; kel=-slope; c0=exp(ic);
199 }
200 if(loginfo!=NULL)
201 fprintf(loginfo, " adj_r2=%g from=%d (%g)\n", adj_r2, from, *(cx+from) );
202 }
203 if(from_min<0) {
204 if(status!=NULL) sprintf(status, "check the datafile");
205 free(cx); return(7);
206 }
207 /* Check the sign of slope */
208 if(kel>=0.0) {
209 /* negative slope i.e. positive kel is ok */
210 if(loginfo!=NULL)
211 fprintf(loginfo, " k(el)=%g adj_r2=%g C(0)=%g; %d data points.\n",
212 kel, adj_r2_max, c0, (to_min-from_min)+1 );
213 /* Calculate the extrapolated values */
214 for(fi=fitNr; fi<ext->frameNr; fi++) {
215 ext->voi[ri].y[fi]=c0*exp(-kel*ext->x[fi]);
216 }
217 } else {
218 /* If slope is positive, then extrapolate with line f(x)=b+0*t */
219 for(fi=fitNr-1, f=0.0, n=0; fi>=0 && n<3; fi--)
220 if(!isnan(dft->voi[ri].y[fi])) {f+=dft->voi[ri].y[fi]; n++;}
221 if(n>0) f/=(double)n;
222 if(status!=NULL)
223 sprintf(status, "curve end is not descending; extrapolation with horizontal line determined as avg of %d samples", n);
224 /* Calculate the extrapolated values */
225 for(fi=fitNr; fi<ext->frameNr; fi++) {
226 ext->voi[ri].y[fi]=f;
227 }
228 }
229 } /* next curve */
230 free(cx);
231
232 if(status!=NULL) sprintf(status, "ok");
233 return 0;
234}

◆ fittime_from_dft()

int fittime_from_dft ( DFT * dft,
double * startTime,
double * endTime,
int * first,
int * last,
int verbose )

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

See also
fittime_from_img, getActualSamplenr, dftEndtime, dftReadModelingData
Returns
Returns the number of samples included in the fit range, or <0 in case of an error.
Parameters
dftPointer to DFT containing (regional tissue) data; times can be in minutes or seconds, as long as units are defined.
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.
lastFunction writes the index of the last included sample (frame) here.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 16 of file fittime.c.

37 {
38 int fi, dataNr;
39
40 if(verbose>0) printf("%s(*dft, %g, %g, first, last)\n", __func__, *startTime, *endTime);
41 if(dft==NULL || startTime==NULL || endTime==NULL) return(-1);
42 if(!isfinite(*startTime)) *startTime=-1.0;
43 if(!isfinite(*endTime)) *endTime=-1.0;
44 *first=*last=0;
45 if(dft->frameNr<=0) {*startTime=*endTime=0.0; return 0;}
46 /* Change start and end times to seconds if necessary */
47 if(dft->timeunit==TUNIT_SEC) {*startTime*=60.; *endTime*=60.;}
48 /* Check that data range is not outside required range */
49 if(dft->x[dft->frameNr-1]<*startTime || dft->x[0]>*endTime) {
50 *startTime=*endTime=0.0; return 0;}
51 /* Get first and last data point */
52 for(fi=0, *first=dft->frameNr; fi<dft->frameNr; fi++)
53 if(dft->x[fi]>=*startTime) {*first=fi; break;}
54 for(*last=fi=*first; fi<dft->frameNr; fi++)
55 if(dft->x[fi]<=*endTime) *last=fi; else break;
56 if(*first>=dft->frameNr) {*startTime=*endTime=0.0; return 0;}
57 /* Correct fit range to frame start and end times */
58 *startTime=(dft->timetype==DFT_TIME_STARTEND?dft->x1[*first]:dft->x[*first]);
59 *endTime=(dft->timetype==DFT_TIME_STARTEND?dft->x2[*last]:dft->x[*last]);
60 /* Calculate the number of data points in the fit range */
61 dataNr=(*last)-(*first)+1;
62 /* Change start and end times back to minutes if necessary */
63 if(dft->timeunit==TUNIT_SEC) {*startTime/=60.; *endTime/=60.;}
64 return dataNr;
65}

Referenced by dftReadModelingData(), and imgReadModelingData().

◆ fittime_from_img()

int fittime_from_img ( IMG * img,
double * fittime,
int verbose )

Get the IMG frame end time of the last frame that is inside (mid time before) the specified maximum fittime.

See also
fittime_from_dft, imgEndtime, imgReadModelingData
Returns
Returns the number of IMG frames included in the fittime, or <0 in case of an error.
Parameters
imgPointer to IMG
fittimePointer containing originally the fit time maximum, after this the last included IMG frame end time. Unit must be seconds. Initially, set to <0 or to a very large value to include all frames.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 74 of file fittime.c.

83 {
84 if(verbose>0) printf("%s(*img, %g)\n", __func__, *fittime);
85 if(img==NULL || fittime==NULL) return(-1);
86 if(!isfinite(*fittime)) *fittime=-1.0;
87 if(img->dimt<=0) {*fittime=0.0; return 0;}
88 if(*fittime<0) {*fittime=img->end[img->dimt-1]; return img->dimt;}
89 int fitdimt=0;
90 for(int fi=0; fi<img->dimt; fi++)
91 if(img->mid[fi]>*fittime) break; else fitdimt++;
92 *fittime=img->end[fitdimt-1];
93 if(verbose>1) {
94 printf(" fitdimt := %d\n", fitdimt);
95 printf(" fittime := %g\n", *fittime);
96 }
97 return fitdimt;
98}

Referenced by imgReadModelingData().

◆ getActualSamplenr()

int getActualSamplenr ( DFT * dft,
int ri )

Returns the actual TAC sample number, not including NaNs, samples with negative x, duplicate samples, or samples with zero weights (if data is weighted).

See also
dftEndtime, fittime_from_dft
Returns
Returns sample number.
Parameters
dftPointer to TAC data in DFT struct; must be sorted by increasing x.
riRegion index [0..voiNr-1].

Definition at line 288 of file fittime.c.

293 {
294 int n, fi;
295 double last_x=-1.0E+99;
296
297 if(dft==NULL || dft->frameNr<1 || ri<0 || ri>=dft->voiNr) return 0;
298 for(fi=n=0; fi<dft->frameNr; fi++) {
299 if(isnan(dft->x[fi])) continue;
300 if(isnan(dft->voi[ri].y[fi])) continue;
301 if(dft->x[fi]<0.0) continue;
302 if(dft->isweight!=0 && dft->w[fi]<=0.0) continue;
303 if(dft->x[fi]==last_x) continue;
304 n++; last_x=dft->x[fi];
305 }
306 return n;
307}

◆ img_k1_using_ki()

int img_k1_using_ki ( DFT * input,
IMG * dyn_img,
int frame_nr,
IMG * ki_img,
IMG * k1_img,
IMG * k2k3_img,
char * status,
int verbose )

Computing pixel-by-pixel the K1 for irreversible PET tracers using previously determined Ki (K1*k3/(k2+k3) and bilinear regression.

Returns
Returns 0 if succesful, and >1 in case of an error.
Parameters
inputPointer to the TAC data to be used as model input. Sample times in minutes. Curve is interpolated to PET frame times, if necessary
dyn_imgPointer to dynamic PET image data. Image and input data must be in the same calibration units
frame_nrNr of frames that will be included in the fit [3-frame_nr]
ki_imgPointer to previously calculated Ki image
k1_imgPointer to initiated IMG structure where K1 values will be placed
k2k3_imgPointer to initiated IMG structure where (k2+k3) values will be placed; enter NULL, if not needed
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 16 of file img_k1.c.

37 {
38 int zi, yi, xi, fi, ret=0;
39 int nnls_n=2, nnls_m, m;
40 DFT tac;
41 clock_t fitStart, fitFinish;
42
43
44 if(verbose>0) {
45 printf("%s(input, dyn_img, %d, ki_img, k1_img, ", __func__, frame_nr);
46 if(k2k3_img==NULL) printf("NULL, "); else printf("k2k3_img, ");
47 if(status==NULL) printf("NULL)\n"); else printf("status)\n");
48 }
49 /* Initial check for the arguments */
50 if(status!=NULL) sprintf(status, "invalid data");
51 if(dyn_img->status!=IMG_STATUS_OCCUPIED || dyn_img->dimt<1) return(1);
52 if(ki_img->status!=IMG_STATUS_OCCUPIED || ki_img->dimt<1) return(1);
53 if(input==NULL || input->frameNr<1) return(1);
54 if(frame_nr>dyn_img->dimt) return(1);
55 if(k1_img==NULL) return(1);
56 if(frame_nr<3) {
57 if(status!=NULL) sprintf(status, "invalid fit time");
58 return(1);
59 }
60
61 /* Check that input contains samples until at least 80% of line fit range */
62 if(verbose>1) {
63 printf("input_last_sample_time := %g\n", input->x[input->frameNr-1]);
64 printf("k1_start_time := %g\n", dyn_img->start[0]/60.0);
65 printf("k1_end_time := %g\n", dyn_img->end[frame_nr-1]/60.0);
66 }
67 if(input->x[input->frameNr-1] <
68 (0.2*dyn_img->mid[0]+0.8*dyn_img->mid[frame_nr-1])/60.0)
69 {
70 sprintf(status, "too few input samples"); return(2);
71 }
72
73 fitStart=clock();
74
75 /* Allocate memory for interpolated and integrated input and
76 tissue pixel TACs */
77 dftInit(&tac); if(dftSetmem(&tac, frame_nr, 2)!=0) {
78 sprintf(status, "out of memory"); return(3);
79 }
80 strcpy(tac.voi[0].voiname, "input"); strcpy(tac.voi[1].voiname, "tissue");
81 tac.voiNr=2; tac.frameNr=frame_nr;
82 for(fi=0; fi<tac.frameNr; fi++) {
83 tac.x1[fi]=dyn_img->start[fi]/60.;
84 tac.x2[fi]=dyn_img->end[fi]/60.;
85 tac.x[fi]=dyn_img->mid[fi]/60.;
86 }
87
88 /* If input sample times are much different from PET frame times,
89 as they usually are if arterial plasma is used as input, then use
90 interpolate4pet(), otherwise with image-derived input use petintegral()
91 */
92 ret=0;
93 if(input->frameNr<dyn_img->dimt) ret=1;
94 for(fi=0; fi<tac.frameNr; fi++) {
95 if(verbose>8) printf(" %g vs %g\n", input->x1[fi], tac.x1[fi]);
96 if(input->x1[fi]>tac.x1[fi]+0.034 || input->x1[fi]<tac.x1[fi]-0.034) {
97 ret++; continue;}
98 if(input->x2[fi]>tac.x2[fi]+0.034 || input->x2[fi]<tac.x2[fi]-0.034) ret++;
99 }
100 if(ret>0) {
101 if(verbose>1) printf("using interpolate4pet() for input curve\n");
102 ret=interpolate4pet(
103 input->x, input->voi[0].y, input->frameNr,
104 tac.x1, tac.x2, tac.voi[0].y, tac.voi[0].y2, tac.voi[0].y3, tac.frameNr
105 );
106 } else {
107 if(verbose>1) printf("copying input curve and using petintegral()\n");
108 /* because times are the same, the values can be copied directly */
109 for(fi=0; fi<tac.frameNr; fi++) tac.voi[0].y[fi]=input->voi[0].y[fi];
110 ret=petintegral(tac.x1, tac.x2, tac.voi[0].y, tac.frameNr,
111 tac.voi[0].y2, tac.voi[0].y3);
112 }
113 if(ret) {
114 dftEmpty(&tac); sprintf(status, "cannot interpolate input data");
115 if(verbose>0) printf(" ret := %d\n", ret);
116 return(4);
117 }
118 if(verbose>3) dftPrint(&tac);
119
120 /*
121 * Allocate result images and fill the header info
122 */
123 /* K1 image */
124 imgEmpty(k1_img);
125 ret=imgAllocate(k1_img, dyn_img->dimz, dyn_img->dimy, dyn_img->dimx, 1);
126 if(ret) {
127 sprintf(status, "cannot allocate memory for K1 image");
128 imgEmpty(k1_img); dftEmpty(&tac); return(5);
129 }
130 ret=imgCopyhdr(dyn_img, k1_img);
131 if(ret) {
132 sprintf(status, "cannot copy header info for result image");
133 imgEmpty(k1_img); dftEmpty(&tac); return(5);
134 }
135 k1_img->unit=CUNIT_ML_PER_ML_PER_MIN;
137 k1_img->start[0]=dyn_img->start[0]; k1_img->end[0]=dyn_img->end[frame_nr-1];
138 if(verbose>9) imgInfo(k1_img);
139
140 /* (k2+k3) image */
141 if(k2k3_img!=NULL) {
142 imgEmpty(k2k3_img);
143 ret=imgAllocate(k2k3_img, dyn_img->dimz, dyn_img->dimy, dyn_img->dimx, 1);
144 if(ret) {
145 sprintf(status, "cannot allocate memory for (k2+k3) image");
146 imgEmpty(k2k3_img); imgEmpty(k1_img); dftEmpty(&tac); return(6);
147 }
148 ret=imgCopyhdr(dyn_img, k2k3_img);
149 if(ret) {
150 sprintf(status, "cannot copy header info for result image");
151 imgEmpty(k2k3_img); imgEmpty(k1_img); dftEmpty(&tac); return(6);
152 }
153 k2k3_img->unit=CUNIT_PER_MIN;
154 k2k3_img->decayCorrection=IMG_DC_NONCORRECTED; k2k3_img->isWeight=0;
155 k2k3_img->start[0]=dyn_img->start[0];
156 k2k3_img->end[0]=dyn_img->end[frame_nr-1];
157 if(verbose>9) imgInfo(k2k3_img);
158 }
159
160 /*
161 * Allocate memory required by NNLS; C99 !!!
162 */
163 if(verbose>1) fprintf(stdout, "allocating memory for NNLS\n");
164 nnls_m=frame_nr;
165 double *nnls_a[nnls_n], nnls_mat[nnls_n][nnls_m], nnls_b[nnls_m],
166 nnls_zz[nnls_m];
167 double nnls_x[nnls_n], nnls_wp[nnls_n], nnls_rnorm;
168 int nnls_index[nnls_n];
169 nnls_a[0]=nnls_mat[0];
170 nnls_a[1]=nnls_mat[1];
171
172 /*
173 * Compute pixel-by-pixel
174 */
175 if(verbose>1) printf("computing K1 pixel-by-pixel\n");
176 for(zi=0; zi<dyn_img->dimz; zi++) {
177 for(yi=0; yi<dyn_img->dimy; yi++) {
178 for(xi=0; xi<dyn_img->dimx; xi++) {
179 /* Initiate pixel output values */
180 k1_img->m[zi][yi][xi][0]=0.0;
181 if(k2k3_img!=NULL) k2k3_img->m[zi][yi][xi][0]=0.0;
182
183 /* Copy and integrate pixel curve */
184 for(m=0; m<nnls_m; m++) tac.voi[1].y[m]=dyn_img->m[zi][yi][xi][m];
185 ret=petintegral(tac.x1, tac.x2, tac.voi[1].y, tac.frameNr,
186 tac.voi[1].y2, NULL);
187 if(ret) continue;
188 /* if AUC at the end is <= 0, then do nothing */
189 if(tac.voi[1].y2[nnls_m-1]<=0.0) continue;
190
191 /* Fill the NNLS data matrix */
192 for(m=0; m<nnls_m; m++) {
193 nnls_a[0][m]=tac.voi[0].y2[m];
194 nnls_a[1][m]=ki_img->m[zi][yi][xi][0]*tac.voi[0].y3[m]-tac.voi[1].y2[m];
195 nnls_b[m]=tac.voi[1].y[m];
196 }
197
198 /* NNLS */
199 ret=nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm,
200 nnls_wp, nnls_zz, nnls_index);
201 if(ret>1) { /* no solution is possible */
202 continue;
203 } else if(ret==1) { /* max iteration count exceeded */ }
204 k1_img->m[zi][yi][xi][0]=nnls_x[0];
205 if(k2k3_img!=NULL) k2k3_img->m[zi][yi][xi][0]=nnls_x[1];
206
207 } /* next column */
208 } /* next row */
209 } /* next plane */
210 dftEmpty(&tac);
211
212 fitFinish=clock(); //printf("CLOCKS_PER_SEC=%ld\n", CLOCKS_PER_SEC);
213 //printf("%ld - %ld\n", fitFinish, fitStart);
214 if(verbose>0 && fitFinish!=(clock_t)(-1)) printf("done in %g seconds.\n",
215 (double)(fitFinish - fitStart) / (double)CLOCKS_PER_SEC );
216
217 return(0);
218}
void dftPrint(DFT *data)
Definition dftio.c:538
void imgInfo(IMG *image)
Definition img.c:359
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
Definition img.c:194
int imgCopyhdr(IMG *image1, IMG *image2)
Definition img.c:471
void imgEmpty(IMG *image)
Definition img.c:121
#define IMG_DC_NONCORRECTED
int nnls(double **a, int m, int n, double *b, double *x, double *rnorm, double *w, double *zz, int *index)
Definition nnls.c:38
float **** m
char decayCorrection
char isWeight

◆ img_logan()

int img_logan ( DFT * input,
IMG * dyn_img,
int start,
int end,
linefit_range fit_range,
float thrs,
double k2,
IMG * vt_img,
IMG * ic_img,
IMG * nr_img,
char * status,
int verbose )

Computing pixel-by-pixel the graphical analysis for reversible PET tracers (Logan plot).

See also
img_patlak, llsqperp, logan_data, mtga_best_perp
Returns
Returns 0 if successful, and >0 in case of an error.
Parameters
inputPointer to the TAC data to be used as model input. Sample times in minutes. Curve is interpolated to PET frame times, if necessary.
dyn_imgPointer to dynamic PET image data. Image and input data must be in the same calibration units.
startThe range of frames where line is fitted, given as the frame start here and next the end index, i.e. [0..frame_nr-1].
endThe range of frames where line is fitted, given as the frame start above and here the end index, i.e. [0..frame_nr-1].
fit_rangeUse the whole range or based on data leave out points from the beginning; PRESET or EXCLUDE_BEGIN.
thrsThreshold as fraction of input AUC.
k2Reference region k2; set to <=0 if not needed.
vt_imgPointer to initiated IMG structure where Vt (or DVR) values will be placed.
ic_imgPointer to initiated IMG structure where plot y axis intercept values times -1 will be placed; enter NULL, if not needed.
nr_imgPointer to initiated IMG structure where the number of plot data points actually used in the fit is written; enter NULL, when not needed.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 228 of file img_mtga.c.

261 {
262 int zi, yi, xi, fi, nr, ret=0;
263 DFT tac;
264 double *plotData, *xaxis, *yaxis, slope, ic, f;
265 double aucrat;
266
267
268 if(verbose>0) {
269 printf("img_logan(%s, dyn_img, %d, %d, %g, %g, ki_img, ", __func__, start, end, thrs, k2);
270 if(ic_img==NULL) printf("NULL, "); else printf("ic_img, ");
271 if(nr_img==NULL) printf("NULL, "); else printf("nr_img, ");
272 if(status==NULL) printf("NULL)\n"); else printf("status)\n");
273 }
274 /* Initial check for the arguments */
275 if(status!=NULL) sprintf(status, "invalid data");
276 if(dyn_img->status!=IMG_STATUS_OCCUPIED || dyn_img->dimt<1) return(1);
277 if(input==NULL || input->frameNr<1) return(2);
278 nr=1+end-start; if(nr<2) return(3);
279 if(end>dyn_img->dimt-1 || start<0) return(4);
280 if(vt_img==NULL) return(5);
281 /* Convert input time units to min */
282 if(input->timeunit==TUNIT_SEC) dftTimeunitConversion(input, TUNIT_MIN);
283
284 /* Check that input contains samples until at least 80% of line fit range */
285 if(verbose>1) {
286 printf("input_last_sample_time := %g\n", input->x[input->frameNr-1]);
287 printf("logan_start_time := %g\n", dyn_img->start[start]/60.0);
288 printf("logan_end_time := %g\n", dyn_img->end[end]/60.0);
289 }
290 if(input->x[input->frameNr-1] < (0.2*dyn_img->mid[start]+0.8*dyn_img->mid[end])/60.0) {
291 sprintf(status, "too few input samples"); return(6);
292 }
293
294 /* Allocate memory for interpolated and integrated input and
295 tissue pixel TACs */
296 dftInit(&tac); if(dftSetmem(&tac, nr, 2)!=0) {sprintf(status, "out of memory"); return(11);}
297 strcpy(tac.voi[0].voiname, "input"); strcpy(tac.voi[1].voiname, "tissue");
298 tac.voiNr=2; tac.frameNr=nr;
299 for(int fi=0; fi<tac.frameNr; fi++) {
300 tac.x1[fi]=dyn_img->start[start+fi]/60.;
301 tac.x2[fi]=dyn_img->end[start+fi]/60.;
302 tac.x[fi]=dyn_img->mid[start+fi]/60.;
303 }
304
305 /* If input sample times are much different from PET frame times,
306 as they usually are if arterial plasma is used as input, then use
307 interpolate4pet(), otherwise with image-derived input use petintegral()
308 */
309 int equal_times;
310 equal_times=check_times_dft_vs_img(dyn_img, input, verbose-1);
311 if(equal_times==1) {
312 if(verbose>1) printf("copying input curve and using petintegral()\n");
313 /* Copy frame start and end times from image to input data */
314 ret=copy_times_from_img_to_dft(dyn_img, input, verbose-1);
315 if(ret) {
316 sprintf(status, "cannot set input sample times");
317 dftEmpty(&tac); return(12);
318 }
319 /* integral must be calculated from the zero time */
320 ret=petintegral(input->x1, input->x2, input->voi[0].y, input->frameNr,
321 input->voi[0].y2, input->voi[0].y3);
322 /* because times are the same, the values can be copied directly */
323 if(ret==0) for(fi=0; fi<tac.frameNr; fi++) {
324 tac.voi[0].y[fi]=input->voi[0].y[start+fi];
325 tac.voi[0].y2[fi]=input->voi[0].y2[start+fi];
326 tac.voi[0].y3[fi]=input->voi[0].y3[start+fi];
327 }
328 } else {
329 if(verbose>1) printf("using interpolate4pet() for input curve\n");
330 ret=interpolate4pet(
331 input->x, input->voi[0].y, input->frameNr,
332 tac.x1, tac.x2, tac.voi[0].y, tac.voi[0].y2, tac.voi[0].y3, tac.frameNr
333 );
334 }
335 if(ret) {
336 dftEmpty(&tac);
337 sprintf(status, "cannot interpolate input data"); return(12);
338 }
339 if(verbose>3) dftPrint(&tac);
340
341 /*
342 * Allocate result images and fill the header info
343 */
344 /* Vt image */
345 imgEmpty(vt_img);
346 ret=imgAllocateWithHeader(vt_img, dyn_img->dimz, dyn_img->dimy, dyn_img->dimx, 1, dyn_img);
347 if(ret) {
348 sprintf(status, "cannot setup memory for Vt image");
349 imgEmpty(vt_img); dftEmpty(&tac); return(21);
350 }
351 vt_img->unit=CUNIT_ML_PER_ML;
353 vt_img->start[0]=dyn_img->start[start]; vt_img->end[0]=dyn_img->end[end];
354 if(verbose>9) imgInfo(vt_img);
355 /* Ic image */
356 if(ic_img!=NULL) {
357 imgEmpty(ic_img);
358 ret=imgAllocateWithHeader(ic_img, dyn_img->dimz, dyn_img->dimy, dyn_img->dimx, 1, dyn_img);
359 if(ret) {
360 sprintf(status, "cannot setup memory for Ic image");
361 imgEmpty(ic_img); imgEmpty(vt_img); dftEmpty(&tac); return(23);
362 }
363 ic_img->unit=CUNIT_UNITLESS; /* mL/mL */
365 ic_img->start[0]=dyn_img->start[start]; ic_img->end[0]=dyn_img->end[end];
366 if(verbose>9) imgInfo(ic_img);
367 }
368 /* Nr image */
369 if(nr_img!=NULL) {
370 imgEmpty(nr_img);
371 ret=imgAllocateWithHeader(nr_img, dyn_img->dimz, dyn_img->dimy, dyn_img->dimx, 1, dyn_img);
372 if(ret) {
373 sprintf(status, "cannot setup memory for nr image");
374 imgEmpty(nr_img); imgEmpty(ic_img); imgEmpty(vt_img); dftEmpty(&tac);
375 return(25);
376 }
377 nr_img->unit=CUNIT_UNITLESS;
379 nr_img->start[0]=dyn_img->start[start]; nr_img->end[0]=dyn_img->end[end];
380 if(verbose>9) imgInfo(ic_img);
381 }
382
383 /* Allocate memory for graphical analysis plot data */
384 plotData=malloc(2*nr*sizeof(double));
385 if(plotData==NULL) {
386 sprintf(status, "cannot allocate memory for plots");
387 imgEmpty(ic_img); imgEmpty(vt_img); dftEmpty(&tac);
388 return(25);
389 }
390 xaxis=plotData; yaxis=plotData+nr;
391 float pxlauc[dyn_img->dimt];
392
393 /* Calculate threshold */
394 thrs*=tac.voi[0].y2[tac.frameNr-1];
395 if(verbose>1) printf(" threshold-AUC := %g\n", thrs);
396
397 /*
398 * Compute pixel-by-pixel
399 */
400 if(verbose>1) printf("computing MTGA pixel-by-pixel\n");
401 int best_nr;
402 for(zi=0; zi<dyn_img->dimz; zi++) {
403 for(yi=0; yi<dyn_img->dimy; yi++) {
404 for(xi=0; xi<dyn_img->dimx; xi++) {
405 /* Initiate pixel output values */
406 vt_img->m[zi][yi][xi][0]=0.0;
407 if(ic_img!=NULL) ic_img->m[zi][yi][xi][0]=0.0;
408 if(nr_img!=NULL) nr_img->m[zi][yi][xi][0]=0.0;
409 /* Copy TTAC values */
410 for(fi=0; fi<tac.frameNr; fi++) tac.voi[1].y[fi]=dyn_img->m[zi][yi][xi][start+fi];
411 /* Compute TTAC AUC(0-t) and check for threshold */
412 ret=fpetintegral(dyn_img->start, dyn_img->end, dyn_img->m[zi][yi][xi],
413 dyn_img->dimt, pxlauc, NULL);
414 if(ret) continue;
415 if((pxlauc[dyn_img->dimt-1]/60.0) < thrs) continue;
416 for(fi=0; fi<tac.frameNr; fi++)
417 tac.voi[1].y2[fi]=pxlauc[start+fi]/60.0; // conc*sec -> conc*min
418 /* Calculate Logan plot data */
419 int pn=logan_data(nr, tac.voi[0].y, tac.voi[0].y2, tac.voi[1].y, tac.voi[1].y2, k2, xaxis, yaxis);
420 /* Line fit */
421 if(fit_range==PRESET || pn<MTGA_BEST_MIN_NR) {
422 ret=llsqperp(xaxis, yaxis, pn, &slope, &ic, &f);
423 best_nr=pn;
424 } else {
425 ret=mtga_best_perp(xaxis, yaxis, pn, &slope, &ic, &f, &best_nr);
426 }
427 if(ret!=0) continue; // line fit failed
428 /* Use 10xAUCratio as upper limit to prevent image where only
429 noise-induced hot spots can be seen */
430 aucrat=tac.voi[1].y2[tac.frameNr-1]/tac.voi[0].y2[tac.frameNr-1];
431 if(slope>10.0*aucrat) {
432 if(verbose>50) printf("%g > 10 x %g\n", slope, aucrat);
433 slope=10.0*aucrat;
434 }
435 /* copy result to pixels */
436 vt_img->m[zi][yi][xi][0]=slope;
437 if(ic_img!=NULL) ic_img->m[zi][yi][xi][0]=-ic;
438 if(nr_img!=NULL) nr_img->m[zi][yi][xi][0]=best_nr;
439 } /* next column */
440 } /* next row */
441 } /* next plane */
442
443 free(plotData); dftEmpty(&tac);
444 return(0);
445}
int check_times_dft_vs_img(IMG *img, DFT *dft, int verbose)
Definition fittime.c:109
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
Definition img.c:279
int fpetintegral(float *x1, float *x2, float *y, int nr, float *ie, float *iie)
Integrate PET TAC data to frame mid times. Float version of petintegral().
Definition integr.c:838
int llsqperp(double *x, double *y, int nr, double *slope, double *ic, double *ssd)
Definition llsqwt.c:382
#define MTGA_BEST_MIN_NR
int mtga_best_perp(double *x, double *y, int nr, double *slope, double *ic, double *ssd, int *fnr)
Definition mtga.c:141
int logan_data(int data_nr, double *i, double *ii, double *c, double *ci, double k2, double *x, double *y)
Definition mtga.c:81

◆ img_patlak()

int img_patlak ( DFT * input,
IMG * dyn_img,
int start,
int end,
linefit_range fit_range,
float thrs,
IMG * ki_img,
IMG * ic_img,
IMG * nr_img,
char * status,
int verbose )

Computing pixel-by-pixel the graphical analysis for irreversible PET tracers (Gjedde-Patlak plot).

See also
img_logan, llsqperp, patlak_data, mtga_best_perp
Returns
Returns 0 if successful, and >0 in case of an error.
Parameters
inputPointer to the TAC data to be used as model input. Sample times in minutes. Curve is interpolated to PET frame times, if necessary.
dyn_imgPointer to dynamic PET image data. Image and input data must be in the same calibration units.
startThe range of frames where line is fitted, given as the frame start here and next the end index, i.e. [0..frame_nr-1].
endThe range of frames where line is fitted, given as the frame start above and here the end index, i.e. [0..frame_nr-1].
fit_rangeUse the whole range or based on data leave out points from the beginning; PRESET or EXCLUDE_BEGIN.
thrsThreshold as fraction of input AUC.
ki_imgPointer to initiated IMG structure where Ki values will be placed.
ic_imgPointer to initiated IMG structure where plot y axis intercept values will be placed; enter NULL, if not needed.
nr_imgPointer to initiated IMG structure where the number of plot data points actually used in the fit is written; enter NULL, when not needed.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 17 of file img_mtga.c.

48 {
49 int zi, yi, xi, fi, nr, ret=0;
50 DFT tac;
51 double *plotData, *xaxis, *yaxis, slope, ic, f;
52
53
54 if(verbose>0) {
55 printf("%s(input, dyn_img, %d, %d, range, %g, ki_img, ", __func__, start, end, thrs);
56 if(ic_img==NULL) printf("NULL, "); else printf("ic_img, ");
57 if(nr_img==NULL) printf("NULL, "); else printf("nr_img, ");
58 if(status==NULL) printf("NULL)\n"); else printf("status)\n");
59 }
60 /* Initial check for the arguments */
61 if(status!=NULL) sprintf(status, "invalid data");
62 if(dyn_img->status!=IMG_STATUS_OCCUPIED || dyn_img->dimt<1) return(1);
63 if(input==NULL || input->frameNr<1) return(2);
64 nr=1+end-start; if(nr<2) return(3);
65 if(end>dyn_img->dimt-1 || start<0) return(4);
66 if(ki_img==NULL) return(5);
67 /* Convert input time units to min */
68 if(input->timeunit==TUNIT_SEC) dftTimeunitConversion(input, TUNIT_MIN);
69
70 /* Check that input contains samples until at least 80% of line fit range */
71 if(verbose>1) {
72 printf("input_last_sample_time := %g\n", input->x[input->frameNr-1]);
73 printf("patlak_start_time := %g\n", dyn_img->start[start]/60.0);
74 printf("patlak_end_time := %g\n", dyn_img->end[end]/60.0);
75 }
76 if(input->x[input->frameNr-1] < (0.2*dyn_img->mid[start]+0.8*dyn_img->mid[end])/60.0) {
77 sprintf(status, "too few input samples"); return(6);
78 }
79
80 /* Allocate memory for interpolated and integrated input and
81 tissue pixel TACs */
82 dftInit(&tac); if(dftSetmem(&tac, nr, 2)!=0) {sprintf(status, "out of memory"); return(11);}
83 strcpy(tac.voi[0].voiname, "input"); strcpy(tac.voi[1].voiname, "tissue");
84 tac.voiNr=2; tac.frameNr=nr;
85 for(fi=0; fi<tac.frameNr; fi++) {
86 tac.x1[fi]=dyn_img->start[start+fi]/60.;
87 tac.x2[fi]=dyn_img->end[start+fi]/60.;
88 tac.x[fi]=dyn_img->mid[start+fi]/60.;
89 }
90
91 /* If input sample times are much different from PET frame times,
92 as they usually are if arterial plasma is used as input, then use
93 interpolate4pet(), otherwise with image-derived input use petintegral()
94 */
95 int equal_times;
96 equal_times=check_times_dft_vs_img(dyn_img, input, verbose-1);
97 if(equal_times==1) {
98 if(verbose>1) printf("copying input curve and using petintegral()\n");
99 /* Copy frame start and end times from image to input data */
100 ret=copy_times_from_img_to_dft(dyn_img, input, verbose-1);
101 if(ret) {
102 sprintf(status, "cannot set input sample times");
103 dftEmpty(&tac); return(12);
104 }
105 /* integral must be calculated from the zero time */
106 ret=petintegral(input->x1, input->x2, input->voi[0].y, input->frameNr,
107 input->voi[0].y2, input->voi[0].y3);
108 /* because times are the same, the values can be copied directly */
109 if(ret==0) for(fi=0; fi<tac.frameNr; fi++) {
110 tac.voi[0].y[fi]=input->voi[0].y[start+fi];
111 tac.voi[0].y2[fi]=input->voi[0].y2[start+fi];
112 tac.voi[0].y3[fi]=input->voi[0].y3[start+fi];
113 }
114 } else {
115 if(verbose>1) printf("using interpolate4pet() for input curve\n");
116 ret=interpolate4pet(
117 input->x, input->voi[0].y, input->frameNr,
118 tac.x1, tac.x2, tac.voi[0].y, tac.voi[0].y2, tac.voi[0].y3, tac.frameNr
119 );
120 }
121 if(ret) {
122 dftEmpty(&tac);
123 sprintf(status, "cannot interpolate input data"); return(12);
124 }
125 if(verbose>3) dftPrint(&tac);
126
127 /*
128 * Allocate result images and fill the header info
129 */
130 /* Ki image */
131 imgEmpty(ki_img);
132 ret=imgAllocateWithHeader(ki_img, dyn_img->dimz, dyn_img->dimy, dyn_img->dimx, 1, dyn_img);
133 if(ret) {
134 sprintf(status, "cannot setup memory for Ki image");
135 imgEmpty(ki_img); dftEmpty(&tac); return(21);
136 }
137 ki_img->unit=CUNIT_ML_PER_ML_PER_MIN; /* mL/(mL*min) */
139 ki_img->start[0]=dyn_img->start[start]; ki_img->end[0]=dyn_img->end[end];
140 if(verbose>9) imgInfo(ki_img);
141 /* Ic image */
142 if(ic_img!=NULL) {
143 imgEmpty(ic_img);
144 ret=imgAllocateWithHeader(ic_img, dyn_img->dimz, dyn_img->dimy, dyn_img->dimx, 1, dyn_img);
145 if(ret) {
146 sprintf(status, "cannot setup memory for Ic image");
147 imgEmpty(ic_img); imgEmpty(ki_img); dftEmpty(&tac); return(23);
148 }
149 ic_img->unit=CUNIT_ML_PER_ML; /* mL/mL */
151 ic_img->start[0]=dyn_img->start[start]; ic_img->end[0]=dyn_img->end[end];
152 if(verbose>9) imgInfo(ic_img);
153 }
154 /* Nr image */
155 if(nr_img!=NULL) {
156 imgEmpty(nr_img);
157 ret=imgAllocateWithHeader(nr_img, dyn_img->dimz, dyn_img->dimy, dyn_img->dimx, 1, dyn_img);
158 if(ret) {
159 sprintf(status, "cannot setup memory for nr image");
160 imgEmpty(nr_img); imgEmpty(ic_img); imgEmpty(ki_img); dftEmpty(&tac);
161 return(25);
162 }
163 nr_img->unit=CUNIT_UNITLESS;
165 nr_img->start[0]=dyn_img->start[start]; nr_img->end[0]=dyn_img->end[end];
166 if(verbose>9) imgInfo(ic_img);
167 }
168
169 /* Allocate memory for graphical analysis plot data */
170 plotData=malloc(2*nr*sizeof(double));
171 if(plotData==NULL) {
172 sprintf(status, "cannot allocate memory for plots");
173 imgEmpty(ic_img); imgEmpty(ki_img); dftEmpty(&tac); return(25);
174 }
175 xaxis=plotData; yaxis=plotData+nr;
176
177 /* Calculate threshold */
178 thrs*=tac.voi[0].y2[tac.frameNr-1];
179 if(verbose>1) printf(" threshold-AUC := %g\n", thrs);
180
181 /*
182 * Compute pixel-by-pixel
183 */
184 if(verbose>1) printf("computing MTGA pixel-by-pixel\n");
185 float pxlauc[dyn_img->dimt];
186 int best_nr;
187 for(zi=0; zi<dyn_img->dimz; zi++) {
188 for(yi=0; yi<dyn_img->dimy; yi++) {
189 for(xi=0; xi<dyn_img->dimx; xi++) {
190 /* Initiate pixel output values */
191 ki_img->m[zi][yi][xi][0]=0.0;
192 if(ic_img!=NULL) ic_img->m[zi][yi][xi][0]=0.0;
193 if(nr_img!=NULL) nr_img->m[zi][yi][xi][0]=0;
194 /* Check for threshold */
195 ret=fpetintegral(dyn_img->start, dyn_img->end, dyn_img->m[zi][yi][xi],
196 dyn_img->dimt, pxlauc, NULL);
197 if(ret) continue;
198 if((pxlauc[dyn_img->dimt-1]/60.0) < thrs) continue;
199 /* Calculate Patlak plot data */
200 for(fi=0; fi<tac.frameNr; fi++) tac.voi[1].y[fi]=dyn_img->m[zi][yi][xi][start+fi];
201 int pn=patlak_data(nr, tac.voi[0].y, tac.voi[0].y2, tac.voi[1].y, xaxis, yaxis);
202 /* Line fit */
203 if(fit_range==PRESET || pn<MTGA_BEST_MIN_NR) {
204 ret=llsqperp(xaxis, yaxis, pn, &slope, &ic, &f);
205 best_nr=pn;
206 } else {
207 ret=mtga_best_perp(xaxis, yaxis, pn, &slope, &ic, &f, &best_nr);
208 }
209 if(ret==0) {
210 ki_img->m[zi][yi][xi][0]=slope;
211 if(ic_img!=NULL) ic_img->m[zi][yi][xi][0]=ic;
212 if(nr_img!=NULL) nr_img->m[zi][yi][xi][0]=best_nr;
213 }
214 } /* next column */
215 } /* next row */
216 } /* next plane */
217
218 free(plotData); dftEmpty(&tac);
219 return(0);
220}
int patlak_data(int data_nr, double *i, double *ii, double *c, double *x, double *y)
Definition mtga.c:22

◆ imgEndtime()

double imgEndtime ( IMG * img)

Get IMG end time. Frame times are assumed to be sorted to increasing order.

See also
dftEndtime, fittime_from_img
Returns
Returns the last frame end time. By default, times are in sec.
Parameters
imgPointer to IMG structure.

Definition at line 339 of file fittime.c.

342 {
343 if(img==NULL || img->dimt<1) return(0.0);
344 for(int fi=img->dimt-1; fi>=0; fi--)
345 if(!isnan(img->end[fi])) return(img->end[fi]);
346 return(0.0);
347}

Referenced by imgReadModelingData().

◆ imgReadModelingData()

int imgReadModelingData ( char * petfile,
char * siffile,
char * inputfile1,
char * inputfile2,
char * inputfile3,
double * fitdur,
int * fitframeNr,
IMG * img,
DFT * inp,
DFT * iinp,
int verifypeak,
FILE * loginfo,
int verbose,
char * status )

Read PET image and input TAC for modelling.

Input calibration units are converted to units of tissue data. Input data is optionally interpolated to tissue times. If input data extends much further than fit duration, the last part is removed to save computation time in simulations. Input data is optionally verified not to end too early, and not to start too late.

Returns
Returns 0 when successful, otherwise a non-zero value.
See also
imgRead, dftRead, dftReadinput, dftReadModelingData, dftEndtime, imgEndtime
Parameters
petfilePET dynamic image filename; one time frame is sufficient here.
siffileOptional SIF. SIF is automatically read with NIfTI and Analyze formats, if found in the same folder and files are consistently named. SIF filename needs to be specified here only if that is not the case, or if other image formats do not contain information on frame times or tracer isotope, or if weights from SIF are needed. Enter NULL if not needed.
inputfile11st input data filename.
inputfile22nd input data filename (or NULL if only not needed).
inputfile33rd input data filename (or NULL if only not needed).
fitdurFit duration (in minutes); shortened if longer than PET data; enter <=0 to use all data in image; input is verified to not be much shorter than fitdur.
fitframeNrNr of time frames (samples) in PET data that are inside fitdur will be written here; pointer MUST be provided.
imgPointer to initiated IMG structure into which PET data will be written.
inpPointer to initiated DFT into which input data (plasma, blood, and/or reference tissue TAC) will be written without interpolation; enter NULL if not needed. Times will be in seconds, like in image.
iinpPointer to initiated DFT into which input data (plasma, blood, and/or reference tissue TAC) will be written, interpolated to PET frames; enter NULL if not needed. Times will be in seconds, like in image.
verifypeakSet to <>0 to verify that input TAC does not start too late and has decent peak to provide reliable AUC0-T.
loginfoGive file pointer (for example stdout) where log information is printed; NULL if not needed; warnings will be printed in stderr anyway.
verboseVerbose level; if zero, then only warnings are printed into stderr.
statusPointer to a string (allocated for at least 256 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 24 of file imginput.c.

67 {
68 int ret, fi, n, first, last, ii, input_nr=0;
69 DFT tmpdft, dft;
70 SIF sif;
71 double f, starttime, endtime;
72 FILE *wfp;
73 char *fname, tmp[512];
74
75
76 if(loginfo!=NULL && verbose>0) {
77 fprintf(loginfo, "imgReadModelingData(\n");
78 fprintf(loginfo, " %s,\n", petfile);
79 fprintf(loginfo, " %s,\n", inputfile1);
80 fprintf(loginfo, " %s,\n", inputfile2);
81 fprintf(loginfo, " %s,\n", inputfile3);
82 fprintf(loginfo, " %g,\n", *fitdur);
83 fprintf(loginfo, " *fitframeNr, *tis, *inp, *iinp *loginfo, %d, *status\n", verbose);
84 fprintf(loginfo, ")\n");
85 }
86 /* Check the function input */
87 if(status!=NULL) sprintf(status, "program error");
88 if(img==NULL || (inp==NULL && iinp==NULL)) return -1;
89 if(petfile==NULL || strlen(petfile)<1) return -2;
90 ret=0;
91 if(inputfile1==NULL || strlen(inputfile1)<1) return -3; else input_nr++;
92 if(inputfile2!=NULL && strlen(inputfile2)>0) input_nr++;
93 if(inputfile3!=NULL && strlen(inputfile3)>0) {
94 if(input_nr<2) return -4;
95 input_nr++;
96 }
97 if(fitframeNr==NULL || fitdur==NULL) return -5;
98 if(status!=NULL) sprintf(status, "arguments validated");
99 /* Warnings will be printed into stderr */
100 wfp=stderr;
101
102 /* Check that input file(s) exist, because image is read first, and it might take a while */
103 if(loginfo!=NULL && verbose>1) fprintf(loginfo, "checking access to input files\n");
104 if(access(inputfile1, 0) == -1) {
105 sprintf(tmp, "cannot read '%s'", inputfile1);
106 if(status!=NULL) strcpy(status, tmp);
107 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
108 else fprintf(wfp, "Error: %s\n", tmp);
109 return(1);
110 }
111 for(ii=2; ii<=input_nr; ii++) {
112 if(ii==2) fname=inputfile2; else fname=inputfile3;
113 if(access(fname, 0) == -1) {
114 sprintf(tmp, "cannot read '%s'", fname);
115 if(status!=NULL) strcpy(status, tmp);
116 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
117 else fprintf(wfp, "Error: %s\n", tmp);
118 return(1);
119 }
120 }
121
122 /* Delete any previous data and initiate temp data */
123 dftEmpty(inp); dftEmpty(iinp); imgEmpty(img);
124
125
126 /*
127 * Read PET image
128 */
129 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading image %s\n", petfile);
130 imgInit(img);
131 ret=imgRead(petfile, img); fflush(stderr); fflush(stdout);
132 if(ret) {
133 sprintf(tmp, "cannot read '%s': %s", petfile, img->statmsg);
134 if(status!=NULL) strcpy(status, tmp);
135 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
136 else fprintf(wfp, "Error: %s\n", tmp);
137 if(loginfo!=NULL) fprintf(loginfo, "imgRead(%s, img) := %d\n", petfile, ret);
138 return(2);
139 }
140 /* Check if PET data is raw or image */
141 if(img->type!=IMG_TYPE_IMAGE) {
142 sprintf(tmp, "%s is not an image.\n", petfile);
143 if(status!=NULL) strcpy(status, tmp);
144 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
145 else fprintf(wfp, "Error: %s\n", tmp);
146 imgEmpty(img); return(3);
147 }
148 if(loginfo!=NULL && verbose>2)
149 fprintf(loginfo, "image contains %d frames and %d planes.\n", img->dimt, img->dimz);
150
151 /* Read SIF, if specified */
152 if(siffile!=NULL && siffile[0]) {
153 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading SIF %s\n", siffile);
154 sifInit(&sif);
155 ret=sifRead(siffile, &sif);
156 if(ret) {
157 sprintf(tmp, "cannot read '%s': %s", siffile, siferrmsg);
158 if(status!=NULL) strcpy(status, tmp);
159 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
160 else fprintf(wfp, "Error: %s\n", tmp);
161 imgEmpty(img); return(4);
162 }
163 /* Get isotope from SIF, if available */
164 {
165 double hl;
167 if(hl>0.0) {
168 img->isotopeHalflife=60.0*hl;
169 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "isotope code read from %s\n", siffile);
170 }
171 }
172 /* Get frame times from SIF if not available in image */
173 if(!imgExistentTimes(img) && img->dimt<=sif.frameNr) {
174 for(fi=0; fi<img->dimt; fi++) {
175 img->start[fi]=sif.x1[fi]; img->end[fi]=sif.x2[fi];
176 img->mid[fi]=0.5*(sif.x1[fi]+sif.x2[fi]);
177 }
178 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "image frame times read from %s\n", siffile);
179 }
180 sifEmpty(&sif);
181 }
182
183 /* Check that image frame times are available */
184 if(loginfo!=NULL && verbose>1) fprintf(loginfo, "checking image contents\n");
185 if(!imgExistentTimes(img)) {
186 strcpy(tmp, "image frame times not available");
187 if(status!=NULL) strcpy(status, tmp);
188 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
189 else fprintf(wfp, "Error: %s\n", tmp);
190 imgEmpty(img); return(5);
191 }
192 /* Make sure that there is no overlap in image frames */
193 if(loginfo!=NULL && verbose>1) fprintf(loginfo, "checking frame overlap in %s\n", petfile);
194 ret=imgDeleteFrameOverlap(img);
195 if(ret) {
196 strcpy(tmp, "image has overlapping frame times");
197 if(status!=NULL) strcpy(status, tmp);
198 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
199 else fprintf(wfp, "Error: %s\n", tmp);
200 imgEmpty(img); return(5);
201 }
202 /* Check fit end time with the PET image */
203 if(!(*fitdur>0.0)) *fitdur=1.0E+99;
204 else if(*fitdur<1.0E+10) *fitdur*=60.0; // fit time must be in sec
205 *fitframeNr=fittime_from_img(img, fitdur, verbose-2);
206 if(*fitframeNr<1 || *fitdur<=3.5) {
207 strcpy(tmp, "image has no data in fit time range");
208 if(status!=NULL) strcpy(status, tmp);
209 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
210 else fprintf(wfp, "Error: %s\n", tmp);
211 imgEmpty(img); return(5);
212 }
213 *fitdur/=60.0; // back to minutes
214 if(loginfo!=NULL && verbose>3) {
215 fprintf(loginfo, "fittimeFinal := %g min\n", *fitdur);
216 fprintf(loginfo, "fitframeNr := %d\n", *fitframeNr);
217 }
218
219
220 /*
221 * Read first input data
222 */
223 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading input data in %s\n", inputfile1);
224 dftInit(&dft);
225 if(dftRead(inputfile1, &dft)) {
226 sprintf(tmp, "cannot read '%s': %s", inputfile1, dfterrmsg);
227 if(status!=NULL) strcpy(status, tmp);
228 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
229 else fprintf(wfp, "Error: %s\n", tmp);
230 imgEmpty(img); return(11);
231 }
232 /* Check TAC nr */
233 if(dft.voiNr>1) {
234 if(verbose>0) {
235 strcpy(tmp, "only first TAC is used as input");
236 if(loginfo!=NULL) fprintf(loginfo, "Warning: %s.\n", tmp);
237 else fprintf(wfp, "Warning: %s.\n", tmp);
238 }
239 dft.voiNr=1;
240 }
241 /* check if file contains NAs (missing values) */
242 if(dft_nr_of_NA(&dft)>0) {
243 strcpy(tmp, "missing values in input file");
244 if(status!=NULL) strcpy(status, tmp);
245 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
246 else fprintf(wfp, "Error: %s.\n", tmp);
247 imgEmpty(img); dftEmpty(&dft); return(12);
248 }
249 /* Check the concentration units */
250 ret=cunit_check_dft_vs_img(&dft, img, tmp, verbose-2);
251 if(ret==0) {
252 if(loginfo!=NULL && verbose>3) fprintf(loginfo, "%s\n", tmp);
253 } else if(ret<0) {
254 fprintf(wfp, "Warning: %s\n", tmp);
255 } else {
256 if(status!=NULL) strcpy(status, tmp);
257 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
258 else fprintf(wfp, "Error: %s.\n", tmp);
259 imgEmpty(img); dftEmpty(&dft); return(13);
260 }
261 if(verbose>3)
262 printf("input time range := %g - %g %s\n",
263 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
264 /* Set time unit to sec like in IMG */
265 if(dft.timeunit==TUNIT_UNKNOWN) {
266 if(dftEndtime(&dft)<0.2*imgEndtime(img)) dft.timeunit=TUNIT_MIN;
267 else dft.timeunit=TUNIT_SEC;
268 fprintf(wfp, "Warning: assuming that times are in %s in %s\n",
269 petTunit(dft.timeunit), inputfile1);
270 }
271 /* Set time unit to sec like in IMG */
272 ret=dftTimeunitConversion(&dft, TUNIT_SEC);
273 if(verbose>1)
274 printf("input time range := %g - %g %s\n",
275 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
276
277 /* Verify the peak if requested; only for the first input TAC, because
278 for example metabolite TAC may not show bolus shape */
279 if(verifypeak!=0) {
280 if(loginfo!=NULL && verbose>1) fprintf(loginfo, "verifying input peak\n");
281 ret=dftVerifyPeak(&dft, 0, verbose-5, tmp);
282 if(ret>0) {
283 if(status!=NULL) strcpy(status, tmp);
284 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
285 else fprintf(wfp, "Error: %s.\n", tmp);
286 imgEmpty(img); dftEmpty(&dft); return(14);
287 }
288 }
289 if(verbose>5)
290 printf("input time range := %g - %g %s\n",
291 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
292
293
294 /*
295 * Read following input files, if required
296 */
297 dftInit(&tmpdft);
298 for(ii=2; ii<=input_nr; ii++) {
299 if(ii==2) fname=inputfile2; else fname=inputfile3;
300
301 /* Make room for one more curve in input data */
302 ret=dftAddmem(&dft, 1);
303 if(ret) {
304 strcpy(tmp, "cannot allocate more memory");
305 if(status!=NULL) strcpy(status, tmp);
306 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
307 else fprintf(wfp, "Error: %s\n", tmp);
308 imgEmpty(img); dftEmpty(&dft); return(15);
309 }
310 /* Read input TAC */
311 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "reading input data in %s\n", fname);
312 if(dftRead(fname, &tmpdft)) {
313 sprintf(tmp, "cannot read '%s': %s", fname, dfterrmsg);
314 if(status!=NULL) strcpy(status, tmp);
315 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
316 else fprintf(wfp, "Error: %s\n", tmp);
317 imgEmpty(img); dftEmpty(&dft); return(16);
318 }
319 /* Check TAC nr */
320 if(tmpdft.voiNr>1) {
321 if(verbose>0) {
322 strcpy(tmp, "only first TAC is used as input");
323 if(loginfo!=NULL) fprintf(loginfo, "Warning: %s.\n", tmp);
324 else fprintf(wfp, "Warning: %s.\n", tmp);
325 }
326 dft.voiNr=1;
327 }
328 /* check if file contains NAs (missing values) */
329 if(dft_nr_of_NA(&tmpdft)>0) {
330 strcpy(tmp, "missing values in input file");
331 if(status!=NULL) strcpy(status, tmp);
332 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
333 else fprintf(wfp, "Error: %s\n", tmp);
334 imgEmpty(img); dftEmpty(&dft); dftEmpty(&tmpdft); return(17);
335 }
336 /* Check and correct the sample time unit */
337 if(tmpdft.timeunit==TUNIT_UNKNOWN) {
338 if(dftEndtime(&tmpdft)<0.2*imgEndtime(img)) tmpdft.timeunit=TUNIT_MIN;
339 else tmpdft.timeunit=TUNIT_SEC;
340 fprintf(wfp, "Warning: assuming that times are in %s in %s\n",
341 petTunit(tmpdft.timeunit), fname);
342 }
343 dftTimeunitConversion(&tmpdft, dft.timeunit);
344 /* Check the concentration units */
345 ret=cunit_check_dft_vs_img(&tmpdft, img, tmp, verbose-2);
346 if(ret==0) {
347 if(loginfo!=NULL && verbose>3) fprintf(loginfo, "%s\n", tmp);
348 } else if(ret<0) {
349 fprintf(wfp, "Warning: %s\n", tmp);
350 } else {
351 if(status!=NULL) strcpy(status, tmp);
352 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
353 else fprintf(wfp, "Error: %s\n", tmp);
354 imgEmpty(img); dftEmpty(&dft); dftEmpty(&tmpdft); return(18);
355 }
356 /* Copy to input data */
357 if(loginfo!=NULL && verbose>1)
358 fprintf(loginfo, "interpolating %d samples into %d samples.\n", tmpdft.frameNr, dft.frameNr);
359 ret=dftInterpolateInto(&tmpdft, &dft, tmp, verbose);
360 if(ret) {
361 if(loginfo!=NULL) fprintf(loginfo, "dftInterpolateInto() := %d\n", ret);
362 if(status!=NULL) strcpy(status, tmp);
363 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
364 else fprintf(wfp, "Error: %s\n", tmp);
365 imgEmpty(img); dftEmpty(&dft); dftEmpty(&tmpdft); return(19);
366 }
367 /* Remove the originally read input data */
368 dftEmpty(&tmpdft);
369
370 } // next input file
371 if(verbose>10)
372 printf("input time range := %g - %g %s\n",
373 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
374
375
376 /*
377 * Check and set input data range vs fit time length
378 */
379 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "checking and setting input sample time range\n");
380 /* Check that input data does not end _much_ before fitdur;
381 dftInterpolateForIMG() below tests this again. */
382 starttime=0; endtime=*fitdur; // start and end times always in min
383 n=fittime_from_dft(&dft, &starttime, &endtime, &first, &last, verbose-1);
384 if(loginfo!=NULL && verbose>2) {
385 fprintf(loginfo, "starttime := %g min\n", starttime);
386 fprintf(loginfo, "endtime := %g min\n", endtime);
387 fprintf(loginfo, "sample_nr := %d\n", n);
388 }
389 if(*fitdur>1.5*endtime && (*fitdur-endtime)>0.15) {
390 strcpy(tmp, "input TAC is too short");
391 if(status!=NULL) strcpy(status, tmp);
392 else if(verbose>0) fprintf(wfp, "Error: %s\n", tmp);
393 imgEmpty(img); dftEmpty(&dft); return(21);
394 }
395#if(0)
396 /* Do NOT test this here! It would prevent using this function in
397 reading steady-state studies etc */
398 if(n<4) {
399 strcpy(tmp, "too few input samples in specified fit duration");
400 if(status!=NULL) strcpy(status, tmp);
401 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s\n", tmp);
402 else fprintf(wfp, "Error: %s\n", tmp);
403 imgEmpty(img); dftEmpty(&dft); return(22);
404 }
405#endif
406 /* Cut off too many input samples to make calculation faster */
407 if(verbose>10) {
408 printf("input time range := %g - %g %s\n",
409 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
410 printf("fitdur := %g min\n", *fitdur);
411 }
412 f=*fitdur*60.0+60.0; // add 60 s to allow time delay correction
413 if(dftEndtime(&dft)>f) {
414 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "Input TAC cutoff at %g sec\n", f);
415 for(fi=0; fi<dft.frameNr; fi++) if(dft.x[fi]>f) break;
416 if(fi<dft.frameNr) fi++;
417 dft.frameNr=fi;
418 }
419 if(verbose>10) printf("input time range := %g - %g %s\n",
420 dft.x[0], dft.x[dft.frameNr-1], petTunit(dft.timeunit));
421
422 /* Copy input data to given pointer, if required */
423 if(inp!=NULL) {
424 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "copying input TAC\n");
425 ret=dftdup(&dft, inp);
426 if(ret!=0) {
427 strcpy(tmp, "cannot copy TAC contents");
428 if(status!=NULL) strcpy(status, tmp);
429 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
430 else fprintf(wfp, "Error: %s\n", tmp);
431 imgEmpty(img); dftEmpty(&dft); return(31);
432 }
433 }
434
435 /* Interpolate input data to given pointer, if required */
436 if(iinp!=NULL) {
437 if(loginfo!=NULL && verbose>0) fprintf(loginfo, "interpolating input TAC\n");
438 ret=dftInterpolateForIMG(&dft, img, *fitframeNr, iinp, NULL, NULL, verbose, tmp);
439 if(ret!=0) {
440 if(status!=NULL) strcpy(status, tmp);
441 else if(loginfo!=NULL) fprintf(loginfo, "Error: %s.\n", tmp);
442 else fprintf(wfp, "Error: %s\n", tmp);
443 imgEmpty(img); dftEmpty(&dft); return(33);
444 }
445 }
446
447 dftEmpty(&dft);
448 if(status!=NULL) sprintf(status, "ok");
449 return(0);
450}
double imgEndtime(IMG *img)
Definition fittime.c:339
int fittime_from_img(IMG *img, double *fittime, int verbose)
Definition fittime.c:74
double dftEndtime(DFT *dft)
Definition fittime.c:315
double hlFromIsotope(char *isocode)
Definition halflife.c:55
int imgExistentTimes(IMG *img)
Definition img.c:613
void imgInit(IMG *image)
Definition img.c:60
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgDeleteFrameOverlap(IMG *img)
Definition imgframe.c:77
void sifInit(SIF *data)
Definition sif.c:17
void sifEmpty(SIF *data)
Definition sif.c:33
int sifRead(char *filename, SIF *data)
Definition sifio.c:21
#define IMG_TYPE_IMAGE
char siferrmsg[128]
Definition sif.c:7
int dftInterpolateForIMG(DFT *input, IMG *img, int frame_nr, DFT *output, double *ti1, double *ti2, int verbose, char *status)
Definition misc_model.c:17
int cunit_check_dft_vs_img(DFT *dft, IMG *img, char *errmsg, int verbose)
Definition units_check.c:18
char type
const char * statmsg
float isotopeHalflife
double * x1
int frameNr
double * x2
char isotope_name[8]

◆ imgSetWeights()

int imgSetWeights ( IMG * img,
int wmet,
int verbose )

Add weights based on average voxel values and frame lengths, just frame lengths, or set all weights to 1 (no weighting).

Existing weights are overwritten. Decay correction is not considered in calculation of weights.

Returns
Returns 0 when successful, otherwise <>0.
See also
dftWeightByFreq, sifWeight, sifWeightByFrames
Parameters
imgPointer to IMG struct; image data is used to calculate relational frame weights, which are also written into IMG struct.
wmetWeighting method: 0=based on mean voxel values times frame lengths; 1=based on frame lengths, 2=set weights to 1 (no weighting).
verboseVerbose level; if zero, then only warnings are printed into stderr

Definition at line 85 of file weight_model.c.

94 {
95 if(verbose>0) printf("imgSetWeights(*img, %d, ...)\n", wmet);
96 /* Check the function input */
97 if(img==NULL) return(1);
98 if(img->status!=IMG_STATUS_OCCUPIED) return(2);
99 if(img->dimt<1 || img->dimx<1 || img->dimy<1 || img->dimz<1) return(3);
100 if(wmet<0 || wmet>2) return(4);
101 img->isWeight=0;
102
103 /* If one time frame, then weight is 1 */
104 if(img->dimt==1) {
105 img->weight[0]=1.0;
106 if(wmet==0 || wmet==1) img->isWeight=1;
107 return(0);
108 }
109
110 int fi, ret;
111 double f, fm;
112
113 if(wmet==2) { /* If weights are to be set to 1 (removed) */
114 for(fi=0; fi<img->dimt; fi++) img->weight[fi]=1.0;
115 return(0);
116 }
117
118 if(wmet==0) { /* weight based on frame mean values and durations */
119 SIF sif;
120 sifInit(&sif);
121 ret=sifAllocateWithIMG(&sif, img, 1, verbose); if(ret) return(100+ret);
122 sifModerateTrues(&sif, 100.0);
123 sifWeight(&sif, 0.0); if(verbose>2) sifPrint(&sif);
124 for(fi=0; fi<img->dimt; fi++) img->weight[fi]=sif.weights[fi];
125 sifEmpty(&sif);
126 } else if(wmet==1) { /* weight based on frame durations */
127 for(fi=0, fm=0.0; fi<img->dimt; fi++) {
128 f=img->end[fi]-img->start[fi]; fm+=f;
129 img->weight[fi]=f;
130 }
131 /* scale weights so that sum of weights equals sample number */
132 if(fm>0.0) f=(double)img->dimt/fm; else f=1.0;
133 for(fi=0; fi<img->dimt; fi++) img->weight[fi]*=f;
134 }
135 img->isWeight=1;
136 return(0);
137}
void sifModerateTrues(SIF *sif, double limit)
Definition weight.c:131
void sifPrint(SIF *data)
Definition sifio.c:234
void sifWeight(SIF *data, double halflife)
Calculate weights for frames in SIF data based on true counts. Weights are normalized to have an aver...
Definition weight.c:28
int sifAllocateWithIMG(SIF *sif, IMG *img, int doCounts, int verbose)
Definition misc_model.c:418
float * weight
double * weights

◆ imgTimeIntegral()

int imgTimeIntegral ( IMG * img,
float t1,
float t2,
IMG * iimg,
int calc_mode,
char * status,
int verbose )

Integration of dynamic image from time1 to time2, storing integrals in iimg, which is allocated here. Frames do not have to be continuous in time. Time unit in integral is sec. Raw data (sinogram) must be divided by frame durations before calling this. You may want to test the time range before applying this routine, because this function accepts relatively large extrapolation.

See also
imgFrameIntegral, dftInterpolateForIMG, imgExistentTimes
Returns
Returns errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.
Parameters
imgIMG data; preferably dynamic, if static, then the specified time range must match with the frame time.
t1Time where to start integration (sec).
t2Time to stop integration (sec); must be higher than t1.
iimgPointer to initiated but empty AUC IMG data.
calc_modeCalculate integral or average: 0=integral, 1=average.
statusPointer to a string (allocated for at least 128 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 147 of file misc_model.c.

164 {
165 int ret;
166 double accept_tdif=1.0; // in seconds
167
168 if(verbose>0) {
169 printf("%s(img, %g, %g, iimg, %d, status, %d)\n", __func__, t1, t2, calc_mode, verbose);
170 fflush(stdout);
171 }
172
173 /* Check the arguments */
174 if(status!=NULL) sprintf(status, "program error");
175 if(img==NULL || iimg==NULL || t1<0.0 || t2<0.0) return STATUS_FAULT;
176 if(img->status!=IMG_STATUS_OCCUPIED) return STATUS_FAULT;
177 float fdur=t2-t1; if(fdur<=0.0) return STATUS_FAULT;
178 if(img->dimt<1) return STATUS_FAULT;
179
180 /* Check that time range matches with image frame */
181 if(img->dimt==1) { // static image (one frame only)
182 /* check that specified times match with image frame times, but accept 1 s differences */
183 if(fabs(img->end[0]-t2)>accept_tdif || fabs(img->start[0]-t1)>accept_tdif) {
184 if(status!=NULL) sprintf(status,
185 "for static image the integration time range must be exactly as long as the scan");
186 return STATUS_FAULT;
187 }
188 /* Set the times, in case there was a small difference */
189 img->end[0]=t2; img->start[0]=t1; img->mid[0]=0.5*(t1+t2);
190 } else { // Dynamic image (more than one frame)
191 /* First PET frame must start before 1/3 of the integration time */
192 /* Last PET frame must end after 2/3 of integration time */
193 if(img->start[0]>(0.66*t1+0.34*t2) || img->end[img->dimt-1]<(0.34*t1+0.66*t2)) {
194 if(status!=NULL) sprintf(status, "integration time range oversteps data range");
195 return STATUS_FAULT;
196 }
197 }
198 if(verbose>10) printf("t1=%g t2=%g fdur=%g\n", t1, t2, fdur);
199
200 /* Get the first and last frame index that resides inside integration time */
201 int f1, f2;
202 if(img->dimt==1) {
203 f1=f2=0;
204 } else {
205 f1=f2=-1;
206 for(int fi=0; fi<img->dimt; fi++) {
207 if(f1<0) {if(img->start[fi]>=t1 && img->end[fi]<=t2) f1=f2=fi;}
208 if(f1>=0) {if(t2>=img->end[fi]) f2=fi;}
209 }
210 }
211 if(verbose>10) printf("f1=%d f2=%d\n", f1, f2);
212
213 float aucroi, t[2], auc[2];
214 if(f1>=0 && f2>=0) {
215
216 /* Integrate over the frames that are included in time range as a whole */
217 ret=imgFrameIntegral(img, f1, f2, iimg, verbose-1);
218 if(ret) {
219 if(status!=NULL) sprintf(status, "cannot integrate (%d)", ret);
220 return STATUS_FAULT;
221 }
222
223 /* If necessary, add the partial integrals */
224 if(img->start[f1]>t1) {
225 t[0]=t1; t[1]=img->start[f1];
226 if(verbose>20) printf("t[0]=%g t[1]=%g\n", t[0], t[1]);
227 for(int zi=0; zi<img->dimz; zi++)
228 for(int yi=0; yi<img->dimy; yi++)
229 for(int xi=0; xi<img->dimx; xi++) {
230 ret=finterpolate(img->mid, img->m[zi][yi][xi], img->dimt, t, NULL, auc, NULL, 2);
231 if(ret) aucroi=0.0; else aucroi=auc[1]-auc[0];
232 iimg->m[zi][yi][xi][0]+=aucroi;
233 }
234 }
235 if(t2>img->end[f2]) {
236 t[0]=img->end[f2]; t[1]=t2;
237 if(verbose>20) printf("t[0]=%g t[1]=%g\n", t[0], t[1]);
238 for(int zi=0; zi<img->dimz; zi++)
239 for(int yi=0; yi<img->dimy; yi++)
240 for(int xi=0; xi<img->dimx; xi++) {
241 ret=finterpolate(img->mid, img->m[zi][yi][xi], img->dimt, t, NULL, auc, NULL, 2);
242 if(ret) aucroi=0.0; else aucroi=auc[1]-auc[0];
243 iimg->m[zi][yi][xi][0]+=aucroi;
244 }
245 }
246
247 } else { // no full frames inside integration range
248
249 /* Create the AUC image */
250 ret=imgAllocateWithHeader(iimg, img->dimz, img->dimy, img->dimx, 1, img);
251 if(ret!=0) {
252 if(status!=NULL) sprintf(status, "cannot setup integral image");
253 return STATUS_FAULT;
254 }
255
256 t[0]=t1; t[1]=t2;
257 for(int zi=0; zi<img->dimz; zi++)
258 for(int yi=0; yi<img->dimy; yi++)
259 for(int xi=0; xi<img->dimx; xi++) {
260 ret=finterpolate(img->mid, img->m[zi][yi][xi], img->dimt, t, NULL, auc, NULL, 2);
261 if(ret) aucroi=0.0; else aucroi=auc[1]-auc[0];
262 iimg->m[zi][yi][xi][0]+=aucroi;
263 }
264
265 }
266
267 /* Set output image time frame */
268 iimg->end[0]=t2; iimg->start[0]=t1; iimg->mid[0]=0.5*(t1+t2);
269
270 /* If required, then calculate average by dividing integral with time. */
271 /* Set units accordingly */
272 if(calc_mode!=0) { // average
273 ret=imgArithmConst(iimg, fdur, ':', 1.0E+10, verbose-1);
274 if(ret!=0) {
275 if(status!=NULL) sprintf(status, "cannot divide integral image");
276 return STATUS_FAULT;
277 }
278 iimg->unit=img->unit;
279 if(status!=NULL) sprintf(status, "average image [%g,%g] calculated",t1,t2);
280 } else { // integral
281 if(img->unit==CUNIT_KBQ_PER_ML) iimg->unit=CUNIT_SEC_KBQ_PER_ML;
282 else iimg->unit=CUNIT_UNKNOWN;
283 if(status!=NULL) sprintf(status, "integral image [%g,%g] calculated",t1,t2);
284 }
285
286 imgSetStatus(iimg, STATUS_OK);
287 return(0);
288}
void imgSetStatus(IMG *img, int status_index)
Definition img.c:345
int imgFrameIntegral(IMG *img, int first, int last, IMG *iimg, int verbose)
Definition imgarithm.c:346
int imgArithmConst(IMG *img, float operand, char operation, float ulimit, int verbose)
Definition imgarithm.c:100
int finterpolate(float *x, float *y, int nr, float *newx, float *newy, float *newyi, float *newyii, int newnr)
float version of interpolate().
Definition integr.c:161

◆ mrl_between_tacs()

int mrl_between_tacs ( double * y1,
double * y2,
int n )

Return the maximum run length between given n length arrays of data

Parameters
y1Array of data1; may contain NaNs
y2Array of data2; may contain NaNs
nNr of samples in array 1 and 2

Definition at line 13 of file mrl.c.

20 {
21 int i, mrl=0, rl=0;
22 char last_sign=0, sign;
23
24 if(n<1 || y1==NULL || y2==NULL) return(0);
25 for(i=0; i<n; i++) {
26 if(isnan(y1[i]) || isnan(y2[i])) continue;
27 if(y1[i]>y2[i]) sign=1; else if(y1[i]<y2[i]) sign=-1; else sign=0;
28 if(sign!=last_sign) {
29 rl=0; last_sign=sign;
30 } else {
31 if(sign!=0) {rl++; if(rl>mrl) mrl=rl;}
32 }
33 }
34 return(mrl);
35}

◆ noiseSD4Simulation()

int noiseSD4Simulation ( double y,
double t1,
double dt,
double hl,
double a,
double * sd,
char * status,
int verbose )

Calculate SD for PET radioactivity concentration data to be used to simulate noise.

Note that SD is dependent on the time units.

Reference: Varga & Szabo. J Cereb Blood Flow Metab 2002;22(2):240-244.

Returns
Returns 0 when successful, otherwise <>0.
Parameters
ySample radioactivity concentration (decay corrected to zero time)
t1Radioactivity measurement (frame) start time (in same units as the halflife)
dtRadioactivity measurement (frame) duration (in same units as the halflife)
hlIsotope halflife (in same units as the sample time); enter 0 if not to be considered
aProportionality factor. Note that it is inside square root.
sdPointer in which SD is written
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 21 of file noise.c.

42 {
43 double d, lambda, f;
44
45 if(verbose>0) printf("noiseSD4Simulation(%g, %g, %g, %g, %g, *sd, ...)\n",
46 y, t1, dt, hl, a);
47 if(status!=NULL) strcpy(status, "invalid data");
48 if(sd==NULL) return 1;
49 if(t1<0.0) return 2;
50 if(dt<=0.0) return 3;
51
52 /* Decay factor (<=1) */
53 if(hl<=0.0) {
54 d=1.0; lambda=0.0;
55 } else {
56 if(status!=NULL) strcpy(status, "invalid half-life");
57 lambda=hl2lambda(hl); if(lambda<0.0) return 4;
58 d=hlLambda2factor(-lambda, t1, dt); if(d<0.0) return 5;
59 }
60 /* SD */
61 f=y*d*dt;
62 if(f<=0.0) *sd=0.0;
63 else *sd=y*sqrt(a/f);
64
65 if(status!=NULL) strcpy(status, "ok");
66 return(0);
67}
double hl2lambda(double halflife)
Definition halflife.c:84
double hlLambda2factor(double lambda, double frametime, double framedur)
Definition halflife.c:98

Referenced by noiseSD4SimulationFromDFT().

◆ noiseSD4SimulationFromDFT()

int noiseSD4SimulationFromDFT ( DFT * dft,
int index,
double pc,
double * sd,
char * status,
int verbose )

Calculate SD for noise simulation from TAC data.

Sample times will be converted to minutes if necessary.

Reference: Varga & Szabo. J Cereb Blood Flow Metab 2002;22(2):240-244.

Returns
Returns 0 when successful, otherwise <>0.
Parameters
dftPointer to TAC data in DFT struct, based on which the SD for each frame is calculated. Contents are not changed. Struct must contain correct values for the isotope, time unit, and frame times (start and end). Status of decay correction is used, and if not known, then data is assumed to be decay corrected.
indexTAC index [0..voiNr-1] which is used to calculate the SD in case DFT contains more than one TAC. Non-effective if DFT contains only one TAC. Set to <0 if mean of all TACs is to be used.
pcProportionality factor
sdPointer to allocated array in which SD is written
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 79 of file noise.c.

99 {
100 int ret, fi;
101 double hl=0.0, t1, deltat;
102 double *y;
103 DFT mean;
104
105 if(verbose>0) printf("noiseSD4SimulationFromDFT(DFT, %d, %g, sd[], ...)\n",
106 index, pc);
107 if(status!=NULL) strcpy(status, "invalid data");
108 if(dft==NULL || sd==NULL) return 1;
109 if(dft->voiNr<1 || dft->frameNr<1) return 2;
110 if(dft->voiNr>1 && index>=dft->voiNr) return 3;
111
112 /* Check that valid frame times are available */
113 if(status!=NULL) strcpy(status, "invalid frame times");
114 for(fi=0; fi<dft->frameNr; fi++)
115 if(dft->x2[fi]<=dft->x1[fi] || dft->x1[fi]<0.0) return 4;
116 if(status!=NULL) strcpy(status, "missing time unit");
117 if(dft->timeunit!=TUNIT_SEC && dft->timeunit!=TUNIT_MIN) return 5;
118
119 /* Check if isotope is available, if it is needed */
122 {
123 hl=hlFromIsotope(dft->isotope);
124 if(status!=NULL) strcpy(status, "missing isotope halflife");
125 if(hl<=0.0) return 6;
126 }
127 if(verbose>1) printf("halflife := %g\n", hl);
128
129 /* Set pointer to activity concentration data */
130 dftInit(&mean);
131 if(dft->voiNr==1) {
132 y=dft->voi[0].y;
133 } else if(index>=0) {
134 y=dft->voi[index].y;
135 } else {
136 /* Compute TAC mean */
137 ret=dftMeanTAC(dft, &mean); if(ret!=0) {
138 if(status!=NULL) strcpy(status, "cannot calculate mean TAC");
139 return 8;
140 }
141 /* and use that */
142 y=mean.voi[0].y;
143 }
144
145 /* Compute SD for each sample time */
146 if(pc<=0.0) pc=1.0;
147 for(fi=0; fi<dft->frameNr; fi++) {
148 t1=dft->x1[fi]; deltat=dft->x2[fi]-dft->x1[fi];
149 if(dft->timeunit==TUNIT_SEC) {t1/=60.0; deltat/=60.0;}
150 ret=noiseSD4Simulation(y[fi], t1, deltat, hl, pc, sd+fi, status, verbose);
151 if(ret!=0) break;
152 }
153 dftEmpty(&mean);
154 if(ret!=0) {
155 if(status!=NULL)
156 sprintf(status, "cannot calculate SD for noise simulation (%d)", ret);
157 return(100+ret);
158 }
159
160 if(status!=NULL) strcpy(status, "ok");
161 return 0;
162}
int dftMeanTAC(DFT *dft, DFT *mean)
Definition dft.c:1580
#define DFT_DECAY_UNKNOWN
#define DFT_DECAY_CORRECTED
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
Definition pearson.c:341
int noiseSD4Simulation(double y, double t1, double dt, double hl, double a, double *sd, char *status, int verbose)
Definition noise.c:21
char decayCorrected
char isotope[8]

◆ plot_fit_svg()

int plot_fit_svg ( DFT * dft1,
DFT * dft2,
char * main_title,
char * fname,
int verbose )

Writes plots of original and fitted TACs in SVG 1.1 format. Data must not contain NaNs.

Returns
Returns 0 if successful, otherwise nonzero.
See also
plot_svg, plot_fitrange_svg
Parameters
dft1Measured data points.
dft2Fitted data points. Times can be different but unit must be the same.
main_titleString for plot main title, or "".
fnameSVG filename; existing file is backed up.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 216 of file plotfit.c.

227 {
228 int ret, n, ri, si, ei;
229 char x_title[64], y_title[64], tac_id[32], tac_title[64];
230 double minx, maxx, miny, maxy, tx1, tx2, ty1, ty2, f;
231 struct svg_viewports viewports; svg_init_viewports(&viewports);
232 int max_color_nr, color_nr;
233 int max_symbol_nr, symbol_nr;
234 SVG_LEGENDS legends; svg_init_legends(&legends);
235 FILE *fp_svg=NULL;
236
237
238 if(verbose>0) {
239 printf("%s(dft1, dft2, mt, fn, %d)\n", __func__, verbose);
240 }
241
242 /* Check data */
243 if(dft1==NULL || dft1->voiNr<1) return(1);
244 if(dft2==NULL) return(1);
245 if(dft2->voiNr!=dft1->voiNr) return(1);
246
247 int is_label=0; if(dft1->voiNr>1) is_label=1;
248
249 /* Check if file exists; backup, if necessary */
250 ret=backupExistingFile(fname, NULL, NULL); if(ret) return(2);
251
252 /* Determine the plot min and max values */
253 minx=maxx=miny=maxy=0;
254 ret=dftMinMax(dft1, &tx1, &tx2, &ty1, &ty2); if(ret) return(3);
255 minx=tx1; maxx=tx2; miny=ty1; maxy=ty2;
256 ret=dftMinMax(dft2, &tx1, &tx2, &ty1, &ty2); if(ret) return(3);
257 if(minx>tx1) minx=tx1;
258 if(maxx<tx2) maxx=tx2;
259 if(miny>ty1) miny=ty1;
260 if(maxy<ty2) maxy=ty2;
261 if(verbose>1) printf("minx:=%g\nmaxx:=%g\nminy:=%g\nmaxy:=%g\n", minx, maxx, miny, maxy);
262 if(miny>0.0) {f=maxy-miny; miny-=0.01*f;}
263
264 /* Calculate the axis ticks */
265 viewports.label_area_viewport.is=is_label; // needed for x axis ticks
266 viewports.x.fixed_min=0; viewports.y.fixed_min=0;
267 viewports.x.min=minx; viewports.x.max=maxx;
268 viewports.y.min=miny; viewports.y.max=maxy;
269 ret=svg_calculate_axes(&viewports, verbose-3); if(ret) return(4);
270
271 /* Set x and y axis titles based on activity and time units */
272 if(verbose>2) printf("set x title\n");
273 strcpy(x_title, "");
274 if(dft1->timeunit==DFTTIME_SEC || dft1->timeunit==DFTTIME_MIN)
275 sprintf(x_title, "Time (%s)", dftTimeunit(dft1->timeunit));
276 else if(dft1->timeunit!=DFTTIME_UNKNOWN)
277 strcpy(x_title, dftTimeunit(dft1->timeunit));
278 if(verbose>2) printf("set y title\n");
279 strcpy(y_title, "");
280 if(dftUnitId(dft1->unit)!=DFTUNIT_UNKNOWN)
281 strcpy(y_title, dftUnit(dftUnitId(dft1->unit)));
282
283 /* Set the plot window and window area sizes */
284 if(verbose>2) printf("set window sizes\n");
285 ret=svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
286 strlen(x_title), is_label, &viewports, verbose-3);
287 if(ret) return(5);
288
289 /* Initiate graphics file */
290 fp_svg=svg_initiate(fname, 0, 0, &viewports, NULL, verbose-3);
291 if(fp_svg==NULL) return(6);
292
293 /* Put the graph titles into their own viewports */
294 ret=svg_create_main_title(fp_svg, main_title, "", &viewports, NULL,verbose-3);
295 if(ret) return(7);
296 ret=svg_create_yaxis_title(fp_svg, y_title, &viewports, NULL, verbose-3);
297 if(ret) return(8);
298 ret=svg_create_xaxis_title(fp_svg, x_title, &viewports, NULL, verbose-3);
299 if(ret) return(9);
300
301 /* Put the plot into its own viewport */
302 ret=svg_start_plot_viewport(fp_svg, &viewports, NULL, verbose-3);
303 if(ret) return(10);
304
305 /* Start coordinate area viewport */
306 ret=svg_start_coordinate_viewport(fp_svg, &viewports, NULL, verbose-3);
307 if(ret) return(11);
308
309 /* Write plot axes */
310 ret=svg_write_axes(fp_svg, &viewports, NULL, verbose-3);
311 if(ret) {
312 if(verbose>0) printf("svg_write_axes() := %d\n", ret);
313 return(12);
314 }
315
316 /*
317 * Draw the plots
318 */
319 max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
320 if(max_color_nr<1) max_color_nr=1; // remainder works only if 2nd operator>0
321 if(verbose>3) printf("max_color_nr := %d\n", max_color_nr);
322 max_symbol_nr=0; while(svgSymbolName(max_symbol_nr)!=NULL) max_symbol_nr++;
323 if(max_symbol_nr<1) max_symbol_nr=1; // remainder works only if 2nd operator>0
324 if(verbose>3) printf("max_symbol_nr := %d\n", max_symbol_nr);
325 if(dft1->voiNr==1) color_nr=0; else color_nr=1;
326 symbol_nr=0;
327 for(ri=0, n=0; ri<dft1->voiNr; ri++) {
328 sprintf(tac_id, "plot_%d", n);
329/*
330 if(strlen(dft1->studynr)>0 && strcmp(dft1->studynr, ".")!=0)
331 sprintf(tac_title, "%s: %s", dft1->studynr, dft1->voi[ri].name);
332 else strcpy(tac_title, dft1->voi[ri].name);
333*/
334 rnameRmDots(dft1->voi[ri].name, tac_title);
335 /* Draw the fitted line */
336 for(si=0; si<dft2->frameNr; si++) if(!isnan(dft2->voi[ri].y[si])) break;
337 for(ei=dft2->frameNr-1; ei>=si; ei--) if(!isnan(dft2->voi[ri].y[ei])) break;
338 if((ei-si)>0) {
339 ret=svg_write_tac(fp_svg, &viewports, 1, tac_id, tac_title,
340 dft2->x+si, dft2->voi[ri].y+si, 1+ei-si,
341 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLFILLED,
342 NULL, verbose-3);
343 if(ret) {svg_legend_empty(&legends); return(21);}
344 }
345 /* Draw the measured points */
346 ret=svg_write_tac(fp_svg, &viewports, 2, tac_id, tac_title,
347 dft1->x, dft1->voi[ri].y, dft1->frameNr,
348 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLFILLED,
349 NULL, verbose-3);
350 if(ret) {svg_legend_empty(&legends); return(22);}
351 /* Set legend too, if requested */
352 if(is_label!=0) {
353 svg_legend_add(&legends, 0, symbol_nr%max_symbol_nr, SYMBOLFILLED,
354 color_nr%max_color_nr, tac_title);
355 }
356 /* Prepare for the next plot */
357 color_nr++; n++;
358 if(color_nr==max_color_nr) {symbol_nr++; color_nr=0;}
359 if(symbol_nr==max_symbol_nr) symbol_nr=0;
360 }
361
362 /* Close the coordinate viewport */
363 ret=svg_end_coordinate_viewport(fp_svg, NULL, verbose-3);
364 if(ret) {svg_legend_empty(&legends); return(91);}
365
366 /* Write the axis ticks */
367 if(svg_write_xticks(fp_svg, &viewports, NULL, verbose-3)!=0) {
368 svg_legend_empty(&legends); return(92);}
369 if(svg_write_yticks(fp_svg, &viewports, NULL, verbose-3)!=0) {
370 svg_legend_empty(&legends); return(93);}
371
372 /* Close the plot viewport */
373 ret=svg_end_plot_viewport(fp_svg, NULL, verbose-3);
374 if(ret) {svg_legend_empty(&legends); return(94);}
375
376 /* Make the plot legends into their own viewport */
377 if(viewports.label_area_viewport.is!=0) {
378 if(verbose>2) printf("creating plot legends\n");
379 ret=svg_create_legends(fp_svg, &viewports, &legends, NULL, verbose-3);
380 if(ret) {svg_legend_empty(&legends); return(95);}
381 }
382 svg_legend_empty(&legends);
383
384 /* Close the SVG file */
385 ret=svg_close(fp_svg, NULL, verbose-3); if(ret) return(101);
386
387 return(0);
388}
int backupExistingFile(char *filename, char *backup_ext, char *status)
Definition backup.c:14
int dftMinMax(DFT *dft, double *minx, double *maxx, double *miny, double *maxy)
Definition dft.c:974
int rnameRmDots(char *rname1, char *rname2)
Definition rname.c:99
void svg_legend_empty(SVG_LEGENDS *legends)
Definition svg_legend.c:26
int svg_write_xticks(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:555
void svg_init_legends(SVG_LEGENDS *legends)
Definition svg_legend.c:14
int svg_create_xaxis_title(FILE *fp, const char *title_text, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_title.c:126
char * svgColorName(const svgColor index)
Definition svg_defs.c:38
int svg_create_main_title(FILE *fp, const char *main_title_text, const char *sub_title_text, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_title.c:17
int svg_legend_add(SVG_LEGENDS *legends, const int plot_type, const int symbol_type, const svgSymbolFill symbol_fill, const int color, const char *text)
Definition svg_legend.c:43
char * svgSymbolName(const svgSymbolType index)
Definition svg_defs.c:67
int svg_define_viewports(const int main_viewport_width, const int main_viewport_height, const int is_main_title, const int is_yaxis_title, const int is_xaxis_title, const int is_label_area, struct svg_viewports *vp, int verbose)
Definition svg_vport.c:65
int svg_end_plot_viewport(FILE *fp, char *errmsg, int verbose)
Definition svg_plot.c:238
int svg_start_coordinate_viewport(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:276
int svg_create_legends(FILE *fp, struct svg_viewports *vp, SVG_LEGENDS *legends, char *errmsg, int verbose)
Definition svg_legend.c:76
void svg_init_viewports(struct svg_viewports *p)
Definition svg_vport.c:43
FILE * svg_initiate(const char *filename, const double height, const double width, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_file.c:22
int svg_calculate_axes(struct svg_viewports *vp, int verbose)
Definition svg_plot.c:364
int svg_write_axes(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:437
int svg_end_coordinate_viewport(FILE *fp, char *errmsg, int verbose)
Definition svg_plot.c:327
int svg_start_plot_viewport(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:181
int svg_create_yaxis_title(FILE *fp, const char *title_text, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_title.c:197
int svg_write_yticks(FILE *fp, struct svg_viewports *vp, char *errmsg, int verbose)
Definition svg_plot.c:655
int svg_write_tac(FILE *fp, struct svg_viewports *vp, const int plot_type, const char *tac_id, const char *tac_title, double *x, double *y, const int data_nr, const char *color, const svgSymbolType symbol_type, const svgSymbolFill symbol_fill, char *errmsg, int verbose)
Definition svg_plot.c:746
int svg_close(FILE *fp, char *errmsg, int verbose)
Definition svg_file.c:107

◆ plot_fitrange_svg()

int plot_fitrange_svg ( DFT * dft1,
DFT * dft2,
char * main_title,
double x1,
double x2,
double y1,
double y2,
char * fname,
int verbose )

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

Returns
Returns 0 if successful, otherwise nonzero.
See also
plot_fit_svg, plot_svg
Parameters
dft1Measured data points
dft2Fitted data points. Times can be different but unit must be the same.
main_titleString for plot main title, or NULL
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 filename; existing file is backed up
verboseVerbose level; set to zero to not to print any comments

Definition at line 16 of file plotfit.c.

35 {
36 int ret, n, ri, si, ei;
37 char x_title[64], y_title[64], tac_id[32], tac_title[64];
38 double minx, maxx, miny, maxy, tx1, tx2, ty1, ty2, f;
39 struct svg_viewports viewports; svg_init_viewports(&viewports);
40 int max_color_nr, color_nr;
41 int max_symbol_nr, symbol_nr;
42 SVG_LEGENDS legends; svg_init_legends(&legends);
43 FILE *fp_svg=NULL;
44
45 if(verbose>0) {
46 printf("%s(dft1, dft2, mt, x1, x2, y1, y2, fn, %d)\n", __func__, verbose);
47 }
48
49 /* Check data */
50 if(dft1==NULL || dft1->voiNr<1) return(1);
51 if(dft2==NULL) return(1);
52 if(dft2->voiNr!=dft1->voiNr) return(1);
53
54 /* Check if file exists; backup, if necessary */
55 ret=backupExistingFile(fname, NULL, NULL); if(ret) return(2);
56
57 int is_label=0; if(dft1->voiNr>1) is_label=1;
58
59 /* Determine the plot min and max x values */
60 ret=dftMinMax(dft1, &tx1, &tx2, NULL, NULL); if(ret) return(3);
61 minx=tx1; maxx=tx2;
62 ret=dftMinMax(dft2, &tx1, &tx2, NULL, NULL); if(ret) return(3);
63 if(minx>tx1) minx=tx1;
64 if(maxx<tx2) maxx=tx2;
65 if(minx>0.0) {
66 f=maxx-minx; minx-=0.05*f;
67 if(minx<0.0) minx=0.0;
68 }
69 if(!isnan(x1)) minx=x1;
70 if(!isnan(x2)) maxx=x2;
71
72 /* Determine the plot min and max y values */
73 ret=dftMaxY(dft1, minx, maxx, &ty1, &ty2); if(ret) return(3);
74 miny=ty1; maxy=ty2;
75 ret=dftMaxY(dft2, minx, maxx, &ty1, &ty2); if(ret) return(3);
76 if(miny>ty1) miny=ty1;
77 if(maxy<ty2) maxy=ty2;
78 if(miny>0.0) {
79 f=maxy-miny; miny-=0.05*f;
80 if(miny<0.0) miny=0.0;
81 }
82 if(!isnan(y1)) miny=y1;
83 if(!isnan(y2)) maxy=y2;
84
85 if(verbose>1) printf("minx:=%g\nmaxx:=%g\nminy:=%g\nmaxy:=%g\n", minx, maxx, miny, maxy);
86
87 /* Calculate the axis ticks */
88 viewports.label_area_viewport.is=is_label; // needed for x axis ticks
89 viewports.x.min=minx; viewports.x.max=maxx;
90 viewports.y.min=miny; viewports.y.max=maxy;
91 if(isnan(x1) || isnan(x2)) viewports.x.fixed_min=0;
92 if(isnan(y1) || isnan(y2)) viewports.y.fixed_min=0;
93 else viewports.y.fixed_min=1;
94 ret=svg_calculate_axes(&viewports, verbose-3); if(ret) return(4);
95
96 /* Set x and y axis titles based on activity and time units */
97 strcpy(x_title, "");
98 if(dft1->timeunit==DFTTIME_SEC || dft1->timeunit==DFTTIME_MIN)
99 sprintf(x_title, "Time (%s)", dftTimeunit(dft1->timeunit));
100 else if(dft1->timeunit!=DFTTIME_UNKNOWN)
101 strcpy(x_title, dftTimeunit(dft1->timeunit));
102 strcpy(y_title, "");
103 if(dftUnitId(dft1->unit)!=DFTUNIT_UNKNOWN)
104 strcpy(y_title, dftUnit(dftUnitId(dft1->unit)));
105
106 /* Set the plot window and window area sizes */
107 ret=svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
108 strlen(x_title), is_label, &viewports, verbose-3);
109 if(ret) return(5);
110
111 /* Initiate graphics file */
112 fp_svg=svg_initiate(fname, 0, 0, &viewports, NULL, verbose-3);
113 if(fp_svg==NULL) return(6);
114
115 /* Put the graph titles into their own viewports */
116 ret=svg_create_main_title(fp_svg, main_title, "", &viewports, NULL,verbose-3);
117 if(ret) return(7);
118 ret=svg_create_yaxis_title(fp_svg, y_title, &viewports, NULL, verbose-3);
119 if(ret) return(8);
120 ret=svg_create_xaxis_title(fp_svg, x_title, &viewports, NULL, verbose-3);
121 if(ret) return(9);
122
123 /* Put the plot into its own viewport */
124 ret=svg_start_plot_viewport(fp_svg, &viewports, NULL, verbose-3);
125 if(ret) return(10);
126
127 /* Start coordinate area viewport */
128 ret=svg_start_coordinate_viewport(fp_svg, &viewports, NULL, verbose-3);
129 if(ret) return(11);
130
131 /* Write plot axes */
132 ret=svg_write_axes(fp_svg, &viewports, NULL, verbose-3);
133 if(ret) return(12);
134
135 /*
136 * Draw the plots
137 */
138 max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
139 if(max_color_nr==0) max_color_nr=1; // remainder works only if 2nd operator>0
140 if(verbose>3) printf("max_color_nr := %d\n", max_color_nr);
141 max_symbol_nr=0; while(svgSymbolName(max_symbol_nr)!=NULL) max_symbol_nr++;
142 if(max_symbol_nr==0) max_symbol_nr=1; // remainder works only if 2nd operator>0
143 if(verbose>3) printf("max_symbol_nr := %d\n", max_symbol_nr);
144 if(dft1->voiNr==1) color_nr=0; else color_nr=1;
145 symbol_nr=0;
146 for(ri=0, n=0; ri<dft1->voiNr; ri++) {
147 sprintf(tac_id, "plot_%d", n);
148/*
149 if(strlen(dft1->studynr)>0 && strcmp(dft1->studynr, ".")!=0)
150 sprintf(tac_title, "%s: %s", dft1->studynr, dft1->voi[ri].name);
151 else strcpy(tac_title, dft1->voi[ri].name);
152*/
153 rnameRmDots(dft1->voi[ri].name, tac_title);
154 /* Draw the fitted line */
155 for(si=0; si<dft2->frameNr; si++) if(!isnan(dft2->voi[ri].y[si])) break;
156 for(ei=dft2->frameNr-1; ei>=si; ei--) if(!isnan(dft2->voi[ri].y[ei])) break;
157 if((ei-si)>0) {
158 ret=svg_write_tac(fp_svg, &viewports, 1, tac_id, tac_title,
159 dft2->x+si, dft2->voi[ri].y+si, 1+ei-si,
160 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLFILLED,
161 NULL, verbose-3);
162 if(ret) {svg_legend_empty(&legends); return(21);}
163 }
164 /* Draw the measured points */
165 ret=svg_write_tac(fp_svg, &viewports, 2, tac_id, tac_title,
166 dft1->x, dft1->voi[ri].y, dft1->frameNr,
167 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, SYMBOLFILLED,
168 NULL, verbose-3);
169 if(ret) {svg_legend_empty(&legends); return(22);}
170 /* Set legend too, if requested */
171 if(is_label!=0) {
172 svg_legend_add(&legends, 0, symbol_nr%max_symbol_nr, SYMBOLFILLED,
173 color_nr%max_color_nr, tac_title);
174 }
175 /* Prepare for the next plot */
176 color_nr++; n++;
177 if(color_nr==max_color_nr) {symbol_nr++; color_nr=0;}
178 if(symbol_nr==max_symbol_nr) symbol_nr=0;
179 }
180
181 /* Close the coordinate viewport */
182 ret=svg_end_coordinate_viewport(fp_svg, NULL, verbose-3);
183 if(ret) {svg_legend_empty(&legends); return(91);}
184
185 /* Write the axis ticks */
186 if(svg_write_xticks(fp_svg, &viewports, NULL, verbose-3)!=0) {
187 svg_legend_empty(&legends); return(92);}
188 if(svg_write_yticks(fp_svg, &viewports, NULL, verbose-3)!=0) {
189 svg_legend_empty(&legends); return(93);}
190
191 /* Close the plot viewport */
192 ret=svg_end_plot_viewport(fp_svg, NULL, verbose-3);
193 if(ret) {svg_legend_empty(&legends); return(94);}
194
195 /* Make the plot legends into their own viewport */
196 if(viewports.label_area_viewport.is!=0) {
197 if(verbose>2) printf("creating plot legends\n");
198 ret=svg_create_legends(fp_svg, &viewports, &legends, NULL, verbose-3);
199 if(ret) {svg_legend_empty(&legends); return(95);}
200 }
201 svg_legend_empty(&legends);
202
203 /* Close the SVG file */
204 ret=svg_close(fp_svg, NULL, verbose-3); if(ret) return(101);
205
206 return(0);
207}
int dftMaxY(DFT *dft, double t1, double t2, double *miny, double *maxy)
Definition dft.c:1090

◆ plot_svg()

int plot_svg ( DFT * dft,
RES * res,
int first,
int last,
char * main_title,
char * x_title,
char * y_title,
int color_scale,
char * fname,
int verbose )

Writes graphical analysis plots in SVG 1.1 format. Assumes that line slope and ic are in res->parameter[0] and [1].

Returns
Returns 0 if successful, otherwise nonzero.
See also
plot_fit_svg, plot_fitrange_svg
Parameters
dftPlot points: X in y2, Y in y3.
resResults containing parameters of line.
firstFirst sample (starting from 0) used in linear fit.
lastlast sample (starting from 0) used in linear fit.
main_titleString for plot main title, or NULL.
x_titleString for X axis title, or NULL.
y_titleString for Y axis title, or NULL.
color_scaleColour-scale: 0=colour, 2=black-and-white.
fnameFile name for SVG; existing file is renamed as *.bak.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 17 of file plotdata.c.

38 {
39 int n, ri, fi, ret;
40 char tac_id[32], tac_title[64];
41 double maxPlotX=0, maxy;
42 double px[2], py[2];
43 struct svg_viewports viewports; svg_init_viewports(&viewports);
44 int max_color_nr, color_nr;
45 int max_symbol_nr, symbol_nr;
46 SVG_LEGENDS legends; svg_init_legends(&legends);
47 FILE *fp_svg=NULL;
48
49 if(verbose>0) {
50 printf("%s(dft, res, %d, %d, mt, xt, yt, fn, cs, %d)\n", __func__, first, last, verbose);
51 }
52
53 /* Check data */
54 if(dft==NULL || dft->voiNr<1) return(1);
55 if(res==NULL || res->voiNr!=dft->voiNr) return(1);
56 if(first>last) return(1);
57
58 int is_label=0; if(dft->voiNr>1) is_label=1;
59 if(color_scale!=0 && color_scale!=2) color_scale=0;
60
61 /* Check if file exists; backup, if necessary */
62 backupExistingFile(fname, NULL, NULL);
63
64 /* Search the largest plot x-value to be used as line end point */
65 for(ri=0; ri<dft->voiNr; ri++) for(fi=0; fi<dft->frameNr; fi++)
66 if(dft->voi[ri].y2[fi]>maxPlotX) maxPlotX=dft->voi[ri].y2[fi];
67 /* Get maxy */
68 maxy=0.0;
69 for(ri=0; ri<dft->voiNr; ri++) for(fi=0; fi<dft->frameNr; fi++)
70 if(dft->voi[ri].y3[fi]>maxy) maxy=dft->voi[ri].y3[fi];
71
72 /* Calculate the axis ticks */
73 viewports.label_area_viewport.is=is_label; // needed for x axis ticks
74 viewports.x.fixed_min=0; viewports.y.fixed_min=0;
75 viewports.x.min=0.0; viewports.x.max=maxPlotX;
76 viewports.y.min=0.0; viewports.y.max=maxy;
77 ret=svg_calculate_axes(&viewports, verbose-3);
78 if(ret) return(2);
79
80 /* Set the plot window and window area sizes */
81 ret=svg_define_viewports(0, 0, strlen(main_title), strlen(y_title),
82 strlen(x_title), is_label, &viewports, verbose-3);
83 if(ret) return(3);
84
85 /* Initiate graphics file */
86 fp_svg=svg_initiate(fname, 0, 0, &viewports, NULL, verbose-3);
87 if(fp_svg==NULL) return(4);
88
89 /* Put the graph titles into their own viewports */
90 ret=svg_create_main_title(fp_svg, main_title, "", &viewports, NULL,verbose-3);
91 if(ret) return(5);
92 ret=svg_create_yaxis_title(fp_svg, y_title, &viewports, NULL, verbose-3);
93 if(ret) return(6);
94 ret=svg_create_xaxis_title(fp_svg, x_title, &viewports, NULL, verbose-3);
95 if(ret) return(7);
96
97 /* Put the plot into its own viewport */
98 ret=svg_start_plot_viewport(fp_svg, &viewports, NULL, verbose-3);
99 if(ret) return(8);
100
101 /* Start coordinate area viewport */
102 ret=svg_start_coordinate_viewport(fp_svg, &viewports, NULL, verbose-3);
103 if(ret) return(9);
104
105 /* Write plot axes */
106 ret=svg_write_axes(fp_svg, &viewports, NULL, verbose-3);
107 if(ret) return(10);
108
109 /*
110 * Draw the plots
111 */
112 int symbol_fill=SYMBOLFILLED;
113 if(color_scale==2) { // black-and-white
114 symbol_fill=SYMBOLOPEN;
115 max_color_nr=1;
116 } else { // colour
117 max_color_nr=0; while(svgColorName(max_color_nr)!=NULL) max_color_nr++;
118 }
119 if(max_color_nr==0) max_color_nr=1; // remainder works only if 2nd operator>0
120 if(verbose>3) printf("max_color_nr := %d\n", max_color_nr);
121 max_symbol_nr=0; while(svgSymbolName(max_symbol_nr)!=NULL) max_symbol_nr++;
122 if(max_symbol_nr==0) max_symbol_nr=1; // remainder works only if 2nd operator>0
123 if(verbose>3) printf("max_symbol_nr := %d\n", max_symbol_nr);
124 if(dft->voiNr==1) color_nr=0; else color_nr=1;
125 symbol_nr=0;
126 for(ri=0, n=0; ri<dft->voiNr; ri++) {
127 sprintf(tac_id, "plot_%d", n);
128 //printf("ri=%d color_nr=%d symbol_nr=%d\n", ri, color_nr, symbol_nr);
129/*
130 if(strlen(dft->studynr)>0 && strcmp(dft->studynr, ".")!=0)
131 sprintf(tac_title, "%s: %s", dft->studynr, dft->voi[ri].name);
132 else strcpy(tac_title, dft->voi[ri].name);
133*/
134 rnameRmDots(dft->voi[ri].name, tac_title);
135 /*printf("tac_title := %s ; color := %s ; symbol := %d\n",
136 tac_title, svgcolor[color_nr%max_color_nr], symbol_nr%(max_symbol_nr+1));*/
137 /* Draw symbols */
138 if(dft->frameNr<150) {
139 /* plot symbols only if less than 150 samples */
140 ret=svg_write_tac(fp_svg, &viewports, 2, tac_id, tac_title,
141 dft->voi[ri].y2, dft->voi[ri].y3, dft->frameNr,
142 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, symbol_fill,
143 NULL, verbose-3);
144 } else {
145 /* plot samples as line if 150 samples or more */
146 ret=svg_write_tac(fp_svg, &viewports, 1, tac_id, tac_title,
147 dft->voi[ri].y2, dft->voi[ri].y3, dft->frameNr,
148 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, symbol_fill,
149 NULL, verbose-3);
150 }
151 if(ret) {svg_legend_empty(&legends); return(21);}
152 /* Draw the line */
153 px[0]=0.0; py[0]=res->voi[ri].parameter[1];
154 px[1]=maxPlotX;
155 py[1]=maxPlotX*res->voi[ri].parameter[0]+res->voi[ri].parameter[1];
156 sprintf(tac_id, "line_%d", n);
157 ret=svg_write_tac(fp_svg, &viewports, 1, tac_id, tac_title,
158 px, py, 2,
159 svgColorName(color_nr%max_color_nr), symbol_nr%max_symbol_nr, symbol_fill,
160 NULL, verbose-3);
161 if(ret) {svg_legend_empty(&legends); return(22);}
162 /* Set legend too, if requested */
163 if(is_label!=0) {
164 svg_legend_add(&legends, 0, symbol_nr%max_symbol_nr, symbol_fill, color_nr%max_color_nr, tac_title);
165 }
166
167 /* Prepare for the next plot */
168 if(color_scale==0) {
169 color_nr++;
170 if(color_nr==max_color_nr) {symbol_nr++; color_nr=0;}
171 if(symbol_nr==max_symbol_nr) symbol_nr=0;
172 }
173 if(color_scale==2) {
174 symbol_nr++;
175 if(symbol_nr==max_symbol_nr) {
176 if(symbol_fill==SYMBOLOPEN) symbol_fill=SYMBOLFILLED; else symbol_fill=SYMBOLOPEN;
177 symbol_nr=0;
178 }
179 }
180 n++;
181 }
182
183 /* Close the coordinate viewport */
184 ret=svg_end_coordinate_viewport(fp_svg, NULL, verbose-3);
185 if(ret) {svg_legend_empty(&legends); return(91);}
186
187 /* Write the axis ticks */
188 if(svg_write_xticks(fp_svg, &viewports, NULL, verbose-3)!=0) {
189 svg_legend_empty(&legends); return(92);}
190 if(svg_write_yticks(fp_svg, &viewports, NULL, verbose-3)!=0) {
191 svg_legend_empty(&legends); return(93);}
192
193 /* Close the plot viewport */
194 ret=svg_end_plot_viewport(fp_svg, NULL, verbose-3);
195 if(ret) {svg_legend_empty(&legends); return(94);}
196
197 /* Make the plot legends into their own viewport */
198 if(viewports.label_area_viewport.is!=0) {
199 if(verbose>2) printf("creating plot legends\n");
200 ret=svg_create_legends(fp_svg, &viewports, &legends, NULL, verbose-3);
201 if(ret) {svg_legend_empty(&legends); return(95);}
202 }
203 svg_legend_empty(&legends);
204
205 /* Close the SVG file */
206 ret=svg_close(fp_svg, NULL, verbose-3); if(ret) return(101);
207 return(0);
208}
int voiNr
ResVOI * voi
double parameter[MAX_RESPARAMS]

◆ plotdata()

int plotdata ( DFT * dft,
RES * res,
int first,
int last,
char * mtitle,
char * xtitle,
char * ytitle,
char * fname )

Write plot and line fit data in XHTML 1.1. Strict table format. Assumes that line slope and ic are in res->parameter[0] and [1].

Returns
Returns 0 if successful, otherwise non-zero.
See also
plotdata_as_dft
Parameters
dftPlot points: X in y2, Y in y3.
resResults containing parameters of line.
firstFirst sample (starting from 0) used in linear fit.
lastlast sample (starting from 0) used in linear fit.
mtitleString for plot main title, or NULL.
xtitleString for X axis title, or NULL.
ytitleString for Y axis title, or NULL.
fnameFilename for plot data; existing file is renamed as *%. If extension is .dft, plot data (excluding lines) is written in DFT format with x values as separate columns before corresponding y values.

Definition at line 217 of file plotdata.c.

236 {
237 int n, ri, row, fi;
238 char tmp[FILENAME_MAX], *cptr=NULL;
239 FILE *fp;
240 double maxPlotX=0, maxRegX=0, maxFitX=0, f;
241
242
243 /* Check data */
244 if(dft==NULL || dft->voiNr<1) return(1);
245 if(res==NULL || res->voiNr!=dft->voiNr) return(1);
246 if(first>last) return(1);
247
248 /* Get filename extension to determine output type */
249 cptr=strrchr(fname, '.');
250 if(cptr!=NULL && strcasecmp(cptr, ".DFT")==0) {
251 /* Write in DFT if required */
252 return(plotdata_as_dft(dft, fname));
253 }
254
255 /* Check if file exists; backup, if necessary */
256 backupExistingFile(fname, NULL, NULL);
257
258 /* Search the largest plot x-value to be used as line end point */
259 for(ri=0; ri<dft->voiNr; ri++) for(fi=0; fi<dft->frameNr; fi++)
260 if(dft->voi[ri].y2[fi]>maxPlotX) maxPlotX=dft->voi[ri].y2[fi];
261
262 /* Open output file */
263 if((fp = fopen(fname, "w")) == NULL) return(3);
264
265 /* Write XHTML doctype and head */
266// n=fprintf(fp, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"ht
267//tp://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n");
268 n=fprintf(fp, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"");
269 if(n<10) return(4);
270 n=fprintf(fp, " \"https://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n");
271 if(n<10) return(4);
272 n=fprintf(fp, "<html xmlns=\"https://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n\n");
273 if(n<20) return(4);
274 /* Write XHTML header */
275 n=fprintf(fp, "<head>\n"); if(n<6) return(4);
276 fprintf(fp, " <title>Graphical analysis plot</title>\n");
277// fprintf(fp, " <meta http-equiv=\"content-type\" cont
278//ent=\"text/html; charset=iso-8859-1\" />\n");
279 fprintf(fp, " <meta http-equiv=\"content-type\" content=\"text/html;");
280 fprintf(fp, " charset=iso-8859-1\" />\n");
281
282 fprintf(fp, " <meta http-equiv=\"content-language\" content=\"en-gb\" />\n");
283 fprintf(fp, " <meta name=\"ProgId\" content=\"Excel.Sheet\" />\n");
284/*
285 fprintf(fp, " <link rel=\"icon\" href=\"https://www.turkupetcentre.
286net/favicon.ico\" type=\"image/x-icon\" />\n");
287 fprintf(fp, " <link rel=\"shortcut icon\" href=\"https://www.turkupetcentre.
288net/favicon.ico\" type=\"image/x-icon\" />\n");
289*/
290 fprintf(fp, " <link rel=\"icon\" href=\"https://www.turkupetcentre.net/");
291 fprintf(fp, "favicon.ico\" type=\"image/x-icon\" />\n");
292 fprintf(fp, " <link rel=\"shortcut icon\" href=\"https://www.turkupet");
293 fprintf(fp, "centre.net/favicon.ico\" type=\"image/x-icon\" />\n");
294
295 fprintf(fp, " <style type=\"text/css\">\n");
296 fprintf(fp, " thead {background-color:#999999; color:black;}\n");
297/* fprintf(fp, " table {text-align:left; width:100%%;
298border-collapse:collapse; empty-cells:show;}\n");*/
299 fprintf(fp, " table {text-align:left; width:100%%;");
300 fprintf(fp, " border-collapse:collapse; empty-cells:show;}\n");
301
302 fprintf(fp, " td {border:1px solid black;}\n");
303 fprintf(fp, " <!--table\n");
304 fprintf(fp, " {mso-displayed-decimal-separator:\"\\.\";\n");
305 fprintf(fp, " mso-displayed-thousand-separator:\" \";}\n");
306 fprintf(fp, " -->\n");
307 fprintf(fp, " </style>\n");
308 fprintf(fp, "</head>\n");
309
310 /* Start writing the body of the HTML file */
311 fprintf(fp, "\n<body>\n");
312
313 /* Start the div for tables */
314 fprintf(fp, "\n<div id=\"tables\">\n");
315
316 /* Write information on the graphical analysis */
317 fprintf(fp, "<table>\n");
318 fprintf(fp, "<tbody>\n");
319 fprintf(fp, "<tr><th>Main title</th><th>%s</th></tr>\n", mtitle);
320 fprintf(fp, "<tr><th>X title</th><th>%s</th></tr>\n", xtitle);
321 fprintf(fp, "<tr><th>Y title</th><th>%s</th></tr>\n", ytitle);
322 if(ctime_r_int(&res->time, tmp))
323 fprintf(fp, "<tr><th>Date</th><th>%s</th></tr>\n", tmp);
324 fprintf(fp, "</tbody>\n");
325 fprintf(fp, "</table>\n");
326
327 /* Write the plots, each to their own table */
328 for(ri=0; ri<dft->voiNr; ri++) {
329 /* Search the largest regional plot x-value to be used as line end points */
330 for(fi=0, maxRegX=maxFitX=0; fi<dft->frameNr; fi++) {
331 if(dft->voi[ri].y2[fi]>maxRegX) maxRegX=dft->voi[ri].y2[fi];
332 if(fi>=first && fi<=last && dft->voi[ri].y2[fi]>maxFitX) maxFitX=dft->voi[ri].y2[fi];
333 }
334 /* Begin a new table */
335 fprintf(fp, "<table>\n");
336 /* Write the title row */
337 fprintf(fp, "<thead>\n");
338 fprintf(fp, "<tr><th>%s %s %s</th>", dft->voi[ri].voiname,
339 dft->voi[ri].hemisphere, dft->voi[ri].place);
340 fprintf(fp, "<th>symbol open</th><th>symbol filled</th><th>text</th>");
341 fprintf(fp, "<th>X</th><th>line</th>");
342 fprintf(fp, "</tr>\n");
343 fprintf(fp, "</thead>\n");
344 /* Write the plot rows */
345 fprintf(fp, "<tbody>\n");
346 row=0;
347 for(fi=0; fi<(dft->frameNr>2?dft->frameNr:2); fi++)
348 if(!isnan(dft->voi[ri].y2[fi]) && !isnan(dft->voi[ri].y3[fi]))
349 {
350 fprintf(fp, "<tr>");
351 if(fi<dft->frameNr) {
352 fprintf(fp, "<th>%g</th>", dft->voi[ri].y2[fi]); /* x-axis value */
353 fprintf(fp, "<th>%g</th>", dft->voi[ri].y3[fi]); /* y-axis value */
354 } else {
355 fprintf(fp, "<th> </th>");
356 fprintf(fp, "<th> </th>");
357 }
358 /* If included in the fit, y-axis value again */
359 if(fi>=first && fi<=last)
360 fprintf(fp, "<th>%g</th>", dft->voi[ri].y3[fi]);
361 else fprintf(fp, "<th></th>");
362 if(fi<dft->frameNr)
363 fprintf(fp, "<th>%g</th>", dft->x[fi]); /* Frame time as text */
364 else
365 fprintf(fp, "<th> </th>");
366 /* Line points */
367 if(row==0) { /* line start */
368 fprintf(fp, "<th>0</th>"); /* x-axis value */
369 fprintf(fp, "<th>%g</th>", res->voi[ri].parameter[1]); /* y-axis value */
370 } else if(row==1) { /* line point at the end of fitted range */
371 fprintf(fp, "<th>%g</th>", maxFitX); /* x-axis value */
372 f=maxFitX*res->voi[ri].parameter[0]+res->voi[ri].parameter[1];
373 fprintf(fp, "<th>%g</th>", f); /* y-axis value */
374 } else if(row==2) { /* line "mid" point at the end of regional data */
375 fprintf(fp, "<th>%g</th>", maxRegX); /* x-axis value */
376 f=maxRegX*res->voi[ri].parameter[0]+res->voi[ri].parameter[1];
377 fprintf(fp, "<th>%g</th>", f); /* y-axis value */
378 } else if(row==3) { /* line end point at the end of all plots */
379 fprintf(fp, "<th>%g</th>", maxPlotX); /* x-axis value */
380 f=maxPlotX*res->voi[ri].parameter[0]+res->voi[ri].parameter[1];
381 fprintf(fp, "<th>%g</th>", f); /* y-axis value */
382 }
383 fprintf(fp, "</tr>\n");
384 row++;
385 }
386 fprintf(fp, "</tbody>\n");
387
388 /* End the data table */
389 fprintf(fp, "</table>\n");
390
391 } /* next region plot */
392
393 /* End the div for tables */
394 fprintf(fp, "</div>\n");
395
396 /* Stop writing the body of the HTML file, and end the file */
397 n=fprintf(fp, "</body></html>\n");
398 if(n==0) return(4);
399
400 /* Close file */
401 fclose(fp);
402
403 return(0);
404}
char * ctime_r_int(const time_t *t, char *buf)
Convert calendard time t into a null-terminated string of the form YYYY-MM-DD hh:mm:ss,...
Definition datetime.c:110
int plotdata_as_dft(DFT *dft, char *fname)
Definition plotdata.c:412
time_t time

◆ plotdata_as_dft()

int plotdata_as_dft ( DFT * dft,
char * fname )

Write plot data in DFT format with x values as separate columns before corresponding y values.

Returns
Returns 0 if successful, otherwise non-zero.
See also
plotdata
Parameters
dftPlot points: X in y2, Y in y3.
fnameFile name for plot data.

Definition at line 412 of file plotdata.c.

417 {
418 int ri, rj, fi, ret;
419 DFT plot;
420
421 /* Check input data */
422 if(dft==NULL || dft->voiNr<1) return(1);
423 /* Create the plot data */
424 dftInit(&plot);
425 ret=dftSetmem(&plot, dft->frameNr, 2*dft->voiNr); if(ret) return(ret);
426 ret=dftCopymainhdr(dft, &plot); if(ret) {dftEmpty(&plot); return(ret);}
427 for(ri=rj=0; ri<dft->voiNr; ri++) {
428 /* x */
429 strcpy(plot.voi[rj].voiname, "X");
430 strcpy(plot.voi[rj].name, plot.voi[rj].voiname);
431 for(fi=0; fi<dft->frameNr; fi++) plot.voi[rj].y[fi]=dft->voi[ri].y2[fi];
432 rj++;
433 /* y */
434 dftCopyvoihdr(dft, ri, &plot, rj);
435 for(fi=0; fi<dft->frameNr; fi++) plot.voi[rj].y[fi]=dft->voi[ri].y3[fi];
436 rj++;
437 }
438 for(fi=0; fi<dft->frameNr; fi++) {
439 plot.x[fi]=dft->x[fi]; plot.x1[fi]=dft->x1[fi]; plot.x2[fi]=dft->x2[fi];
440 }
441 plot.voiNr=2*dft->voiNr; plot.frameNr=dft->frameNr;
442 /* Save plot data */
443 strcpy(plot.comments, "");
444 ret=dftWrite(&plot, fname);
445 dftEmpty(&plot);
446 return(ret);
447}
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
char comments[_DFT_COMMENT_LEN+1]

Referenced by plotdata().

◆ sif2dft()

int sif2dft ( SIF * sif,
DFT * dft )

Convert SIF data to DFT data.

See also
sifAllocateWithIMG, dftAllocateWithIMG
Returns
Returns 0 if successful, otherwise >0.
Parameters
sifPointer to SIF struct containing data to be converted.
dftPointer to initiated but empty DFT struct.

Definition at line 350 of file misc_model.c.

355 {
356 int fi, ri, tacNr, ret;
357
358 /* Check input */
359 if(dft==NULL || sif==NULL) return 1;
360 if(sif->frameNr<1) return 2;
361 tacNr=sif->colNr-2; if(tacNr<=0) tacNr=1;
362
363 /* Allocate memory */
364 ret=dftSetmem(dft, sif->frameNr, tacNr);
365 if(ret) return(100+ret);
366 dft->voiNr=tacNr;
367 dft->frameNr=sif->frameNr;
368
369 // Set header contents
372 for(fi=0; fi<dft->frameNr; fi++) {
373 dft->x[fi]=0.5*(sif->x1[fi]+sif->x2[fi]);
374 dft->x1[fi]=sif->x1[fi];
375 dft->x2[fi]=sif->x2[fi];
376 }
377 dft->timeunit=TUNIT_SEC;
378 dft->isweight=0;
379 strcpy(dft->unit, imgUnit(CUNIT_COUNTS));
380 for(ri=0; ri<dft->voiNr; ri++) {
381 /* Set ROI name */
382 if(ri==0) sprintf(dft->voi[ri].voiname, "Prompt");
383 else if(ri==1) sprintf(dft->voi[ri].voiname, "Random");
384 else if(ri==2) sprintf(dft->voi[ri].voiname, "True");
385 else if(ri==3) sprintf(dft->voi[ri].voiname, "Weight");
386 else snprintf(dft->voi[ri].voiname, 7, "%06d", ri+1);
387 strcpy(dft->voi[ri].name, dft->voi[ri].voiname);
388 /* Copy TAC values */
389 if(ri==0 && ri<sif->colNr-2) {
390 for(fi=0; fi<dft->frameNr; fi++) dft->voi[ri].y[fi]=sif->prompts[fi];
391 } else if(ri==1 && ri<sif->colNr-2) {
392 for(fi=0; fi<dft->frameNr; fi++) dft->voi[ri].y[fi]=sif->randoms[fi];
393 } else if(ri==2 && ri<sif->colNr-2) {
394 for(fi=0; fi<dft->frameNr; fi++) dft->voi[ri].y[fi]=sif->trues[fi];
395 } else if(ri==3 && ri<sif->colNr-2) {
396 for(fi=0; fi<dft->frameNr; fi++) dft->voi[ri].y[fi]=sif->weights[fi];
397 } else {
398 for(fi=0; fi<dft->frameNr; fi++) dft->voi[ri].y[fi]=0.0;
399 }
400 }
401 strcpy(dft->studynr, sif->studynr);
402 strcpy(dft->isotope, hlCorrectIsotopeCode(sif->isotope_name));
403
404 return 0;
405}
char * hlCorrectIsotopeCode(char *isocode)
Definition halflife.c:141
double * prompts
char studynr[MAX_STUDYNR_LEN+1]
int colNr
double * randoms
double * trues

◆ sifAllocateWithIMG()

int sifAllocateWithIMG ( SIF * sif,
IMG * img,
int doCounts,
int verbose )

Allocate memory for SIF based on information in IMG.

Frame times are set, 'counts' are optionally set to mean of voxel values times frame lengths, scaled to 0-1E7. Weights are not calculated.

See also
sif2dft, dftAllocateWithIMG
Returns
Returns 0 if successful, otherwise <>0.
Parameters
sifPointer to initiated SIF struct which will be allocated here.
imgPointer to IMG struct from where necessary information is read.
doCountsSet (1) or do not set (0) counts, based on sum of all image voxel values and frame lengths.
verboseVerbose level; if zero, then only warnings are printed into stderr.

Definition at line 418 of file misc_model.c.

427 {
428 int fi, ret;
429 float *cs;
430 double f, mf;
431
432 if(verbose>0) {printf("%s(*sif, *img, %d, ...)\n", __func__, doCounts); fflush(stdout);}
433 /* Check the input data */
434 if(sif==NULL || img==NULL) return 1;
435 if(img->status!=IMG_STATUS_OCCUPIED) return 2;
436 if(img->dimt<1) return 3;
437 if(doCounts<0 || doCounts>1) return 4;
438
439 /* Delete any previous SIF contents */
440 sifEmpty(sif);
441
442 /* Allocate memory for SIF data */
443 ret=sifSetmem(sif, img->dimt); if(ret!=0) return(10+ret);
444
445 /* Set SIF information */
446 sif->version=1;
447 sif->colNr=4;
448 strcpy(sif->isotope_name, imgIsotope(img));
449 strcpy(sif->studynr, img->studyNr);
450 sif->scantime=img->scanStart;
451 for(fi=0; fi<img->dimt; fi++) {sif->x1[fi]=img->start[fi]; sif->x2[fi]=img->end[fi];}
452
453 if(doCounts==0) return 0; // that's it then
454
455 /* Calculate average curve of all pixels */
456 if(verbose>1) printf("calculate image average curve.\n");
457 cs=(float*)malloc(img->dimt*sizeof(float));
458 if(cs==NULL) {sifEmpty(sif); return(20);}
459 ret=imgAverageTAC(img, cs); if(ret!=0) {sifEmpty(sif); return(20+ret);}
460 /* Multiply average curve with frame durations, and get the max */
461 for(fi=0, mf=0.0; fi<sif->frameNr; fi++) {
462 f=sif->x2[fi]-sif->x1[fi]; if(f<=0.1) f=0.1;
463 cs[fi]*=f; if(cs[fi]>mf) mf=cs[fi];
464 }
465 /* Put scaled counts into SIF */
466 if(mf>0.0) f=1.0E+007/mf; else f=1.0;
467 for(fi=0, mf=0.0; fi<sif->frameNr; fi++) {
468 sif->prompts[fi]=sif->trues[fi]=cs[fi]*f;
469 sif->randoms[fi]=0.0;
470 }
471 free(cs);
472 if(verbose>2) sifPrint(sif);
473 return 0;
474}
char * imgIsotope(IMG *img)
Definition imgdecayc.c:76
int imgAverageTAC(IMG *img, float *tac)
Definition imgeval.c:15
int sifSetmem(SIF *data, int frameNr)
Definition sif.c:56
time_t scanStart
int version
time_t scantime

Referenced by imgSetWeights().