off-axis-hologram-sim
August 4, 2026 · View on GitHub
Off-axis digital hologram simulator for digital holographic microscopy (DHM), in MATLAB / GNU Octave.
A single, self-contained script that simulates the entire off-axis DHM chain end to end — from a transparent 3D object, through diffraction and an off-axis interferometer, into a quantized camera frame, and back out again via numerical reconstruction. It produces synthetic holograms with known ground truth, which is exactly what you need to develop, debug, or benchmark a reconstruction pipeline when you don't want to be at the optical table.
There is no reconstruction "cheating" anywhere: the object wave is propagated with the angular spectrum method, the hologram is recorded as a real intensity pattern |O + R|², quantized to 12-bit camera counts, and then reconstructed only from those counts.
What it simulates
| Stage | Model |
|---|---|
| Object | Transparent sphere, n = 1.551 in air (Δn = 0.551). Two runs: 3 µm and 25 µm diameter. |
| Object phase | Projection approximation. The phase k₀·Δn·dz is accumulated over Nz = 100 slices through the sphere. There is no propagation between slices, so this is mathematically identical to a single thin phase mask carrying the integrated optical path — it does not model refraction inside the volume. See the note below. |
| Microscope | 4f system, M = 50×, tube lens f = 200 mm → objective f = 4 mm. Coordinate magnification encoded in the pixel pitch (88 nm → 4.4 µm); amplitude scaled by 1/M for energy conservation. |
| Free-space diffraction | Angular spectrum method (ASM) from the image plane to the hologram plane, z_h = 50 mm. Evanescent components are clipped. |
| Interferometer | Off-axis plane reference wave. Carrier set for a 4-pixel fringe period, fringes tilted −45° relative to y, so the ±1 orders sit on the FFT diagonal. |
| Camera | 4.4 µm pixel pitch, 12-bit ADC quantization (0–4095 counts), 1024 × 1024 grid. |
| Reconstruction | 2D FFT → circular bandpass around the +1 order (radius N/5) → circshift demodulation to DC → inverse FFT → backward ASM to the image plane → amplitude and wrapped phase. |
Light source is a He-Ne laser at λ = 632.8 nm throughout.
Scope note: the object is a thin phase mask
The slice loop that builds the object wave multiplies the field by exp(i·k₀·Δn·dz) per slice without propagating between slices. Because those multiplications commute and no diffraction happens in between, the result collapses exactly to
U(x,y) = exp( i · k₀ · Δn · L(x,y) )
where L(x,y) is the geometric path length through the sphere. This is the projection (thin-element) approximation. Checked numerically against a directly-computed projected mask: maximum phase difference 3.8·10⁻¹³ rad, i.e. floating-point noise.
That matters for how you read the results: diffraction is modelled — fully, by the angular spectrum propagation from the image plane to the hologram plane, which is where the actual holographic recording physics lives. What is not modelled is refraction and multiple scattering within the object. For a weakly-refracting sphere the projection approximation is standard and reasonable; for strongly scattering samples it is not. Turning this into a true split-step beam propagation method means interleaving asm_prop between the slices.
The 25 µm sphere in particular induces Δφ ≈ 136.8 rad (21.8 × 2π), which is well outside the weak-phase regime — treat that case as a stress test for the reconstruction and unwrapping code, not as a physically faithful forward model of a 25 µm bead.
Requirements
- GNU Octave (7+) — free, and what this was developed against, or
- MATLAB (R2019b+)
Octave users additionally want the image package for PNG output; the script loads it if present and degrades gracefully with a warning if not:
brew install octave # macOS
sudo apt install octave # Debian/Ubuntu
Usage
octave --no-gui off_axis_hologram.m
Or from inside MATLAB / Octave:
off_axis_hologram
The script runs headless (figure('visible','off')) and writes its output as PNG files into the working directory. It is fast: a full run over both spheres takes ~6 s (measured with Octave 10.3 on an Apple Silicon Mac).
Octave may print FALLBACK ... SW vertex processing lines while rendering the figures. That is a harmless OpenGL software-rasterizer notice, not a simulation error.
Output
For each of the two spheres (3um, 25um):
| File | Contents |
|---|---|
hologram_<label>_overview.png | 6-panel summary: object phase, propagated amplitude, off-axis hologram, log-FFT, reconstructed amplitude, reconstructed phase |
hologram_<label>_raw.png | The raw 16-bit hologram as the camera would deliver it — this is the file to feed into your own reconstruction code |
hologram_<label>_recon_phase.png | Reconstructed wrapped phase, 8-bit |
hologram_<label>_fourier_space.png | Fourier space with calibrated frequency axes in 1/mm, 0.1 %–99.9 % clipped |
The console also prints the parameter set, the maximum induced phase (in rad and in multiples of 2π), the continuous hologram range, and the realized camera count range — useful for confirming you are not clipping the ADC.
Tuning it for your own setup
All parameters live in one block at the top of the script:
lambda = 632.8e-9; % source wavelength [m]
M = 50; % magnification
f_tube = 200e-3; % tube lens [m]
dn = 0.551; % object–medium refractive index contrast
px_cam = 4.4e-6; % camera pixel pitch [m]
bit_depth = 12; % ADC bit depth
N = 1024; % grid size
Nz = 100; % volume slices
z_h = 50e-3; % image plane → hologram plane distance [m]
f_carr = 1/(4*dx_i); % off-axis carrier (4-pixel fringes)
Object sizes are set in the nesneler cell array. Two sanity constraints are worth respecting when you change things:
- Carrier vs. bandwidth — the +1 order must not overlap DC. The default puts the carrier at a 4-pixel fringe period with a bandpass radius of N/5; widen the filter and you will start pulling in the DC term.
- Sampling —
dx_s = px_cam / Mis the effective sample-plane pixel (88 nm by default). The object must be resolvable at that pitch.
Note on comments: the in-code comments and console output are in Turkish. The physics is not.
License
GNU Affero General Public License v3.0 (AGPL-3.0-or-later).
In short: you may use, study, modify and redistribute this freely, but derivative works must also be AGPL-3.0 — including when you only offer them to users over a network. If you use this in published research, a citation is appreciated but not required by the license.
Related
- dhm-hybrid — the full DHM reconstruction and analysis application these synthetic holograms were built to test.