Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
181d198
Update install doc and readme with info on optional deps
olivhoenen Mar 20, 2025
7e45d56
Also apply COCOS 11/17 sign conversion to `dodpsi_like` when converti…
maarten-ic Apr 1, 2025
3f46e3f
Update backend selection logic
maarten-ic Apr 3, 2025
e27d256
Initial logic to implement iterorganization/IMAS-Python#21
maarten-ic Apr 2, 2025
c26bf0b
Restructure pulse_schedule resampling to reuse more existing logic
maarten-ic Apr 3, 2025
25bc4fd
Refactoring and suppress some log messages
maarten-ic Apr 3, 2025
55bd0c6
More refactoring
maarten-ic Apr 3, 2025
0634710
Add documentation
maarten-ic Apr 3, 2025
639adde
Fix typo
maarten-ic Apr 3, 2025
111f650
Extend DD version range to which the pulse schedule conversion applies
maarten-ic Apr 4, 2025
4e42d11
Remove numpy<2 restriction
maarten-ic Apr 15, 2025
f4ebddc
Use datapath with UDA when fetching IDS properties
maarten-ic Apr 23, 2025
12b52e3
Revert "Update backend selection logic"
maarten-ic May 2, 2025
7d810dd
Warn only once for paths that do not exist in the target IDS per conv…
maarten-ic May 21, 2025
09104ac
Add CODEOWNERS
olivhoenen Jun 3, 2025
ff0f628
Add example in doc to list available IDS+occ in a data-entry (#35)
olivhoenen Jun 6, 2025
d0c5c8e
Minor edit
olivhoenen Jun 6, 2025
a03fea7
Apply suggestions on code and text of the documentation
olivhoenen Jun 6, 2025
e35187a
Modify lazy loading test to generate random data without complex numb…
Nush395 Jun 9, 2025
cec6fdd
Remove logic for building the Data Dictionary
maarten-ic Jun 6, 2025
da8b1a6
Update documentation
maarten-ic Jun 6, 2025
fbbedd3
Make saxonche an optional dependency
maarten-ic Jun 11, 2025
0eed64b
Remove Bamboo CI scripts
maarten-ic Jun 11, 2025
1992218
Changelog for release 2.0.1
olivhoenen Jun 18, 2025
60e35d4
Fixup release notes and install doc
olivhoenen Jun 18, 2025
40de236
Fix typo in readme
olivhoenen Jun 18, 2025
540033f
Merge branch 'main' into develop
olivhoenen Jun 18, 2025
e4d5a91
Add example for em_coupling conversion
maarten-ic Jun 25, 2025
7b01446
Add DD 3 to 4 conversion logic
maarten-ic Jul 2, 2025
ddd141f
Fix bugs with ids_convert
maarten-ic Jul 3, 2025
4c50b0f
Use debug log level when multiple alternative coordinates are set
maarten-ic Jul 4, 2025
2d26092
Ensure that 0D numpy arrays are unpacked when filling lazy loaded IDS…
maarten-ic Jul 8, 2025
9446e62
Set access_layer_language to IMAS-Python on put()
maarten-ic Aug 1, 2025
a09186a
Initial implementation of equilibrium DD3to4 conversion for boundary_…
maarten-ic Aug 25, 2025
9a7f8f7
Update python versions used in github actions
maarten-ic Aug 25, 2025
e7e1ca5
Enable tests for Python 3.7 and 3.8
maarten-ic Aug 25, 2025
9b21a4f
Move back to `ubuntu-22.04` as runner
maarten-ic Aug 25, 2025
bcd47fe
Use `ubuntu-latest`, don't test python 3.7
maarten-ic Aug 25, 2025
d3f3793
Update conversion logic to fill equilibrium contour_tree
maarten-ic Aug 28, 2025
83ff945
Fix formatting
maarten-ic Aug 28, 2025
fb8476d
Do not fill contour tree in conversion logic when there is no magneti…
maarten-ic Aug 28, 2025
17d7616
Bypass __setattr__ logic when creating a deepcopy
maarten-ic Aug 26, 2025
3aa96c3
Refactor type hints to use PEP 604 syntax and clean up import statements
munechika-koyo Sep 9, 2025
504b997
Refactor type hints to use pathlib.Path instead of Path for consistency
munechika-koyo Sep 11, 2025
9c7bff5
Clarify that process-db-analysis shows usage across any occurrence of…
maarten-ic Sep 23, 2025
fa0a085
Add new 3to4 conversion rules to change sign of poloidal flux
maarten-ic Sep 25, 2025
e2195e4
Remove psi/ggd/coefficients from COCOS sign flip conversion rule
maarten-ic Sep 26, 2025
14afe29
[GH#59] Convert name/identifier(DD3) to description/name(DD4)
dee-mew Sep 10, 2025
842cde1
Merge branch 'develop' into renaming_3to4_name_identifier
dee-mew Sep 26, 2025
2d4f1de
resolved the lint error for code length limit
dee-mew Sep 29, 2025
a149238
Merge pull request #68 from dee-mew/renaming_3to4_name_identifier
olivhoenen Sep 29, 2025
aa79dcb
Merge branch 'develop' of https://github.com/iterorganization/imas-py…
maarten-ic Sep 29, 2025
85d9037
Update documentation
maarten-ic Sep 29, 2025
7f2e15f
Merge pull request #62 from maarten-ic/feature/dd3to4-boundary-conver…
olivhoenen Sep 29, 2025
59e5e65
Move logged message from critical to warning when imas_core is not av…
olivhoenen Sep 30, 2025
05f858a
Remove code for AL4 from db_entry_al
maarten-ic Oct 7, 2025
82f07eb
Update log messages when using UDA backend
maarten-ic Oct 7, 2025
898ead2
Simplify benchmark logic
maarten-ic Oct 7, 2025
39045fd
Further remove logic for AL4 support
maarten-ic Oct 7, 2025
aa88658
Remove `get_training_imas_db_entry` reference from documentation
maarten-ic Oct 7, 2025
3230a0d
Update UDA warnings and docs
maarten-ic Oct 13, 2025
dc50127
Add warning when a user implicitly converts an IDS between major vers…
maarten-ic Oct 29, 2025
deed79d
Fix min_version_guard when AL-Core is not present
olivhoenen Nov 3, 2025
f84445e
Remove guard as IMAS-Python dropped the AL4 support
olivhoenen Nov 3, 2025
8f1db5f
Disable implicit conversion between major versions of the DD
maarten-ic Nov 13, 2025
d15fe1a
Fix failing test cases
maarten-ic Nov 13, 2025
1e268c0
fix issues in coordinate validation
prasad-sawantdesai Nov 17, 2025
b7bbd8c
first fill the data and check later
prasad-sawantdesai Nov 17, 2025
36d0135
fixed black formatting
prasad-sawantdesai Nov 18, 2025
af759c3
fix comments suggested by Maarten
prasad-sawantdesai Nov 20, 2025
96738c8
Fix issue with fill_consistent and simplify logic
maarten-ic Nov 20, 2025
cf7a590
[GH#71] Take into account identifier aliases (#77)
dee-mew Nov 27, 2025
836798d
Add imas-core dependency
olivhoenen Dec 10, 2025
bade438
Add CSV output option to `imas process-db-analysis` (#85)
maarten-ic Dec 10, 2025
0c38d57
Update changelog for release 2.1.0
olivhoenen Dec 11, 2025
ec033b6
fix sphinx ext_links
olivhoenen Dec 11, 2025
3660a01
remove EOL Python versions from tests
olivhoenen Dec 11, 2025
ef79559
avoid running test on MDSplus when the backend is not available
olivhoenen Dec 11, 2025
72d7ea3
fixup changelog ext links to issues and PRs
olivhoenen Dec 11, 2025
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
6 changes: 2 additions & 4 deletions .github/workflows/test_with_pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ on:

jobs:
test:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] # Test on multiple Python versions
python-version: ["3.10", "3.11", "3.12", "3.13"] # Test on multiple Python versions

steps:
- name: Checkout repository
Expand All @@ -20,8 +20,6 @@ jobs:

uses: actions/setup-python@v4
with:
# until saxonche is available in 3.13
# https://saxonica.plan.io/issues/6561
python-version: ${{ matrix.python-version }}
- name: Display Python version
run: python -c "import sys; print(sys.version)"
Expand Down
103 changes: 49 additions & 54 deletions benchmarks/core_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
available_serializers,
available_slicing_backends,
create_dbentry,
factory,
hlis,
)

N_SLICES = 32
Expand All @@ -26,13 +24,13 @@ def fill_slices(core_profiles, times):
times: time values to fill a slice for
"""
core_profiles.ids_properties.homogeneous_time = 1 # HOMOGENEOUS
core_profiles.ids_properties.comment = "Generated for the IMAS-Python benchmark suite"
core_profiles.ids_properties.comment = (
"Generated for the IMAS-Python benchmark suite"
)
core_profiles.ids_properties.creation_date = datetime.date.today().isoformat()
core_profiles.code.name = "IMAS-Python ASV benchmark"
core_profiles.code.version = imas.__version__
core_profiles.code.repository = (
"https://github.com/iterorganization/IMAS-Python"
)
core_profiles.code.repository = "https://github.com/iterorganization/IMAS-Python"

core_profiles.time = np.array(times)
core_profiles.profiles_1d.resize(len(times))
Expand All @@ -50,13 +48,13 @@ def fill_slices(core_profiles, times):
profiles_1d.ion.resize(len(ions))
profiles_1d.neutral.resize(len(ions))
for i, ion in enumerate(ions):
if hasattr(profiles_1d.ion[i], 'label'):
if hasattr(profiles_1d.ion[i], "label"):
profiles_1d.ion[i].label = ion
profiles_1d.neutral[i].label = ion
if hasattr(profiles_1d.ion[i], 'name'):
if hasattr(profiles_1d.ion[i], "name"):
profiles_1d.ion[i].name = ion
profiles_1d.neutral[i].name = ion

# profiles_1d.ion[i].label = profiles_1d.neutral[i].label = ion
profiles_1d.ion[i].z_ion = 1.0
profiles_1d.ion[i].neutral_index = profiles_1d.neutral[i].ion_index = i + 1
Expand All @@ -70,31 +68,31 @@ def fill_slices(core_profiles, times):


class GetSlice:
params = [hlis, available_slicing_backends]
param_names = ["hli", "backend"]
params = [available_slicing_backends]
param_names = ["backend"]

def setup(self, hli, backend):
self.dbentry = create_dbentry(hli, backend)
core_profiles = factory[hli].core_profiles()
def setup(self, backend):
self.dbentry = create_dbentry(backend)
core_profiles = imas.IDSFactory().core_profiles()
fill_slices(core_profiles, TIME)
self.dbentry.put(core_profiles)

def time_get_slice(self, hli, backend):
def time_get_slice(self, backend):
for t in TIME:
self.dbentry.get_slice("core_profiles", t, imas.ids_defs.CLOSEST_INTERP)

def teardown(self, hli, backend):
def teardown(self, backend):
if hasattr(self, "dbentry"): # imas + netCDF has no dbentry
self.dbentry.close()


class Get:
params = [hlis, available_backends]
param_names = ["hli", "backend"]
params = [available_backends]
param_names = ["backend"]
setup = GetSlice.setup
teardown = GetSlice.teardown

def time_get(self, hli, backend):
def time_get(self, backend):
self.dbentry.get("core_profiles")


Expand All @@ -103,8 +101,8 @@ class LazyGet:
param_names = ["lazy", "backend"]

def setup(self, lazy, backend):
self.dbentry = create_dbentry("imas", backend)
core_profiles = factory["imas"].core_profiles()
self.dbentry = create_dbentry(backend)
core_profiles = imas.IDSFactory().core_profiles()
fill_slices(core_profiles, TIME)
self.dbentry.put(core_profiles)

Expand All @@ -118,75 +116,72 @@ def teardown(self, lazy, backend):


class Generate:
params = [hlis]
param_names = ["hli"]
def setup(self):
self.core_profiles = imas.IDSFactory().core_profiles()

def setup(self, hli):
self.core_profiles = factory[hli].core_profiles()

def time_generate(self, hli):
def time_generate(self):
fill_slices(self.core_profiles, TIME)

def time_generate_slices(self, hli):
def time_generate_slices(self):
for t in TIME:
fill_slices(self.core_profiles, [t])

def time_create_core_profiles(self, hli):
factory[hli].core_profiles()
def time_create_core_profiles(self):
imas.IDSFactory().core_profiles()


class Put:
params = [["0", "1"], hlis, available_backends]
params = [["0", "1"], available_backends]
param_names = ["disable_validate", "hli", "backend"]

def setup(self, disable_validate, hli, backend):
create_dbentry(hli, backend).close() # catch unsupported combinations
self.core_profiles = factory[hli].core_profiles()
def setup(self, disable_validate, backend):
create_dbentry(backend).close() # catch unsupported combinations
self.core_profiles = imas.IDSFactory().core_profiles()
fill_slices(self.core_profiles, TIME)
os.environ["IMAS_AL_DISABLE_VALIDATE"] = disable_validate

def time_put(self, disable_validate, hli, backend):
with create_dbentry(hli, backend) as dbentry:
def time_put(self, disable_validate, backend):
with create_dbentry(backend) as dbentry:
dbentry.put(self.core_profiles)


class PutSlice:
params = [["0", "1"], hlis, available_slicing_backends]
param_names = ["disable_validate", "hli", "backend"]
params = [["0", "1"], available_slicing_backends]
param_names = ["disable_validate", "backend"]

def setup(self, disable_validate, hli, backend):
create_dbentry(hli, backend).close() # catch unsupported combinations
self.core_profiles = factory[hli].core_profiles()
def setup(self, disable_validate, backend):
create_dbentry(backend).close() # catch unsupported combinations
self.core_profiles = imas.IDSFactory().core_profiles()
os.environ["IMAS_AL_DISABLE_VALIDATE"] = disable_validate

def time_put_slice(self, disable_validate, hli, backend):
with create_dbentry(hli, backend) as dbentry:
def time_put_slice(self, disable_validate, backend):
with create_dbentry(backend) as dbentry:
for t in TIME:
fill_slices(self.core_profiles, [t])
dbentry.put_slice(self.core_profiles)


class Serialize:
params = [hlis, available_serializers]
param_names = ["hli", "serializer"]
params = [available_serializers]
param_names = ["serializer"]

def setup(self, hli, serializer):
self.core_profiles = factory[hli].core_profiles()
def setup(self, serializer):
self.core_profiles = imas.IDSFactory().core_profiles()
fill_slices(self.core_profiles, TIME)

def time_serialize(self, hli, serializer):
def time_serialize(self, serializer):
self.core_profiles.serialize(serializer)


class Deserialize:
params = [hlis, available_serializers]
param_names = ["hli", "serializer"]
params = [available_serializers]
param_names = ["serializer"]

def setup(self, hli, serializer):
self.core_profiles = factory[hli].core_profiles()
def setup(self, serializer):
self.core_profiles = imas.IDSFactory().core_profiles()
fill_slices(self.core_profiles, TIME)
self.data = self.core_profiles.serialize(serializer)
self.core_profiles = factory[hli].core_profiles()
self.core_profiles = imas.IDSFactory().core_profiles()

def time_deserialize(self, hli, serializer):
def time_deserialize(self, serializer):
self.core_profiles.deserialize(self.data)
45 changes: 20 additions & 25 deletions benchmarks/edge_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import imas

from .utils import available_backends, create_dbentry, factory, hlis
from .utils import available_backends, create_dbentry

N_POINTS = 600 # number of random R,Z points
N_LINES = 1200 # number of random lines in R,Z plane
Expand All @@ -27,9 +27,7 @@ def fill_ggd(edge_profiles, times):
edge_profiles.ids_properties.creation_date = datetime.date.today().isoformat()
edge_profiles.code.name = "IMAS-Python ASV benchmark"
edge_profiles.code.version = imas.__version__
edge_profiles.code.repository = (
"https://github.com/iterorganization/IMAS-Python"
)
edge_profiles.code.repository = "https://github.com/iterorganization/IMAS-Python"

# This GGD grid is not a valid description, but it's a good stress test for the
# typical access patterns that exist in GGD grids
Expand Down Expand Up @@ -124,45 +122,42 @@ def fill_ggd(edge_profiles, times):


class Get:
params = [hlis, available_backends]
param_names = ["hli", "backend"]
params = [available_backends]
param_names = ["backend"]

def setup(self, hli, backend):
self.dbentry = create_dbentry(hli, backend)
edge_profiles = factory[hli].edge_profiles()
def setup(self, backend):
self.dbentry = create_dbentry(backend)
edge_profiles = imas.IDSFactory().edge_profiles()
fill_ggd(edge_profiles, TIME)
self.dbentry.put(edge_profiles)

def time_get(self, hli, backend):
def time_get(self, backend):
self.dbentry.get("edge_profiles")

def teardown(self, hli, backend):
def teardown(self, backend):
if hasattr(self, "dbentry"): # imas + netCDF has no dbentry
self.dbentry.close()


class Generate:
params = [hlis]
param_names = ["hli"]

def time_generate(self, hli):
edge_profiles = factory[hli].edge_profiles()
def time_generate(self):
edge_profiles = imas.IDSFactory().edge_profiles()
fill_ggd(edge_profiles, TIME)

def time_create_edge_profiles(self, hli):
factory[hli].edge_profiles()
def time_create_edge_profiles(self):
imas.IDSFactory().edge_profiles()


class Put:
params = [["0", "1"], hlis, available_backends]
param_names = ["disable_validate", "hli", "backend"]
params = [["0", "1"], available_backends]
param_names = ["disable_validate", "backend"]

def setup(self, disable_validate, hli, backend):
create_dbentry(hli, backend).close() # catch unsupported combinations
self.edge_profiles = factory[hli].edge_profiles()
def setup(self, disable_validate, backend):
create_dbentry(backend).close() # catch unsupported combinations
self.edge_profiles = imas.IDSFactory().edge_profiles()
fill_ggd(self.edge_profiles, TIME)
os.environ["IMAS_AL_DISABLE_VALIDATE"] = disable_validate

def time_put(self, disable_validate, hli, backend):
with create_dbentry(hli, backend) as dbentry:
def time_put(self, disable_validate, backend):
with create_dbentry(backend) as dbentry:
dbentry.put(self.edge_profiles)
32 changes: 8 additions & 24 deletions benchmarks/utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import importlib
import logging
import uuid
from pathlib import Path

import imas
import imas.exception
import imas.ids_defs

# Backend constants
HDF5 = "HDF5"
Expand Down Expand Up @@ -56,28 +56,12 @@ def backend_exists(backend):
backend for backend in available_backends if backend not in [ASCII, NETCDF]
]

hlis = ["imas"]
DBEntry = {
"imas": imas.DBEntry,
}
factory = {
"imas": imas.IDSFactory(),
}
available_serializers = [imas.ids_defs.ASCII_SERIALIZER_PROTOCOL]

available_serializers = [
imas.ids_defs.ASCII_SERIALIZER_PROTOCOL,
imas.ids_defs.FLEXBUFFERS_SERIALIZER_PROTOCOL,
]

def create_dbentry(hli, backend):
if backend == NETCDF:
if hli == "imas": # check if netcdf backend is available
try:
assert (
imas.DBEntry._select_implementation("x.nc").__name__
== "NCDBEntryImpl"
)
except (AttributeError, AssertionError):
raise NotImplementedError(
"This version of IMAS-Python doesn't implement netCDF."
) from None

path = Path.cwd() / f"DB-{hli}-{backend}"
return DBEntry[hli](create_uri(backend, path), "w")
def create_dbentry(backend):
path = Path.cwd() / f"DB-{backend}"
return imas.DBEntry(create_uri(backend, path), "w")
7 changes: 7 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ def pytest_addoption(parser):
"hdf5": HDF5_BACKEND,
"mdsplus": MDSPLUS_BACKEND,
}
try:
from imas.db_entry import DBEntry
from imas_core.exception import ImasCoreBackendException
DBEntry("imas:mdsplus?path=dummy","r")
except ImasCoreBackendException as iex:
if "not available" in str(iex.message):
_BACKENDS.pop("mdsplus")


try:
Expand Down
Loading
Loading