Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ 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.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.1] - 2026-07-22

This release extends the controlled vocabularies with unit-type information for demand types. The model data itself is unchanged.

### Added
- **Unit types in the demand-type vocabulary:** the new canonical `EDP_TYPES` mapping records each demand type's short acronym and the physical quantity it is measured in (`UnitType`), and the new `UNIT_TYPES` vocabulary enumerates the valid unit types: `acceleration`, `speed`, `displacement`, `unitless`, `rotation`, `force`, `force_per_length`, and `pressure`. Consumers (e.g., Pelicun 3.10+) can infer physical units for demand data from the vocabulary instead of maintaining hardcoded lists.

### Changed
- `EDP_to_demand_type` is now derived from `EDP_TYPES`. Its content is identical to before, so existing consumers are unaffected.

### Distribution
- Version 3.1 is published to PyPI as `simcenter-dlml`. The GitHub repository's `releases/latest` continues to point to v2.1.0 for legacy Pelicun (≤3.9) compatibility.

---

## [3.0] - 2026-07-13

This release turns the library into an installable Python package and adds a programmatic API, a command-line interface, and the DLML Explorer web app. The model data itself is unchanged and remains backward compatible.
Expand Down
1 change: 1 addition & 0 deletions doc/source/release_notes/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Version 3
.. toctree::
:maxdepth: 2

v3.1
v3.0

Version 2
Expand Down
22 changes: 22 additions & 0 deletions doc/source/release_notes/v3.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.. _changes_v3_1:

===========================
Version 3.1 (July 22, 2026)
===========================

This release extends the controlled vocabularies with unit-type information for demand types. The model data itself is unchanged.

Added
-----

- **Unit types in the demand-type vocabulary:** the new canonical ``EDP_TYPES`` mapping records each demand type's short acronym and the physical quantity it is measured in (``UnitType``), and the new ``UNIT_TYPES`` vocabulary enumerates the valid unit types: ``acceleration``, ``speed``, ``displacement``, ``unitless``, ``rotation``, ``force``, ``force_per_length``, and ``pressure``. Consumers (e.g., Pelicun 3.10+) can infer physical units for demand data from the vocabulary instead of maintaining hardcoded lists.

Changed
-------

- ``EDP_to_demand_type`` is now derived from ``EDP_TYPES``. Its content is identical to before, so existing consumers are unaffected.

Distribution
------------

- Version 3.1 is published to PyPI as ``simcenter-dlml``. The GitHub repository's ``releases/latest`` continues to point to v2.1.0 for legacy Pelicun (≤3.9) compatibility.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "simcenter-dlml"
version = "3.1.dev0"
version = "3.1"
description = "Damage and Loss Model Library"
readme = "README.md"
license = { text = "BSD-3-Clause" }
Expand Down
4 changes: 4 additions & 0 deletions src/dlml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
from dlml.vocabulary import (
DEMAND_TYPES,
DISTRIBUTION_FAMILIES,
EDP_TYPES,
UNIT_TYPES,
EDP_to_demand_type,
)

Expand All @@ -32,7 +34,9 @@
'DEMAND_TYPES',
'DISTRIBUTION_FAMILIES',
'DatasetFileNotFoundError',
'EDP_TYPES',
'EDP_to_demand_type',
'UNIT_TYPES',
'UnknownDatasetError',
'__version__',
'available_collections',
Expand Down
106 changes: 67 additions & 39 deletions src/dlml/vocabulary.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

These enumerations are the authoritative definition of the controlled
vocabularies that appear in the packaged model parameters: the demand types a
fragility or loss model may be conditioned on, and the statistical
distribution families a model parameter may use. They are owned here, in the
data library, so a single source of truth governs what the data may contain.
fragility or loss model may be conditioned on, the unit type each demand is
measured in, and the statistical distribution families a model parameter may
use. They are owned here, in the data library, so a single source of truth
governs what the data may contain.

The values mirror pelicun's current definitions -- ``EDP_to_demand_type`` in
``pelicun.base`` and the ``rv_class_map`` registry in ``pelicun.uq`` -- and
Expand All @@ -14,51 +15,78 @@

from __future__ import annotations

