Tomographic Kernels
This section contains the analytical expressions for the 3D X-ray transform and inner products in the RKHS.
Special Functions
The tomographic feature maps and their inner products involve definite integrals of Gaussian density functions. Hence, we define:
HeteroTomo3D.unicdf — Function
unicdf(x::Float64) -> Float64CDF of the standard normal distribution, i.e.,
\[\Phi(x) = \mathbb{P}(Z \le x) = \frac{1}{2} \left( 1 + \operatorname{erf}\left( \frac{x}{\sqrt{2}} \right) \right).\]
julia> using HeteroTomo3D;
julia> unicdf(0.0)
0.5
julia> unicdf(1.0)
0.8413447460685429HeteroTomo3D.antid_erf — Function
antid_erf(z::Float64)::Float64Compute the antiderivative of the scaled error function, i.e.,
\[\Phi(z) = \sqrt{\pi} \int_{0}^{z} \operatorname{erf}(t) \, dt + 1 = \sqrt{\pi} z \operatorname{erf}(z) + \exp(- z^{2}).\]
Examples
julia> using HeteroTomo3D;
julia> antid_erf(2.0)
3.5466412019384204HeteroTomo3D.affine_erf — Function
affine_erf(w::Float64, c::Float64, γ::Float64) -> Float64Compute the antiderivative of the Gaussian function with an affine argument, i.e.,
\[\int_{-w}^{w} \exp(- \gamma (z - c)^2) \, dz.\]
Arguments
w::Float64: Integration limitc::Float64: Shift parameter in the affine argumentγ::Float64: Bandwidth parameter for the Gaussian
Examples
julia> using HeteroTomo3D;
julia> w = 0.5; c = 0.1; γ = 10.0;
julia> sign(affine_erf(w, c, γ)) == sign(w)
trueHeteroTomo3D.bvncdf — Function
bvncdf(p::Float64, q::Float64, ρ::Float64)::Float64Output the CDF of the bivariate standard normal distribution with correlation coefficient ρ, i.e.,
\[\Phi_{2}(p, q; \rho) = \mathbb{P}(Z_1 \le p, Z_2 \le q) \quad \text{where} \quad \begin{bmatrix} Z_1 \\ Z_2 \end{bmatrix} \sim \mathcal{N}\left(\mathbf{0}, \begin{bmatrix} 1 & \rho \\ \rho & 1 \end{bmatrix}\right)\]
Arguments
p::Float64: First inputq::Float64: Second inputρ::Float64: Correlation coefficient in [-1, 1]
Examples
julia> using HeteroTomo3D;
julia> 10^5 * bvncdf(-2.0, -2.0 , 0.0)
51.75685036595643
julia> 10^5 * bvncdf(-2.0, -2.0 , 0.9)
1336.5628669461514Reference
Tsay, Wen-Jen, and Peng-Hsuan Ke, A simple approximation for the bivariate normal integral (2021)
Tomographic RKHS
HeteroTomo3D.backproject — Function
backproject(q::UnitQuaternion{T}, x::NTuple{2, T}, z::NTuple{3, T}, γ::T) where {T<:Real} -> TEvaluates the point of the tomographic feature map analytically, i.e., computes
\[\varphi_{\gamma}(\mathbf{R}_{\mathbf{q}}, \mathbf{x})(\mathbf{z}) = \int_{-W(\mathbf{x})}^{W(\mathbf{x})} \exp(-\gamma \| \mathbf{R}_{\mathbf{q}} \mathbf{z} - [\mathbf{x} : z] \|^2) \, dz\]
Arguments
q::UnitQuaternion{T}: Rotation of the kernelx::NTuple{2, T}: Coordinates of the kernel center in the planez::NTuple{3, T}: Coordinates of the evaluation point in 3D spaceγ::T: Bandwidth parameter for Gaussian kernel
Examples
julia> using HeteroTomo3D;
julia> q = shortest_arc(0.0, 1.0, 0.0)
UnitQuaternion{Float64}(0.7071067811865476, 0.7071067811865475, -0.0, 0.0)
julia> backproject(q, (0.1, -0.2), (0.3, -0.4, 0.5), 10.0)
0.15197718857623901HeteroTomo3D.inner_product — Function
inner_product(q::UnitQuaternion{T}, x1::NTuple{2, T}, x2::NTuple{2, T}, γ::T) where {T<:Real} -> TEvaluates the inner product between two tomographic feature maps exactly.
Arguments
q::UnitQuaternion{T}: Relative rotation between the two kernels, i.e.,q2 * inv(q1).x1::NTuple{2, T}: Coordinates of the first kernel center in the planex2::NTuple{2, T}: Coordinates of the second kernel center in the planeγ::T: Bandwidth parameter for Gaussian kernel
See also collinear_inner_product, noncollinear_inner_product.
HeteroTomo3D.build_gram_matrix! — Function
build_gram_matrix!(K::BlockMatrix{T}, X::EvaluationGrid, Q::QuaternionGrid{T}, γ::T) where {T<:Real}Constructs the (s * r * n) x (s * r * n) Gram matrix K for the mean representer theorem. Iterates over functions (i), quaternions (j), and evaluation points (k), adhering to the column-major indexing k + (j - 1) s + (i - 1) s r.
See also collinear_inner_product, noncollinear_inner_product.
The calculation of the inner product between two tomographic feature maps depends on the collinearity of two viewing axes. This collinearity can be quantifies as
\[\rho = \mathbf{e}_{3}^{\top} \mathbf{R}_{\mathbf{q}_{2}} \mathbf{R}_{\mathbf{q}_{1}}^{\top} \mathbf{e}_{3} \in [-1, +1]\]
For more details, see:
HeteroTomo3D.collinear_inner_product — Function
collinear_inner_product(q::UnitQuaternion{T}, x1::NTuple{2, T}, x2::NTuple{2, T}, γ::T) where {T<:Real} -> TEvaluates the inner product between two tomographic feature maps when the viewing directions are strictly parallel or anti-parallel.
Arguments
q::UnitQuaternion{T}: Relative rotation between the two kernels, i.e.,q2 * inv(q1)x1::NTuple{2, T}: Coordinates of the first kernel center in the planex2::NTuple{2, T}: Coordinates of the second kernel center in the planeγ::T: Bandwidth parameter for Gaussian kernel
Examples
julia> using HeteroTomo3D;
julia> q_parallel = UnitQuaternion(sqrt(2) / 2, 0.0, 0.0, sqrt(2) / 2);
julia> x1 = (0.1, -0.2); x2 = (0.3, -0.4); γ = 5.0;
julia> val1 = collinear_inner_product(q_parallel, x1, x2, γ)
0.33994859230087116
julia> val2 = collinear_inner_product(inv(q_parallel), x2, x1, γ)
0.33994859230087116
julia> isapprox(val1, val2, atol=1e-10) # Symmetry check
trueSee also noncollinear_inner_product.
HeteroTomo3D.noncollinear_inner_product — Function
noncollinear_inner_product(q::UnitQuaternion{T}, x1::NTuple{2, T}, x2::NTuple{2, T}, γ::T) where {T<:Real} -> TEvaluates the inner product between two tomographic feature maps when the viewing directions are non-collinear.
Arguments
q::UnitQuaternion{T}: Relative rotation between the two kernels, i.e.,q2 * inv(q1)x1::NTuple{2, T}: Coordinates of the first kernel center in the planex2::NTuple{2, T}: Coordinates of the second kernel center in the planeγ::T: Bandwidth parameter for Gaussian kernel
Examples
julia> using HeteroTomo3D;
julia> using Random; Random.seed!(123);
julia> q = rand(UnitQuaternion)
UnitQuaternion{Float64}(-0.28204731317456205, -0.6391304265753365, -0.7091703923721498, -0.09507347442567807)
julia> x1 = (0.1, -0.2); x2 = (0.3, -0.4); γ = 5.0;
julia> val1 = noncollinear_inner_product(q, x1, x2, γ)
0.2589394161448219
julia> val2 = noncollinear_inner_product(inv(q), x2, x1, γ)
0.2589394161448219
julia> isapprox(val1, val2, atol=1e-10) # Symmetry check
trueSee also collinear_inner_product.