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.unicdfFunction
unicdf(x::Float64) -> Float64

CDF 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.8413447460685429
source
HeteroTomo3D.antid_erfFunction
antid_erf(z::Float64)::Float64

Compute 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.5466412019384204
source
HeteroTomo3D.affine_erfFunction
affine_erf(w::Float64, c::Float64, γ::Float64) -> Float64

Compute 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 limit
  • c::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)
true
source
HeteroTomo3D.bvncdfFunction
bvncdf(p::Float64, q::Float64, ρ::Float64)::Float64

Output 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 input
  • q::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.5628669461514

Reference

Tsay, Wen-Jen, and Peng-Hsuan Ke, A simple approximation for the bivariate normal integral (2021)

source

Tomographic RKHS

HeteroTomo3D.backprojectFunction
backproject(q::UnitQuaternion{T}, x::NTuple{2, T}, z::NTuple{3, T}, γ::T) where {T<:Real} -> T

Evaluates 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 kernel
  • x::NTuple{2, T}: Coordinates of the kernel center in the plane
  • z::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.15197718857623901
source
HeteroTomo3D.inner_productFunction
inner_product(q::UnitQuaternion{T}, x1::NTuple{2, T}, x2::NTuple{2, T}, γ::T) where {T<:Real} -> T

Evaluates 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 plane
  • x2::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.

source
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.

source

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_productFunction
collinear_inner_product(q::UnitQuaternion{T}, x1::NTuple{2, T}, x2::NTuple{2, T}, γ::T) where {T<:Real} -> T

Evaluates 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 plane
  • x2::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
true

See also noncollinear_inner_product.

source
HeteroTomo3D.noncollinear_inner_productFunction
noncollinear_inner_product(q::UnitQuaternion{T}, x1::NTuple{2, T}, x2::NTuple{2, T}, γ::T) where {T<:Real} -> T

Evaluates 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 plane
  • x2::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
true

See also collinear_inner_product.

source