Geometry
SwissVAMyKnife.PropagationScheme
— TypeSwissVAMyKnife.ParallelRayOptics
— TypeParallelRayOptics(angles, μ, DMD_diameter)
Type to represent the parallel ray optical approach. This is suited for a printer with an index matching bath. This is equivalent to an inverse (attenuated) Radon transform as the forward model of the printer.
angles
is a range orVector
(orCuVector
) storing the illumination angles.DMD_diameter
is the diameter of the DMD along the vial radius. So this is not the height along the rotation axis!μ
is the absorption coefficient of the resin in units of inverse meters Soμ=100.0 1/m
means that after 10mm of propagation the intensity isI(10mm) = I_0 * exp(-10.0mm * 100.0/m) = I_0 * exp(-1)
.
See also VialRayOptics
for a printer without index matching bath.
Examples
julia> ParallelRayOptics(range(0, 2π, 401)[begin:end-1], 1 / 256)
ParallelRayOptics{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}(0.0:0.015707963267948967:6.267477343911637, 0.00390625)
julia> ParallelRayOptics(range(0, 2π, 401)[begin:end-1], nothing)
ParallelRayOptics{Nothing, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}(0.0:0.015707963267948967:6.267477343911637, nothing)
SwissVAMyKnife.VialRayOptics
— TypeType to represent a ray optical approach where refraction and reflection intensity loss at the glass vial is considered. This is equivalent to an inverse (attenuated) Radon transform as the forward model of the printer.
angles
is a range orVector
(orCuVector
) storing the illumination angles.μ
is the absorption coefficient of the resin in units of inverse meters Soμ=100.0 1/m
means that after 10mm of propagation the intensity isI(10mm) = I_0 * exp(-10.0mm * 100.0/m) = I_0 * exp(-1)
.R_outer
is the outer radius of the glass vial.R_inner
is the inner radius of the glass vial.DMD_diameter
is the diameter of the DMD along the vial radius. So this is not the height along the rotation axis!n_vial
is the refractive index of the glass vial.n_resin
is the refractive index of the resin.polarization=PolarizationRandom()
is the polarization of the light. SeePolarization
for the options.
Examples
julia> VialRayOptics(angles=range(0,2π, 501)[begin:end-1],
μ=nothing,
R_outer=6e-3,
R_inner=5.5e-3,
DMD_diameter=2 * R_outer,
n_vial=1.47,
n_resin=1.48,
polarization=PolarizationRandom()
)
SwissVAMyKnife.WaveOptics
— TypeWaveOptics(;z, λ, L, μ=nothing, angles)
Parameters
z
: the different depths we propagate the field. Should beVector
or range.λ
: wavelength in the medium. So divide by the refractive index!L
: The side length of the array. You should satisfyL ≈ abs(z[begin]) + abs(z[end])
μ
: Absorption coefficient.angles
: the angles we illuminate the sample. Should beVector
or range.
SwissVAMyKnife.Polarization
— TypePolarization
PolarizationParallel()
describes a parallel polarization.PolarizationPerpendicular()
describes a perpendicular polarization.PolarizationRandom()
describes a random polarization.
Optimization
SwissVAMyKnife.optimize_patterns
— Functionoptimize_patterns(target, ps::WaveOptics, op::GradientBased, loss::Union{LossThreshold, LossThresholdSparsity})
Optimize the patterns to match the target with the wave optical model. target
is the target intensity. ps
is the wave optical model. op
is the optimization method. loss
is the loss function.
optimize_patterns(target, ps::{VialRayOptics, ParallelRayOptics}, op::GradientBased, loss::LossTarget)
Function to optimize a target
volume. This method returns the optimized patterns, the printed intensity and the optimization result.
See VialRayOptics
how to specify the geometry of the vial. See ParallelRayOptics
how to specify the geometry of the vial.
See PropagationScheme
for the options for the different propagation schemes. See OptimizationScheme
for the options for the different optimization schemes. See LossTarget
for the options for the different loss functions.
Examples
julia> patterns, printed_intensity, res = optimize_patterns(target, VialRayOptics(angles=range(0,2π, 501)[begin:end-1],
μ=nothing,
R_outer=6e-3,
R_inner=5.5e-3,
n_vial=1.47,
n_resin=1.48,
polarization=PolarizationRandom()
), GradientBased(), LossThreshold())
optimize_patterns(target::AbstractArray{T}, ps::ParallelRayOptics, op::OSMO) where T
Optimize patterns with the OSMO
optimization algorithm. This is only supported for ParallelRayOptics
.
Examples
julia> optimize_patterns(target, ParallelRayOptics(range(0, 2π, 401)[begin:end-1], 1 / 256), OSMO())
Optimizer
SwissVAMyKnife.OptimizationScheme
— Typeabstract type OptimizationScheme end
List of possible schemes:
Supported for all <:PropagationScheme
.
Supported only for ParallelRayOptics
SwissVAMyKnife.GradientBased
— TypeGradientBased(; optimizer=LBFSG(), options=Optim.options(iterations=30, store_trace=true))
Define parameters for the GradientBased
optimization algorithm. Optim.jl is used for the optimization. L-BFGS is the default optimizer which performs well for the optimization of the reconstruction problem. 30 iterations are used as default. The trace of the optimization is stored by default.
Example
julia> GradientBased(; optimizer=LBFGS(), options=Optim.Options(iterations=30, store_trace=true))
SwissVAMyKnife.OSMO
— TypeOSMO(; iterations=10, thresholds=(0.7f0, 0.8f0))
Define parameters for the OSMO optimization algorithm. We recommend to use GradientBased
instead of OSMO.
Reference
Rackson, Charles M., et al. Object-space optimization of tomographic reconstructions for additive manufacturing. Additive Manufacturing 48 (2021): 102367.
Loss Function
SwissVAMyKnife.LossTarget
— TypeLossTarget
Abstract type for loss functions.
List of implemented loss functions:
LossThreshold
SwissVAMyKnife.LossThreshold
— TypeLossThreshold(;sum_f=abs2, thresholds=(0.65f0, 0.75f0))
Loss function for polymerization. Keeps the object voxels in the range [T_U, 1]
and the empty space in the range [0, T_L]
.
\[\mathcal{L} = \underbrace{\sum_{v \,\in\,\text{object}} |\text{ReLu}(T_U - I_v)|^K}_\text{force object polymerization} + $$ $$+\underbrace{\sum_{v\,\notin\,\text{object}} |\text{ReLu}(I_v - T_L) |^K}_{\text{keep empty space unpolymerized}} +\]
\[+\underbrace{\sum_{v \,\in\,\text{object}} |\text{ReLu}(I_v - 1)|^K}_{\text{avoid overpolymerization}}\]
- The default
K=2
corresponds tosum_f=abs2
. (T_L, T_U) = thresholds
julia> l = LossThreshold(thresholds=(0.5, 0.7))
LossThreshold{typeof(abs2), Float64}(abs2, (0.5, 0.7))
julia> x = [1.0, 0.0, 0.55]
3-element Vector{Float64}:
1.0
0.0
0.55
julia> target = [1, 0, 1]
3-element Vector{Int64}:
1
0
1
julia> l(x, target, nothing)
0.022499999999999975
julia> (0.7 - 0.55)^2
0.022499999999999975