From d12006f837afd5a31ba9c7d07d56aa452000e12a Mon Sep 17 00:00:00 2001 From: Aadil Latif Date: Wed, 17 Jun 2026 07:23:43 -0600 Subject: [PATCH 1/2] Remove .DS_Store files, add LICENSE, update README/pyproject/__init__ --- LICENSE | 13 +++++++++++++ README.md | 2 +- pyproject.toml | 2 +- src/ditto/__init__.py | 2 +- tests/.DS_Store | Bin 6148 -> 0 bytes .../IEEE13Nodeckt_CIM100x.XML.zip | Bin 0 -> 26822 bytes 6 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 LICENSE delete mode 100644 tests/.DS_Store create mode 100644 tests/data/cim_iec_61968_13/IEEE13Nodeckt_CIM100x.XML.zip diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ed13423 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +BSD-3-Clause License + +Copyright (c) 2018, Alliance for Sustainable Energy LLC, All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md index d625d84..d8a1500 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![PyPI version](https://badge.fury.io/py/NREL-ditto.svg)](https://pypi.org/project/NREL-ditto/) [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD--3--Clause-yellow.svg)](https://opensource.org/license/bsd-3-clause/) [![codecov](https://codecov.io/gh/NLR-Distribution-Suite/ditto/graph/badge.svg?token=1TSI2L9HNR)](https://codecov.io/gh/NLR-Distribution-Suite/ditto) • [![Documentation](https://github.com/NLR-Distribution-Suite/ditto/actions/workflows/gh-pages.yml/badge.svg?branch=main)](https://github.com/NLR-Distribution-Suite/ditto/actions/workflows/gh-pages.yml) . [![pages-build-deployment](https://github.com/NLR-Distribution-Suite/ditto/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/NLR-Distribution-Suite/ditto/actions/workflows/pages/pages-build-deployment) . [![Pytest](https://github.com/NLR-Distribution-Suite/ditto/actions/workflows/pull_request_tests.yml/badge.svg)](https://github.com/NLR-Distribution-Suite/ditto/actions/workflows/pull_request_tests.yml) . [![Upload to PyPi](https://github.com/NLR-Distribution-Suite/ditto/actions/workflows/publish_to_pypi.yaml/badge.svg)](https://github.com/NLR-Distribution-Suite/ditto/actions/workflows/publish_to_pypi.yaml) • [![CodeFactor](https://www.codefactor.io/repository/github/nlr-distribution-suite/ditto/badge)](https://www.codefactor.io/repository/github/nlr-distribution-suite/ditto) • ![MCP Server](https://img.shields.io/badge/MCP_Server-enabled-brightgreen) • ![MCP Tools](https://img.shields.io/badge/MCP_Tools-12-blue) • [![PyPI Downloads](https://static.pepy.tech/personalized-badge/nrel-ditto?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/nrel-ditto) # DiTTo diff --git a/pyproject.toml b/pyproject.toml index f4bf495..9f27de7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ classifiers = [ ] dependencies = [ "opendssdirect.py", - "grid-data-models==2.3.2", + "grid-data-models==2.3.4", "rdflib", "NREL-altdss-schema==0.0.3", "typer", diff --git a/src/ditto/__init__.py b/src/ditto/__init__.py index 3dc1f76..b3f4756 100644 --- a/src/ditto/__init__.py +++ b/src/ditto/__init__.py @@ -1 +1 @@ -__version__ = "0.1.0" +__version__ = "0.1.2" diff --git a/tests/.DS_Store b/tests/.DS_Store deleted file mode 100644 index 07b092c91c4fcfe7aa98bc1412d128d90552604e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHLF-rq682wUDELEf;g5$Y3IjA@Z!YLKO)gMr`6)SjNvF#u(hm*6eA{}&A`~^-5 zj&6d8An4!leMx8&?|SGWBKaVBm*gdR_u3>)iAXH9sxw4IBFZB%dIe-D!R?$9k<&Hf zKq1Gd&<0hgMq5-)uw8|7z&Y^O9N@J(h}BxAIvrr`cGqutcY9{75`}dodFrS)GmJ{5 z&E04djQm-_J1w;D7qi&aAF%5+Q-u`cQ58Cyv|%Z1&ktkHPMfLeZESXB_4bZ68SPya zY3wSJtW+F}^8$^rLe-swoEhWjnT5Wgs2v>jzNC`~6uR6w;2f|W=u^capa09f@BeluS8@(G z2mX}HIuZx-Vui8`GJPD&2R@4Ve+3z6^Z5Z7Xp9x22H}1P NNE=+{9QaiSJ^=zu<&^*c diff --git a/tests/data/cim_iec_61968_13/IEEE13Nodeckt_CIM100x.XML.zip b/tests/data/cim_iec_61968_13/IEEE13Nodeckt_CIM100x.XML.zip new file mode 100644 index 0000000000000000000000000000000000000000..a3e7f8112485b01a38c1b56ed5e8a59ed1e39d96 GIT binary patch literal 26822 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%0A5;1@IV(x~cRKw+f~Ne#i1 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 t_ Date: Wed, 17 Jun 2026 10:16:07 -0600 Subject: [PATCH 2/2] Fix OpenDSS writer and roundtrip conversion --- README.md | 5 ++++- .../controllers/distribution_regulator_controller.py | 4 ++++ src/ditto/writers/opendss/write.py | 7 ++++--- tests/test_opendss/test_roundtrip_conversion.py | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d8a1500..f920f7a 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,9 @@ system = DistributionSystem.from_json(Path("IEEE13NODE.json")) |--------|--------|-------------| | OpenDSS | ✅ Complete | Full support for OpenDSS models | | CIM/IEC 61968-13 | ✅ Complete | Common Information Model support | -| CYME | 🚧 In Progress | CYME network models | +| CYME | ✅ Complete | CYME network models | +| Synergi | 🚧 In Progress | Synergi network models | + ### Writers (Output) @@ -142,6 +144,7 @@ system = DistributionSystem.from_json(Path("IEEE13NODE.json")) |--------|--------|-------------| | OpenDSS | ✅ Complete | Full DSS file generation | | JSON/GDM | ✅ Complete | Serialized GDM format | +| CIM/IEC 61968-13 | ✅ Complete | Common Information Model support | ## Supported Components diff --git a/src/ditto/writers/opendss/controllers/distribution_regulator_controller.py b/src/ditto/writers/opendss/controllers/distribution_regulator_controller.py index b88365c..98043e8 100644 --- a/src/ditto/writers/opendss/controllers/distribution_regulator_controller.py +++ b/src/ditto/writers/opendss/controllers/distribution_regulator_controller.py @@ -16,6 +16,10 @@ def __init__(self, model: RegulatorController, xfmr_name: str, system: Distribut self.model: RegulatorController = model self.xfmr_name = xfmr_name + def map_tapped_winding(self): + # self.system.get_component(component=, name=self.xfmr_name) + self.opendss_dict["Winding"] = self.model.tapped_winding + def map_name(self): self.opendss_dict["Name"] = self.get_opendss_safe_name(self.model.name) self.opendss_dict["Transformer"] = self.get_opendss_safe_name(self.xfmr_name) diff --git a/src/ditto/writers/opendss/write.py b/src/ditto/writers/opendss/write.py index 1cc032b..e7bf75c 100644 --- a/src/ditto/writers/opendss/write.py +++ b/src/ditto/writers/opendss/write.py @@ -85,10 +85,9 @@ def _should_expand_two_phase_transformer(self, model_map: Any) -> bool: if model_map.altdss_composition_name != "Transformer": return False - phases = model_map.opendss_dict.get("Phases") buses = model_map.opendss_dict.get("Bus", []) - if phases != 2 or not buses: - return False + # if phases != 2 or not buses: + # return False phase_tokens = self._get_bus_phase_tokens(buses[0]) phase_tokens = [token for token in phase_tokens if token != "0"] @@ -302,6 +301,7 @@ def write( # noqa controller_map.populate_opendss_dictionary() controller_dss_string = self._get_dss_string(controller_map) controller_outputs.append((controller_map, controller_dss_string)) + break output_folder = output_path output_folder, output_redirect = self._build_directory_structure( @@ -340,6 +340,7 @@ def write( # noqa for model_map_to_write in model_maps_to_write: dss_string = self._get_dss_string(model_map_to_write) + if dss_string.startswith("new Vsource"): dss_string = dss_string.replace("new Vsource", "Clear\n\nNew Circuit") diff --git a/tests/test_opendss/test_roundtrip_conversion.py b/tests/test_opendss/test_roundtrip_conversion.py index de55435..68911a0 100644 --- a/tests/test_opendss/test_roundtrip_conversion.py +++ b/tests/test_opendss/test_roundtrip_conversion.py @@ -34,4 +34,4 @@ def test_opendss_roundtrip_converion(DSS_MODEL, tmp_path): post_converion_metrics = get_metrics(dss_master_file) assert np.allclose( pre_converion_metrics, post_converion_metrics, rtol=0.01, atol=0.01 - ), "Round trip coversion exceeds error tolerance" + ), f"Round trip coversion exceeds error tolerance, \npre: {pre_converion_metrics}, \npost: {post_converion_metrics}"