Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
53b1c5a
📝 Update documentation headers and links for clarity
munechika-koyo Jun 26, 2026
52bfdaf
✨ Add blending utilities for core and edge profile functions
munechika-koyo Jul 16, 2026
83458b8
♻️ Refactor cell subset ID handling to use a set
munechika-koyo Jul 27, 2026
2a13487
Fix int(round()) -> round()
munechika-koyo Jul 27, 2026
b479f8f
🏷️ Enhance blend_core_edge_functions with overloads for return3d para…
munechika-koyo Jul 27, 2026
d39aa1b
✨ Add get_ggd_subset_data function for loading GGD-related data
munechika-koyo Jul 27, 2026
3932757
✨ Add grid_radial module and get_ids_numeric_field function for core …
munechika-koyo Jul 27, 2026
4bbb5cd
🔥 Remove unused GridData class and load_core_grid function from core_…
munechika-koyo Jul 27, 2026
f9b060b
♻️ Refactor imports in blend and core modules; update load_equilibriu…
munechika-koyo Jul 27, 2026
345a691
✨ Update radiation module to include EmissivityData class and new loa…
munechika-koyo Jul 27, 2026
33f6461
⚰️ Remove unused imports from radiation_3d notebook
munechika-koyo Jul 27, 2026
de9c058
✨ Enhance load_radiation_emitter function to support dual emissivity …
munechika-koyo Jul 27, 2026
99909b5
🐛 Fix grid data loading checks for radiation core profiles
munechika-koyo Jul 28, 2026
2b842f2
🎨 Add checks for duplicate core and GGD emissivity values in load_rad…
munechika-koyo Jul 28, 2026
7a8901e
✨ Add iter_jintrac_radiation_values function and update dataset registry
munechika-koyo Jul 28, 2026
ac9a233
✨ Add test for synthetic JINTRAC radiation values dataset and enhance…
munechika-koyo Jul 28, 2026
05271a3
📝 Update CHANGELOG
munechika-koyo Jul 28, 2026
c376967
🎨 Format x-axis tick labels for integrated emission spectrum plot
munechika-koyo Aug 1, 2026
ed0ffdf
🐛 Fix type conversion for process identifier in load_radiation_emitte…
munechika-koyo Aug 1, 2026
3dc31d2
🎨 Add primitive name generation for radiation emitter in load_radiati…
munechika-koyo Aug 1, 2026
db620c2
🐛 Fix syntax error in example and ensure integer comparison for grid …
munechika-koyo Aug 1, 2026
235dccb
🎨 Add warning messages for EMPTY_FLOAT in get_ion_state function and …
munechika-koyo Aug 1, 2026
97c4241
🐛 Update return type and default value for return3d parameter in blen…
munechika-koyo Aug 1, 2026
baad36b
🐛 Refactor subset identifier handling to use `subset.identifier.index…
munechika-koyo Aug 1, 2026
a2ceb2b
🐛 Update process identifier handling to use `process.identifier.index…
munechika-koyo Aug 1, 2026
bcb08a4
🐛 Update index assignment to use `element.object[0].index.value` in l…
munechika-koyo Aug 1, 2026
bd8996b
🐛 Fix comparison of grid_subset_index to use direct value instead of …
munechika-koyo Aug 1, 2026
add3d8c
🎨 Add support for IMAS memory backend tests and update related test c…
munechika-koyo Aug 3, 2026
16962b4
📚 Update README
munechika-koyo Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.5.1] - 2026-07-28

### Added

- Add synthetic JINTRAC radiation values dataset support and related regression tests
- Extend radiation emitter loading to support dual emissivity sources with improved validation

### Changed

- Improve radiation emitter loading checks for duplicate emissivity values and core-profile grid data

### Fixed

- Fix grid data loading checks for radiation core profiles
- Improve error handling in radiation emitter loading workflows

## [0.5.0] - 2026-06-24

