pandahub 0.3.8__zip → 0.3.10__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pandahub-0.3.8 → pandahub-0.3.10}/CHANGELOG.md +10 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/PKG-INFO +1 -1
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/routers/net.py +3 -2
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/routers/variants.py +18 -8
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/lib/PandaHub.py +240 -128
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub.egg-info/PKG-INFO +1 -1
- {pandahub-0.3.8 → pandahub-0.3.10}/pyproject.toml +1 -1
- {pandahub-0.3.8 → pandahub-0.3.10}/test/performance_test.py +8 -8
- {pandahub-0.3.8 → pandahub-0.3.10}/test/test_networks.py +12 -12
- {pandahub-0.3.8 → pandahub-0.3.10}/test/test_projects.py +2 -2
- {pandahub-0.3.8 → pandahub-0.3.10}/CONTRIBUTING.rst +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/LICENSE +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/MANIFEST.in +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/README.md +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/__init__.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/__init__.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/dependencies.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/internal/__init__.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/internal/db.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/internal/schemas.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/internal/settings.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/internal/toolbox.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/internal/users.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/main.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/routers/__init__.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/routers/auth.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/routers/projects.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/routers/timeseries.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/api/routers/users.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/lib/__init__.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/lib/database_toolbox.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/lib/datatypes.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/lib/mongodb_indexes.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/lib/timeseries/__init__.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/lib/timeseries/data_sources/__init__.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/lib/timeseries/data_sources/mongo_data.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub/lib/timeseries/output_writer_mongodb.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub.egg-info/SOURCES.txt +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub.egg-info/dependency_links.txt +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub.egg-info/requires.txt +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/pandahub.egg-info/top_level.txt +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/requirements.txt +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/setup.cfg +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/setup.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/test/__init__.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/test/conftest.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/test/test_client.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/test/test_timeseries.py +0 -0
- {pandahub-0.3.8 → pandahub-0.3.10}/tutorials/config.py +0 -0
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## [0.3.10]
|
|
4
|
+
|
|
5
|
+
- BREAKING: changed signatures of create_variant function and route
|
|
6
|
+
|
|
7
|
+
## [0.3.9]
|
|
8
|
+
|
|
9
|
+
- BREAKING: inserting multiple networks with the same name does not represent an error anymore, networks are only unique by their net_id (_id field of the collection)
|
|
10
|
+
- BREAKING: passing net_id as str will not remap to the project name internally but look up on the _id field
|
|
11
|
+
- IMPROVED: fix race condition when calling write_network_to_db without net_id
|
|
12
|
+
|
|
3
13
|
## [0.3.8]
|
|
4
14
|
|
|
5
15
|
- BREAKING: specifying variant as list will raise an error instead of a deprecation warning
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pandahub
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.10
|
|
4
4
|
Summary: Data hub for pandapower and pandapipes networks based on MongoDB
|
|
5
5
|
Author-email: Jan Ulffers <jan.ulffers@iee.fraunhofer.de>, Leon Thurner <leon.thurner@retoflow.de>, Jannis Kupka <jannis.kupka@retoflow.de>, Mike Vogt <mike.vogt@iee.fraunhofer.de>, Joschka Thurner <joschka.thurner@retoflow.de>, Alexander Scheidler <alexander.scheidler@iee.fraunhofer.de>
|
|
6
6
|
License: Copyright (c) 2022 by University of Kassel, Fraunhofer Institute for Energy Economics
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Optional, Any
|
|
2
2
|
|
|
3
3
|
import pandapower as pp
|
|
4
|
+
import pandapipes as pps
|
|
4
5
|
from fastapi import APIRouter, Depends
|
|
5
6
|
from pydantic import BaseModel
|
|
6
7
|
|
|
@@ -25,7 +26,7 @@ class GetNetFromDB(BaseModel):
|
|
|
25
26
|
|
|
26
27
|
@router.post("/get_net_from_db")
|
|
27
28
|
def get_net_from_db(data: GetNetFromDB, ph=Depends(pandahub)):
|
|
28
|
-
net = ph.
|
|
29
|
+
net = ph.get_network_by_name(**data.model_dump())
|
|
29
30
|
return pp.to_json(net)
|
|
30
31
|
|
|
31
32
|
|
|
@@ -49,7 +50,7 @@ def write_network_to_db(data: WriteNetwork, ph=Depends(pandahub)):
|
|
|
49
50
|
|
|
50
51
|
class BaseCRUDModel(BaseModel):
|
|
51
52
|
project_id: str
|
|
52
|
-
|
|
53
|
+
net_id: int | str
|
|
53
54
|
element_type: str
|
|
54
55
|
|
|
55
56
|
class GetNetValueModel(BaseCRUDModel):
|
|
@@ -17,7 +17,7 @@ router = APIRouter(
|
|
|
17
17
|
|
|
18
18
|
class GetVariantsModel(BaseModel):
|
|
19
19
|
project_id: str
|
|
20
|
-
net_id: int
|
|
20
|
+
net_id: int | str
|
|
21
21
|
|
|
22
22
|
@router.post("/get_variants")
|
|
23
23
|
def get_variants(data: GetVariantsModel, ph=Depends(pandahub)):
|
|
@@ -30,17 +30,27 @@ def get_variants(data: GetVariantsModel, ph=Depends(pandahub)):
|
|
|
30
30
|
|
|
31
31
|
class CreateVariantModel(BaseModel):
|
|
32
32
|
project_id: str
|
|
33
|
-
|
|
33
|
+
net_id: int
|
|
34
|
+
name: str | None = None
|
|
35
|
+
default_name: str | None = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class CreateVariantResponseModel(BaseModel):
|
|
39
|
+
net_id: int
|
|
40
|
+
index: int
|
|
41
|
+
name: str | None = None
|
|
42
|
+
date_created: int
|
|
43
|
+
date_changed: int
|
|
44
|
+
|
|
34
45
|
|
|
35
46
|
@router.post("/create_variant")
|
|
36
|
-
def create_variant(data: CreateVariantModel, ph=Depends(pandahub)):
|
|
37
|
-
|
|
38
|
-
ph.
|
|
39
|
-
return ph.create_variant(data.variant_data)
|
|
47
|
+
def create_variant(data: CreateVariantModel, ph=Depends(pandahub)) -> CreateVariantResponseModel:
|
|
48
|
+
ph.set_active_project_by_id(data.project_id)
|
|
49
|
+
return ph.create_variant(net_id=data.net_id, name=data.name, default_name=data.default_name)
|
|
40
50
|
|
|
41
51
|
class DeleteVariantModel(BaseModel):
|
|
42
52
|
project_id: str
|
|
43
|
-
net_id: int
|
|
53
|
+
net_id: int | str
|
|
44
54
|
index: int
|
|
45
55
|
|
|
46
56
|
@router.post("/delete_variant")
|
|
@@ -51,7 +61,7 @@ def delete_variant(data: DeleteVariantModel, ph=Depends(pandahub)):
|
|
|
51
61
|
|
|
52
62
|
class UpdateVariantModel(BaseModel):
|
|
53
63
|
project_id: str
|
|
54
|
-
net_id: int
|
|
64
|
+
net_id: int | str
|
|
55
65
|
index: int
|
|
56
66
|
data: dict
|
|
57
67
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import builtins
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
|
+
import time
|
|
5
6
|
import warnings
|
|
6
7
|
from inspect import signature, _empty
|
|
7
8
|
from collections.abc import Callable
|
|
@@ -16,7 +17,7 @@ from functools import reduce
|
|
|
16
17
|
from operator import getitem
|
|
17
18
|
from uuid import UUID
|
|
18
19
|
from pymongo import MongoClient, ReplaceOne
|
|
19
|
-
from pymongo.errors import ServerSelectionTimeoutError
|
|
20
|
+
from pymongo.errors import ServerSelectionTimeoutError, DuplicateKeyError
|
|
20
21
|
|
|
21
22
|
import pandapipes as pps
|
|
22
23
|
from pandapipes import from_json_string as from_json_pps, FromSerializableRegistryPpipe
|
|
@@ -91,6 +92,7 @@ class PandaHub:
|
|
|
91
92
|
user_id=None,
|
|
92
93
|
datatypes=DATATYPES,
|
|
93
94
|
mongodb_indexes=MONGODB_INDEXES,
|
|
95
|
+
elements_without_vars = None,
|
|
94
96
|
):
|
|
95
97
|
mongo_client_args = {
|
|
96
98
|
"host": connection_url,
|
|
@@ -115,6 +117,7 @@ class PandaHub:
|
|
|
115
117
|
{"var_type": np.nan},
|
|
116
118
|
]
|
|
117
119
|
}
|
|
120
|
+
self._elements_without_vars = ["variant"] if elements_without_vars is None else elements_without_vars
|
|
118
121
|
if check_server_available:
|
|
119
122
|
self.server_is_available()
|
|
120
123
|
|
|
@@ -707,7 +710,8 @@ class PandaHub:
|
|
|
707
710
|
db = self._get_project_database()
|
|
708
711
|
return list(db["_networks"].find())
|
|
709
712
|
|
|
710
|
-
|
|
713
|
+
|
|
714
|
+
def get_network_by_name(
|
|
711
715
|
self,
|
|
712
716
|
name,
|
|
713
717
|
include_results=True,
|
|
@@ -721,16 +725,16 @@ class PandaHub:
|
|
|
721
725
|
self.set_active_project_by_id(project_id)
|
|
722
726
|
self.check_permission("read")
|
|
723
727
|
db = self._get_project_database()
|
|
724
|
-
|
|
725
|
-
if
|
|
728
|
+
net_id = self._get_net_id_from_name(name, db)
|
|
729
|
+
if net_id is None:
|
|
726
730
|
return None
|
|
727
|
-
return self.
|
|
728
|
-
|
|
731
|
+
return self.get_network(
|
|
732
|
+
net_id, include_results, only_tables, geo_mode=geo_mode, variant=variant, convert=convert
|
|
729
733
|
)
|
|
730
734
|
|
|
731
|
-
def
|
|
735
|
+
def get_network(
|
|
732
736
|
self,
|
|
733
|
-
|
|
737
|
+
net_id,
|
|
734
738
|
include_results=True,
|
|
735
739
|
only_tables=None,
|
|
736
740
|
convert=True,
|
|
@@ -739,7 +743,7 @@ class PandaHub:
|
|
|
739
743
|
):
|
|
740
744
|
self.check_permission("read")
|
|
741
745
|
return self._get_net_from_db_by_id(
|
|
742
|
-
|
|
746
|
+
net_id,
|
|
743
747
|
include_results,
|
|
744
748
|
only_tables,
|
|
745
749
|
convert=convert,
|
|
@@ -749,7 +753,7 @@ class PandaHub:
|
|
|
749
753
|
|
|
750
754
|
def _get_net_from_db_by_id(
|
|
751
755
|
self,
|
|
752
|
-
|
|
756
|
+
net_id,
|
|
753
757
|
include_results=True,
|
|
754
758
|
only_tables=None,
|
|
755
759
|
convert=True,
|
|
@@ -757,20 +761,20 @@ class PandaHub:
|
|
|
757
761
|
variant=None,
|
|
758
762
|
):
|
|
759
763
|
db = self._get_project_database()
|
|
760
|
-
meta = self._get_network_metadata(db,
|
|
764
|
+
meta = self._get_network_metadata(db, net_id)
|
|
761
765
|
|
|
762
766
|
package = pp if meta.get("sector", "power") == "power" else pps
|
|
763
767
|
net = package.create_empty_network()
|
|
764
768
|
|
|
765
769
|
# add all elements that are stored as dataframes
|
|
766
|
-
collection_names = self.
|
|
770
|
+
collection_names = self.get_net_collections(db)
|
|
767
771
|
for collection_name in collection_names:
|
|
768
772
|
el = self._element_name_of_collection(collection_name)
|
|
769
773
|
self._add_element_from_collection(
|
|
770
774
|
net,
|
|
771
775
|
db,
|
|
772
776
|
el,
|
|
773
|
-
|
|
777
|
+
net_id,
|
|
774
778
|
include_results=include_results,
|
|
775
779
|
only_tables=only_tables,
|
|
776
780
|
geo_mode=geo_mode,
|
|
@@ -797,7 +801,8 @@ class PandaHub:
|
|
|
797
801
|
value = json.loads(value[11:], cls=io_pp.PPJSONDecoder, registry_class=registry)
|
|
798
802
|
net[key] = value
|
|
799
803
|
|
|
800
|
-
|
|
804
|
+
|
|
805
|
+
def get_subnet_by_name(
|
|
801
806
|
self,
|
|
802
807
|
name,
|
|
803
808
|
bus_filter=None,
|
|
@@ -811,11 +816,11 @@ class PandaHub:
|
|
|
811
816
|
):
|
|
812
817
|
self.check_permission("read")
|
|
813
818
|
db = self._get_project_database()
|
|
814
|
-
|
|
815
|
-
if
|
|
819
|
+
net_id = self._get_net_id_from_name(name, db)
|
|
820
|
+
if net_id is None:
|
|
816
821
|
return None
|
|
817
|
-
return self.
|
|
818
|
-
|
|
822
|
+
return self.get_subnet(
|
|
823
|
+
net_id,
|
|
819
824
|
bus_filter=bus_filter,
|
|
820
825
|
include_results=include_results,
|
|
821
826
|
add_edge_branches=add_edge_branches,
|
|
@@ -824,7 +829,7 @@ class PandaHub:
|
|
|
824
829
|
additional_filters=additional_filters,
|
|
825
830
|
)
|
|
826
831
|
|
|
827
|
-
def
|
|
832
|
+
def get_subnet(
|
|
828
833
|
self,
|
|
829
834
|
net_id,
|
|
830
835
|
bus_filter=None,
|
|
@@ -1034,7 +1039,7 @@ class PandaHub:
|
|
|
1034
1039
|
)
|
|
1035
1040
|
|
|
1036
1041
|
# add all other collections
|
|
1037
|
-
collection_names = self.
|
|
1042
|
+
collection_names = self.get_net_collections(db)
|
|
1038
1043
|
for collection in collection_names:
|
|
1039
1044
|
table_name = self._element_name_of_collection(collection)
|
|
1040
1045
|
# skip all element tables that we have already added
|
|
@@ -1072,33 +1077,67 @@ class PandaHub:
|
|
|
1072
1077
|
|
|
1073
1078
|
def write_network_to_db(
|
|
1074
1079
|
self,
|
|
1075
|
-
net,
|
|
1076
|
-
name,
|
|
1080
|
+
net: pp.pandapowerNet | pps.pandapipesNet,
|
|
1081
|
+
name: str,
|
|
1077
1082
|
sector="power",
|
|
1078
|
-
overwrite=True,
|
|
1079
|
-
project_id=None,
|
|
1080
|
-
metadata=None,
|
|
1081
|
-
skip_results=False,
|
|
1082
|
-
net_id=None,
|
|
1083
|
-
):
|
|
1083
|
+
overwrite: bool = True,
|
|
1084
|
+
project_id: str = None,
|
|
1085
|
+
metadata: dict = None,
|
|
1086
|
+
skip_results: bool = False,
|
|
1087
|
+
net_id: int | str = None,
|
|
1088
|
+
) -> dict:
|
|
1089
|
+
"""
|
|
1090
|
+
Write a pandapower or pandapipes network to the database.
|
|
1091
|
+
|
|
1092
|
+
A network is uniquely identified only by its net_id (multiple networks with the same name are allowed).
|
|
1093
|
+
If no net_id is passed, an incrementing integer id is generated.
|
|
1094
|
+
Raises an error if a passed net_id already exists in the database unless overwrite is set to True.
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
Parameters
|
|
1098
|
+
----------
|
|
1099
|
+
net:
|
|
1100
|
+
pandapower or pandapipes network
|
|
1101
|
+
name:
|
|
1102
|
+
name of the network
|
|
1103
|
+
sector:
|
|
1104
|
+
sector of the network
|
|
1105
|
+
overwrite:
|
|
1106
|
+
if True, an existing network with the same net_id will be overwritten
|
|
1107
|
+
project_id:
|
|
1108
|
+
id of the project (defaults to active project)
|
|
1109
|
+
metadata:
|
|
1110
|
+
additional metadata to be stored with the network
|
|
1111
|
+
skip_results:
|
|
1112
|
+
if True, results tables are not stored in the database
|
|
1113
|
+
net_id:
|
|
1114
|
+
id of the network. If None, a new integer id is generated
|
|
1115
|
+
|
|
1116
|
+
Returns
|
|
1117
|
+
-------
|
|
1118
|
+
dict
|
|
1119
|
+
metadata of the created network
|
|
1120
|
+
"""
|
|
1084
1121
|
if project_id:
|
|
1085
1122
|
self.set_active_project_by_id(project_id)
|
|
1086
1123
|
self.check_permission("write")
|
|
1087
1124
|
db = self._get_project_database()
|
|
1088
|
-
|
|
1089
|
-
# if not isinstance(net, pp.pandapowerNet) and not isinstance(net, pps.pandapipesNet):
|
|
1090
|
-
# raise PandaHubError("net must be a pandapower or pandapipes object")
|
|
1091
|
-
|
|
1092
|
-
if self._network_with_name_exists(name, db):
|
|
1093
|
-
if overwrite:
|
|
1094
|
-
self.delete_net_from_db(name)
|
|
1095
|
-
else:
|
|
1096
|
-
raise PandaHubError("Network name already exists")
|
|
1125
|
+
networks_coll = db["_networks"]
|
|
1097
1126
|
|
|
1098
1127
|
if net_id is None:
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1128
|
+
net_id = self._get_int_index("_networks")
|
|
1129
|
+
else:
|
|
1130
|
+
try:
|
|
1131
|
+
networks_coll.insert_one({"_id": net_id})
|
|
1132
|
+
except DuplicateKeyError:
|
|
1133
|
+
if overwrite:
|
|
1134
|
+
self.delete_network(net_id)
|
|
1135
|
+
networks_coll.insert_one({"_id": net_id})
|
|
1136
|
+
else:
|
|
1137
|
+
msg = f"Network with net_id {net_id} already exists"
|
|
1138
|
+
raise PandaHubError(msg)
|
|
1139
|
+
|
|
1140
|
+
networks_coll.update_one({"_id": net_id}, {"$set": {"name": name, "sector": sector}})
|
|
1102
1141
|
|
|
1103
1142
|
data = {}
|
|
1104
1143
|
dtypes = {}
|
|
@@ -1114,10 +1153,13 @@ class PandaHub:
|
|
|
1114
1153
|
if element_data.empty:
|
|
1115
1154
|
continue
|
|
1116
1155
|
element_data = element_data.copy(deep=True)
|
|
1117
|
-
if
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1156
|
+
if element not in self._elements_without_vars:
|
|
1157
|
+
if "var_type" in element_data:
|
|
1158
|
+
element_data["var_type"] = element_data["var_type"].fillna("base")
|
|
1159
|
+
else:
|
|
1160
|
+
element_data["var_type"] = "base"
|
|
1161
|
+
element_data["not_in_var"] = np.empty((len(element_data.index), 0)).tolist()
|
|
1162
|
+
element_data["variant"] = None
|
|
1121
1163
|
element_data = convert_element_to_dict(element_data, net_id, self._datatypes.get(element))
|
|
1122
1164
|
self._write_element_to_db(db, element, element_data)
|
|
1123
1165
|
|
|
@@ -1128,14 +1170,12 @@ class PandaHub:
|
|
|
1128
1170
|
|
|
1129
1171
|
# write network metadata
|
|
1130
1172
|
network_data = {
|
|
1131
|
-
"name": name,
|
|
1132
|
-
"sector": sector,
|
|
1133
1173
|
"dtypes": dtypes,
|
|
1134
1174
|
"data": data,
|
|
1135
1175
|
}
|
|
1136
1176
|
if metadata is not None:
|
|
1137
1177
|
network_data.update(metadata)
|
|
1138
|
-
|
|
1178
|
+
networks_coll.update_one({"_id": net_id}, {"$set": network_data})
|
|
1139
1179
|
return network_data | {"_id": net_id}
|
|
1140
1180
|
|
|
1141
1181
|
def _write_net_collections_to_db(self, db, collections):
|
|
@@ -1151,16 +1191,22 @@ class PandaHub:
|
|
|
1151
1191
|
db[collection_name].insert_many(element_data, ordered=False)
|
|
1152
1192
|
# print(f"\nFAILED TO WRITE TABLE '{element_type}' TO DATABASE! (details above)")
|
|
1153
1193
|
|
|
1154
|
-
def
|
|
1155
|
-
|
|
1194
|
+
def delete_network(self, net_id):
|
|
1195
|
+
if net_id is None:
|
|
1196
|
+
raise PandaHubError(f"No net_id was passed", 404)
|
|
1156
1197
|
db = self._get_project_database()
|
|
1157
|
-
|
|
1158
|
-
if _id is None:
|
|
1159
|
-
raise PandaHubError("Network does not exist", 404)
|
|
1160
|
-
collection_names = self._get_net_collections(db) # TODO
|
|
1198
|
+
collection_names = self.get_net_collections(db)
|
|
1161
1199
|
for collection_name in collection_names:
|
|
1162
|
-
db[collection_name].delete_many({"net_id":
|
|
1163
|
-
db["_networks"].delete_one({"_id":
|
|
1200
|
+
db[collection_name].delete_many({"net_id": net_id})
|
|
1201
|
+
db["_networks"].delete_one({"_id": net_id})
|
|
1202
|
+
|
|
1203
|
+
def delete_network_by_name(self, name):
|
|
1204
|
+
self.check_permission("write")
|
|
1205
|
+
db = self._get_project_database()
|
|
1206
|
+
net_id = self._get_net_id_from_name(name, db)
|
|
1207
|
+
if net_id is None:
|
|
1208
|
+
raise PandaHubError(f"Network with name {name} does not exist", 404)
|
|
1209
|
+
self.delete_network(net_id)
|
|
1164
1210
|
|
|
1165
1211
|
def network_with_name_exists(self, name):
|
|
1166
1212
|
self.check_permission("read")
|
|
@@ -1177,19 +1223,23 @@ class PandaHub:
|
|
|
1177
1223
|
nets = pd.DataFrame(list(db.find(fi, projection=proj)))
|
|
1178
1224
|
return nets
|
|
1179
1225
|
|
|
1180
|
-
def
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
def _get_id_from_name(self, name, db):
|
|
1184
|
-
metadata = self._get_metadata_from_name(name, db)
|
|
1226
|
+
def _get_net_id_from_name(self, name, db):
|
|
1227
|
+
metadata = list(db["_networks"].find({"name": name}))
|
|
1185
1228
|
if len(metadata) > 1:
|
|
1186
|
-
|
|
1229
|
+
msg = (f"Multiple networks with the name {metadata[0]['name']} found in the database. "
|
|
1230
|
+
f"Use the corresponding function which selects the network by net_id instead.")
|
|
1231
|
+
raise PandaHubError(msg)
|
|
1187
1232
|
return None if len(metadata) == 0 else metadata[0]["_id"]
|
|
1188
1233
|
|
|
1189
1234
|
def _network_with_name_exists(self, name, db):
|
|
1190
|
-
return self.
|
|
1235
|
+
return self._get_net_id_from_name(name, db) is not None
|
|
1191
1236
|
|
|
1192
1237
|
def _get_net_collections(self, db, with_areas=True):
|
|
1238
|
+
return self.get_net_collections(db, with_areas)
|
|
1239
|
+
|
|
1240
|
+
def get_net_collections(self, db=None, with_areas=True):
|
|
1241
|
+
if db is None:
|
|
1242
|
+
db = self.get_project_database()
|
|
1193
1243
|
if with_areas:
|
|
1194
1244
|
collection_filter = {"name": {"$regex": "^net_"}}
|
|
1195
1245
|
else:
|
|
@@ -1268,16 +1318,12 @@ class PandaHub:
|
|
|
1268
1318
|
# -------------------------
|
|
1269
1319
|
|
|
1270
1320
|
def get_net_value_from_db(
|
|
1271
|
-
self,
|
|
1321
|
+
self, net_id, element_type, element_index, parameter, variant=None, project_id=None
|
|
1272
1322
|
):
|
|
1273
1323
|
if project_id:
|
|
1274
1324
|
self.set_active_project_by_id(project_id)
|
|
1275
1325
|
self.check_permission("write")
|
|
1276
1326
|
db = self._get_project_database()
|
|
1277
|
-
if isinstance(net, str):
|
|
1278
|
-
net_id = self._get_id_from_name(net, db)
|
|
1279
|
-
else:
|
|
1280
|
-
net_id = net
|
|
1281
1327
|
|
|
1282
1328
|
collection = self._collection_name_of_element(element_type)
|
|
1283
1329
|
dtypes = self._datatypes.get(element_type)
|
|
@@ -1303,14 +1349,14 @@ class PandaHub:
|
|
|
1303
1349
|
return document[parameter]
|
|
1304
1350
|
|
|
1305
1351
|
def delete_element(
|
|
1306
|
-
self,
|
|
1352
|
+
self, net_id, element_type, element_index, variant=None, project_id=None, **kwargs
|
|
1307
1353
|
) -> dict:
|
|
1308
1354
|
"""
|
|
1309
1355
|
Delete an element from the database.
|
|
1310
1356
|
|
|
1311
1357
|
Parameters
|
|
1312
1358
|
----------
|
|
1313
|
-
|
|
1359
|
+
net_id: str or int
|
|
1314
1360
|
Network to add elements to, either a name or numeric id
|
|
1315
1361
|
element_type: str
|
|
1316
1362
|
Name of the element type (e.g. bus, line)
|
|
@@ -1326,7 +1372,7 @@ class PandaHub:
|
|
|
1326
1372
|
The deleted element as dict with all fields
|
|
1327
1373
|
"""
|
|
1328
1374
|
return self.delete_elements(
|
|
1329
|
-
|
|
1375
|
+
net_id=net_id,
|
|
1330
1376
|
element_type=element_type,
|
|
1331
1377
|
element_indexes=[element_index],
|
|
1332
1378
|
variant=variant,
|
|
@@ -1336,7 +1382,7 @@ class PandaHub:
|
|
|
1336
1382
|
|
|
1337
1383
|
def delete_elements(
|
|
1338
1384
|
self,
|
|
1339
|
-
|
|
1385
|
+
net_id: Union[int, str],
|
|
1340
1386
|
element_type: str,
|
|
1341
1387
|
element_indexes: list[int],
|
|
1342
1388
|
variant: Union[int, None] = None,
|
|
@@ -1348,7 +1394,7 @@ class PandaHub:
|
|
|
1348
1394
|
|
|
1349
1395
|
Parameters
|
|
1350
1396
|
----------
|
|
1351
|
-
|
|
1397
|
+
net_id: str or int
|
|
1352
1398
|
Network to add elements to, either a name or numeric id
|
|
1353
1399
|
element_type: str
|
|
1354
1400
|
Name of the element type (e.g. bus, line)
|
|
@@ -1365,7 +1411,7 @@ class PandaHub:
|
|
|
1365
1411
|
"""
|
|
1366
1412
|
if not isinstance(element_indexes, list):
|
|
1367
1413
|
raise TypeError("Parameter element_indexes must be a list of ints!")
|
|
1368
|
-
|
|
1414
|
+
self.validate_variant(variant, element_type)
|
|
1369
1415
|
if project_id:
|
|
1370
1416
|
self.set_active_project_by_id(project_id)
|
|
1371
1417
|
|
|
@@ -1373,11 +1419,6 @@ class PandaHub:
|
|
|
1373
1419
|
db = self._get_project_database()
|
|
1374
1420
|
collection = self._collection_name_of_element(element_type)
|
|
1375
1421
|
|
|
1376
|
-
if isinstance(net, str):
|
|
1377
|
-
net_id = self._get_id_from_name(net, db)
|
|
1378
|
-
else:
|
|
1379
|
-
net_id = net
|
|
1380
|
-
|
|
1381
1422
|
element_filter = {
|
|
1382
1423
|
"index": {"$in": element_indexes},
|
|
1383
1424
|
"net_id": int(net_id),
|
|
@@ -1405,7 +1446,7 @@ class PandaHub:
|
|
|
1405
1446
|
|
|
1406
1447
|
def set_net_value_in_db(
|
|
1407
1448
|
self,
|
|
1408
|
-
|
|
1449
|
+
net_id,
|
|
1409
1450
|
element_type,
|
|
1410
1451
|
element_index,
|
|
1411
1452
|
parameter,
|
|
@@ -1414,7 +1455,7 @@ class PandaHub:
|
|
|
1414
1455
|
project_id=None,
|
|
1415
1456
|
**kwargs,
|
|
1416
1457
|
):
|
|
1417
|
-
|
|
1458
|
+
self.validate_variant(variant, element_type)
|
|
1418
1459
|
if project_id:
|
|
1419
1460
|
self.set_active_project_by_id(project_id)
|
|
1420
1461
|
self.check_permission("write")
|
|
@@ -1423,10 +1464,6 @@ class PandaHub:
|
|
|
1423
1464
|
if value is not None and dtypes is not None and parameter in dtypes:
|
|
1424
1465
|
value = dtypes[parameter](value)
|
|
1425
1466
|
collection = self._collection_name_of_element(element_type)
|
|
1426
|
-
if isinstance(net, str):
|
|
1427
|
-
net_id = self._get_id_from_name(net, db)
|
|
1428
|
-
else:
|
|
1429
|
-
net_id = net
|
|
1430
1467
|
element_filter = {
|
|
1431
1468
|
"index": element_index,
|
|
1432
1469
|
"net_id": int(net_id),
|
|
@@ -1478,7 +1515,7 @@ class PandaHub:
|
|
|
1478
1515
|
|
|
1479
1516
|
def set_object_attribute(
|
|
1480
1517
|
self,
|
|
1481
|
-
|
|
1518
|
+
net_id,
|
|
1482
1519
|
element_type,
|
|
1483
1520
|
element_index,
|
|
1484
1521
|
parameter,
|
|
@@ -1486,7 +1523,7 @@ class PandaHub:
|
|
|
1486
1523
|
variant=None,
|
|
1487
1524
|
project_id=None,
|
|
1488
1525
|
):
|
|
1489
|
-
|
|
1526
|
+
self.validate_variant(variant, element_type)
|
|
1490
1527
|
if project_id:
|
|
1491
1528
|
self.set_active_project_by_id(project_id)
|
|
1492
1529
|
self.check_permission("write")
|
|
@@ -1495,10 +1532,6 @@ class PandaHub:
|
|
|
1495
1532
|
if dtypes is not None and parameter in dtypes:
|
|
1496
1533
|
value = dtypes[parameter](value)
|
|
1497
1534
|
collection = self._collection_name_of_element(element_type)
|
|
1498
|
-
if isinstance(net, str):
|
|
1499
|
-
net_id = self._get_id_from_name(net, db)
|
|
1500
|
-
else:
|
|
1501
|
-
net_id = net
|
|
1502
1535
|
|
|
1503
1536
|
js = list(db[collection].find({"index": element_index, "net_id": net_id}))[0]
|
|
1504
1537
|
obj = json_to_object(js["object"])
|
|
@@ -1544,7 +1577,7 @@ class PandaHub:
|
|
|
1544
1577
|
|
|
1545
1578
|
def create_element(
|
|
1546
1579
|
self,
|
|
1547
|
-
|
|
1580
|
+
net_id: Union[int, str],
|
|
1548
1581
|
element_type: str,
|
|
1549
1582
|
element_index: int,
|
|
1550
1583
|
element_data: dict,
|
|
@@ -1557,7 +1590,7 @@ class PandaHub:
|
|
|
1557
1590
|
|
|
1558
1591
|
Parameters
|
|
1559
1592
|
----------
|
|
1560
|
-
|
|
1593
|
+
net_id: str or int
|
|
1561
1594
|
Network to add elements to, either as name or numeric id
|
|
1562
1595
|
element_type: str
|
|
1563
1596
|
Name of the element type (e.g. bus, line)
|
|
@@ -1575,7 +1608,7 @@ class PandaHub:
|
|
|
1575
1608
|
The created element (element_data with added _id field)
|
|
1576
1609
|
"""
|
|
1577
1610
|
return self.create_elements(
|
|
1578
|
-
|
|
1611
|
+
net_id=net_id,
|
|
1579
1612
|
element_type=element_type,
|
|
1580
1613
|
elements_data=[{"index": element_index, **element_data}],
|
|
1581
1614
|
variant=variant,
|
|
@@ -1585,7 +1618,7 @@ class PandaHub:
|
|
|
1585
1618
|
|
|
1586
1619
|
def create_elements(
|
|
1587
1620
|
self,
|
|
1588
|
-
|
|
1621
|
+
net_id: Union[int, str],
|
|
1589
1622
|
element_type: str,
|
|
1590
1623
|
elements_data: list[dict],
|
|
1591
1624
|
variant: int | None = None,
|
|
@@ -1597,7 +1630,7 @@ class PandaHub:
|
|
|
1597
1630
|
|
|
1598
1631
|
Parameters
|
|
1599
1632
|
----------
|
|
1600
|
-
|
|
1633
|
+
net_id: str or int
|
|
1601
1634
|
Network to add elements to, either a name or numeric id
|
|
1602
1635
|
element_type: str
|
|
1603
1636
|
Name of the element type (e.g. bus, line)
|
|
@@ -1612,7 +1645,7 @@ class PandaHub:
|
|
|
1612
1645
|
list
|
|
1613
1646
|
A list of the created elements (elements_data with added _id fields)
|
|
1614
1647
|
"""
|
|
1615
|
-
|
|
1648
|
+
self.validate_variant(variant, element_type)
|
|
1616
1649
|
if project_id:
|
|
1617
1650
|
self.set_active_project_by_id(project_id)
|
|
1618
1651
|
self.check_permission("write")
|
|
@@ -1621,10 +1654,6 @@ class PandaHub:
|
|
|
1621
1654
|
var_data = {"var_type": "base", "not_in_var": [], "variant": None}
|
|
1622
1655
|
else:
|
|
1623
1656
|
var_data = {"var_type": "addition", "not_in_var": [], "variant": variant}
|
|
1624
|
-
if isinstance(net, str):
|
|
1625
|
-
net_id = self._get_id_from_name(net, db)
|
|
1626
|
-
else:
|
|
1627
|
-
net_id = net
|
|
1628
1657
|
|
|
1629
1658
|
data = []
|
|
1630
1659
|
for elm_data in elements_data:
|
|
@@ -1707,39 +1736,78 @@ class PandaHub:
|
|
|
1707
1736
|
logger.info(f"creating indexes in {collection} collection")
|
|
1708
1737
|
project_db[collection].create_indexes(indexes)
|
|
1709
1738
|
|
|
1739
|
+
def _get_int_index(self, collection: str, index_field: str = "_id", query_filter: dict | None = None,
|
|
1740
|
+
retries: int = 10) -> int:
|
|
1741
|
+
"""Create a document in a collection with an incrementing integer value for the index_field key.
|
|
1742
|
+
|
|
1743
|
+
! This function expects a unique index set in the database on collection.index_field, compound with the keys in query_filter (if not None) !
|
|
1744
|
+
|
|
1745
|
+
Parameters
|
|
1746
|
+
----------
|
|
1747
|
+
collection:
|
|
1748
|
+
The collection to create the document in.
|
|
1749
|
+
index_field:
|
|
1750
|
+
The field holding the incrementing integer index.
|
|
1751
|
+
query_filter:
|
|
1752
|
+
A query filter to apply when searching for the highest existing index.
|
|
1753
|
+
retries:
|
|
1754
|
+
Number of retries to create the index in case of a race condition.
|
|
1755
|
+
|
|
1756
|
+
Returns
|
|
1757
|
+
-------
|
|
1758
|
+
The value of the created index.
|
|
1759
|
+
"""
|
|
1760
|
+
query_filter = query_filter if query_filter is not None else {}
|
|
1761
|
+
coll = self.get_project_database(collection)
|
|
1762
|
+
for retry in range(retries):
|
|
1763
|
+
try:
|
|
1764
|
+
max_index = next(coll.find(query_filter, projection={index_field: 1})
|
|
1765
|
+
.sort(index_field, -1)
|
|
1766
|
+
.limit(1),
|
|
1767
|
+
None)
|
|
1768
|
+
index = 0 if max_index is None else int(max_index[0][index_field]) + 1
|
|
1769
|
+
coll.insert_one({index_field: index})
|
|
1770
|
+
break
|
|
1771
|
+
except DuplicateKeyError:
|
|
1772
|
+
continue
|
|
1773
|
+
else:
|
|
1774
|
+
msg = f"Failed to create integer index for field {index_field} in {collection}!"
|
|
1775
|
+
raise PandaHubError(msg)
|
|
1776
|
+
return index
|
|
1777
|
+
|
|
1778
|
+
|
|
1710
1779
|
# -------------------------
|
|
1711
1780
|
# Variants
|
|
1712
1781
|
# -------------------------
|
|
1713
1782
|
|
|
1714
|
-
def create_variant(
|
|
1783
|
+
def create_variant(
|
|
1784
|
+
self,
|
|
1785
|
+
net_id: int,
|
|
1786
|
+
name: str | None = None,
|
|
1787
|
+
default_name: str = "Variant",
|
|
1788
|
+
index: int | None = None,
|
|
1789
|
+
) -> dict:
|
|
1715
1790
|
db = self._get_project_database()
|
|
1716
|
-
net_id = int(data["net_id"])
|
|
1717
1791
|
if index is None:
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
for coll in self._get_net_collections(db):
|
|
1734
|
-
db[coll].update_many(
|
|
1735
|
-
{"$or": [{"var_type": None}, {"var_type": np.nan}]},
|
|
1736
|
-
{"$set": {"var_type": "base", "not_in_var": [], "variant": None}},
|
|
1737
|
-
)
|
|
1738
|
-
return data
|
|
1792
|
+
index = self._get_int_index("variant", index_field="index", query_filter={"net_id": net_id})
|
|
1793
|
+
|
|
1794
|
+
if name is None:
|
|
1795
|
+
name = f"{default_name} {index + 1}"
|
|
1796
|
+
now = int(time.time())
|
|
1797
|
+
variant = {
|
|
1798
|
+
"net_id": net_id,
|
|
1799
|
+
"index": index,
|
|
1800
|
+
"name": name,
|
|
1801
|
+
"date_created": now,
|
|
1802
|
+
"date_changed": now,
|
|
1803
|
+
}
|
|
1804
|
+
db["variant"].insert_one(variant)
|
|
1805
|
+
del variant["_id"]
|
|
1806
|
+
return variant
|
|
1739
1807
|
|
|
1740
1808
|
def delete_variant(self, net_id, index):
|
|
1741
1809
|
db = self._get_project_database()
|
|
1742
|
-
collection_names = self.
|
|
1810
|
+
collection_names = self.get_net_collections(db)
|
|
1743
1811
|
for coll in collection_names:
|
|
1744
1812
|
# remove references to deleted objects
|
|
1745
1813
|
db[coll].update_many(
|
|
@@ -1775,12 +1843,17 @@ class PandaHub:
|
|
|
1775
1843
|
dict
|
|
1776
1844
|
mongodb query filter for the given variant
|
|
1777
1845
|
"""
|
|
1778
|
-
|
|
1846
|
+
self.validate_variant(variant)
|
|
1779
1847
|
if variant is None:
|
|
1780
1848
|
return self.base_variant_filter
|
|
1781
1849
|
return {"$or": [{"var_type": "base", "not_in_var": {"$ne": variant}},
|
|
1782
1850
|
{"var_type": {"$in": ["change", "addition"]}, "variant": variant}, ]}
|
|
1783
1851
|
|
|
1852
|
+
def validate_variant(self, variant: int | None, element_type: str | None = None):
|
|
1853
|
+
"""Raise a ValueError if variant is not int | None or element_type does not support variants."""
|
|
1854
|
+
validate_variant_type(variant)
|
|
1855
|
+
if element_type is not None and variant is not None and element_type in self._elements_without_vars:
|
|
1856
|
+
raise ValueError(f"{element_type} does not support variants")
|
|
1784
1857
|
|
|
1785
1858
|
# -------------------------
|
|
1786
1859
|
# Bulk operations
|
|
@@ -2976,7 +3049,7 @@ class PandaHub:
|
|
|
2976
3049
|
"ph.create_element_in_db was renamed - use ph.create_element instead!"
|
|
2977
3050
|
)
|
|
2978
3051
|
return self.create_element(
|
|
2979
|
-
|
|
3052
|
+
net_id=net,
|
|
2980
3053
|
element_type=element,
|
|
2981
3054
|
element_index=element_index,
|
|
2982
3055
|
element_data=data,
|
|
@@ -2997,7 +3070,7 @@ class PandaHub:
|
|
|
2997
3070
|
"Watch out for changed order of project_id and variant args"
|
|
2998
3071
|
)
|
|
2999
3072
|
return self.create_elements(
|
|
3000
|
-
|
|
3073
|
+
net_id=net,
|
|
3001
3074
|
element_type=element_type,
|
|
3002
3075
|
elements_data=elements_data,
|
|
3003
3076
|
variant=variant,
|
|
@@ -3011,13 +3084,52 @@ class PandaHub:
|
|
|
3011
3084
|
"ph.delete_net_element was renamed - use ph.delete_element instead!"
|
|
3012
3085
|
)
|
|
3013
3086
|
return self.delete_element(
|
|
3014
|
-
|
|
3087
|
+
net_id=net,
|
|
3015
3088
|
element_type=element,
|
|
3016
3089
|
element_index=element_index,
|
|
3017
3090
|
variant=variant,
|
|
3018
3091
|
project_id=project_id,
|
|
3019
3092
|
)
|
|
3020
3093
|
|
|
3094
|
+
def get_net_from_db(self, *args, **kwargs):
|
|
3095
|
+
msg = ("Getting a network by name can be ambiguous and will throw an error if more than one Network with the "
|
|
3096
|
+
"given name exists. Preferably, switch to get_network() and pass the network id. "
|
|
3097
|
+
"If you want to continue to retrieve a network by its name, switch to get_network_by_name(). "
|
|
3098
|
+
"get_net_from_db() will be removed in future versions.")
|
|
3099
|
+
warnings.warn(msg, DeprecationWarning)
|
|
3100
|
+
return self.get_network_by_name(*args, **kwargs)
|
|
3101
|
+
|
|
3102
|
+
def get_net_from_db_by_id(self, *args, **kwargs):
|
|
3103
|
+
msg = "get_net_from_db_by_id() has been renamed - use get_network() as drop-in replacement. This function will be removed in future versions."
|
|
3104
|
+
warnings.warn(msg, DeprecationWarning)
|
|
3105
|
+
self.get_network(*args, **kwargs)
|
|
3106
|
+
|
|
3107
|
+
def get_subnet_from_db(self, *args, **kwargs):
|
|
3108
|
+
msg = ("Getting a network by name can be ambiguous and will throw an error if more than one Network with the "
|
|
3109
|
+
"given name exists. Preferably, switch to get_subnet() and pass the network id. "
|
|
3110
|
+
"If you want to continue to retrieve a subnet by its name, switch to get_subnet_by_name(). "
|
|
3111
|
+
"get_subnet_from_db() will be removed in future versions.")
|
|
3112
|
+
warnings.warn(msg, DeprecationWarning)
|
|
3113
|
+
return self.get_subnet_by_name(*args, **kwargs)
|
|
3114
|
+
|
|
3115
|
+
def get_subnet_from_db_by_id(self,*args, **kwargs):
|
|
3116
|
+
msg = "get_subnet_from_db_by_id() has been renamed - use get_subnet() as drop-in replacement. This function will be removed in future versions."
|
|
3117
|
+
warnings.warn(msg, DeprecationWarning)
|
|
3118
|
+
return self.get_subnet(*args, **kwargs)
|
|
3119
|
+
|
|
3120
|
+
def delete_net_from_db(self, name):
|
|
3121
|
+
msg = ("Deleting a network by name can be ambiguous and will throw an error if more than one Network with the "
|
|
3122
|
+
"given name exists. Preferably, switch to delete_network() and pass the network id. "
|
|
3123
|
+
"If you want to continue to delete a net by its name, switch to delete_network_by_name(). "
|
|
3124
|
+
"delete_net_from_db() will be removed in future versions.")
|
|
3125
|
+
warnings.warn(msg, DeprecationWarning)
|
|
3126
|
+
return self.delete_network_by_name(name)
|
|
3127
|
+
|
|
3128
|
+
def _get_net_collections(self, db, with_areas=True):
|
|
3129
|
+
msg = "_get_net_collections() has been made public - use get_net_collections() as drop-in replacement. This function will be removed in future versions."
|
|
3130
|
+
warnings.warn(msg, DeprecationWarning)
|
|
3131
|
+
return self.get_net_collections(db, with_areas)
|
|
3132
|
+
|
|
3021
3133
|
|
|
3022
3134
|
if __name__ == "__main__":
|
|
3023
3135
|
self = PandaHub()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pandahub
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.10
|
|
4
4
|
Summary: Data hub for pandapower and pandapipes networks based on MongoDB
|
|
5
5
|
Author-email: Jan Ulffers <jan.ulffers@iee.fraunhofer.de>, Leon Thurner <leon.thurner@retoflow.de>, Jannis Kupka <jannis.kupka@retoflow.de>, Mike Vogt <mike.vogt@iee.fraunhofer.de>, Joschka Thurner <joschka.thurner@retoflow.de>, Alexander Scheidler <alexander.scheidler@iee.fraunhofer.de>
|
|
6
6
|
License: Copyright (c) 2022 by University of Kassel, Fraunhofer Institute for Energy Economics
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pandahub"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.10" # File format version '__format_version__' is tracked in __init__.py
|
|
8
8
|
authors=[
|
|
9
9
|
{ name = "Jan Ulffers", email = "jan.ulffers@iee.fraunhofer.de" },
|
|
10
10
|
{ name = "Leon Thurner", email = "leon.thurner@retoflow.de" },
|
|
@@ -17,13 +17,13 @@ def get_test_net(n_buses):
|
|
|
17
17
|
pp.create_sgens(net, net.bus.index[::50], p_mw=0, q_mvar=0)
|
|
18
18
|
pp.create_gens(net, net.bus.index[::1000], p_mw=0, q_mvar=0)
|
|
19
19
|
pp.create_lines(net, net.bus.index[::2], net.bus.index[1::2], 1.0, "NAYY 4x50 SE")
|
|
20
|
-
pp.create_transformers_from_parameters(net, net.bus.index[::1000],
|
|
20
|
+
pp.create_transformers_from_parameters(net, net.bus.index[::1000],
|
|
21
21
|
net.bus.index[1::1000],
|
|
22
22
|
vn_hv_kv=20.,
|
|
23
23
|
vn_lv_kv=0.4,
|
|
24
24
|
sn_mva=0.4,
|
|
25
25
|
vkr_percent=5.,
|
|
26
|
-
vk_percent=0.5,
|
|
26
|
+
vk_percent=0.5,
|
|
27
27
|
pfe_kw=0,
|
|
28
28
|
i0_percent=0,
|
|
29
29
|
)
|
|
@@ -31,7 +31,7 @@ def get_test_net(n_buses):
|
|
|
31
31
|
line_indices = list(net.line.index) + list(net.line.index)
|
|
32
32
|
pp.create_switches(net, line_buses, line_indices, "l")
|
|
33
33
|
return net
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
def write_test_net_to_mongodb(net, project_name):
|
|
36
36
|
ph = PandaHub()
|
|
37
37
|
if ph.project_exists(project_name):
|
|
@@ -39,14 +39,14 @@ def write_test_net_to_mongodb(net, project_name):
|
|
|
39
39
|
ph.delete_project(True)
|
|
40
40
|
ph.create_project(project_name)
|
|
41
41
|
ph.write_network_to_db(net, "test_net")
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
def load_test_subnet_from_mongodb(project_name):
|
|
44
44
|
ph = PandaHub()
|
|
45
45
|
ph.set_active_project(project_name)
|
|
46
46
|
buses = list(range(1000))
|
|
47
47
|
t0 = time.time()
|
|
48
|
-
subnet = ph.
|
|
49
|
-
|
|
48
|
+
subnet = ph.get_subnet_by_name("test_net",
|
|
49
|
+
bus_filter={"index": {"$in": buses}})
|
|
50
50
|
t1 = time.time()
|
|
51
51
|
print("LOADED NET IN %.2fs"%(t1-t0))
|
|
52
52
|
return subnet
|
|
@@ -54,11 +54,11 @@ def load_test_subnet_from_mongodb(project_name):
|
|
|
54
54
|
def profile_load_test(project_name):
|
|
55
55
|
lp = LineProfiler()
|
|
56
56
|
lp_wrapper = lp(load_test_subnet_from_mongodb)
|
|
57
|
-
lp.add_function(PandaHub.
|
|
57
|
+
lp.add_function(PandaHub.get_subnet)
|
|
58
58
|
lp.add_function(PandaHub._add_element_from_collection)
|
|
59
59
|
lp_wrapper(project_name)
|
|
60
60
|
lp.print_stats()
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
if __name__ == '__main__':
|
|
63
63
|
n_buses = 3e6 #3 Million buses
|
|
64
64
|
project_name = "test_%u"%n_buses
|
|
@@ -21,7 +21,7 @@ def test_additional_res_tables(ph):
|
|
|
21
21
|
net1 = pp.create_empty_network()
|
|
22
22
|
net1['res_test'] = pd.DataFrame(data={'col1': [1, 2], 'col2': [3, 4]})
|
|
23
23
|
ph.write_network_to_db(net1, 'test')
|
|
24
|
-
net2 = ph.
|
|
24
|
+
net2 = ph.get_network_by_name('test')
|
|
25
25
|
|
|
26
26
|
assert('res_test' in net2)
|
|
27
27
|
assert(net1.res_test.shape == (2,2))
|
|
@@ -50,14 +50,14 @@ def test_network_io(ph):
|
|
|
50
50
|
# we check storing two different networks consecutively to ensure the nets are properly separated
|
|
51
51
|
for net, name in [(net1, name1), (net2, name2)]:
|
|
52
52
|
if ph.network_with_name_exists(name):
|
|
53
|
-
ph.
|
|
53
|
+
ph.delete_network_by_name(name)
|
|
54
54
|
|
|
55
55
|
assert ph.network_with_name_exists(name) == False
|
|
56
56
|
|
|
57
57
|
ph.write_network_to_db(net, name)
|
|
58
58
|
assert ph.network_with_name_exists(name) == True
|
|
59
59
|
|
|
60
|
-
net_loaded = ph.
|
|
60
|
+
net_loaded = ph.get_network_by_name(name)
|
|
61
61
|
|
|
62
62
|
pp.runpp(net)
|
|
63
63
|
pp.runpp(net_loaded)
|
|
@@ -66,18 +66,18 @@ def test_network_io(ph):
|
|
|
66
66
|
# doesn't compare to itself
|
|
67
67
|
# assert pp.nets_equal(net, net_loaded, check_dtype=False)
|
|
68
68
|
|
|
69
|
-
net3 = ph.
|
|
69
|
+
net3 = ph.get_network_by_name(name, only_tables=["bus"])
|
|
70
70
|
assert len(net3.bus) == len(net.bus)
|
|
71
71
|
assert len(net3.line) == 0
|
|
72
72
|
assert len(net3.load) == 0
|
|
73
73
|
|
|
74
74
|
# delete first network
|
|
75
|
-
ph.
|
|
75
|
+
ph.delete_network_by_name(name1)
|
|
76
76
|
assert ph.network_with_name_exists(name1) == False
|
|
77
77
|
|
|
78
78
|
# check that second network is still in database
|
|
79
79
|
assert ph.network_with_name_exists(name2) == True
|
|
80
|
-
net2_loaded = ph.
|
|
80
|
+
net2_loaded = ph.get_network_by_name(name2)
|
|
81
81
|
pp.runpp(net2_loaded)
|
|
82
82
|
assert pp.nets_equal(net2, net2_loaded, check_only_results=True)
|
|
83
83
|
|
|
@@ -90,20 +90,20 @@ def test_load_subnetwork(ph):
|
|
|
90
90
|
net = nw_pp.mv_oberrhein()
|
|
91
91
|
ph.write_network_to_db(net, name)
|
|
92
92
|
|
|
93
|
-
subnet = ph.
|
|
93
|
+
subnet = ph.get_subnet_by_name(name, bus_filter={"vn_kv": 110})
|
|
94
94
|
expected_sizes = [("bus", 4), ("line", 0), ("trafo", 2), ("ext_grid", 2)]
|
|
95
95
|
|
|
96
96
|
for element, size in expected_sizes:
|
|
97
97
|
assert len(subnet[element]) == size
|
|
98
98
|
assert len(subnet["res_" + element]) == size
|
|
99
99
|
|
|
100
|
-
subnet = ph.
|
|
100
|
+
subnet = ph.get_subnet_by_name(name, bus_filter={"vn_kv": 110},
|
|
101
101
|
include_results=False)
|
|
102
102
|
for element, size in expected_sizes:
|
|
103
103
|
assert len(subnet[element]) == size
|
|
104
104
|
assert len(subnet["res_" + element]) == 0
|
|
105
105
|
|
|
106
|
-
subnet = ph.
|
|
106
|
+
subnet = ph.get_subnet_by_name(name, bus_filter={"vn_kv": 110},
|
|
107
107
|
add_edge_branches=False)
|
|
108
108
|
expected_sizes = [("bus", 2), ("line", 0), ("trafo", 0), ("ext_grid", 2)]
|
|
109
109
|
|
|
@@ -135,7 +135,7 @@ def test_access_and_set_single_values(ph):
|
|
|
135
135
|
ph.delete_element(name, element, index)
|
|
136
136
|
with pytest.raises(PandaHubError):
|
|
137
137
|
ph.get_net_value_from_db(name, element, index, parameter)
|
|
138
|
-
net = ph.
|
|
138
|
+
net = ph.get_network_by_name(name)
|
|
139
139
|
assert index not in net[element].index
|
|
140
140
|
|
|
141
141
|
|
|
@@ -143,7 +143,7 @@ def test_pandapipes(ph):
|
|
|
143
143
|
ph.set_active_project('pytest')
|
|
144
144
|
net = nw_pps.gas_versatility()
|
|
145
145
|
ph.write_network_to_db(net, 'versatility')
|
|
146
|
-
net2 = ph.
|
|
146
|
+
net2 = ph.get_network_by_name('versatility', convert=False)
|
|
147
147
|
pps.pipeflow(net)
|
|
148
148
|
pps.pipeflow(net2)
|
|
149
149
|
assert nets_equal(net, net2, check_only_results=True)
|
|
@@ -167,7 +167,7 @@ if __name__ == '__main__':
|
|
|
167
167
|
ph.create_project('pytest')
|
|
168
168
|
net = nw_pps.gas_versatility()
|
|
169
169
|
ph.write_network_to_db(net, 'versatility')
|
|
170
|
-
net2 = ph.
|
|
170
|
+
net2 = ph.get_network_by_name('versatility')
|
|
171
171
|
pps.pipeflow(net)
|
|
172
172
|
pps.pipeflow(net2)
|
|
173
173
|
# test_network_io(ph)
|
|
@@ -53,7 +53,7 @@ def test_upgrade_project():
|
|
|
53
53
|
raise pandahub.PandaHubError("net must be a pandapower or pandapipes object")
|
|
54
54
|
if self._network_with_name_exists(name, db):
|
|
55
55
|
if overwrite:
|
|
56
|
-
self.
|
|
56
|
+
self.delete_network_by_name(name)
|
|
57
57
|
else:
|
|
58
58
|
raise pandahub.PandaHubError("Network name already exists")
|
|
59
59
|
max_id_network = db["_networks"].find_one(sort=[("_id", -1)])
|
|
@@ -92,7 +92,7 @@ def test_upgrade_project():
|
|
|
92
92
|
ph.set_active_project("pytest")
|
|
93
93
|
ph.upgrade_project_to_latest_version()
|
|
94
94
|
# and test if everything went fine
|
|
95
|
-
net2 = ph.
|
|
95
|
+
net2 = ph.get_network_by_name("simple_network")
|
|
96
96
|
assert pp.nets_equal(net, net2, check_dtype=False)
|
|
97
97
|
|
|
98
98
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|