void project( float *obj, int ox, int oy, int oz, float *data, int dx, int dy, int dz, float *center, float *theta, int istart, int iend) { float *gridx = (float *)malloc((oy+1)*sizeof(float)); float *gridy = (float *)malloc((oz+1)*sizeof(float)); float *coordx = (float *)malloc((oz+1)*sizeof(float)); float *coordy = (float *)malloc((oy+1)*sizeof(float)); float *ax = (float *)malloc((oy+oz)*sizeof(float)); float *ay = (float *)malloc((oy+oz)*sizeof(float)); float *bx = (float *)malloc((oy+oz)*sizeof(float)); float *by = (float *)malloc((oy+oz)*sizeof(float)); float *coorx = (float *)malloc((oy+oz)*sizeof(float)); float *coory = (float *)malloc((oy+oz)*sizeof(float)); float *dist = (float *)malloc((oy+oz)*sizeof(float)); int *indi = (int *)malloc((oy+oz)*sizeof(int)); assert(coordx != NULL && coordy != NULL && ax != NULL && ay != NULL && by != NULL && bx != NULL && coorx != NULL && coory != NULL && dist != NULL && indi != NULL); int s, p, d; int quadrant; float theta_p, sin_p, cos_p; float mov, xi, yi; int asize, bsize, csize; preprocessing(oy, oz, dz, center[0], &mov, gridx, gridy); // Outputs: mov, gridx, gridy // For each projection angle for (p=istart; p<iend; p++) { // Calculate the sin and cos values // of the projection angle and find // at which quadrant on the cartesian grid. theta_p = fmod(theta[p], 2*M_PI); quadrant = calc_quadrant(theta_p); sin_p = sinf(theta_p); cos_p = cosf(theta_p); for (d=0; d<dz; d++) { // Calculate coordinates xi = -oy-oz; yi = (1-dz)/2.0+d+mov; calc_coords( oy, oz, xi, yi, sin_p, cos_p, gridx, gridy, coordx, coordy); // Merge the (coordx, gridy) and (gridx, coordy) trim_coords( oy, oz, coordx, coordy, gridx, gridy, &asize, ax, ay, &bsize, bx, by); // Sort the array of intersection points (ax, ay) and // (bx, by). The new sorted intersection points are // stored in (coorx, coory). Total number of points // are csize. sort_intersections( quadrant, asize, ax, ay, bsize, bx, by, &csize, coorx, coory); // Calculate the distances (dist) between the // intersection points (coorx, coory). Find the // indices of the pixels on the object grid. calc_dist( oy, oz, csize, coorx, coory, indi, dist); // For each slice for (s=0; s<dy; s++) { // Calculate simdata calc_simdata(p, s, d, oy, oz, dy, dz, csize, indi, dist, obj, data); // Output: simulated data } } } free(gridx); free(gridy); free(coordx); free(coordy); free(ax); free(ay); free(bx); free(by); free(coorx); free(coory); free(dist); free(indi); }
void ospml_hybrid(const float* data, int dy, int dt, int dx, const float* center, const float* theta, float* recon, int ngridx, int ngridy, int num_iter, const float* reg_pars, int num_block, const float* ind_block) { if(dy == 0 || dt == 0 || dx == 0) return; float* gridx = (float*) malloc((ngridx + 1) * sizeof(float)); float* gridy = (float*) malloc((ngridy + 1) * sizeof(float)); float* coordx = (float*) malloc((ngridy + 1) * sizeof(float)); float* coordy = (float*) malloc((ngridx + 1) * sizeof(float)); float* ax = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* ay = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* bx = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* by = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* coorx = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* coory = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* dist = (float*) malloc((ngridx + ngridy) * sizeof(float)); int* indi = (int*) malloc((ngridx + ngridy) * sizeof(int)); assert(coordx != NULL && coordy != NULL && ax != NULL && ay != NULL && by != NULL && bx != NULL && coorx != NULL && coory != NULL && dist != NULL && indi != NULL); int s, q, p, d, i, m, n, os; int quadrant; float theta_p, sin_p, cos_p; float mov, xi, yi; int asize, bsize, csize; float* simdata; float upd; int ind_data, ind_recon; float* sum_dist; float sum_dist2; float *E, *F, *G; int ind0, ind1, indg[8]; float totalwg, wg[8], mg[8], rg[8], gammag[8]; int subset_ind1, subset_ind2; for(i = 0; i < num_iter; i++) { simdata = (float*) calloc((dt * dy * dx), sizeof(float)); // For each slice for(s = 0; s < dy; s++) { preprocessing(ngridx, ngridy, dx, center[s], &mov, gridx, gridy); // Outputs: mov, gridx, gridy subset_ind1 = dt / num_block; subset_ind2 = subset_ind1; // For each ordered-subset num_subset for(os = 0; os < num_block + 1; os++) { if(os == num_block) { subset_ind2 = dt % num_block; } sum_dist = (float*) calloc((ngridx * ngridy), sizeof(float)); E = (float*) calloc((ngridx * ngridy), sizeof(float)); F = (float*) calloc((ngridx * ngridy), sizeof(float)); G = (float*) calloc((ngridx * ngridy), sizeof(float)); // For each projection angle for(q = 0; q < subset_ind2; q++) { p = ind_block[q + os * subset_ind1]; // Calculate the sin and cos values // of the projection angle and find // at which quadrant on the cartesian grid. theta_p = fmodf(theta[p], 2.0f * (float) M_PI); quadrant = calc_quadrant(theta_p); sin_p = sinf(theta_p); cos_p = cosf(theta_p); // For each detector pixel for(d = 0; d < dx; d++) { // Calculate coordinates xi = -ngridx - ngridy; yi = 0.5f * (1 - dx) + d + mov; calc_coords(ngridx, ngridy, xi, yi, sin_p, cos_p, gridx, gridy, coordx, coordy); // Merge the (coordx, gridy) and (gridx, coordy) trim_coords(ngridx, ngridy, coordx, coordy, gridx, gridy, &asize, ax, ay, &bsize, bx, by); // Sort the array of intersection points (ax, ay) and // (bx, by). The new sorted intersection points are // stored in (coorx, coory). Total number of points // are csize. sort_intersections(quadrant, asize, ax, ay, bsize, bx, by, &csize, coorx, coory); // Calculate the distances (dist) between the // intersection points (coorx, coory). Find the // indices of the pixels on the reconstruction grid. calc_dist(ngridx, ngridy, csize, coorx, coory, indi, dist); // Calculate simdata calc_simdata(s, p, d, ngridx, ngridy, dt, dx, csize, indi, dist, recon, simdata); // Output: simdata // Calculate dist*dist sum_dist2 = 0.0f; for(n = 0; n < csize - 1; n++) { sum_dist2 += dist[n] * dist[n]; sum_dist[indi[n]] += dist[n]; } // Update if(sum_dist2 != 0.0f) { ind_data = d + p * dx + s * dt * dx; ind_recon = s * ngridx * ngridy; upd = data[ind_data] / simdata[ind_data]; for(n = 0; n < csize - 1; n++) { E[indi[n]] -= recon[indi[n] + ind_recon] * upd * dist[n]; } } } } // Weights for inner neighborhoods. totalwg = 4 + 4 / sqrt(2); wg[0] = 1 / totalwg; wg[1] = 1 / totalwg; wg[2] = 1 / totalwg; wg[3] = 1 / totalwg; wg[4] = 1 / sqrt(2) / totalwg; wg[5] = 1 / sqrt(2) / totalwg; wg[6] = 1 / sqrt(2) / totalwg; wg[7] = 1 / sqrt(2) / totalwg; // (inner region) for(n = 1; n < ngridx - 1; n++) { for(m = 1; m < ngridy - 1; m++) { ind0 = m + n * ngridy; ind1 = ind0 + s * ngridx * ngridy; indg[0] = ind1 + 1; indg[1] = ind1 - 1; indg[2] = ind1 + ngridy; indg[3] = ind1 - ngridy; indg[4] = ind1 + ngridy + 1; indg[5] = ind1 + ngridy - 1; indg[6] = ind1 - ngridy + 1; indg[7] = ind1 - ngridy - 1; for(q = 0; q < 8; q++) { mg[q] = recon[ind1] + recon[indg[q]]; rg[q] = recon[ind1] - recon[indg[q]]; gammag[q] = 1 / (1 + fabs(rg[q] / reg_pars[1])); F[ind0] += 2 * reg_pars[0] * wg[q] * gammag[q]; G[ind0] -= 2 * reg_pars[0] * wg[q] * gammag[q] * mg[q]; } } } // Weights for edges. totalwg = 3 + 2 / sqrt(2); wg[0] = 1 / totalwg; wg[1] = 1 / totalwg; wg[2] = 1 / totalwg; wg[3] = 1 / sqrt(2) / totalwg; wg[4] = 1 / sqrt(2) / totalwg; // (top) for(m = 1; m < ngridy - 1; m++) { ind0 = m; ind1 = ind0 + s * ngridx * ngridy; indg[0] = ind1 + 1; indg[1] = ind1 - 1; indg[2] = ind1 + ngridy; indg[3] = ind1 + ngridy + 1; indg[4] = ind1 + ngridy - 1; for(q = 0; q < 5; q++) { mg[q] = recon[ind1] + recon[indg[q]]; rg[q] = recon[ind1] - recon[indg[q]]; gammag[q] = 1 / (1 + fabs(rg[q] / reg_pars[1])); F[ind0] += 2 * reg_pars[0] * wg[q] * gammag[q]; G[ind0] -= 2 * reg_pars[0] * wg[q] * gammag[q] * mg[q]; } } // (bottom) for(m = 1; m < ngridy - 1; m++) { ind0 = m + (ngridx - 1) * ngridy; ind1 = ind0 + s * ngridx * ngridy; indg[0] = ind1 + 1; indg[1] = ind1 - 1; indg[2] = ind1 - ngridy; indg[3] = ind1 - ngridy + 1; indg[4] = ind1 - ngridy - 1; for(q = 0; q < 5; q++) { mg[q] = recon[ind1] + recon[indg[q]]; rg[q] = recon[ind1] - recon[indg[q]]; gammag[q] = 1 / (1 + fabs(rg[q] / reg_pars[1])); F[ind0] += 2 * reg_pars[0] * wg[q] * gammag[q]; G[ind0] -= 2 * reg_pars[0] * wg[q] * gammag[q] * mg[q]; } } // (left) for(n = 1; n < ngridx - 1; n++) { ind0 = n * ngridy; ind1 = ind0 + s * ngridx * ngridy; indg[0] = ind1 + 1; indg[1] = ind1 + ngridy; indg[2] = ind1 - ngridy; indg[3] = ind1 + ngridy + 1; indg[4] = ind1 - ngridy + 1; for(q = 0; q < 5; q++) { mg[q] = recon[ind1] + recon[indg[q]]; rg[q] = recon[ind1] - recon[indg[q]]; gammag[q] = 1 / (1 + fabs(rg[q] / reg_pars[1])); F[ind0] += 2 * reg_pars[0] * wg[q] * gammag[q]; G[ind0] -= 2 * reg_pars[0] * wg[q] * gammag[q] * mg[q]; } } // (right) for(n = 1; n < ngridx - 1; n++) { ind0 = (ngridy - 1) + n * ngridy; ind1 = ind0 + s * ngridx * ngridy; indg[0] = ind1 - 1; indg[1] = ind1 + ngridy; indg[2] = ind1 - ngridy; indg[3] = ind1 + ngridy - 1; indg[4] = ind1 - ngridy - 1; for(q = 0; q < 5; q++) { mg[q] = recon[ind1] + recon[indg[q]]; rg[q] = recon[ind1] - recon[indg[q]]; gammag[q] = 1 / (1 + fabs(rg[q] / reg_pars[1])); F[ind0] += 2 * reg_pars[0] * wg[q] * gammag[q]; G[ind0] -= 2 * reg_pars[0] * wg[q] * gammag[q] * mg[q]; } } // Weights for corners. totalwg = 2 + 1 / sqrt(2); wg[0] = 1 / totalwg; wg[1] = 1 / totalwg; wg[2] = 1 / sqrt(2) / totalwg; // (top-left) ind0 = 0; ind1 = ind0 + s * ngridx * ngridy; indg[0] = ind1 + 1; indg[1] = ind1 + ngridy; indg[2] = ind1 + ngridy + 1; for(q = 0; q < 3; q++) { mg[q] = recon[ind1] + recon[indg[q]]; rg[q] = recon[ind1] - recon[indg[q]]; gammag[q] = 1 / (1 + fabs(rg[q] / reg_pars[1])); F[ind0] += 2 * reg_pars[0] * wg[q] * gammag[q]; G[ind0] -= 2 * reg_pars[0] * wg[q] * gammag[q] * mg[q]; } // (top-right) ind0 = (ngridy - 1); ind1 = ind0 + s * ngridx * ngridy; indg[0] = ind1 - 1; indg[1] = ind1 + ngridy; indg[2] = ind1 + ngridy - 1; for(q = 0; q < 3; q++) { mg[q] = recon[ind1] + recon[indg[q]]; rg[q] = recon[ind1] - recon[indg[q]]; gammag[q] = 1 / (1 + fabs(rg[q] / reg_pars[1])); F[ind0] += 2 * reg_pars[0] * wg[q] * gammag[q]; G[ind0] -= 2 * reg_pars[0] * wg[q] * gammag[q] * mg[q]; } // (bottom-left) ind0 = (ngridx - 1) * ngridy; ind1 = ind0 + s * ngridx * ngridy; indg[0] = ind1 + 1; indg[1] = ind1 - ngridy; indg[2] = ind1 - ngridy + 1; for(q = 0; q < 3; q++) { mg[q] = recon[ind1] + recon[indg[q]]; rg[q] = recon[ind1] - recon[indg[q]]; gammag[q] = 1 / (1 + fabs(rg[q] / reg_pars[1])); F[ind0] += 2 * reg_pars[0] * wg[q] * gammag[q]; G[ind0] -= 2 * reg_pars[0] * wg[q] * gammag[q] * mg[q]; } // (bottom-right) ind0 = (ngridy - 1) + (ngridx - 1) * ngridy; ind1 = ind0 + s * ngridx * ngridy; indg[0] = ind1 - 1; indg[1] = ind1 - ngridy; indg[2] = ind1 - ngridy - 1; for(q = 0; q < 3; q++) { mg[q] = recon[ind1] + recon[indg[q]]; rg[q] = recon[ind1] - recon[indg[q]]; gammag[q] = 1 / (1 + fabs(rg[q] / reg_pars[1])); F[ind0] += 2 * reg_pars[0] * wg[q] * gammag[q]; G[ind0] -= 2 * reg_pars[0] * wg[q] * gammag[q] * mg[q]; } q = 0; for(n = 0; n < ngridx * ngridy; n++) { G[q] += sum_dist[n]; q++; } for(n = 0; n < ngridx; n++) { for(m = 0; m < ngridy; m++) { q = m + n * ngridy; if(F[q] != 0.0) { ind0 = q + s * ngridx * ngridy; recon[ind0] = (-G[q] + sqrt(G[q] * G[q] - 8 * E[q] * F[q])) / (4 * F[q]); } } } free(sum_dist); free(E); free(F); free(G); } } free(simdata); } free(gridx); free(gridy); free(coordx); free(coordy); free(ax); free(ay); free(bx); free(by); free(coorx); free(coory); free(dist); free(indi); }
void bart( float *data, int dx, int dy, int dz, float *center, float *theta, float *recon, int ngridx, int ngridy, int num_iter, int num_block, float *ind_block) { float *gridx = (float *)malloc((ngridx+1)*sizeof(float)); float *gridy = (float *)malloc((ngridy+1)*sizeof(float)); float *coordx = (float *)malloc((ngridy+1)*sizeof(float)); float *coordy = (float *)malloc((ngridx+1)*sizeof(float)); float *ax = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *ay = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *bx = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *by = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *coorx = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *coory = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *dist = (float *)malloc((ngridx+ngridy)*sizeof(float)); int *indi = (int *)malloc((ngridx+ngridy)*sizeof(int)); assert(coordx != NULL && coordy != NULL && ax != NULL && ay != NULL && by != NULL && bx != NULL && coorx != NULL && coory != NULL && dist != NULL && indi != NULL); int s, q, p, d, i, m, n, os; int quadrant; float theta_p, sin_p, cos_p; float mov, xi, yi; int asize, bsize, csize; float *simdata; float upd; int ind_data, ind_recon; float *sum_dist; float sum_dist2; float *update; int subset_ind1, subset_ind2; for (i=0; i<num_iter; i++) { simdata = (float *)calloc((dx*dy*dz), sizeof(float)); // For each slice for (s=0; s<dy; s++) { preprocessing(ngridx, ngridy, dz, center[s], &mov, gridx, gridy); // Outputs: mov, gridx, gridy subset_ind1 = dx/num_block; subset_ind2 = subset_ind1; // For each ordered-subset num_subset for (os=0; os<num_block+1; os++) { if (os == num_block) { subset_ind2 = dx%num_block; } sum_dist = (float *)calloc((ngridx*ngridy), sizeof(float)); update = (float *)calloc((ngridx*ngridy), sizeof(float)); // For each projection angle for (q=0; q<subset_ind2; q++) { p = ind_block[q+os*subset_ind1]; // Calculate the sin and cos values // of the projection angle and find // at which quadrant on the cartesian grid. theta_p = fmod(theta[p], 2*M_PI); quadrant = calc_quadrant(theta_p); sin_p = sinf(theta_p); cos_p = cosf(theta_p); // For each detector pixel for (d=0; d<dz; d++) { // Calculate coordinates xi = -1e6; yi = -(dz-1)/2.0+d+mov; calc_coords( ngridx, ngridy, xi, yi, sin_p, cos_p, gridx, gridy, coordx, coordy); // Merge the (coordx, gridy) and (gridx, coordy) trim_coords( ngridx, ngridy, coordx, coordy, gridx, gridy, &asize, ax, ay, &bsize, bx, by); // Sort the array of intersection points (ax, ay) and // (bx, by). The new sorted intersection points are // stored in (coorx, coory). Total number of points // are csize. sort_intersections( quadrant, asize, ax, ay, bsize, bx, by, &csize, coorx, coory); // Calculate the distances (dist) between the // intersection points (coorx, coory). Find the // indices of the pixels on the reconstruction grid. calc_dist( ngridx, ngridy, csize, coorx, coory, indi, dist); // Calculate simdata calc_simdata(p, s, d, ngridx, ngridy, dy, dz, csize, indi, dist, recon, simdata); // Output: simdata // Calculate dist*dist sum_dist2 = 0.0; for (n=0; n<csize-1; n++) { sum_dist2 += dist[n]*dist[n]; sum_dist[indi[n]] += dist[n]; } // Update if (sum_dist2 != 0.0) { ind_data = d+s*dz+p*dy*dz; upd = (data[ind_data]-simdata[ind_data])/sum_dist2; for (n=0; n<csize-1; n++) { update[indi[n]] += upd*dist[n]; } } } } m = 0; for (n = 0; n < ngridx*ngridy; n++) { if (sum_dist[n] != 0.0) { ind_recon = s*ngridx*ngridy; recon[m+ind_recon] += update[m]/sum_dist[n]; } m++; } free(sum_dist); free(update); } } free(simdata); } free(gridx); free(gridy); free(coordx); free(coordy); free(ax); free(ay); free(bx); free(by); free(coorx); free(coory); free(dist); free(indi); }
void fbp( float *data, int dx, int dy, int dz, float *center, float *theta, float *recon, int ngridx, int ngridy, char *fname, int istart, int iend) { float *gridx = (float *)malloc((ngridx+1)*sizeof(float)); float *gridy = (float *)malloc((ngridy+1)*sizeof(float)); float *coordx = (float *)malloc((ngridy+1)*sizeof(float)); float *coordy = (float *)malloc((ngridx+1)*sizeof(float)); float *ax = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *ay = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *bx = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *by = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *coorx = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *coory = (float *)malloc((ngridx+ngridy)*sizeof(float)); float *dist = (float *)malloc((ngridx+ngridy)*sizeof(float)); int *indi = (int *)malloc((ngridx+ngridy)*sizeof(int)); assert(coordx != NULL && coordy != NULL && ax != NULL && ay != NULL && by != NULL && bx != NULL && coorx != NULL && coory != NULL && dist != NULL && indi != NULL); int s, p, d, n; int quadrant; float theta_p, sin_p, cos_p; float mov, xi, yi; int asize, bsize, csize; float* simdata; int ind_data, ind_recon; simdata = (float *)calloc((dx*dy*dz), sizeof(float)); // For each slice for (s=istart; s<iend; s++) { preprocessing(ngridx, ngridy, dz, center[s], &mov, gridx, gridy); // Outputs: mov, gridx, gridy // For each projection angle for (p=0; p<dx; p++) { // Calculate the sin and cos values // of the projection angle and find // at which quadrant on the cartesian grid. theta_p = fmod(theta[p], 2*M_PI); quadrant = calc_quadrant(theta_p); sin_p = sinf(theta_p); cos_p = cosf(theta_p); // For each detector pixel for (d=0; d<dz; d++) { // Calculate coordinates xi = -ngridx-ngridy; yi = (1-dz)/2.0+d+mov; calc_coords( ngridx, ngridy, xi, yi, sin_p, cos_p, gridx, gridy, coordx, coordy); // Merge the (coordx, gridy) and (gridx, coordy) trim_coords( ngridx, ngridy, coordx, coordy, gridx, gridy, &asize, ax, ay, &bsize, bx, by); // Sort the array of intersection points (ax, ay) and // (bx, by). The new sorted intersection points are // stored in (coorx, coory). Total number of points // are csize. sort_intersections( quadrant, asize, ax, ay, bsize, bx, by, &csize, coorx, coory); // Calculate the distances (dist) between the // intersection points (coorx, coory). Find the // indices of the pixels on the reconstruction grid. calc_dist( ngridx, ngridy, csize, coorx, coory, indi, dist); // Calculate simdata calc_simdata(p, s, d, ngridx, ngridy, dy, dz, csize, indi, dist, recon, simdata); // Output: simdata // Calculate dist*dist float sum_dist2 = 0.0; for (n=0; n<csize-1; n++) { sum_dist2 += dist[n]*dist[n]; } // Update if (sum_dist2 != 0.0) { ind_recon = s*ngridx*ngridy; ind_data = d+s*dz+p*dy*dz; for (n=0; n<csize-1; n++) { recon[indi[n]+ind_recon] += data[ind_data]*dist[n]; } } } } } free(simdata); free(gridx); free(gridy); free(coordx); free(coordy); free(ax); free(ay); free(bx); free(by); free(coorx); free(coory); free(dist); free(indi); }
void fbp(const float *data, int dy, int dt, int dx, const float *center, const float *theta, float *recon, int ngridx, int ngridy, const char *fname, const float *filter_par) { int s, p, d, n; int quadrant; float theta_p, sin_p, cos_p; float mov, xi, yi; int asize, bsize, csize; int ind_data, ind_recon; float *gridx, *gridy, *coordx, *coordy, *ax, *ay, *bx, *by, *coorx, *coory, *dist; int *indi; gridx = (float *)malloc((size_t)(ngridx + 1) * sizeof(float)); gridy = (float *)malloc((size_t)(ngridy + 1) * sizeof(float)); coordx = (float *)malloc((size_t)(ngridy + 1) * sizeof(float)); coordy = (float *)malloc((size_t)(ngridx + 1) * sizeof(float)); ax = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); ay = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); bx = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); by = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); coorx = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); coory = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); dist = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); indi = (int *)malloc((size_t)(ngridx + ngridy) * sizeof(int)); /* unused arguments: */ (void)fname; (void)filter_par; assert(coordx != NULL && coordy != NULL && ax != NULL && ay != NULL && by != NULL && bx != NULL && coorx != NULL && coory != NULL && dist != NULL && indi != NULL); /* For each slice */ for (s = 0; s < dy; s++) { preprocessing(ngridx, ngridy, dx, center[s], &mov, gridx, gridy); /* Outputs: mov, gridx, gridy */ /* For each projection angle */ for (p = 0; p < dt; p++) { /* Calculate the sin and cos values of the projection angle and find at which quadrant on the cartesian grid. */ theta_p = (float)fmod(theta[p], 2 * M_PI); quadrant = calc_quadrant(theta_p); sin_p = sinf(theta_p); cos_p = cosf(theta_p); /* For each detector pixel */ for (d = 0; d < dx; d++) { /* Calculate coordinates */ xi = (float)(-ngridx - ngridy); yi = (float)(1 - dx) / 2.0f + (float)d + mov; calc_coords(ngridx, ngridy, xi, yi, sin_p, cos_p, gridx, gridy, coordx, coordy); /* Merge the (coordx, gridy) and (gridx, coordy) */ trim_coords(ngridx, ngridy, coordx, coordy, gridx, gridy, &asize, ax, ay, &bsize, bx, by); /* Sort the array of intersection points (ax, ay) and (bx, by). The new sorted intersection points are stored in (coorx, coory). Total number of points are csize. */ sort_intersections(quadrant, asize, ax, ay, bsize, bx, by, &csize, coorx, coory); /* Calculate the distances (dist) between the intersection points (coorx, coory). Find the indices of the pixels on the reconstruction grid. */ calc_dist(ngridx, ngridy, csize, coorx, coory, indi, dist); /* Update */ ind_recon = s * ngridx * ngridy; ind_data = d + p * dx + s * dt * dx; for (n = 0; n < csize - 1; n++) { recon[indi[n] + ind_recon] += data[ind_data] * dist[n]; } } } } free(gridx); free(gridy); free(coordx); free(coordy); free(ax); free(ay); free(bx); free(by); free(coorx); free(coory); free(dist); free(indi); }
void art(const float* data, int dy, int dt, int dx, const float* center, const float* theta, float* recon, int ngridx, int ngridy, int num_iter) { if(dy == 0 || dt == 0 || dx == 0) return; float* gridx = (float*) malloc((ngridx + 1) * sizeof(float)); float* gridy = (float*) malloc((ngridy + 1) * sizeof(float)); float* coordx = (float*) malloc((ngridy + 1) * sizeof(float)); float* coordy = (float*) malloc((ngridx + 1) * sizeof(float)); float* ax = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* ay = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* bx = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* by = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* coorx = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* coory = (float*) malloc((ngridx + ngridy) * sizeof(float)); float* dist = (float*) malloc((ngridx + ngridy) * sizeof(float)); int* indi = (int*) malloc((ngridx + ngridy) * sizeof(int)); float* simdata = (float*) malloc((dy * dt * dx) * sizeof(float)); assert(coordx != NULL && coordy != NULL && ax != NULL && ay != NULL && by != NULL && bx != NULL && coorx != NULL && coory != NULL && dist != NULL && indi != NULL && simdata != NULL); int s, p, d, i, n; int quadrant; float theta_p, sin_p, cos_p; float mov, xi, yi; int asize, bsize, csize; float upd; int ind_data, ind_recon; for(i = 0; i < num_iter; i++) { // initialize simdata to zero memset(simdata, 0, dy * dt * dx * sizeof(float)); preprocessing(ngridx, ngridy, dx, center[0], &mov, gridx, gridy); // Outputs: mov, gridx, gridy // For each projection angle for(p = 0; p < dt; p++) { // Calculate the sin and cos values // of the projection angle and find // at which quadrant on the cartesian grid. theta_p = fmodf(theta[p], 2.0f * (float) M_PI); quadrant = calc_quadrant(theta_p); sin_p = sinf(theta_p); cos_p = cosf(theta_p); // For each detector pixel for(d = 0; d < dx; d++) { // Calculate coordinates xi = -ngridx - ngridy; yi = 0.5f * (1 - dx) + d + mov; calc_coords(ngridx, ngridy, xi, yi, sin_p, cos_p, gridx, gridy, coordx, coordy); // Merge the (coordx, gridy) and (gridx, coordy) trim_coords(ngridx, ngridy, coordx, coordy, gridx, gridy, &asize, ax, ay, &bsize, bx, by); // Sort the array of intersection points (ax, ay) and // (bx, by). The new sorted intersection points are // stored in (coorx, coory). Total number of points // are csize. sort_intersections(quadrant, asize, ax, ay, bsize, bx, by, &csize, coorx, coory); // Calculate the distances (dist) between the // intersection points (coorx, coory). Find the // indices of the pixels on the reconstruction grid. calc_dist(ngridx, ngridy, csize, coorx, coory, indi, dist); // Calculate dist*dist float sum_dist2 = 0.0f; for(n = 0; n < csize - 1; n++) { sum_dist2 += dist[n] * dist[n]; } if(sum_dist2 != 0.0f) { // For each slice for(s = 0; s < dy; s++) { // Calculate simdata calc_simdata(s, p, d, ngridx, ngridy, dt, dx, csize, indi, dist, recon, simdata); // Output: simdata // Update ind_data = d + p * dx + s * dt * dx; ind_recon = s * ngridx * ngridy; upd = (data[ind_data] - simdata[ind_data]) / sum_dist2; for(n = 0; n < csize - 1; n++) { recon[indi[n] + ind_recon] += upd * dist[n]; } } } } } } free(gridx); free(gridy); free(coordx); free(coordy); free(ax); free(ay); free(bx); free(by); free(coorx); free(coory); free(dist); free(indi); free(simdata); }