Modified optika.sensors.signal() to model charge diffusion using a Monte-Carlo simulation.#162
Open
roytsmart wants to merge 13 commits into
Open
Modified optika.sensors.signal() to model charge diffusion using a Monte-Carlo simulation.#162roytsmart wants to merge 13 commits into
optika.sensors.signal() to model charge diffusion using a Monte-Carlo simulation.#162roytsmart wants to merge 13 commits into
Conversation
6f14ac3 to
58915e2
Compare
…Monte-Carlo simulation.
…or refactor. Sensor pipeline: - Rename the sensor methods to `collect` -> `expose` -> `measure` (was `bin_rays` -> `expose` -> `readout`), update the `_sequential.py` caller. - `expose` centers the wavelength bin edges and is shared by any per-pixel photon image; tidy the empty-pixel mean-cosine division. Review fixes (internal consistency of the breaking changes): - `fit_eqe` now passes the cosine `direction=1` instead of a 3d vector to the (now cosine-based) standalone `quantum_efficiency_effective`. This was masked by the joblib cache, so a cold cache would have broken all three device materials; verified by running the fit uncached. - Update the stale docstring examples that still used the old API (`quantum_efficiency_effective(rays=...)`, `width_charge_diffusion(rays=...)`, and a vector `direction` to the standalone QE); confirmed by a full doc build. - Revert the `RayVectorArray.intensity` default back to `1` and fix a cosmetic typo in the new `RayVectorArray.n` property. Add a `test_n` exercising the `RayVectorArray.n` complex-index property. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
88ff3fc to
7057014
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #162 +/- ##
==========================================
- Coverage 99.32% 99.30% -0.03%
==========================================
Files 116 116
Lines 5797 5908 +111
==========================================
+ Hits 5758 5867 +109
- Misses 39 41 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Document the `n` property (complex index of refraction: real part is the index of refraction, imaginary part is the extinction coefficient k = alpha * lambda / 4 pi). - Run black on the sensor material modules to satisfy the formatting check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Rename its first argument `photons_absorbed` -> `photons_transmitted` and model the transmitted->absorbed step (the fraction `1 - e^(-alpha t)` that is absorbed before escaping out the back), so it is now drop-in comparable with the Monte-Carlo `electrons_measured()`: at 5.9 keV the two agree to ~0.003% on the mean and ~0.6% on the std. - Add the matching `thickness_substrate` parameter and align the shared parameter docstrings/summary with `electrons_measured()`. - Fix two latent bugs: the docstring example called `electrons_measured` with the old `photons_absorbed=` keyword, and the broadcast shape accidentally referenced the module-level `absorbance` function. - Update the MC summary line, which still said "photons absorbed" despite the argument now being `photons_transmitted`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Mark the defensive `ValueError` branches with `# pragma: nocover`, matching the existing convention (e.g. `_sequential.py`): the `expose` ambiguous wavelength-axis check and the `absorbance` method dispatch. - Mark the `@numba.njit` `_electrons_measured_numba` kernel `# pragma: nocover`; JIT-compiled code cannot be traced by coverage.py. - Extend `test_electrons_measured` with an `axis_xy` parametrize and a per-pixel photon grid so the charge-diffusion branch of `electrons_measured` is exercised. `_ramanathan_2020.py` is now at 100% line coverage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Parametrize `test_absorbance` over `method` ("Beer-Lambert" and "exact") so
the exact (`layer_absorbance`) branch is exercised.
- Add a `transmittance` method test mirroring the other method tests, covering
its `direction`/`normal` None-default handling.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…otons_transmitted`. The Monte-Carlo kernel now samples the absorption depth from an exponential truncated to the light-sensitive region, so every input photon is treated as absorbed. The escape fraction is applied as Poisson thinning in `signal()` (exactly equivalent). `electrons_measured_approx()` reverts to splitting the absorbed photons into partial/complete charge collection, and `signal()` computes absorbance from the start rather than transmittance. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…within the substrate. The exact `electrons_measured` kernel samples the absorption depth from an exponential truncated to the substrate `[0, D)`, so the approximate model must do the same. The partial-collection fraction is now the implant fraction conditioned on absorption within the substrate, `(1 - exp(-alpha*W)) / (1 - exp(-alpha*D))`, which restores agreement between `electrons_measured_approx` and `electrons_measured`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The `signal()` `method` parameter docstring described nonexistent `exact`/ `approx` methods; it now documents the actual `monte-carlo` and `expected` options, and notes that the per-pixel `expected` method applies no charge diffusion. Adds `test_electrons_measured_diffusion`, which injects photons into a single pixel and checks that the spatial spread of the diffused charge matches the analytic width from `optika.sensors.charge_diffusion`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…` method. The per-pixel charge-collection model needs the cosine of the refracted angle inside the light-sensitive region, which depends on the ambient index of refraction. Rather than threading an ambient-index argument through `expose`/`signal`, `collect` now refracts each ray with its own `rays.n` via the new `AbstractSensorMaterial.direction_refracted` method and flux-weights the resulting (complex) substrate-side cosine per pixel. `material.signal` consumes this already-refracted cosine and forwards it to `signal` with equal ambient/substrate indices so the internal Snell step is a no-op while the effective absorption still uses the correct substrate index; its `n` parameter is removed. `AbstractBackIlluminatedSiliconSensorMaterial.electrons_measured` is refactored to reuse `direction_refracted`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.