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.
anglesis a range orVector(orCuVector) storing the illumination angles.DMD_diameteris 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/mmeans 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.
anglesis a range orVector(orCuVector) storing the illumination angles.μis the absorption coefficient of the resin in units of inverse meters Soμ=100.0 1/mmeans that after 10mm of propagation the intensity isI(10mm) = I_0 * exp(-10.0mm * 100.0/m) = I_0 * exp(-1).R_outeris the outer radius of the glass vial.R_inneris the inner radius of the glass vial.DMD_diameteris the diameter of the DMD along the vial radius. So this is not the height along the rotation axis!n_vialis the refractive index of the glass vial.n_resinis the refractive index of the resin.polarization=PolarizationRandom()is the polarization of the light. SeePolarizationfor 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 beVectoror 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 beVectoror range.
SwissVAMyKnife.Polarization — TypePolarizationPolarizationParallel()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 TOptimize 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 endList 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 — TypeLossTargetAbstract 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=2corresponds 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