Skip to content

EMCCD Camera Simulation

Here I wanted to make a small interactive EMCCD simulator for a single pixel (in ADU), mostly to build intuition.

The website version is deliberately simplified so that it runs fast in-browser, but the logic is still the same as in a full camera model: we generate electrons, we add background processes, we multiply in the EM register, and finally we read out with noise and offset.

Model

Big picture

Lets look at one pixel in one frame. A useful way to think about the measured value is: 1. start from digital offset, 2. add the EM-amplified charge converted to ADU, 3. then add readout/pattern imperfections.

One compact way to write this is

\[ D = B_{\mathrm{off}}(\boldsymbol\theta_{\mathrm{ADC}}) + G_{\mathrm{ADC}}(\boldsymbol\theta_{\mathrm{ADC}}) \Big[ \mathcal{M}\!\big(N^{\mathrm{in}}; g_{\mathrm{EM}}(\boldsymbol\theta_{\mathrm{EM}})\big) + \epsilon^{\mathrm{read}}(\boldsymbol\theta_{\mathrm{read}}) \Big]. \]

where

  • \(B_{\mathrm{off}}\) is the digital bias/offset
  • \(G_{\mathrm{ADC}}\) is the conversion gain (ADU per output electron)
  • \(\mathcal{M}\) is the stochastic EM multiplication
  • \(\epsilon^{\mathrm{read}}\) is output amplifier read noise

The number of electrons entering the EM register is

\[ N^{\mathrm{in}}=N^{\mathrm{sig}}+N^{\mathrm{bg}}. \]

Signal and background terms

For the signal part, we use Poisson counting:

\[ N^{\mathrm{sig}}\sim \mathrm{Poisson}(\mu^{\mathrm{sig}}),\quad \mu^{\mathrm{sig}} = \eta_{\mathrm{QE}}(\boldsymbol\theta_{\mathrm{QE}}) T_{\mathrm{opt}}(\boldsymbol\theta_{\mathrm{opt}}) I(\boldsymbol\theta_{\mathrm{img}}) t_{\mathrm{exp}}. \]

Then we split the background into dark current, CIC, and stray light:

\[ N^{\mathrm{bg}}=N^{\mathrm{dark}}+N^{\mathrm{CIC}}+N^{\mathrm{stray}}. \]
\[ \begin{aligned} N^{\mathrm{dark}} &\sim \mathrm{Poisson}(\mu^{\mathrm{dark}}), \quad \mu^{\mathrm{dark}}=r^{\mathrm{dark}}(\boldsymbol\theta_{\mathrm{dark}})\,t_{\mathrm{exp}},\\ N^{\mathrm{CIC}} &\sim \mathrm{Poisson}(\mu^{\mathrm{CIC}}), \quad \mu^{\mathrm{CIC}}=r^{\mathrm{CIC}}(\boldsymbol\theta_{\mathrm{clk}}),\\ N^{\mathrm{stray}} &\sim \mathrm{Poisson}(\mu^{\mathrm{stray}}), \quad \mu^{\mathrm{stray}}=\eta_{\mathrm{QE}}T_{\mathrm{opt}}\Phi^{\mathrm{stray}}(\boldsymbol\theta_{\mathrm{env}})\,t_{\mathrm{exp}}. \end{aligned} \]

EM stage and readout

Given \(n\) input electrons, the EM register amplifies stochastically:

\[ N^{\mathrm{out}}\sim \mathcal{M}(n; g_{\mathrm{EM}}),\quad \mathbb{E}[N^{\mathrm{out}}\mid n]=g_{\mathrm{EM}}n, \]

In this simulator, \(\mathcal{M}\) is implemented as a Gamma (Erlang) law conditioned on the input count:

\[ N^{\mathrm{out}} \mid N^{\mathrm{in}}=n \sim \Gamma(\text{shape}=n,\ \text{scale}=g_{\mathrm{EM}}), \]

with the convention \(N^{\mathrm{out}}=0\) for \(n=0\).
So for integer \(n\), the EM output is the sum of \(n\) exponential gains (mean \(g_{\mathrm{EM}}\) each).

At high EM gain, the excess-noise factor for a typical EMCCD approaches \(\sqrt{2}\).

Read noise is usually well approximated by a Gaussian:

\[ \epsilon^{\mathrm{read}}\sim \mathcal{N}\!\big(0,\sigma_{\mathrm{read}}^2(\boldsymbol\theta_{\mathrm{read}})\big). \]

What the interactive demo actually uses

For the interactive widget below we use a reduced version of the model (same spirit, fewer knobs), so that it stays responsive on the page:

\[ \begin{aligned} N_{\text{sig}} &\sim \text{Poisson}(\mu_{\text{signal}} t_{\text{exp}}), \\ N_{\text{str}} &\sim \text{Poisson}(\mu_{\text{stray}} t_{\text{exp}}), \\ N_{\text{dark}} &\sim \text{Poisson}(\mu_{\text{dark}} t_{\text{exp}}), \\ N_{\text{cic}} &\sim \text{Poisson}(N_{\text{cic}}), \end{aligned} \]
\[ N_{\text{in}} = N_{\text{sig}} + N_{\text{str}} + N_{\text{dark}} + N_{\text{cic}}, \quad Y \mid N_{\text{in}}=n \sim \Gamma(\text{shape}=n,\ \text{scale}=g_{\text{em}}), \]
\[ D = B_{\text{offset}} + GY + \mathcal{N}(0, e_{\text{read}}). \]

Interactive Web Simulation

This simulator runs directly in your browser on the MkDocs page.

EMCCD Monte Carlo Playground Interactive in-browser simulation
B_offset [ADU]
log10(t_exp [s])
G [ADU/e-]
log10(mu_signal [e-/s])
mu_stray [e-/s]
log10(mu_dark [e-/s])
N_cic [e-/frame]
log10(g_em [x])
e_read [ADU rms]
n_samples