### Added
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ pip install cherab-imas
mamba install -c conda-forge cherab-imas
```

> [!NOTE]
> Some IMAS features that rely on the memory backend require a working `imas_core` runtime. On platforms where that backend is unavailable (for example, some macOS Intel environments), a subset of tests that exercise those features may be skipped automatically, while the core package functionality remains available.

## 📝 Documentation

See the [official documentation](https://cherab.github.io/imas/) to learn more.
2 changes: 1 addition & 1 deletion docs/notebooks/plasma/4_emission.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@
" title=\"Ray-traced emission spectrum integrated over wavelength bands\",\n",
" ylabel=\"Radiance [W/m²/sr]\",\n",
" xlocator=range(len(wavelength_bands)),\n",
" xticklabels=[f\"{band[0]} – {band[1]}\" for band in wavelength_bands],\n",
" xticklabels=[f\"{band[0]:g} – {band[1]:g}\" for band in wavelength_bands],\n",
")\n",
"\n",
"axs.format(\n",
Expand Down
4 changes: 0 additions & 4 deletions docs/notebooks/radiation/radiation_3d.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,8 @@
"source": [
"import numpy as np\n",
"import ultraplot as uplt\n",
"from imas import DBEntry\n",
"from raysect.optical import World\n",
"from rich import print as rprint\n",
"from rich.table import Table\n",
"\n",
"from cherab.core.math import sample3d_grid\n",
"from cherab.imas.datasets import iter_jorek\n",
"from cherab.imas.emitter import load_radiation_emitter\n",
"\n",
Expand Down
4 changes: 3 additions & 1 deletion docs/source/api.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# API Reference
(api-reference)=

# 📚 API Reference

This page contains auto-generated API reference documentation.

Expand Down
8 changes: 5 additions & 3 deletions docs/source/contributing.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Contributing
(contributing)=

# 🤝 Contributing

We welcome contributions to `cherab-imas`! Whether you're fixing bugs, adding new features, or improving documentation, your help is appreciated.

Expand All @@ -17,7 +19,7 @@ If you encounter any issues or have suggestions for improvements, please open an

### Prerequisites

Development tasks are managed using `pixi`. If you don't have `pixi` installed, please refer to the https://pixi.sh documentation for installation instructions.
Development tasks are managed using `pixi`. If you don't have `pixi` installed, please refer to the <https://pixi.sh> documentation for installation instructions.
Other tools like `git` can be installed globally via `pixi`:

```bash
Expand Down Expand Up @@ -74,7 +76,7 @@ If you want to host the documentation locally, you can do so with:
pixi run doc-serve
```

The documentation will be served at http://localhost:8000.
The documentation will be served at <http://localhost:8000>.

:::
:::{md-tab-item} lint/format
Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ examples.md
```

