RISA
cuda_kernels_fan2para.h
Go to the documentation of this file.
1 /*
2  * This file is part of the RISA-library.
3  *
4  * Copyright (C) 2016 Helmholtz-Zentrum Dresden-Rossendorf
5  *
6  * RISA is free software: You can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * RISA is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with RISA. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Date: 30 November 2016
20  * Authors: Tobias Frust (FWCC) <t.frust@hzdr.de>
21  *
22  */
23 
24 #ifndef CUDA_KERNELS_FAN2PARA_H_
25 #define CUDA_KERNELS_FAN2PARA_H_
26 
27 #include <risa/Fan2Para/Fan2Para.h>
28 
30 
31 #define _USE_MATH_DEFINES
32 #include <cmath>
33 #include <stdio.h>
34 
35 namespace risa {
36 namespace cuda {
37 
38 template<typename T>
39 auto ellipse_kreis_uwe(T alpha, T DX, T DZ, T SourceRingDiam) -> T {
40 
41  //Hilfsvariablen
42  T L, R, CA, eps, p1, p2, gamma, ae;
43 
44  L = sqrt(DX * DX + DZ * DZ);
45  R = 0.5 * SourceRingDiam;
46  CA = cos(alpha);
47 
48  eps = (L * L + R * DX * CA) / (L * sqrt(L * L + R * R + 2.0 * R * DX * CA));
49  eps = acos(eps);
50 
51  p1 = (L * L - R * DX) / (L * sqrt(L * L + R * R - 2.0 * R * DX));
52  p2 = (L * L + R * DX) / (L * sqrt(L * L + R * R + 2.0 * R * DX));
53  gamma = 0.5 * (acos(p1) - acos(p2));
54 
55  ae = (eps * CA + gamma)
56  / sqrt(eps * eps + 2.0 * eps * gamma * CA + gamma * gamma);
57 
58  if (alpha <= M_PI)
59  return acos(ae);
60  else
61  return 2.0 * M_PI - acos(ae);
62 }
63 
64 __global__ void interpolation(int k, const float* __restrict__ SinFan_data,
65  float* __restrict__ SinPar_data, const float* __restrict__ Gamma,
66  const float* __restrict__ Teta, const float* __restrict__ alpha_kreis,
67  const float* __restrict__ s, const int* __restrict__ teta_nach_ray_1,
68  const int* __restrict__ teta_nach_ray_2,
69  const int* __restrict__ teta_vor_ray_1,
70  const int* __restrict__ teta_vor_ray_2,
71  const int* __restrict__ gamma_vor_ray_1,
72  const int* __restrict__ gamma_vor_ray_2,
73  const int* __restrict__ gamma_nach_ray_1,
74  const int* __restrict__ gamma_nach_ray_2,
75  const float* __restrict__ teta_ziel_ray_1,
76  const float* __restrict__ teta_ziel_ray_2,
77  const float* __restrict__ gamma_ziel_ray_1,
78  const float* __restrict__ gamma_ziel_ray_2, const int* __restrict__ ray_1,
79  const int* __restrict__ ray_2, const parameters* __restrict__ params) {
80 
81  int i = glados::cuda::getX();
82  int j = glados::cuda::getY();
83  //finish all threads, that operate outside the bounds of the data field
84  if (i >= (*params).numberOfParallelDetectors_
85  && j >= (*params).numberOfParallelProjections_)
86  return;
87 
88  //Übergabe-Paramter
89  float WZiel_1 = 0, WZiel_2 = 0, WZiel_end = 0, V1 = 0, V2 = 0, W1 = 0,
90  W2 = 0, W3 = 0, W4 = 0;
91 
92  //k defines, which plane to use
93  unsigned long long ind = j * (*params).numberOfParallelDetectors_ + i
94  + (k * (*params).numberOfParallelProjections_
95  * (*params).numberOfParallelDetectors_);
96 
97  float temp_1 = s[i] / (*params).rDetector_;
98 
99  if (temp_1 <= 1 || temp_1 >= -1) {
100 
101  if (ray_1[ind] == true) {
102  //Interpolationspunkte nehmen für Fall 1
103  W1 = SinFan_data[teta_vor_ray_1[ind] * (*params).numberOfFanDetectors_
104  + gamma_vor_ray_1[ind]];
105  W2 = SinFan_data[teta_vor_ray_1[ind] * (*params).numberOfFanDetectors_
106  + gamma_nach_ray_1[ind]];
107  W3 = SinFan_data[teta_nach_ray_1[ind] * (*params).numberOfFanDetectors_
108  + gamma_vor_ray_1[ind]];
109  W4 = SinFan_data[teta_nach_ray_1[ind] * (*params).numberOfFanDetectors_
110  + gamma_nach_ray_1[ind]];
111 
112  //Interpolation durchführen für Fall 1
113  V1 = W1
114  + ((teta_ziel_ray_1[ind] - Teta[teta_vor_ray_1[ind]])
115  / (Teta[teta_nach_ray_1[ind]] - Teta[teta_vor_ray_1[ind]]))
116  * (W3 - W1);
117  V2 = W2
118  + ((teta_ziel_ray_1[ind] - Teta[teta_vor_ray_1[ind]])
119  / (Teta[teta_nach_ray_1[ind]] - Teta[teta_vor_ray_1[ind]]))
120  * (W4 - W2);
121  WZiel_1 = V1
122  + ((gamma_ziel_ray_1[ind] - Gamma[gamma_vor_ray_1[ind]])
123  / (Gamma[gamma_nach_ray_1[ind]]
124  - Gamma[gamma_vor_ray_1[ind]])) * (V2 - V1);
125  }
126  if (ray_2[ind] == true) {
127 
128  //Interpolationspunkte nehmen für Fall 2
129  W1 = SinFan_data[teta_vor_ray_2[ind] * (*params).numberOfFanDetectors_
130  + gamma_vor_ray_2[ind]];
131  W2 = SinFan_data[teta_vor_ray_2[ind] * (*params).numberOfFanDetectors_
132  + gamma_nach_ray_2[ind]];
133  W3 = SinFan_data[teta_nach_ray_2[ind] * (*params).numberOfFanDetectors_
134  + gamma_vor_ray_2[ind]];
135  W4 = SinFan_data[teta_nach_ray_2[ind] * (*params).numberOfFanDetectors_
136  + gamma_nach_ray_2[ind]];
137 
138  //Interpolation durchführen für Fall 2
139  V1 = W1
140  + ((teta_ziel_ray_2[ind] - Teta[teta_vor_ray_2[ind]])
141  / (Teta[teta_nach_ray_2[ind]] - Teta[teta_vor_ray_2[ind]]))
142  * (W3 - W1);
143  V2 = W2
144  + ((teta_ziel_ray_2[ind] - Teta[teta_vor_ray_2[ind]])
145  / (Teta[teta_nach_ray_2[ind]] - Teta[teta_vor_ray_2[ind]]))
146  * (W4 - W2);
147  WZiel_2 = V1
148  + ((gamma_ziel_ray_2[ind] - Gamma[gamma_vor_ray_2[ind]])
149  / (Gamma[gamma_nach_ray_2[ind]]
150  - Gamma[gamma_vor_ray_2[ind]])) * (V2 - V1);
151  }
152 
153  if (ray_1[ind] + ray_2[ind] > 0)
154 
155  WZiel_end = (float) ray_1[ind]
156  / ((float) ray_1[ind] + (float) ray_2[ind]) * WZiel_1
157  + (float) ray_2[ind] / ((float) ray_1[ind] + (float) ray_2[ind])
158  * WZiel_2;
159  }
160  //conversion from 360 to 180 degrees
161  const int address = j * (*params).numberOfParallelDetectors_;
162  const int parallelSize = (*params).numberOfParallelProjections_
163  * (*params).numberOfParallelDetectors_;
164  const int detectorSize_2 = (*params).numberOfParallelDetectors_ / 2;
165  int mirrorOffset = 0;
166  if (i < detectorSize_2)
167  mirrorOffset = (*params).numberOfParallelDetectors_ - i - 1;
168  else
169  mirrorOffset = -(i % detectorSize_2) + detectorSize_2 - 1;
170  if (j < ((*params).numberOfParallelProjections_ / 2))
171  //first half of the parallel sinogram
172  atomicAdd(&SinPar_data[address + i], WZiel_end*0.5);
173  else
174  //second half of the parallel sinogram
175  atomicAdd(&SinPar_data[address - parallelSize / 2 + mirrorOffset],
176  WZiel_end * 0.5);
177 }
178 
179 template<typename T>
180 __global__ void setValue(T* data, T value, int size) {
181  auto id = glados::cuda::getX();
182  if (id >= size)
183  return;
184  data[id] = value;
185 }
186 
187 }
188 }
189 
190 #endif //CUDA_KERNELS_FAN2PARA_H_
auto ellipse_kreis_uwe(T alpha, T DX, T DZ, T SourceRingDiam) -> T
__global__ void interpolation(int k, const float *__restrict__ SinFan_data, float *__restrict__ SinPar_data, const float *__restrict__ Gamma, const float *__restrict__ Teta, const float *__restrict__ alpha_kreis, const float *__restrict__ s, const int *__restrict__ teta_nach_ray_1, const int *__restrict__ teta_nach_ray_2, const int *__restrict__ teta_vor_ray_1, const int *__restrict__ teta_vor_ray_2, const int *__restrict__ gamma_vor_ray_1, const int *__restrict__ gamma_vor_ray_2, const int *__restrict__ gamma_nach_ray_1, const int *__restrict__ gamma_nach_ray_2, const float *__restrict__ teta_ziel_ray_1, const float *__restrict__ teta_ziel_ray_2, const float *__restrict__ gamma_ziel_ray_1, const float *__restrict__ gamma_ziel_ray_2, const int *__restrict__ ray_1, const int *__restrict__ ray_2, const parameters *__restrict__ params)
__device__ auto getY() -> unsigned int
Definition: Coordinates.h:35
collects all parameters that are needed in the fan to parallel beam interpolation kernel ...
Definition: Fan2Para.h:42
__global__ void setValue(T *data, T value, int size)
__device__ auto getX() -> unsigned int
Definition: Coordinates.h:30