Metadata-Version: 2.4
Name: endf-userpy
Version: 0.1.0a6
Summary: High-level interpretation of ENDF-6 data
Home-page: https://github.com/IAEA-NDS/endf-userpy
Author: Georg Schnabel, Daniel Lopez Aldama
License: MIT
Project-URL: Repository, https://github.com/IAEA-NDS/endf-userpy
Project-URL: Issues, https://github.com/IAEA-NDS/endf-userpy/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Fortran
Classifier: Programming Language :: C
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.22
Requires-Dist: scipy
Requires-Dist: endf_parserpy>=0.14
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license
Dynamic: license-file
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# endf-userpy

High-level interpretation of ENDF-6 nuclear data files.

`endf-userpy` is a Python library that answers user-friendly questions
about ENDF-6 nuclear data evaluations: "what is the cross section of
the (n,2n) reaction on Fe-56?", "what is the energy spectrum of
neutrons emitted from U-238 at 14 MeV?", "how much Co-60m is produced
per (n,gamma) reaction on Co-59?".

The library does not parse ENDF-6 itself. It builds on
[endf_parserpy](https://github.com/IAEA-NDS/endf-parserpy), which
turns an ENDF-6 file into a nested Python dict (`endf_dict`).
endf-userpy then walks that dict to reconstruct cross sections,
yields, and differential distributions, hiding which MF section a
piece of data lives in.

> **Status.** This is an early alpha release. The public API is
> stabilising but may still change. See "Known limitations" below.
> Feedback by creating issues is appreciated.

## Installation

> **PyPI releases lag behind `main`.** Development is active and
> new capabilities land several PRs at a time before a release is
> cut. Recent additions that are on `main` but not yet on PyPI
> include end-to-end JAX autodiff through the top-level API across
> all supported MF sections, resolved-resonance reconstruction
> (MLBW, Reich-Moore, and R-Matrix Limited with KRM=3) plus
> unresolved-resonance URR Case C with Gauss-Legendre or Ross-10
> fluctuation-integral quadrature, numpy / numba / JAX backends on
> every resonance formalism, the gamma production pipeline
> (MF12/13/14/15), the tabulated photon spectra path, and MF6
> LAW=5 charged-particle elastic scattering (nuclear-amplitude
> Legendre and tabulated LTP forms, with CM-to-LAB conversion). If
> you need those, **install from source** (see below).
> `pip install endf-userpy` gives you the last tagged
> release, which may be missing recent work.

```bash
pip install endf-userpy
```

Prebuilt wheels are available for cpython 3.9â€“3.13 on:

- Linux x86_64 (`manylinux_2_28`)
- macOS arm64 (>= 11.0)
- macOS x86_64 (>= 10.12)
- Windows AMD64

Other platforms or Python versions install from the sdist
automatically and need a Fortran compiler (`gfortran`) on `PATH`.

Runtime dependencies (`numpy`, `scipy`, `endf_parserpy`) are pulled
in automatically. Some examples additionally use `matplotlib`.

### From source (recommended for latest features)

```bash
git clone https://github.com/IAEA-NDS/endf-userpy
cd endf-userpy
pip install -e .
```

The default install is pure Python and needs no compiler. To also
build the optional Fortran parity-oracle extension used by the
equivalence-test suite, set `ENDF_USERPY_BUILD_FORTRAN=1` before
`pip install` (requires `gfortran` on `PATH`; Windows users can
opt into the Intel Fortran compiler `ifx` with
`ENDF_USERPY_USE_IFX=1`).

## Quick start

```python
import numpy as np
from endf_parserpy import EndfParserFactory
from endf_userpy.quantities import (
    get_available_reactions,
    get_reaction_xs,
)

parser = EndfParserFactory.create()
endf_dict = parser.parsefile("tests/data/n-004_Be_009.endf")

print(get_available_reactions(endf_dict))
# ['(n,total)', '(n,n_0)', '(n,nonelas)', '(n,2n)', '(n,g)', ...]

eincs = np.array([0.0253, 1e3, 1e6, 1.4e7])  # eV
print(get_reaction_xs(endf_dict, "(n,total)", eincs))
# [6.162 6.144 3.341 1.528]   barn
```

## Public API

All user-facing functions live in `endf_userpy.quantities` and take
an `endf_dict` (already parsed) plus user-friendly string identifiers.

| Function | Returns | What it does |
| --- | --- | --- |
| `get_available_reactions(endf_dict)` | list of reaction strings | introspect a file |
| `get_declared_residuals(endf_dict)` | list of residual strings | every MF8-declared (ZAP, LFS) pair |
| `is_residual_declared(endf_dict, residual)` | bool | whether a specific residual is MF8-declared |
| `get_declared_isomer_states(endf_dict, residual)` | list of suffix strings | isomer states declared for a residual |
| `get_incident_energies(endf_dict, reaction)` | array | tabulated Einc mesh for a channel |
| `get_emission_energies(endf_dict, reaction, particle)` | array | tabulated Eout mesh |
| `get_reaction_xs(endf_dict, reaction, eincs)` | array | cross section of a named channel |
| `get_residual_production_xs(endf_dict, residual, eincs)` | array | production of a specific residual nucleus, isomer-resolved |
| `get_particle_production_xs(endf_dict, reaction, particle, eincs)` | array | ejectile production cross section |
| `get_particle_production_dxs_dE(endf_dict, reaction, particle, eincs, eouts)` | array | dÏƒ/dE energy spectrum of emitted particle |
| `get_particle_production_dxs_dmu(endf_dict, reaction, particle, eincs, mus)` | array | dÏƒ/dÎ© angular distribution |
| `get_particle_production_ddxs(endf_dict, reaction, particle, eincs, eouts, mus)` | array | dÂ²Ïƒ/dE/dÎ© double-differential |
| `get_particle_production_discrete_gamma_lines(endf_dict, reaction, eincs)` | list of per-line records | per-line `(Eg, y_per_ein, angdist_per_ein)` for MF12 discrete gammas |

Reaction strings for a neutron projectile follow the ENDF-6 MT
convention:

| String | MT | Meaning |
| --- | --- | --- |
| `"(n,total)"` | MT1 | total cross section |
| `"(n,n_0)"` | MT2 | elastic scattering |
| `"(n,nonelas)"` | MT3 | non-elastic sum |
| `"(n,n)"` | MT4 | inelastic scattering **sum** (MT51..MT91) |
| `"(n,n_i)"` for `i = 1, 2, ...` | MT51 + i-1 | inelastic to i-th discrete level |
| `"(n,2n)"` | MT16 | (n,2n) |
| `"(n,3n)"` | MT17 | (n,3n) |
| `"(n,fission)"` | MT18 | **total fission** (all chances) |
| `"(n,f)"` | MT19 | **first-chance fission only** |
| `"(n,nf)"` | MT20 | second-chance fission |
| `"(n,2nf)"` | MT21 | third-chance fission |
| `"(n,3nf)"` | MT38 | fourth-chance fission |
| `"(n,g)"` | MT102 | radiative capture |
| `"(n,p)"` | MT103 | (n,proton) |
| `"(n,d)"` | MT104 | (n,deuteron) |
| `"(n,t)"` | MT105 | (n,triton) |
| `"(n,h)"` | MT106 | (n,Â³He) |
| `"(n,a)"` | MT107 | (n,Î±) |

Two subtleties worth calling out:

- **Fission**: `(n,f)` and `(n,fission)` are **not** the same. `(n,f)`
  is MT19 (first-chance fission only); `(n,fission)` is MT18 (total
  fission summed over all chances). Most modern evaluations put all
  their fission data under MT18 and leave MT19â€“MT21 empty
  (JENDL-5 U-238, ENDF/B-VIII.1 Pu-239, TENDL-2021 U-235 all do
  this), so `(n,fission)` is the query users almost always want.
  `(n,f)` will return 0 on those files. Some files that split by
  fission chance (older ENDF/B releases, some evaluations of
  higher actinides) do populate MT19 individually; on those,
  `(n,f)` gives you the first-chance piece only.
- **Inelastic scattering**: `(n,n)` is MT4 (**sum** over discrete
  levels + continuum, MT51..MT91). `(n,n_0)` is MT2 (elastic).
  `(n,n_1)` is MT51 (inelastic to the first excited state), and so
  on. See the "Aggregate-reaction sum-MT queries under-count on
  sparse files" note under Known limitations for the admission-
  heuristic caveat.

Full lookup: `endf_userpy/primitives/reactions.py:REACTION_DICT`.
`get_available_reactions(endf_dict)` returns the strings the file
actually populates, so passing that list to your query is the
safest way to avoid a silent zero from a mistyped or file-missing MT.

Particles: `"n"`, `"p"`, `"d"`, `"t"`, `"h"` (helium-3),
`"a"` (alpha), `"g"` (gamma).
Residual nuclei: `"Z-Sym-A"` (e.g. `"27-Co-60"`) or `"Sym-A"`
(e.g. `"Co-60"`), with optional isomer suffix `g`, `m`, `m1`, `m2`,
... (`"Co-60m"` = first metastable).

## Runtime policies (`RunOptions`)

Every top-level `get_*` function takes a keyword-only `options:
RunOptions | None = None` argument. The default `RunOptions()`
is physics-first: resonance reconstruction on, MT5 catch-all
redistributed to its specific residuals, activation-convention
residual sum. Override a single field with
`RunOptions(above_range='raise', backend='jax')`;
`dataclasses.replace()` handles composition.

```python
from endf_userpy.run_options import RunOptions

opts = RunOptions(above_range='nan', backend='numba')
xs = get_reaction_xs(endf_dict, '(n,total)', eincs, options=opts)
```

Fields (defined in `endf_userpy/run_options.py`):

| Field | Default | What it does |
| --- | --- | --- |
| `above_range` | `'warn_nan'` | How to handle incident energies above the file's upper Ein bound. One of `'warn_nan'`, `'nan'`, `'warn_zero'`, `'zero'`, `'raise'`. |
| `resonance_range` | `'warn'` | How to handle Ein inside the resolved-resonance region when `include_resonance=False` (raw MF3 there is a subtractive background and can be negative). One of `'warn'`, `'warn_nan'`, `'nan'`, `'raise'`. Ignored when `include_resonance=True`. |
| `include_resonance` | `True` | Compose the MF2 resolved-resonance reconstruction (MLBW / Reich-Moore / R-Matrix Limited KRM=3 / URR Case C) on top of the MF3 background per the ENDF-6 additive convention. Files without MF2 silently no-op. Set `False` to return raw MF3. |
| `mt5_contrib` | `True` | Whether to redistribute the MT5 catch-all contribution into specific-MT residual queries (via MF6 ZAP tags). Set `False` to drop MT5 entirely from such queries. |
| `include_target` | `False` | Whether `get_residual_production_xs` includes target-conserving channels (MT2 elastic, MT4 / MT51..MT91 inelastic) when the queried residual is the target in its ground state. Default follows the activation-library convention (IRDFF / EAF / NJOY-ACTIVA): channels that de-excite back to the ground state don't count toward "production of the target". Set `True` for the inclusive sum. Isomer queries are unaffected. |
| `backend` | `'auto'` | Numerical backend. `'auto'` picks numpy with opportunistic numba acceleration on MF2 resonance kernels (~30x speedup on actinides). `'numpy'` pure numpy. `'numba'` requires numba (raises at construction if missing). `'jax'` enables end-to-end autodiff and `@jax.jit` (requires jax). Advanced users may pass an `array_ns` adapter object directly. |
| `broadening_mesh_bounds` | `None` | `(emin, emax)` for the internal mesh of the broadening DDX / dxs_dE path. Required under `@jax.jit` with a tracer `energies_out`; otherwise auto. Include the `n_kernel_widths * kernel_width` margin on both sides. |
| `broadening_window_kernel_widths` | `None` | Target span of each windowed sub-convolution inside `adaptive_convolve`, in units of `kernel_width`. Controls memory-vs-compile-time trade-off for broadened DDX / dxs_dE under jit. Default resolves to `200` (concrete grid) or `inf` (tracer). Set `50` for maximum eager-memory savings; `inf` to disable windowing. No effect unless `broadening=` is passed to the entry point. |
| `urr_quadrature` | `'gauss_legendre_32'` | LRU=2 URR fluctuation-integral quadrature. `'gauss_legendre_32'` matches Monte Carlo on the Ï‡Â² integrand to ~1e-7; `'ross_10'` is the NJOY-unresr-parity choice. Only effective when `include_resonance=True` and the file has an LSSF=0 URR range. |
| `aggregation` | `'bottom_up'` | Admission-direction policy for scalar XS queries. `'bottom_up'` combines the most fine-grained MF3 MTs available (pre-#135 default). `'top_down'` uses the most aggregated MF3-tabulated MT that can address the query, avoiding interpolation-grid-mismatch error between separately-tabulated children. Differential APIs always use bottom-up (sum MTs don't carry per-ejectile distributions). |

Validation runs at `RunOptions(...)` construction, so a typo like
`above_range='warn_naan'` raises immediately rather than deep inside
a leaf reader.

### Per-call `broadening=` (not on `RunOptions`)

`get_particle_production_dxs_dE` and `get_particle_production_ddxs`
accept a keyword-only `broadening=None` argument separate from
`options=`. It is a **measurement-resolution kernel** applied to
the full outgoing-energy spectrum: when non-zero, both the
continuum part (convolved along `E_out` via `adaptive_convolve`)
and the **Dirac-delta discrete-line content** (MF12/MF13 discrete
gammas, MF6 LAW=1 ND>0 discrete lines, MF6 LAW=2/3/4/5 two-body
kinematic deltas) are folded with the same kernel and summed.
Without broadening the deltas cannot be represented on a
continuous `energies_out` grid; the default drops them with a
warning. Accepted forms:

| Value | Behavior |
| --- | --- |
| `None` (default) | Continuum returned as-is; discrete-line content dropped; one summary UserWarning per top-level call names the affected MTs. |
| `0` | Same as `None` but the warning is silenced. Use when the user has already acknowledged the drop and wants an unbroadened spectrum. |
| `sigma_eV` (positive float) | Convolve the continuum with a Gaussian kernel of standard deviation `sigma_eV` AND fold each discrete delta with the same Gaussian; add the two contributions. |
| `(kernel, width)` | Same as the positive-float case but with a user-provided kernel. `kernel` is a callable `k(E_rel) -> density` on the detuning axis, `width` is the kernel's effective support (used to size the convolution mesh). |

`broadening=` is a per-call physics knob, not a run-time policy â€”
different queries on the same file want different kernels, so it
lives on the signature rather than on `RunOptions`. The related
jit-safety knobs (`broadening_mesh_bounds`,
`broadening_window_kernel_widths`) stay on `RunOptions` because they
describe the compile-time shape of the convolution mesh, not the
physics of the kernel.

## Examples

Nine runnable examples in `examples/`:

| File | What it shows |
| --- | --- |
| `01_inspect_file.py` | discover what is in a file |
| `02_reaction_xs.py` | cross sections of named channels with consistency check |
| `03_particle_production_xs.py` | secondary-particle production from Fe-56 |
| `04_residual_production_isomers.py` | Co-58g/m and Co-60g/m via (n,2n) and (n,gamma) |
| `05_emission_spectra_14mev.py` | classic 14 MeV neutron emission spectrum from U-238 |
| `06_ddx_uranium_14mev.py` | double-differential cross section heatmap |
| `07_photonuclear_residuals.py` | (g,Nn) cascade on Au-197 |
| `08_policies_and_broadening.py` | the `RunOptions` policy knobs and the `broadening=` Gaussian folder |
| `09_isomer_introspection.py` | enumerate declared residuals and isomer states before querying |

Examples 1-2 use a small file shipped under `tests/data/`. Examples
3-9 each include the `wget` command to fetch the JENDL-5 file(s)
they need.

## Known limitations

- **Resonance reconstruction defaults to on.** Every runtime policy
  lives on `RunOptions` (passed via a keyword-only `options=`
  argument to every `get_*` XS API):
  `options=RunOptions(include_resonance=False)` opts out and returns
  raw MF3. The default `RunOptions()` has `include_resonance=True`
  and composes the resonance reconstruction on top of the MF3
  background per the ENDF-6 additive convention. Raw MF3 for
  evaluations that store the resolved-resonance region (RRR) as a
  **subtractive background** is not the physical cross section and
  can be negative (e.g. JENDL-5 Cu-63 MT1/MT2 tabulate `-0.9 barn`
  at thermal energies); when `include_resonance=False`, one summary
  `UserWarning` per call names the affected MTs and RRR bounds, and
  the `resonance_range` policy on `RunOptions` controls what gets
  written for the in-RRR points (`'warn'` default, `'warn_nan'`,
  `'nan'`, `'raise'`). Supported formalisms: **LRU=1 LRF=2 MLBW**,
  **LRU=1 LRF=3 Reich-Moore**, **LRU=1 LRF=7 R-Matrix Limited
  (KRM=3, KRL=0, IFG=0, NRO=0, KBK=0, KPS=0)**, and **LRU=2 LRF=2
  URR (Case C, INT=2)** with Gauss-Legendre (default) or Ross-10
  fluctuation-integral quadrature (set via `RunOptions(urr_quadrature=...)`).
  Unsupported ranges (Adler-Adler LRF=4, LRF=7 with KRMâ‰ 3 or with
  KBK/KPS/IFG/NRO out of range, URR with non-INT=2 tables)
  contribute zero and a `UserWarning` names the specific formalism.
  All backends supported via `RunOptions(backend=...)` with
  `'auto'` (default), `'numpy'`, `'numba'`, or `'jax'`; JAX
  propagates `jax.grad` to file-side ER / Î“n / Î“Î³ / Î“f leaves.
  For files that pre-process to a full PENDF (e.g. NJOY RECONR
  output), pass the PENDF file in with
  `options=RunOptions(include_resonance=False)`.
- **Aggregate-reaction sum-MT queries under-count on sparse files.**
  `get_reaction_xs("(n,n)")` resolves to MT4 (inelastic-scattering
  sum over MT51..90). The admission heuristic drops the parent MT4
  as soon as any child MT51..90 carries detailed MF4/5/6
  distributions -- correct on well-formed evaluations where the
  full discrete-level series is populated, avoiding double-counting.
  On files with **sparse discrete-level enumeration** where some
  child MT has an MF3 cross section but no MF4/5/6/12/13 detail,
  that child's contribution is silently missed by the query (parent
  is dropped in favour of children, and the missing child falls
  through the escape hatch because its ancestor MT4 IS in MF3). Rare
  in modern ENDF/B-VIII, JEFF-4, TENDL-2021, JENDL-5 evaluations
  that populate the full MT51..90 series. When the pathology hits,
  one summary `UserWarning` per (file, parent) is emitted naming
  the missed children; the numeric answer is unchanged. Query the
  parent MT directly (bypasses the heuristic) or ask for the
  missing child MTs individually to recover the missing
  contribution.
- **MT5 catch-all rescue applies only to unique-path MTs.** When an
  evaluation packages a residual channel into MF6/MT5 (the "any other"
  catch-all) instead of the specific MT for that residual,
  `get_reaction_xs` and `get_residual_production_xs` route the MT5
  contribution to the specific MT so the requested reaction is not
  silently zero. The routing only fires when the specific MT is a
  **unique path** to its residual, meaning the residual is unshared
  with any other MT: gamma emission (MT102), single-proton emission
  (MT103), and neutron multiplication with mult >= 2 (MT16 (n,2n),
  MT17 (n,3n), etc.). Deuteron (MT104), triton (MT105), He-3 (MT106)
  and alpha (MT107) emissions are **not** rescued from MT5 because
  their residual ZA is also produced by multi-particle-exit MTs
  (MT28 (n,np) shares MT104's residual; MT32 (n,nd) and MT41
  (n,2np) share MT105's; MT44 (n,n2p) and MT115 (n,pd) share
  MT106's; MT34 (n,n3He), MT116 (n,pt), MT183 (n,npd) and MT190
  (n,2n2p) share MT107's), and lumping the full MT5 catch-all
  onto the single-ejectile MT would over-count the reaction
  whenever the file also folds those multi-particle paths into
  the same catch-all. Also **not** rescued: discrete-level
  scattering MTs (51..90, 601..648, 651..699, 701..748, 751..798,
  801..848, 851..898), continuum-channel MTs (91, 649, 699, 749,
  799, 849, 899), MT4 for a neutron projectile (single-neutron
  ejectile shared with elastic MT2), or the particle-production sum
  MTs (201..207). Files that carry those reactions only through MT5
  return zero for the specific-MT query with no warning -- an MT5
  catch-all cannot be uniquely apportioned across discrete levels,
  a single-neutron ejectile, or a composite-particle ejectile
  whose residual is shared with other exit channels. Ask for MT5
  directly (or use `get_residual_production_xs` for the specific
  residual, or check `get_available_reactions` first) if the file
  evaluation uses an unenumerated catch-all.
- **DDX drops kinematic-delta channels unless broadened.** The
  double-differential API cannot represent elastic and discrete-level
  inelastic channels on a continuous `Eout` grid (their outgoing
  energy is a Dirac delta at `E' = E'_kin(mu, E_in)`). When called
  with `broadening=None` (the default), the API skips those channels
  and emits a `UserWarning` listing the dropped MTs and pointing at
  the `broadening=sigma_eV` argument that folds each delta into a
  finite-width kernel that plots on the grid. They also appear in
  the 1D `dÏƒ/dE` spectrum as sharp peaks.
- **`sigma` above the file's Ein mesh.** By default,
  `get_reaction_xs` and the other `get_*` XS APIs fill above-range
  incident energies with `NaN` and emit one summary `UserWarning`
  per call. Configure via the `above_range` policy on `RunOptions`
  (`options=RunOptions(above_range='nan')`); accepted values are
  `'warn_nan'` (default), `'nan'`, `'warn_zero'`, `'zero'`, `'raise'`.
- **Unimplemented representations** raise `NotImplementedError`:
  MF14 LTT=2 (tabulated photon angular, blocked upstream in
  `endf_parserpy`'s recipe). MF6 LAW=3 (two-body isotropic in CM),
  LAW=4 (recoil), and LAW=5 (charged-particle elastic with phase
  shift): angular distributions are **supported** via the per-LAW
  reconstructions, but their continuous double-differential path
  (`compute_dist2d_from_subsec`) raises because the outgoing energy
  for these laws is a Dirac delta pinned by two-body kinematics,
  not a tabulated (E', mu) distribution. The DDX pipeline accepts
  LAW=2/3/4/5 subsections and folds the kinematic delta with a
  user `broadening=` kernel when the caller supplies one; without
  `broadening=`, those channels drop with a `UserWarning` (see the
  DDX kinematic-delta note above). MF6 LAW=5 scope: nuclear-amplitude
  Legendre `LTP=1` for both `LIDP=0` (distinguishable particles)
  and `LIDP=1` (identical particles, p+p via manual eq. 6.14 with
  the eq. 6.10 Rutherford formula), plus the `LIDP=0` tabulated
  `LTP in {12, 14, 15}` nuclear-plus-interference forms (manual
  eq. 6.19-6.20), in both the stored CM frame and after a two-body
  elastic CM-to-LAB conversion. `LTP=2` (residual-XS Legendre
  expansion) and the hypothetical `LIDP=1` + tabulated-LTP
  combination (not used in any neutron-adjacent corpus file)
  still raise.
- **Stubs.** `endf_userpy/discrete_quantities.py` and
  `endf_userpy/translation.py` are work-in-progress sketches; do not
  rely on them.

See [CONTRIBUTING.md](CONTRIBUTING.md) for the testing conventions
and per-representation coverage table.

## Filing issues

[github.com/IAEA-NDS/endf-userpy/issues](https://github.com/IAEA-NDS/endf-userpy/issues)

## License and copyright

`endf-userpy` is distributed under the MIT license,
see the `LICENSE` file for details.

Nothing in this license shall be construed as a waiver, either express or implied,
of any of the privileges and immunities accorded to the IAEA by its Member States.

Copyright (c) 2026 International Atomic Energy Agency