#: Mapping from a demand's full descriptive name to its short demand-type
#: code (e.g. ``'Peak Floor Acceleration' -> 'PFA'``). The keys are the
#: demand-type names a model's ``Demand``/``Type`` field may use; a spectral
#: name may additionally carry a ``|<period>`` qualifier in the data, such as
#: The valid unit types a demand may be measured in. A demand type's unit
#: type identifies the physical quantity its values represent (so a consumer
#: can pick the appropriate unit for it); ``'unitless'`` marks dimensionless
#: demands, and ``'rotation'`` marks radian-measured demands that undergo no
#: unit conversion.
UNIT_TYPES: frozenset[str] = frozenset(
{
'acceleration',
'speed',
'displacement',
'unitless',
'rotation',
'force',
'force_per_length',
'pressure',
}
)

#: Mapping from a demand's full descriptive name to its properties: the short
#: demand-type code under ``'Acronym'`` (e.g. ``'Peak Floor Acceleration' ->
#: 'PFA'``) and the physical quantity it is measured in under ``'UnitType'``
#: (one of :data:`UNIT_TYPES`). The keys are the demand-type names a model's
#: ``Demand``/``Type`` field may use. Some demands carry an additional
#: qualifier, such as the period for spectral accelerations as ``|<period>``:
#: ``'Spectral Acceleration|1.0'``.
EDP_to_demand_type: dict[str, str] = { # pelicun-compatible name
EDP_TYPES: dict[str, dict[str, str]] = {
# Drifts
'Story Drift Ratio': 'PID',
'Peak Interstory Drift Ratio': 'PID',
'Roof Drift Ratio': 'PRD',
'Peak Roof Drift Ratio': 'PRD',
'Damageable Wall Drift': 'DWD',
'Racking Drift Ratio': 'RDR',
'Mega Drift Ratio': 'PMD',
'Residual Drift Ratio': 'RID',
'Residual Interstory Drift Ratio': 'RID',
'Peak Effective Drift Ratio': 'EDR',
'Story Drift Ratio': {'Acronym': 'PID', 'UnitType': 'unitless'},
'Peak Interstory Drift Ratio': {'Acronym': 'PID', 'UnitType': 'unitless'},
'Roof Drift Ratio': {'Acronym': 'PRD', 'UnitType': 'unitless'},
'Peak Roof Drift Ratio': {'Acronym': 'PRD', 'UnitType': 'unitless'},
'Damageable Wall Drift': {'Acronym': 'DWD', 'UnitType': 'unitless'},
'Racking Drift Ratio': {'Acronym': 'RDR', 'UnitType': 'unitless'},
'Mega Drift Ratio': {'Acronym': 'PMD', 'UnitType': 'unitless'},
'Residual Drift Ratio': {'Acronym': 'RID', 'UnitType': 'unitless'},
'Residual Interstory Drift Ratio': {'Acronym': 'RID', 'UnitType': 'unitless'},
'Peak Effective Drift Ratio': {'Acronym': 'EDR', 'UnitType': 'unitless'},
# Floor response
'Peak Floor Acceleration': 'PFA',
'Peak Floor Velocity': 'PFV',
'Peak Floor Displacement': 'PFD',
'Peak Floor Acceleration': {'Acronym': 'PFA', 'UnitType': 'acceleration'},
'Peak Floor Velocity': {'Acronym': 'PFV', 'UnitType': 'speed'},
'Peak Floor Displacement': {'Acronym': 'PFD', 'UnitType': 'displacement'},
# Component response
'Peak Link Rotation Angle': 'LR',
'Peak Link Beam Chord Rotation': 'LBR',
'Peak Link Rotation Angle': {'Acronym': 'LR', 'UnitType': 'rotation'},
'Peak Link Beam Chord Rotation': {'Acronym': 'LBR', 'UnitType': 'rotation'},
# Wind Intensity
'Peak Gust Wind Speed': 'PWS',
'Peak Gust Wind Speed': {'Acronym': 'PWS', 'UnitType': 'speed'},
# Wind Demands
'Peak Wind Force': 'PWF',
'Peak Internal Force': 'PIF',
'Peak Line Force': 'PLF',
'Peak Wind Pressure': 'PWP',
'Peak Wind Force': {'Acronym': 'PWF', 'UnitType': 'force'},
'Peak Internal Force': {'Acronym': 'PIF', 'UnitType': 'force'},
'Peak Line Force': {'Acronym': 'PLF', 'UnitType': 'force_per_length'},
'Peak Wind Pressure': {'Acronym': 'PWP', 'UnitType': 'pressure'},
# Inundation Intensity
'Peak Inundation Height': 'PIH',
'Peak Inundation Height': {'Acronym': 'PIH', 'UnitType': 'displacement'},
# Shaking Intensity
'Peak Ground Acceleration': 'PGA',
'Peak Ground Velocity': 'PGV',
'Spectral Acceleration': 'SA',
'Spectral Velocity': 'SV',
'Spectral Displacement': 'SD',
'Peak Spectral Acceleration': 'SA',
'Peak Spectral Velocity': 'SV',
'Peak Spectral Displacement': 'SD',
'Permanent Ground Deformation': 'PGD',
'Peak Ground Acceleration': {'Acronym': 'PGA', 'UnitType': 'acceleration'},
'Peak Ground Velocity': {'Acronym': 'PGV', 'UnitType': 'speed'},
'Spectral Acceleration': {'Acronym': 'SA', 'UnitType': 'acceleration'},
'Spectral Velocity': {'Acronym': 'SV', 'UnitType': 'speed'},
'Spectral Displacement': {'Acronym': 'SD', 'UnitType': 'displacement'},
'Peak Spectral Acceleration': {'Acronym': 'SA', 'UnitType': 'acceleration'},
'Peak Spectral Velocity': {'Acronym': 'SV', 'UnitType': 'speed'},
'Peak Spectral Displacement': {'Acronym': 'SD', 'UnitType': 'displacement'},
'Permanent Ground Deformation': {'Acronym': 'PGD', 'UnitType': 'displacement'},
# Placeholder for advanced calculations
'One': 'ONE',
'One': {'Acronym': 'ONE', 'UnitType': 'unitless'},
}

#: Mapping from a demand's full descriptive name to its short demand-type
#: code, derived from :data:`EDP_TYPES` (e.g.
#: ``'Peak Floor Acceleration' -> 'PFA'``).
EDP_to_demand_type: dict[str, str] = { # pelicun-compatible name
name: info['Acronym'] for name, info in EDP_TYPES.items()
}

#: The valid demand-type names (the keys of :data:`EDP_to_demand_type`). A
Expand Down
47 changes: 47 additions & 0 deletions tests/test_vocabulary.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,51 @@ def test_demand_type_codes_are_nonempty_strings():
)


