-
Notifications
You must be signed in to change notification settings - Fork 14
[GH#71] Take into account identifier aliases #77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
072a058
ce23a41
71feb5c
81418a1
cd2da9d
99e5dce
ce95f99
a752965
b7d6dbe
beb6f79
698cf9a
235aeee
2bdb6b8
3c1eec3
340ea33
ce50797
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,13 +11,16 @@ enumerated list of options for defining, for example: | |
| a neutron, or a photon. | ||
| - Plasma heating may come from neutral beam injection, electron cyclotron heating, | ||
| ion cyclotron heating, lower hybrid heating, alpha particles. | ||
| - These may have alternative naming conventions supported through aliases | ||
| (e.g., "235U" and "U_235" for Uranium 235). | ||
|
|
||
| Identifiers are a list of possible valid labels. Each label has three | ||
| Identifiers are a list of possible valid labels. Each label has up to four | ||
| representations: | ||
|
|
||
| 1. An index (integer) | ||
| 2. A name (short string) | ||
| 3. A description (long string) | ||
| 4. List of aliases (list of short strings) | ||
|
|
||
|
|
||
| Identifiers in IMAS-Python | ||
|
|
@@ -44,6 +47,14 @@ the available identifiers is stored as ``imas.identifiers.identifiers``. | |
| print(csid.total.index) | ||
| print(csid.total.description) | ||
|
|
||
| # Access identifiers with aliases (when available) | ||
| mid = imas.identifiers.materials_identifier | ||
| print(mid["235U"]) # Access by canonical name | ||
| print(mid["U_235"]) # Access by alias | ||
|
|
||
| # Both return the same object | ||
| assert mid["235U"] is mid["U_235"] | ||
|
|
||
| # Item access is also possible | ||
| print(identifiers["edge_source_identifier"]) | ||
|
|
||
|
|
@@ -64,8 +75,8 @@ Assigning identifiers in IMAS-Python | |
|
|
||
| IMAS-Python implements smart assignment of identifiers. You may assign an identifier | ||
| enum value (for example ``imas.identifiers.core_source_identifier.total``), a | ||
| string (for example ``"total"``) or an integer (for example ``"1"``) to an | ||
| identifier structure (for example ``core_profiles.source[0].identifier``) to set | ||
| string (for example ``"total"`` or its alias), or an integer (for example ``"1"``) | ||
| to an identifier structure (for example ``core_profiles.source[0].identifier``) to set | ||
| all three child nodes ``name``, ``index`` and ``description`` in one go. See | ||
| below example: | ||
|
|
||
|
|
@@ -86,6 +97,15 @@ below example: | |
| # 3. Assign an integer. This looks up the index in the identifier enum: | ||
| core_sources.source[0].identifier = 1 | ||
|
|
||
| # Identifiers can still be assigned with the old alias name for backward compatibility: | ||
| materials = imas.IDSFactory().materials() | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| materials.material.resize(1) | ||
| mid = imas.identifiers.materials_identifier | ||
| # Assign using canonical name | ||
| materials.material[0].identifier = "235U" | ||
| # Or assign using alias (equivalent to above) | ||
| materials.material[0].identifier = "U_235" | ||
|
|
||
| # Inspect the contents of the structure | ||
| imas.util.inspect(core_sources.source[0].identifier) | ||
|
|
||
|
|
@@ -101,18 +121,72 @@ below example: | |
| imas.util.inspect(core_sources.source[1].identifier) | ||
|
|
||
|
|
||
| Identifier aliases | ||
| ------------------ | ||
|
|
||
| Some identifiers may have multiple aliases defined in the Data Dictionary. Aliases are | ||
| former names kept as an option to ensure better backward compatibility after a change | ||
| and support multiple naming conventions. An identifier can have any number of | ||
| comma-separated aliases. | ||
|
|
||
| Aliases can be accessed in the same ways as canonical names, and all aliases for an | ||
| identifier point to the same object. | ||
|
|
||
| Aliases that begin with a number (e.g., 235U) cannot be accessed using dot notation | ||
| (e.g., material_identifier.235U) due to Python's syntax restrictions. Instead, such | ||
| aliases must be accessed using dictionary-style indexing, for example: | ||
| material_identifier["235U"]. | ||
|
|
||
| .. code-block:: python | ||
| :caption: Working with identifier aliases | ||
|
|
||
| import imas | ||
|
|
||
| # Get materials identifier which has some aliases defined | ||
| mid = imas.identifiers.materials_identifier | ||
|
|
||
| # Access by canonical name | ||
| uranium235_by_name = mid["235U"] | ||
| print(f"Name: {uranium235_by_name.name}") | ||
| print(f"Aliases: {uranium235_by_name.aliases}") # List of all aliases | ||
| print(f"First alias: {uranium235_by_name.alias}") # First alias for compatibility | ||
| print(f"Index: {uranium235_by_name.index}") | ||
| print(f"Description: {uranium235_by_name.description}") | ||
|
|
||
| # Access by any alias - all return the same object | ||
| uranium235_by_alias1 = mid["U_235"] | ||
| uranium235_by_alias2 = mid["Uranium_235"] | ||
| print(f"Same objects: {uranium235_by_name is uranium235_by_alias1 is uranium235_by_alias2}") | ||
|
|
||
| # You can also use attribute access for aliases (when valid Python identifiers) | ||
| uranium235_by_attr = mid.U_235 | ||
| print(f"Same object: {uranium235_by_name is uranium235_by_attr}") | ||
|
|
||
| # When assigning to IDS structures, any alias works the same way | ||
| materials = imas.IDSFactory().materials() | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. materials ids is not present in the data dictionary. Could you use wall IDS which uses materials_indentfier. |
||
| materials.material.resize(1) | ||
|
|
||
| # These assignments are all equivalent: | ||
| materials.material[0].identifier = "235U" # canonical name | ||
| materials.material[0].identifier = "U_235" # first alias | ||
| materials.material[0].identifier = "Uranium_235" # another alias | ||
| materials.material[0].identifier = mid["235U"] # enum value | ||
| materials.material[0].identifier = mid.U_235 # enum value via alias | ||
|
|
||
|
|
||
| Compare identifiers | ||
| ------------------- | ||
|
|
||
| Identifier structures can be compared against the identifier enum as well. They | ||
| compare equal when: | ||
|
|
||
| 1. ``index`` is an exact match | ||
| 2. ``name`` is an exact match, or ``name`` is not filled in the IDS node | ||
| 2. ``name`` is an exact match, or ``name`` matches an alias, or ``name`` is not filled in the IDS node | ||
|
|
||
| The ``description`` does not have to match with the Data Dictionary definition, | ||
| but a warning is logged if the description in the IDS node does not match with | ||
| the Data Dictionary description: | ||
| the Data Dictionary description. The comparison also takes aliases into account, | ||
| so an identifier will match both its canonical name and any defined alias: | ||
|
|
||
| .. code-block:: python | ||
| :caption: Comparing identifiers | ||
|
|
@@ -139,6 +213,15 @@ the Data Dictionary description: | |
| >>> core_sources.source[0].identifier.name = "totalX" | ||
| >>> core_sources.source[0].identifier == csid.total | ||
| False | ||
| >>> # Alias comparison example with materials identifier | ||
| >>> mid = imas.identifiers.materials_identifier | ||
| >>> materials = imas.IDSFactory().materials() | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| >>> materials.material.resize(1) | ||
| >>> materials.material[0].identifier.index = 20 | ||
| >>> materials.material[0].identifier.name = "U_235" # Using alias | ||
| >>> # Compares equal to the canonical identifier even though name is alias | ||
| >>> materials.material[0].identifier == mid["235U"] | ||
| True | ||
|
|
||
|
|
||
| .. seealso:: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we always use
nameattribute? In the IDS it stored asstr('materials_identifier.235U')