Metadata-Version: 2.4
Name: TDCRPy
Version: 2.20.14
Summary: TDCR model — Monte Carlo efficiency estimation for liquid scintillation counting
Home-page: https://github.com/RomainCoulon/TDCRPy
Author: Romain Coulon
Author-email: romain.coulon@bipm.org
Project-URL: Documentation, https://github.com/RomainCoulon/TDCRPy/
Project-URL: Bug Tracker, https://github.com/RomainCoulon/TDCRPy/issues
Keywords: TDCR,Monte-Carlo,radionuclide,liquid scintillation,counting
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Natural Language :: French
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENCE.md
Requires-Dist: numpy
Requires-Dist: scipy
Requires-Dist: matplotlib
Requires-Dist: tqdm
Requires-Dist: numba
Requires-Dist: setuptools
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: sphinx; extra == "dev"
Requires-Dist: sphinx-rtd-theme; extra == "dev"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license-file
Dynamic: project-url
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# TDCRPy

<div align="center">

<img src="docs/logo1.png" alt="TDCRPy Logo" width="200"/>

**A Photo-Physical Stochastic Model for Liquid Scintillation Counting**

![License](https://img.shields.io/badge/license-MIT-blue.svg)
![Python](https://img.shields.io/badge/python-3.11%2B-blue)
![Version](https://img.shields.io/badge/version-2.20.14-green)
![Status](https://img.shields.io/badge/status-stable-green)
![BIPM](https://img.shields.io/badge/maintained%20by-BIPM-005696)

</div>

---

## 📖 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).
* Full optical Monte Carlo transport (`opticalTransport=True`).
* C/N (CIEMAT/NIST) 2-PMT efficiency curves.

Technical details are described in:

* [Coulon et al., *Applied Radiation and Isotopes* (2024)](https://doi.org/10.1016/j.apradiso.2024.111518)
* [Coulon et al., BIPM Technical Report](http://dx.doi.org/10.13140/RG.2.2.15682.80321)

---

## 📦 Installation

TDCRPy requires Python ≥ 3.11 and a standard scientific environment.

```shell
pip install TDCRPy
```

To upgrade to the latest version:

```shell
pip install TDCRPy --upgrade
```

### Run Tests

Verify the installation by running the unit tests:

```shell
python -m unittest tdcrpy.test.test_tdcrpy
```

---

## ⚡ Quick Start

Estimate detection efficiencies for **Co-60** using the full stochastic model.

```python
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

```python
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:

```python
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:

```python
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:

```python
# 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):

```python
result = tdcrpy.TDCRPy.TDCRPy(L, Rad, pmf, N, kB, V, opticalTransport=True)
```

### C/N Efficiency Curve

Compute the **CIEMAT/NIST efficiency curve** — detection efficiency as a
function of the free parameter *L* for a 2-PMT coincidence system:

```python
import numpy as np
import matplotlib.pyplot as plt
import tdcrpy.TDCR_model_lib as tl

rad = "H-3"
kB  = 1e-5   # Birks constant (cm keV⁻¹)
V   = 10     # volume (mL)
ne  = 1000   # quenching integration bins

L_vec = np.linspace(1, 20, 80)
eff_D = np.array([tl.modelAnalyticalCN(L, rad, kB, V, ne)[2] for L in L_vec])

plt.plot(L_vec, eff_D)
plt.xlabel("L (photons keV⁻¹)")
plt.ylabel("eff_D (double coincidence)")
plt.title(f"C/N efficiency curve — {rad}")
plt.grid(True)
plt.show()
```

To find *L* from a measured C/N counting ratio `CN` (counts_D / counts_S):

```python
from scipy.optimize import brentq

CN_meas = 0.62   # measured D/S ratio

def residual(L):
    eA, eB, eD = tl.modelAnalyticalCN(L, rad, kB, V, ne)
    return eD / ((eA + eB) / 2) - CN_meas

L0 = brentq(residual, 0.5, 30)
_, _, eff_D = tl.modelAnalyticalCN(L0, rad, kB, V, ne)
print(f"L = {L0:.3f} photons/keV,  eff_D = {eff_D:.5f}")
```

---

## ⚙️ Configuration & Physics

Display the current physics settings:

```python
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

Notebooks are organised in subfolders by topic under [`notebooks/`](https://github.com/RomainCoulon/TDCRPy/tree/main/notebooks).

### Getting started — [`notebooks/getting_started/`](https://github.com/RomainCoulon/TDCRPy/tree/main/notebooks/getting_started)

| Notebook | Description |
| :--- | :--- |
| [tuturial.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/getting_started/tuturial.ipynb) | **End-to-end tutorial**: fixed-L efficiencies, TDCR fitting (symmetric and asymmetric), radionuclide mixtures, full optical MC transport |
| [changeParameters.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/getting_started/changeParameters.ipynb) | **Configuration**: how to modify every physics parameter (quenching bins, stopping power model, cocktail, PMT efficiencies, dead time…) |

### Detection models — [`notebooks/models/`](https://github.com/RomainCoulon/TDCRPy/tree/main/notebooks/models)

| Notebook | Description |
| :--- | :--- |
| [analyticalModel.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/models/analyticalModel.ipynb) | **Analytical model** (`effA`): fast beta-spectrum-based efficiency for pure β emitters; symmetric and asymmetric PMT configurations |
| [CNmethod.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/models/CNmethod.ipynb) | **CIEMAT/NIST (C/N) method**: 2-PMT coincidence efficiency curve using `modelAnalyticalCN`; L-fitting from measured C/N ratio |
| [cerenkovModel.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/models/cerenkovModel.ipynb) | **Čerenkov counting model**: Frank-Tamm-based efficiency for high-energy beta emitters |
| [opticalTransport.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/models/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 — [`notebooks/nuclides/`](https://github.com/RomainCoulon/TDCRPy/tree/main/notebooks/nuclides)

| Notebook | Description |
| :--- | :--- |
| [H-3.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/nuclides/H-3.ipynb) | **Tritium (H-3)**: low-energy pure β; analytical and stochastic efficiency, micelle correction effect |
| [Co-60.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/nuclides/Co-60.ipynb) | **Co-60**: γ-emitter with complex decay; analytical approximation vs full stochastic model |
| [Fe-55.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/nuclides/Fe-55.ipynb) | **Fe-55**: electron-capture nuclide producing Mn K-α X-rays and Auger electrons |
| [Sr-90_Y-90.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/nuclides/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](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/nuclides/Zr-93.ipynb) | **Zr-93**: β/EC branching ratio nuclide with X-ray emission |

### Physics sub-models — [`notebooks/physics/`](https://github.com/RomainCoulon/TDCRPy/tree/main/notebooks/physics)

| Notebook | Description |
| :--- | :--- |
| [quenchingModel.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/physics/quenchingModel.ipynb) | **Birks quenching**: quenched energy vs initial energy for electrons and α particles as a function of kB |
| [stoppingPower.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/physics/stoppingPower.ipynb) | **Stopping power models**: comparison of tan_xia, joy_luo, ashley and other models for electrons |
| [readBetaSpectrum.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/physics/readBetaSpectrum.ipynb) | **Beta spectra**: reading and visualising deposited-energy spectra from BetaShape + MCNP calculations |
| [interaction.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/physics/interaction.ipynb) | **Radiation–matter interactions**: photon and electron energy deposition via MCNP response matrices |

### Advanced — [`notebooks/advanced/`](https://github.com/RomainCoulon/TDCRPy/tree/main/notebooks/advanced)

| Notebook | Description |
| :--- | :--- |
| [mixture.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/advanced/mixture.ipynb) | **Radionuclide mixtures**: efficiency of arbitrary multi-component samples with activity fractions |
| [efficiencyCuve.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/advanced/efficiencyCuve.ipynb) | **TDCR efficiency curve**: eff_D and eff_T vs light yield L for a series of kB values |
| [distrubutionTDCR.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/advanced/distrubutionTDCR.ipynb) | **TDCR distribution**: histogram of per-event efficiency values over MC trials; statistical characterisation |
| [cocktailComposition.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/advanced/cocktailComposition.ipynb) | **Cocktail composition**: effect of aqueous fraction (H₂O / HCl) on detection efficiency for H-3 and Sr-90 |
| [cocktailResponse.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/advanced/cocktailResponse.ipynb) | **Cocktail comparison**: eff_D for 12 commercial LS cocktails × 6 nuclides (H-3, C-14, Fe-55, Cr-51, Co-60, Cd-109) |

### Sensitivity — [`notebooks/sensitivity/`](https://github.com/RomainCoulon/TDCRPy/tree/main/notebooks/sensitivity)

| Notebook | Description |
| :--- | :--- |
| [parameterSensitivity.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/sensitivity/parameterSensitivity.ipynb) | **Parameter sensitivity study**: sweeps every tunable model parameter (L, kB, PMT quantum efficiency, cocktail composition, stopping-power model, quenching numerics, micelle correction, counting-chain parameters, optical transport, MC convergence) around its nominal value for H-3 and Sr-90, with a summary tornado chart |

### Validation — [`notebooks/validation/`](https://github.com/RomainCoulon/TDCRPy/tree/main/notebooks/validation)

| Notebook | Description |
| :--- | :--- |
| [functional_validation.ipynb](https://github.com/RomainCoulon/TDCRPy/blob/main/notebooks/validation/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](https://doi.org/10.1016/j.apradiso.2024.111518)

---

## ⚖️ License

This project is licensed under the **MIT License**.  
Copyright © BIPM (Bureau International des Poids et Mesures).
