TPCCLIB
Loading...
Searching...
No Matches
misc_model.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6
7/*****************************************************************************/
8#include "libtpcmodext.h"
9/*****************************************************************************/
10
11/*****************************************************************************/
19 DFT *input,
21 IMG *img,
23 int frame_nr,
26 DFT *output,
29 double *ti1,
32 double *ti2,
34 int verbose,
37 char *status
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}
134/*****************************************************************************/
135
136/*****************************************************************************/
150 IMG *img,
152 float t1,
154 float t2,
156 IMG *iimg,
158 int calc_mode,
161 char *status,
163 int verbose
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}
289/*****************************************************************************/
290
291/*****************************************************************************/
298 DFT *dft,
301 int tacNr,
303 IMG *img
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}
343/*****************************************************************************/
344
345/*****************************************************************************/
352 SIF *sif,
354 DFT *dft
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}
406/*****************************************************************************/
407
408/*****************************************************************************/
420 SIF *sif,
422 IMG *img,
424 int doCounts,
426 int verbose
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}
475/*****************************************************************************/
476
477/*****************************************************************************/
int dftSetmem(DFT *data, int frameNr, int voiNr)
Definition dft.c:57
void dftEmpty(DFT *data)
Definition dft.c:20
int dftAllocateWithHeader(DFT *dft, int frameNr, int voiNr, DFT *dft_from)
Definition dft.c:702
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 copy_times_from_img_to_dft(IMG *img, DFT *dft, int verbose)
Definition fittime.c:246
int check_times_dft_vs_dft(DFT *dft1, DFT *dft2, int verbose)
Definition fittime.c:169
char * hlCorrectIsotopeCode(char *isocode)
Definition halflife.c:141
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
Definition img.c:279
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
char * imgIsotope(IMG *img)
Definition imgdecayc.c:76
int imgAverageTAC(IMG *img, float *tac)
Definition imgeval.c:15
char * imgUnit(int dunit)
Definition imgunits.c:315
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
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
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_FORMAT_STANDARD
#define DFT_TIME_STARTEND
#define IMG_STATUS_OCCUPIED
void sifPrint(SIF *data)
Definition sifio.c:234
int sifSetmem(SIF *data, int frameNr)
Definition sif.c:56
void sifEmpty(SIF *data)
Definition sif.c:33
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
char * petTunit(int tunit)
Definition petunits.c:226
#define MAX_STUDYNR_LEN
Definition libtpcmisc.h:163
#define MAX_UNITS_LEN
Definition libtpcmisc.h:95
Header file for libtpcmodext.
int sifAllocateWithIMG(SIF *sif, IMG *img, int doCounts, int verbose)
Definition misc_model.c:418
int dftAllocateWithIMG(DFT *dft, int tacNr, IMG *img)
Definition misc_model.c:296
int sif2dft(SIF *sif, DFT *dft)
Definition misc_model.c:350
int imgTimeIntegral(IMG *img, float t1, float t2, IMG *iimg, int calc_mode, char *status, int verbose)
Definition misc_model.c:147
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 _type
int timetype
Voi * voi
int timeunit
char studynr[MAX_STUDYNR_LEN+1]
double * x1
int voiNr
double * x2
int frameNr
int isweight
char isotope[8]
double * x
char unit[MAX_UNITS_LEN+1]
unsigned short int dimx
float **** m
char unit
char status
time_t scanStart
unsigned short int dimt
float * start
unsigned short int dimz
unsigned short int dimy
float * end
char studyNr[MAX_STUDYNR_LEN+1]
float * mid
double * x1
double * prompts
int frameNr
double * x2
int version
char studynr[MAX_STUDYNR_LEN+1]
time_t scantime
char isotope_name[8]
double * weights
int colNr
double * randoms
double * trues
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]
double * y3