Possible bug in dark current calculation
name: Bug report
about: Create a report to help us improve
title: 'Average Dark current is always 0 when using Dark Current model'
labels: 'dark current'
assignees: ''
What happened: I'm trying to replicate the dark current calculation by itself (so I'm using just the average_dark_current function in this part of the repository https://gitlab.com/esa/pyxel/-/blob/master/pyxel/models/charge_generation/dark_current.py?ref_type=heads)
The problem lies in the room temperature factor (and therefore also in the np.exp(-band_gap * e_0 / (2 * k_b * temperature))
part of the formula).
Testing with the following parameters:
- room_temperature = 300 [K]
- bandgap_room_temperature = 1.1108214488636363 [eV] (computed with
band_gap_silicon(300)
- k_b = 1.38064852e-23 [J/K], the value from astropy constants
The problem is caused by the Boltzmann constant, as by doing:
-band_gap_room_temperature * e / (2 * k_b * room_temperature)
, we end up with -3.645057274857774e+20,
so when doing
room_temperature_factor = room_temperature ** (3 / 2) * np.exp(
-band_gap_room_temperature * e_0 / (2 * k_b * room_temperature)
)
the room temperature factor is exactly zero (because np.exp(-3.645057274857774e+20) = 0)
What you expected to happen: This might be a long stretch because I'm not knowledgeable enough on the topic, but I think it might be because the Boltzmann constant is supposed to be used in eV/K instead of J/K (the one in Astropy and used in the code). If we did this, we would have:
- k_b = 8.617333262e-05 [eV/K] (taken from ScyPy constants) (this would also make the room temp. factor a pure number, I don't know if it's supposed to be)
- -band_gap_room_temperature * e / (2 * k_b * room_temperature) = -58.40023565108834
- room_temperature ** (3 / 2) * np.exp( -band_gap_room_temperature * e_0 / (2 * k_b * room_temperature) ) = 2.253106896830241e-22
Despite being very small, this number does not throw any error when doing the entire formula calculation (specifically, in the (1 / room_temperature_factor)
step)
Minimal Complete Verifiable Example:
# Put your MCVE code here
# starting values, fixed to reproduce
figure_of_merit = 0.02
pixel_area = 2.2500000000000005e-06
e_0 = 2.718281828459045
temperature = 80
room_temperature = 300
k_b = 1.38064852e-23
k_b_ev = 8.617333262e-05
band_gap = 1.151917643097643 # computed with band_gap_silicon(80)
band_gap_room_temperature = 1.1108214488636363 # # computed with band_gap_silicon(300)
# with k_b in eV/K
room_temperature_factor = room_temperature ** (3 / 2) * np.exp(
-band_gap_room_temperature * e_0 / (2 * k_b_ev * room_temperature)
)
# 2.253106896830241e-22
avg_dark_current = (
pixel_area # in cm^2
* figure_of_merit # in nA/cm^2
* 1e-9 # conversion to A/cm^2
* (1 / e_0) # conversion to e-/s/cm^2
* temperature ** (3 / 2)
* np.exp(-band_gap * e_0 / (2 * k_b_ev * temperature))
* (1 / room_temperature_factor)
) # Unit: e-/s/pixel
print(avg_dark_current) # 1.2335395220629222e-91
# with k_b in J/K
room_temperature_factor = room_temperature ** (3 / 2) * np.exp(
-band_gap_room_temperature * e_0 / (2 * k_b * room_temperature)
)
# 0
avg_dark_current = (
pixel_area # in cm^2
* figure_of_merit # in nA/cm^2
* 1e-9 # conversion to A/cm^2
* (1 / e_0) # conversion to e-/s/cm^2
* temperature ** (3 / 2)
* np.exp(-band_gap * e_0 / (2 * k_b * temperature))
* (1 / room_temperature_factor) # error here, as goes 1/0
) # Unit: e-/s/pixel
print(avg_dark_current)
Anything else we need to know?: I'm not sure if I should open a separate issue for this, but it's a problem inherent of dark current calculation: Since the average dark current is extremely small (in range e-15 -> e-17), when computing temporal noise with
dark_signal_2d = np.ones(shape) * avg_dark_current * time_step
dark_current_shot_noise_2d = np.random.poisson(
dark_signal_2d
)
every number in dark_current_shot_noise_2d is exactly 0, since the lambda is extremely small. I'm not sure if this is intended, but it's a bit odd
Environment: since this problem concerns only numpy and python: Numpy: 1.26.4 Python: 3.12