def test_unit_types_are_the_expected_set():
"""UNIT_TYPES carries exactly the five valid unit types."""
assert (
frozenset(
{
'acceleration',
'speed',
'displacement',
'unitless',
'rotation',
'force',
'force_per_length',
'pressure',
}
)
== vocabulary.UNIT_TYPES
)


def test_edp_types_entries_are_well_formed():
"""Every EDP_TYPES entry has exactly an Acronym and a valid UnitType."""
for name, info in vocabulary.EDP_TYPES.items():
assert set(info) == {'Acronym', 'UnitType'}, name
assert isinstance(info['Acronym'], str)
assert info['Acronym']
assert info['UnitType'] in vocabulary.UNIT_TYPES, name


def test_demand_type_mapping_is_derived_from_edp_types():
"""EDP_to_demand_type is the name-to-acronym projection of EDP_TYPES."""
assert vocabulary.EDP_to_demand_type == {
name: info['Acronym'] for name, info in vocabulary.EDP_TYPES.items()
}
assert list(vocabulary.EDP_to_demand_type) == list(vocabulary.EDP_TYPES)


def test_names_sharing_an_acronym_share_a_unit_type():
"""Two names with the same acronym agree on the unit type, so a consumer
may safely look up units at the acronym level."""
by_acronym: dict[str, str] = {}
for name, info in vocabulary.EDP_TYPES.items():
expected = by_acronym.setdefault(info['Acronym'], info['UnitType'])
assert info['UnitType'] == expected, name


def test_distribution_families_include_the_core_set():
"""The family set carries pelicun's core distributions, incl. the
``deterministic`` default used for an absent family."""
Expand All @@ -70,7 +115,9 @@ def test_vocabulary_is_reexported_from_package():
"""The canonical names are reachable directly from the package root."""
assert dlml.DEMAND_TYPES is vocabulary.DEMAND_TYPES
assert dlml.DISTRIBUTION_FAMILIES is vocabulary.DISTRIBUTION_FAMILIES
assert dlml.EDP_TYPES is vocabulary.EDP_TYPES
assert dlml.EDP_to_demand_type is vocabulary.EDP_to_demand_type
assert dlml.UNIT_TYPES is vocabulary.UNIT_TYPES


# ---------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading