TDCR model — Monte Carlo efficiency estimation for liquid scintillation counting
Project description
TDCRPy
A Photo-Physical Stochastic Model for Liquid Scintillation Counting
📖 Overview
TDCRPy is a Python package developed and maintained by the BIPM (Bureau International des Poids et Mesures). It estimates detection efficiencies of liquid scintillation counters using the TDCR (Triple to Double Coincidence Ratio) or CIEMAT/NIST methods.
The calculation is based on a photo-physical stochastic Monte Carlo model, allowing users to address:
- Complex decay schemes (beta spectra via BetaShape, gamma interactions via MCNP matrices).
- Radionuclide mixtures with arbitrary activity fractions.
- Ionisation quenching via the Birks model (electrons and alpha particles).
- Reverse micelle effects in cocktails used for aqueous samples.
- Asymmetric PMT configurations (per-channel free parameters).
- Dynamic efficiency evolution over time (with
radioactivedecay). - Full optical Monte Carlo transport (
opticalTransport=True).
Technical details are described in:
📦 Installation
TDCRPy requires Python ≥ 3.11 and a standard scientific environment.
pip install TDCRPy
To upgrade to the latest version:
pip install TDCRPy --upgrade
Run Tests
Verify the installation by running the unit tests:
python -m unittest tdcrpy.test.test_tdcrpy
⚡ Quick Start
Estimate detection efficiencies for Co-60 using the full stochastic model.
import tdcrpy
L = 1.2 # free parameter (photons keV⁻¹)
Rad = "Co-60" # radionuclide
pmf = "1" # activity fraction (100 %)
N = 10000 # Monte Carlo trials (≥ 10 000 recommended)
kB = 1.0e-5 # Birks constant (cm keV⁻¹)
V = 10 # scintillator volume (mL)
result = tdcrpy.TDCRPy.TDCRPy(L, Rad, pmf, N, kB, V)
print(f"eff_S = {result[0]:.4f} ± {result[1]:.4f}") # single events
print(f"eff_D = {result[2]:.4f} ± {result[3]:.4f}") # double coincidences
print(f"eff_T = {result[4]:.4f} ± {result[5]:.4f}") # triple coincidences
Find L from a Measured TDCR Ratio
TD = 0.9776 # measured T/D ratio
result = tdcrpy.TDCRPy.eff(TD, Rad, pmf, kB, V)
print(f"L = {result[0]:.4f} photons/keV")
print(f"eff_T = {result[6]:.4f} ± {result[7]:.4f}")
🛠 Advanced Features
Asymmetric PMT Configuration
Pass a 3-tuple for the free parameter to model per-channel asymmetry:
L = (1.1, 1.3, 1.2) # (L_A, L_B, L_C) in photons keV⁻¹
result = tdcrpy.TDCRPy.TDCRPy(L, "Co-60", "1", N, kB, V)
print(f"eff_AB = {result[6]:.4f}") # A–B double coincidences
print(f"eff_BC = {result[8]:.4f}")
print(f"eff_AC = {result[10]:.4f}")
Radionuclide Mixtures
Provide comma-separated nuclides and their relative activity fractions:
result = tdcrpy.TDCRPy.TDCRPy(L, "Co-60, H-3", "0.8, 0.2", N, kB, V)
Analytical Model (Pure Beta Emitters)
A faster, deterministic alternative for pure β⁻ nuclides:
# Returns (L0, L_opt, eff_S, eff_D, eff_T)
result = tdcrpy.TDCRPy.effA(TD, "H-3", "1", kB, V)
print(f"L0 = {result[0]:.4f} photons/keV")
print(f"eff_T = {result[4]:.4f}")
Full Optical Monte Carlo Transport
Enable stochastic photon-transport for each event: photons are sampled from a Poisson distribution, distributed equally among PMTs, and converted to photoelectrons via Binomial draws (quantum efficiency):
result = tdcrpy.TDCRPy.TDCRPy(L, Rad, pmf, N, kB, V, opticalTransport=True)
Dynamic Decay
Combine with radioactivedecay to track efficiency as a sample decays:
import radioactivedecay as rd
import tdcrpy as td
inv0 = rd.Inventory({'Mo-99': 1.0}, 'Bq')
inv1 = inv0.decay(30.0, 'h') # decay 30 h
acts = inv1.activities('Bq')
total = sum(acts.values())
nucs = ", ".join(k for k, v in acts.items() if v > 0)
fracs = ", ".join(str(v / total) for k, v in acts.items() if v > 0)
result = td.TDCRPy.TDCRPy(1.0, nucs, fracs, N, kB, V)
⚙️ Configuration & Physics
Display the current physics settings:
import tdcrpy as td
td.TDCR_model_lib.readParameters(disp=True)
Configuration Reference
| Parameter | Setter | Default | Unit | Description |
|---|---|---|---|---|
| Electron bins | modifynE_electron(n) |
1000 | — | Integration bins for electron quenching |
| Alpha bins | modifynE_alpha(n) |
1000 | — | Integration bins for alpha quenching |
| Stopping power | modifysp_model(m) |
tan_xia |
— | Low-energy model (tan_xia, joy_luo, …) |
| Birks parameter | modifyChou_param(k) |
0 | cm²/MeV² | Chou bimolecular quenching constant |
| Density | modifyDensity(ρ) |
0.98 | g/cm³ | Scintillator density (Ultima Gold) |
| Mean Z / A | modifyZ(z), modifyA(a) |
3.25 / 5.94 | — | Effective atomic/mass number |
| Cocktail | modifyLScocktail(name, fAq) |
Ultima Gold |
— | LS cocktail + aqueous fraction |
| Micelle correction | modifyMicCorr(b) |
False | — | Activate reverse-micelle correction |
| Micelle diameter | modifyDiam_micelle(d) |
2 | nm | Mean micelle diameter |
| Quantum efficiency | modifyEffQ(q) |
0.25,0.25,0.25 |
— | PMT quantum efficiencies (A, B, C) |
| Optical transport | modifyOpticalTransport(b) |
False | — | Enable full optical MC transport |
| Resolving time | modifyTau(τ) |
50 | ns | Coincidence resolving time |
| Dead time | modifyDeadTime(t) |
30 | µs | Extended dead time |
| Measurement time | modifyMeasTime(T) |
60 | min | Measurement duration |
📓 Notebooks
Getting started
| Notebook | Description |
|---|---|
| tuturial.ipynb | End-to-end tutorial: fixed-L efficiencies, TDCR fitting (symmetric and asymmetric), radionuclide mixtures, full optical MC transport |
| changeParameters.ipynb | Configuration: how to modify every physics parameter (quenching bins, stopping power model, cocktail, PMT efficiencies, dead time…) |
Detection models
| Notebook | Description |
|---|---|
| analyticalModel.ipynb | Analytical model (effA): fast beta-spectrum-based efficiency for pure β emitters; symmetric and asymmetric PMT configurations |
| CNmethod.ipynb | CIEMAT/NIST (C/N) method: 2-PMT coincidence system efficiency using modelAnalyticalCN |
| cerenkovModel.ipynb | Čerenkov counting model: Frank-Tamm-based efficiency for high-energy beta emitters |
| opticalTransport.ipynb | Optical MC transport: comparison of semi-analytical vs full photon-transport model (opticalTransport=True) for H-3, Fe-55, Co-60 |
Nuclide case studies
| Notebook | Description |
|---|---|
| H-3.ipynb | Tritium (H-3): low-energy pure β; analytical and stochastic efficiency, micelle correction effect |
| Co-60.ipynb | Co-60: γ-emitter with complex decay; analytical approximation vs full stochastic model |
| Fe-55.ipynb | Fe-55: electron-capture nuclide producing Mn K-α X-rays and Auger electrons |
| Sr-90_Y-90.ipynb | Sr-90/Y-90 mixture: secular equilibrium of two pure β emitters (0.546 and 2.28 MeV endpoints) |
| Zr-93.ipynb | Zr-93: β/EC branching ratio nuclide with X-ray emission |
Physics sub-models
| Notebook | Description |
|---|---|
| quenchingModel.ipynb | Birks quenching: quenched energy vs initial energy for electrons and α particles as a function of kB |
| stoppingPower.ipynb | Stopping power models: comparison of tan_xia, joy_luo, ashley and other models for electrons |
| readBetaSpectrum.ipynb | Beta spectra: reading and visualising deposited-energy spectra from BetaShape + MCNP calculations |
| interaction.ipynb | Radiation–matter interactions: photon and electron energy deposition via MCNP response matrices |
Advanced / experimental
| Notebook | Description |
|---|---|
| mixture.ipynb | Radionuclide mixtures: efficiency of arbitrary multi-component samples with pmf_1 fractions |
| efficiencyCuve.ipynb | Efficiency curve (quench curve): eff_D and eff_T vs light yield L for a series of kB values |
| distrubutionTDCR.ipynb | TDCR distribution: histogram of per-event efficiency values over MC trials; statistical characterisation |
| dynamicDecay.ipynb | Dynamic efficiency: time-dependent efficiency during daughter-nuclide ingrowth (requires radioactivedecay) |
Validation
| Notebook | Description |
|---|---|
| functional_validation.ipynb | Cross-version validation: compare two TDCRPy versions side-by-side for H-3, Fe-55, Co-60, Sr-90, Cd-109 across analytical and stochastic models; configurable VERSION_REF / VERSION_NEW |
📚 Citation
If you use TDCRPy in your work, please cite:
R. Coulon, J. Hu — TDCRPy: A Python package for TDCR measurements
Applied Radiation and Isotopes (2024)
DOI: 10.1016/j.apradiso.2024.111518
⚖️ License
This project is licensed under the MIT License.
Copyright © BIPM (Bureau International des Poids et Mesures).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tdcrpy-2.20.12.tar.gz.
File metadata
- Download URL: tdcrpy-2.20.12.tar.gz
- Upload date:
- Size: 22.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c473a722856e34690252ea561578db4ac682b66244e7b68d67a2fb34c54c73b
|
|
| MD5 |
19732a339c0a4b25d29ccaea62e4b75b
|
|
| BLAKE2b-256 |
7e51c42eeaa1db5fe26d96f69e8a36c50a42275b10a9794b266ec4f5303447e4
|
Provenance
The following attestation bundles were made for tdcrpy-2.20.12.tar.gz:
Publisher:
python-publish.yml on RomainCoulon/TDCRPy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tdcrpy-2.20.12.tar.gz -
Subject digest:
4c473a722856e34690252ea561578db4ac682b66244e7b68d67a2fb34c54c73b - Sigstore transparency entry: 1956870872
- Sigstore integration time:
-
Permalink:
RomainCoulon/TDCRPy@2f19b77e4249804b47d5d3fe91056a53540695ec -
Branch / Tag:
refs/tags/2.20.12 - Owner: https://github.com/RomainCoulon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@2f19b77e4249804b47d5d3fe91056a53540695ec -
Trigger Event:
push
-
Statement type:
File details
Details for the file tdcrpy-2.20.12-py3-none-any.whl.
File metadata
- Download URL: tdcrpy-2.20.12-py3-none-any.whl
- Upload date:
- Size: 23.5 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
819864b175e30022954e12f0ca5eff862b7fc4df6eed79f329716b49b65ca5fb
|
|
| MD5 |
315921ea7c614032790abc0ecc4dfeed
|
|
| BLAKE2b-256 |
8422d65dbd0714088be71e717007401eb7d1aa70398c38c4ea2898701e7f0a0e
|
Provenance
The following attestation bundles were made for tdcrpy-2.20.12-py3-none-any.whl:
Publisher:
python-publish.yml on RomainCoulon/TDCRPy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tdcrpy-2.20.12-py3-none-any.whl -
Subject digest:
819864b175e30022954e12f0ca5eff862b7fc4df6eed79f329716b49b65ca5fb - Sigstore transparency entry: 1956871027
- Sigstore integration time:
-
Permalink:
RomainCoulon/TDCRPy@2f19b77e4249804b47d5d3fe91056a53540695ec -
Branch / Tag:
refs/tags/2.20.12 - Owner: https://github.com/RomainCoulon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@2f19b77e4249804b47d5d3fe91056a53540695ec -
Trigger Event:
push
-
Statement type: