Skip to content

Commit

Permalink
Added `optika.sensors.AbstractImagingSensorMaterial.photons_incident(…
Browse files Browse the repository at this point in the history
…)` method to compute the expected number of incident photons given the number of measured electrons. (#108)
  • Loading branch information
byrdie authored Dec 9, 2024
1 parent 4d8a89c commit 39b2b35
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 2 deletions.
67 changes: 67 additions & 0 deletions optika/sensors/_materials/_materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,31 @@ def electrons_measured(
The vector perpendicular to the surface of the sensor.
"""

@abc.abstractmethod
def photons_incident(
self,
electrons: u.Quantity | na.AbstractScalar,
wavelength: u.Quantity | na.AbstractScalar,
direction: na.AbstractCartesian3dVectorArray,
normal: na.AbstractCartesian3dVectorArray,
) -> na.AbstractScalar:
"""
Given the number of electrons measured by the sensor,
and a grid of wavelengths, compute the expected number of
photons incident on the sensor.
Parameters
----------
electrons
The number of electrons measured by the sensor.
wavelength
An assumed grid of wavelengths for the incident photons.
direction
An assumed propagation direction for the incident photons.
normal
The vector perpendicular to the surface of the sensor.
"""

@abc.abstractmethod
def charge_diffusion(
self,
Expand Down Expand Up @@ -822,6 +847,15 @@ def electrons_measured(

return result

def photons_incident(
self,
electrons: u.Quantity | na.AbstractScalar,
wavelength: u.Quantity | na.AbstractScalar,
direction: na.AbstractCartesian3dVectorArray,
normal: na.AbstractCartesian3dVectorArray,
) -> na.AbstractScalar:
return electrons * u.photon / u.electron

def charge_diffusion(
self,
rays: optika.rays.RayVectorArray,
Expand Down Expand Up @@ -1121,6 +1155,39 @@ def electrons_measured(

return result

def photons_incident(
self,
electrons: u.Quantity | na.AbstractScalar,
wavelength: u.Quantity | na.AbstractScalar,
direction: na.AbstractCartesian3dVectorArray,
normal: na.AbstractCartesian3dVectorArray,
) -> na.AbstractScalar:
"""
Compute the expected number of incident photons for a given number
of electrons.
Parameters
----------
electrons
The energy collected by the sensor in units of electrons.
wavelength
The assumed wavelength of the incident photons.
direction
The assumed direction of the incident photons.
normal
The vector perpendicular to the surface of the sensor.
"""

qe = self.quantum_efficiency(
rays=optika.rays.RayVectorArray(
wavelength=wavelength,
direction=direction,
),
normal=normal,
)

return electrons / qe

def charge_diffusion(
self,
rays: optika.rays.RayVectorArray,
Expand Down
45 changes: 43 additions & 2 deletions optika/sensors/_materials/_materials_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,14 +245,55 @@ class AbstractTestAbstractImagingSensorMaterial(
)
def test_electrons_measured(
self,
a: optika.sensors.AbstractBackilluminatedCCDMaterial,
a: optika.sensors.AbstractImagingSensorMaterial,
rays: optika.rays.RayVectorArray,
normal: na.AbstractCartesian3dVectorArray,
):
result = a.electrons_measured(rays, normal)
assert isinstance(result, optika.rays.RayVectorArray)
assert np.all(result.intensity >= 0 * u.electron)

@pytest.mark.parametrize(
argnames="electrons",
argvalues=[
100 * u.electron,
],
)
@pytest.mark.parametrize(
argnames="wavelength",
argvalues=[
100 * u.AA,
],
)
@pytest.mark.parametrize(
argnames="direction",
argvalues=[
na.Cartesian3dVectorArray(0, 0, 1),
],
)
@pytest.mark.parametrize(
argnames="normal",
argvalues=[
na.Cartesian3dVectorArray(0, 0, -1),
],
)
def test_photons_incident(
self,
a: optika.sensors.AbstractImagingSensorMaterial,
electrons: u.Quantity | na.AbstractScalar,
wavelength: u.Quantity | na.AbstractScalar,
direction: na.AbstractCartesian3dVectorArray,
normal: na.AbstractCartesian3dVectorArray,
):
result = a.photons_incident(
electrons=electrons,
wavelength=wavelength,
direction=direction,
normal=normal,
)
assert isinstance(na.as_named_array(result), na.AbstractScalar)
assert result.unit.is_equivalent(u.photon)

@pytest.mark.parametrize(
argnames="rays",
argvalues=[
Expand All @@ -272,7 +313,7 @@ def test_electrons_measured(
)
def test_charge_diffusion(
self,
a: optika.sensors.AbstractBackilluminatedCCDMaterial,
a: optika.sensors.AbstractImagingSensorMaterial,
rays: optika.rays.RayVectorArray,
normal: na.AbstractCartesian3dVectorArray,
):
Expand Down

0 comments on commit 39b2b35

Please sign in to comment.