Clearance screening
Clearance screening compares a radioactive inventory against per-nuclide
clearance levels. The clearance index CI = sum_i A_i / CL_i adds up each
nuclide’s activity divided by its clearance level, and the sum-of-fractions
rule treats CI <= 1 as satisfying the screening criterion (the boundary
included). Nucleide’s nucleide.alara helpers run that arithmetic over plain
{nuclide: activity} dicts, and nucleide.fispact reads the clearance-bearing
inventory table from FISPACT-II output. This tutorial shows both; the
implementations live in crates/alara-io and crates/fispact-io.
Reading the FISPACT-II clearance block
FISPACT-II prints a wide inventory table with a per-nuclide clearance column
when the input deck sets the HAZARDS and CLEAR keywords.
fispact_parse_clearance reads that table from the output text — one dict per
(nuclide, time step) row:
from pathlib import Path
from nucleide.fispact import fispact_parse_clearance
text = Path("fixtures/fispact/clearance.out").read_text()
rows = fispact_parse_clearance(text)
print(len(rows))
step1 = [r for r in rows if r["interval"] == 1]
for r in step1:
print(r["nuclide"], r["flags"], r["activity_bq"], r["clearance_index"], r["half_life_s"])
7
V-55 > 0.0 0.0 -1.0
Fe-56 #> 0.0 0.0 -1.0
Co-60 > 4000000.0 1000000.0 166360000.0
Rb-86m & 8000000000.0 4000000000.0 61.0
Each row carries the 1-based interval, the step time in seconds (time_s)
with its verbatim time_label, a cooling flag (true for COOLING TIME IS
steps), the nuclide name in the shared dialect spelling (Co-60), the
verbatim flag characters, the activity_bq column, the half-life in seconds,
and the code’s own clearance_index column — FISPACT-II’s per-nuclide
A_i / CL_i against its internal clearance library, not against a caller
table. Stable nuclides are stored with half_life_s == -1.0 (V-55 and Fe-56
above). The flags keep FISPACT-II’s markers verbatim: # stable, > present
before irradiation, & gamma spectrum approximately calculated, ?
convergence not reached.
Screening against the default clearance table
alara_clearance_index computes the clearance index over an inventory dict.
With limits=None (the default) the comparison uses Nucleide’s vendored
transcription of EU 2013/59/Euratom Annex VII Table A — 260
activity-concentration limits in Bq/g for solid material. Because that table
lists concentrations, the inventory must be massic activities (Bq/g), not
total activities (Bq):
from nucleide.alara import (
alara_clearance_eu_table,
alara_clearance_index,
alara_sum_of_fractions,
)
eu = alara_clearance_eu_table()
print(len(eu), eu["Co-60"], eu["H-3"])
inventory = {"Co-60": 0.05, "Cs-137": 0.2} # Bq/g
print(alara_clearance_index(inventory))
out = alara_sum_of_fractions(inventory)
print(out["sum"], out["class"], out["max_nuclide"], out["max_fraction"])
260 0.1 100.0
2.5
2.5 exceeded Cs-137 2.0
alara_sum_of_fractions returns the same sum plus the screening class
("satisfied" when sum <= 1, otherwise "exceeded") and the dominant
contributor — the nuclide with the largest single fraction A_i / CL_i (here
Cs-137 at 0.2 Bq/g against a 0.1 Bq/g limit). Nuclide keys accept any
shared-dialect spelling ("Co60", "Co-60", and "co-60" resolve to the
same nuclide); results report the canonical spelling.
Spanish conditional tables
For Spanish conditional NORM landfill screening, alara_clearance_es_table
selects one of the three CSN Tables 1–3 explicitly by landfill type; the
caller picks the governing table and there is no cross-table logic:
from nucleide.alara import alara_clearance_es_table, alara_sum_of_fractions
es = alara_clearance_es_table("non_hazardous", "slags")
print(len(es))
inventory = {"Ra-226": 0.2, "K-40": 5.0} # Bq/g
print(alara_sum_of_fractions(inventory, es)["class"])
40
satisfied
The class boundary
The boundary sits exactly at sum == 1 and belongs to the satisfied side: an
inventory sitting exactly at its combined limits classifies as satisfied, and
one float step above flips the class:
toy_limits = {"Co60": 10.0, "H3": 5.0, "Fe55": 2.0}
at = alara_sum_of_fractions({"Co60": 10.0}, toy_limits)
print(at["sum"], at["class"])
above = alara_sum_of_fractions({"Co60": 10.000000000000002}, toy_limits)
print(above["sum"], above["class"])
1.0 satisfied
1.0000000000000002 exceeded
A custom limit table
Pass a {nuclide: limit} dict as limits to screen against site-specific or
national values instead of the EU table. Activities and limits must share one
unit basis — here both sides are total activities in Bq, so the comparison is
consistent even though the numbers look nothing like Bq/g concentrations:
print(alara_clearance_index({"Co60": 10.0, "H3": 2.5}, toy_limits))
1.5
Every inventory nuclide needs a table entry, and every activity must be finite and non-negative; violations raise a clear error instead of being skipped:
try:
alara_clearance_index({"Mn54": 1.0}, toy_limits)
except ValueError as exc:
print(exc)
nuclide Mn54 has no clearance limit (table holds 3 entries)
From a parsed inventory to a screening result
Tying the two halves together: take one time step from the parsed FISPACT-II block and screen it against a caller-supplied limit table in the matching basis (total Bq on both sides):
step1_inv = {r["nuclide"]: r["activity_bq"] for r in rows if r["interval"] == 1}
limits = {"V-55": 1.0, "Fe-56": 1.0, "Co-60": 4.0e6, "Rb-86m": 8.0e9}
out = alara_sum_of_fractions(step1_inv, limits)
print(out["sum"], out["class"], out["max_nuclide"], out["max_fraction"])
2.0 exceeded Co-60 1.0
Screening arithmetic, not a compliance decision
These helpers are screening arithmetic, not a compliance decision. Real clearance calls for the governing regulatory table for the material and pathway, complete material bookkeeping, and the national transposition of the underlying directive. The vendored EU table is a transcription of one directive’s annex for solid materials, and the Spanish tables transcribe the CSN conditional NORM landfill levels; a sum below 1 marks an inventory as passing this arithmetic check — not as cleared for release.
See also
tests/test_clearance.pyfor the boundary probes, the error cases, and an end-to-end parse-and-screen replay.- Sample data files for
fixtures/fispact/, including the clearance-block sample used above. - Python API reference for
the full
nucleide.alaraandnucleide.fispactsignatures.