Computing pixel-by-pixel the K1 for irreversible PET tracers using previously determined Ki (K1*k3/(k2+k3) and bilinear regression.
37 {
38 int zi, yi, xi, fi, ret=0;
39 int nnls_n=2, nnls_m, m;
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
50 if(status!=NULL) sprintf(status, "invalid data");
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
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 }
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
76
78 sprintf(status, "out of memory"); return(3);
79 }
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
89
90
91
92 ret=0;
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");
105 );
106 } else {
107 if(verbose>1) printf("copying input curve and using petintegral()\n");
108
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 }
119
120
121
122
123
126 if(ret) {
127 sprintf(status, "cannot allocate memory for K1 image");
129 }
131 if(ret) {
132 sprintf(status, "cannot copy header info for result image");
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];
139
140
141 if(k2k3_img!=NULL) {
144 if(ret) {
145 sprintf(status, "cannot allocate memory for (k2+k3) image");
147 }
149 if(ret) {
150 sprintf(status, "cannot copy header info for result image");
152 }
153 k2k3_img->
unit=CUNIT_PER_MIN;
156 k2k3_img->
end[0]=dyn_img->
end[frame_nr-1];
157 if(verbose>9)
imgInfo(k2k3_img);
158 }
159
160
161
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
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
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
184 for(m=0; m<nnls_m; m++) tac.
voi[1].
y[m]=dyn_img->
m[zi][yi][xi][m];
186 tac.
voi[1].
y2, NULL);
187 if(ret) continue;
188
189 if(tac.
voi[1].
y2[nnls_m-1]<=0.0)
continue;
190
191
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
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) {
202 continue;
203 } else if(ret==1) { }
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 }
208 }
209 }
211
212 fitFinish=clock();
213
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}
int dftSetmem(DFT *data, int frameNr, int voiNr)
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
int imgCopyhdr(IMG *image1, IMG *image2)
void imgEmpty(IMG *image)
int petintegral(double *x1, double *x2, double *y, int nr, double *ie, double *iie)
Integrate PET TAC data to frame mid times.
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.
#define IMG_STATUS_OCCUPIED
#define IMG_DC_NONCORRECTED
int nnls(double **a, int m, int n, double *b, double *x, double *rnorm, double *w, double *zz, int *index)
char voiname[MAX_REGIONSUBNAME_LEN+1]