```{toctree}
:caption: Reference 📖
:caption: Reference
:hidden:
:maxdepth: 1

Expand Down
3 changes: 2 additions & 1 deletion src/cherab/imas/datasets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@
the internet connectivity.
"""

from ._builtin import bolometer_moc
from ._builtin import bolometer_moc, iter_jintrac_radiation_values
from ._fetchers import iter_jintrac, iter_jorek, iter_solps
from ._utils import clear_cache

__all__ = [
"iter_jintrac",
"iter_solps",
"iter_jorek",
"iter_jintrac_radiation_values",
"bolometer_moc",
"clear_cache",
]
114 changes: 114 additions & 0 deletions src/cherab/imas/datasets/_builtin.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
"""Provide functionality to create builtin IMAS sample datasets."""

import datetime
from pathlib import Path

import numpy as np
import pooch
from raysect.core.math import Point3D, Vector3D, rotate_z, to_cylindrical

from imas import DBEntry, IDSFactory
from imas.ids_defs import IDS_TIME_MODE_HOMOGENEOUS
from imas.ids_toplevel import IDSToplevel

from ..ids.common.ggd import load_grid

N_CH = 5 # Number of channels per camera
N_APERTURE = 3 # Number of apertures per channel (for collimator cameras)
Expand All @@ -27,6 +31,79 @@
Y_AXIS = Vector3D(0, 1, 0)


def _iter_jintrac_radiation_values_data() -> tuple[IDSToplevel, IDSToplevel]:
"""Create synthetic radiation/equilibrium IDS objects for values-based emitter tests.

Returns
-------
tuple[IDSToplevel, IDSToplevel]
A pair containing ``(equilibrium_ids, radiation_ids)``.

Raises
------
RuntimeError
If the source JINTRAC dataset does not contain required equilibrium/core/edge data.
"""
from ._fetchers import iter_jintrac

with DBEntry(iter_jintrac(), "r") as entry:
equilibrium = entry.get("equilibrium", autoconvert=False)
core_profiles = entry.get("core_profiles", autoconvert=False)
edge_profiles = entry.get("edge_profiles", autoconvert=False)

if not len(equilibrium.time):
raise RuntimeError("The source equilibrium IDS has no time slices.")
if not len(core_profiles.profiles_1d):
raise RuntimeError("The source core_profiles IDS has no 1D profile data.")
if not len(edge_profiles.grid_ggd):
raise RuntimeError("The source edge_profiles IDS has no GGD grid.")

src_grid = core_profiles.profiles_1d[0].grid
rho_tor_norm = np.asarray(src_grid.rho_tor_norm, dtype=np.float64)
psi = np.asarray(src_grid.psi, dtype=np.float64)

if rho_tor_norm.size == 0 or psi.size == 0:
raise RuntimeError("The source core_profiles grid does not contain psi/rho_tor_norm data.")

radiation = IDSFactory(equilibrium._version).new("radiation")
radiation.ids_properties.homogeneous_time = equilibrium.ids_properties.homogeneous_time
radiation.ids_properties.comment = "Synthetic radiation IDS for CHERAB-IMAS values tests"
radiation.ids_properties.creation_date = datetime.date.today().isoformat()
radiation.time = np.asarray(equilibrium.time, dtype=np.float64)

radiation.grid_ggd.resize(1)
radiation.grid_ggd[0] = edge_profiles.grid_ggd[0]

radiation.process.resize(1)
process = radiation.process[0]
process.identifier.index = 901 # custom emission, referenced: https://imas-data-dictionary.readthedocs.io/en/latest/generated/identifier/radiation_identifier.html
process.identifier.name = "total"
process.profiles_1d.resize(1)
process.profiles_1d[0].grid.rho_tor_norm = rho_tor_norm
process.profiles_1d[0].grid.psi = psi

# Smooth, strictly positive core emissivity profile.
core_values = 2.0e5 * (1.0 - 0.7 * np.clip(rho_tor_norm, 0.0, 1.0) ** 1.5) + 2.0e4
process.profiles_1d[0].electrons.emissivity = core_values

_, subsets, subset_id = load_grid(radiation.grid_ggd[0], with_subsets=True)
subset_name = next((name for name, index in subset_id.items() if index == 5), None)
if subset_name is None:
raise RuntimeError("Unable to find GGD subset id=5 (cells) in source grid_ggd.")

num_cells = len(subsets[subset_name])
if num_cells == 0:
raise RuntimeError("The selected GGD subset (id=5) contains no cells.")

edge_values = np.linspace(4.0e4, 1.0e5, num_cells, dtype=np.float64)
process.ggd.resize(1)
process.ggd[0].electrons.emissivity.resize(1)
process.ggd[0].electrons.emissivity[0].grid_subset_index = 5
process.ggd[0].electrons.emissivity[0].values = edge_values

return equilibrium, radiation


def _bolo_data():
"""
Create a mock bolometer IDS dataset.
Expand Down Expand Up @@ -283,3 +360,40 @@ def bolometer_moc() -> str:
entry.put(ids)

return str(path)


def iter_jintrac_radiation_values() -> str:
"""Return a synthetic radiation dataset for values-based emitter examples/tests.

This builtin dataset is generated from the fetched ``iter_jintrac`` sample and contains:
- one ``equilibrium`` IDS (copied from ``iter_jintrac``), and
- one ``radiation`` IDS with both core-profile emissivity and GGD emissivity values.

.. note::

This dataset is intended for testing and demonstration purposes only, and does not
represent any real physical scenario.

Returns
-------
str
Path to the synthetic dataset file.

Examples
--------
>>> from cherab.imas import datasets
>>> data_path = datasets.iter_jintrac_radiation_values()
>>> data_path
'.../cherab/imas/iter_jintrac_radiation_values.nc'
"""
path = Path(pooch.os_cache("cherab/imas")) / "iter_jintrac_radiation_values.nc"

path.parent.mkdir(parents=True, exist_ok=True)

if not path.exists():
equilibrium, radiation = _iter_jintrac_radiation_values_data()
with DBEntry(str(path), "w", dd_version=equilibrium._version) as entry:
entry.put(equilibrium)
entry.put(radiation)

return str(path)
1 change: 1 addition & 0 deletions src/cherab/imas/datasets/_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
"iter_jintrac": ["iter_scenario_53298_seq1_DD4.nc", "iter_scenario_53298_seq1_DD4_mod.nc"],
"iter_solps": ["iter_scenario_123364_1.nc"],
"iter_jorek": ["iter_disruption_113112_1.nc"],
"iter_jintrac_radiation_values": ["iter_jintrac_radiation_values.nc"],
"bolometer_moc": ["bolometer_moc.nc"],
}
Loading
Loading