diff --git a/message_ix_models/model/transport/files.py b/message_ix_models/model/transport/files.py index 7fc53cf93b..01cf9c2e76 100644 --- a/message_ix_models/model/transport/files.py +++ b/message_ix_models/model/transport/files.py @@ -8,6 +8,7 @@ if TYPE_CHECKING: import genno from genno.core.key import KeyLike + from sdmx.model.common import BaseDataflowDefinition from message_ix_models import Context @@ -86,6 +87,53 @@ def add_tasks( c.add("load_file", path, key=self.key, dims=dims, name=self.key.name) return (self.key,) + def generate_dfd(self) -> "BaseDataflowDefinition": + from importlib.metadata import version + + from ixmp.report.util import get_reversed_rename_dims + from packaging.version import parse + from sdmx.model.common import ConceptScheme + from sdmx.model.v21 import DataflowDefinition, DataStructureDefinition + + from message_ix_models.util.sdmx import read + + # Read the existing agency scheme + ece = read("IIASA_ECE:AGENCIES")["IIASA_ECE"] + name_for_id = self.key.name.upper().replace(" ", "_") + version = parse(version("message_ix_models")).base_version + ma_kwargs = dict(maintainer=ece, version=version) + + # Create a shared concept scheme + cs = ConceptScheme(id="CS_MESSAGE_TRANSPORT", **ma_kwargs) + + # Create a data structure definition + dsd = DataStructureDefinition( + id=f"DS_{name_for_id}", **ma_kwargs, name=self.doc + ) + + # Add dimensions + dims = get_reversed_rename_dims() + for dim in self.key.dims: + # Symbol ('n') → Dimension ID ('node') → upper case + dim_id = dims.get(dim, dim).upper() + + concept = cs.setdefault(id="dim_id") + dsd.dimensions.getdefault(id=dim_id, concept_identity=concept) + + dfd = DataflowDefinition( + id=f"DF_{name_for_id}", **ma_kwargs, name=self.doc, structure=dsd + ) + # TODO Add annotations: preferred file name + + # TODO Generate a CSV template file + # 1. In the current format.abs + # 2. In SDMX-CSV. + # dm = DataMessage() + # dm.data.append(DataSet(structure)) + # template = + + return dfd + ExogenousDataFile( "pdt-cap-ref", diff --git a/message_ix_models/tests/model/transport/test_files.py b/message_ix_models/tests/model/transport/test_files.py index 743adbc993..bd538abc34 100644 --- a/message_ix_models/tests/model/transport/test_files.py +++ b/message_ix_models/tests/model/transport/test_files.py @@ -43,3 +43,8 @@ def test_configure_build( # Dimensions are as expected assert set(Key(result).dims) == set(file.key.dims) + + @pytest.mark.parametrize("file", FILES, ids=lambda f: "-".join(f.parts)) + def test_generate_dfd(self, file) -> None: + dfd = file.generate_dfd() + del dfd