pandahub 0.3.13__zip → 0.3.15__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.
Files changed (49) hide show
  1. {pandahub-0.3.13 → pandahub-0.3.15}/PKG-INFO +1 -1
  2. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/lib/PandaHub.py +76 -38
  3. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/lib/database_toolbox.py +19 -0
  4. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub.egg-info/PKG-INFO +1 -1
  5. {pandahub-0.3.13 → pandahub-0.3.15}/pyproject.toml +1 -1
  6. {pandahub-0.3.13 → pandahub-0.3.15}/CHANGELOG.md +0 -0
  7. {pandahub-0.3.13 → pandahub-0.3.15}/CONTRIBUTING.rst +0 -0
  8. {pandahub-0.3.13 → pandahub-0.3.15}/LICENSE +0 -0
  9. {pandahub-0.3.13 → pandahub-0.3.15}/MANIFEST.in +0 -0
  10. {pandahub-0.3.13 → pandahub-0.3.15}/README.md +0 -0
  11. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/__init__.py +0 -0
  12. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/__init__.py +0 -0
  13. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/dependencies.py +0 -0
  14. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/internal/__init__.py +0 -0
  15. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/internal/db.py +0 -0
  16. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/internal/schemas.py +0 -0
  17. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/internal/settings.py +0 -0
  18. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/internal/toolbox.py +0 -0
  19. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/internal/users.py +0 -0
  20. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/main.py +0 -0
  21. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/routers/__init__.py +0 -0
  22. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/routers/auth.py +0 -0
  23. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/routers/net.py +0 -0
  24. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/routers/projects.py +0 -0
  25. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/routers/timeseries.py +0 -0
  26. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/routers/users.py +0 -0
  27. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/api/routers/variants.py +0 -0
  28. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/lib/__init__.py +0 -0
  29. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/lib/datatypes.py +0 -0
  30. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/lib/mongodb_indexes.py +0 -0
  31. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/lib/timeseries/__init__.py +0 -0
  32. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/lib/timeseries/data_sources/__init__.py +0 -0
  33. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/lib/timeseries/data_sources/mongo_data.py +0 -0
  34. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub/lib/timeseries/output_writer_mongodb.py +0 -0
  35. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub.egg-info/SOURCES.txt +0 -0
  36. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub.egg-info/dependency_links.txt +0 -0
  37. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub.egg-info/requires.txt +0 -0
  38. {pandahub-0.3.13 → pandahub-0.3.15}/pandahub.egg-info/top_level.txt +0 -0
  39. {pandahub-0.3.13 → pandahub-0.3.15}/requirements.txt +0 -0
  40. {pandahub-0.3.13 → pandahub-0.3.15}/setup.cfg +0 -0
  41. {pandahub-0.3.13 → pandahub-0.3.15}/setup.py +0 -0
  42. {pandahub-0.3.13 → pandahub-0.3.15}/test/__init__.py +0 -0
  43. {pandahub-0.3.13 → pandahub-0.3.15}/test/conftest.py +0 -0
  44. {pandahub-0.3.13 → pandahub-0.3.15}/test/performance_test.py +0 -0
  45. {pandahub-0.3.13 → pandahub-0.3.15}/test/test_client.py +0 -0
  46. {pandahub-0.3.13 → pandahub-0.3.15}/test/test_networks.py +0 -0
  47. {pandahub-0.3.13 → pandahub-0.3.15}/test/test_projects.py +0 -0
  48. {pandahub-0.3.13 → pandahub-0.3.15}/test/test_timeseries.py +0 -0
  49. {pandahub-0.3.13 → pandahub-0.3.15}/tutorials/config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pandahub
3
- Version: 0.3.13
3
+ Version: 0.3.15
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
@@ -38,6 +38,7 @@ from pandahub.lib.database_toolbox import (
38
38
  get_dtypes,
39
39
  decompress_timeseries_data,
40
40
  convert_geojsons,
41
+ get_metadata_for_timeseries_collections
41
42
  )
42
43
  from pandahub.lib.mongodb_indexes import MONGODB_INDEXES
43
44
 
@@ -1674,21 +1675,22 @@ class PandaHub:
1674
1675
  var_data = {"var_type": "base", "not_in_var": [], "variant": None}
1675
1676
  else:
1676
1677
  var_data = {"var_type": "addition", "not_in_var": [], "variant": variant}
1677
-
1678
+ net_doc = db["_networks"].find_one({"_id": net_id})
1678
1679
  data = []
1679
1680
  for elm_data in elements_data:
1680
- self._add_missing_defaults(db, net_id, element_type, elm_data)
1681
+ self._add_missing_defaults(element_type, elm_data, net_doc)
1681
1682
  self._ensure_dtypes(element_type, elm_data)
1682
1683
  data.append({**elm_data, **var_data, "net_id": net_id})
1683
1684
  collection = self._collection_name_of_element(element_type)
1684
1685
  db[collection].insert_many(data, ordered=False)
1685
1686
  return data
1686
1687
 
1687
- def _add_missing_defaults(self, db, net_id, element_type, element_data):
1688
+ def _add_missing_defaults(self, element_type, element_data, net_doc):
1688
1689
  func_str = f"create_{element_type}"
1689
- if not hasattr(pp, func_str):
1690
+ package = pp if net_doc['sector'] == 'power' else pps
1691
+ if not hasattr(package, func_str):
1690
1692
  return
1691
- create_func = getattr(pp, func_str)
1693
+ create_func = getattr(package, func_str)
1692
1694
  sig = signature(create_func)
1693
1695
  params = sig.parameters
1694
1696
 
@@ -1704,7 +1706,6 @@ class PandaHub:
1704
1706
  if element_type in ["line", "trafo", "trafo3w"]:
1705
1707
  # add standard type values
1706
1708
  std_type = element_data["std_type"]
1707
- net_doc = db["_networks"].find_one({"_id": net_id})
1708
1709
  if net_doc is not None:
1709
1710
  # std_types = json.loads(net_doc["data"]["std_types"], cls=io_pp.PPJSONDecoder)[element_type]
1710
1711
  std_types = net_doc["data"]["std_types"]
@@ -1715,6 +1716,9 @@ class PandaHub:
1715
1716
  if element_type == "line":
1716
1717
  if "g_us_per_km" not in element_data:
1717
1718
  element_data["g_us_per_km"] = 0
1719
+ if element_type in ['sink', 'source']:
1720
+ if not 'mdot_kg_per_s' in element_data:
1721
+ element_data["mdot_kg_per_s"] = None
1718
1722
 
1719
1723
  def _ensure_dtypes(self, element_type, data):
1720
1724
  dtypes = self._datatypes.get(element_type)
@@ -2050,9 +2054,21 @@ class PandaHub:
2050
2054
  self.check_permission("write")
2051
2055
  db = self._get_project_database()
2052
2056
  if self.collection_is_timeseries(collection_name, project_id, global_database):
2053
- metadata = kwargs
2054
- if data_type is not None:
2055
- metadata["data_type"] = data_type
2057
+ # get metadata dictionary based on the input arguments
2058
+ metadata = get_metadata_for_timeseries_collections(db, data_type=data_type, **kwargs)
2059
+ _id = metadata["_id"]
2060
+
2061
+ # delete overlapping timeseries already in the database
2062
+ filter = {
2063
+ "metadata._id": _id,
2064
+ "timestamp": {
2065
+ "$gte": timeseries.index.min(),
2066
+ "$lte": timeseries.index.max()
2067
+ }
2068
+ }
2069
+ db.timeseries.delete_many(filter)
2070
+
2071
+ # create new timeseries documents
2056
2072
  if isinstance(timeseries, pd.Series):
2057
2073
  documents = [
2058
2074
  {"metadata": metadata, "timestamp": idx, "value": value}
@@ -2063,7 +2079,12 @@ class PandaHub:
2063
2079
  {"metadata": metadata, "timestamp": idx, **row.to_dict()}
2064
2080
  for idx, row in timeseries.iterrows()
2065
2081
  ]
2066
- return db[collection_name].insert_many(documents)
2082
+ db[collection_name].insert_many(documents)
2083
+
2084
+ if kwargs.get("return_id"):
2085
+ return _id
2086
+ return None
2087
+
2067
2088
  document = create_timeseries_document(
2068
2089
  timeseries=timeseries,
2069
2090
  data_type=data_type,
@@ -2328,19 +2349,22 @@ class PandaHub:
2328
2349
  self.check_permission("read")
2329
2350
  db = self._get_project_database()
2330
2351
  if self.collection_is_timeseries(collection_name, project_id, global_database):
2331
- meta_filter = {
2332
- "metadata." + key: value for key, value in filter_document.items()
2333
- }
2352
+ metadata = get_metadata_for_timeseries_collections(db, **kwargs)
2334
2353
  pipeline = []
2335
- pipeline.append({"$match": meta_filter})
2354
+ pipeline.append({"$match": {"metadata._id": metadata["_id"]}})
2336
2355
  pipeline.append({"$project": {"_id": 0, "metadata": 0}})
2337
2356
  timeseries = db[collection_name].aggregate_pandas_all(pipeline)
2357
+ if len(timeseries) == 0:
2358
+ raise PandaHubError("no documents matching the provided filter found", 404)
2338
2359
  timeseries.set_index("timestamp", inplace=True)
2339
2360
  if include_metadata:
2340
2361
  raise NotImplementedError(
2341
2362
  "Not implemented yet for timeseries collections"
2342
2363
  )
2343
- return timeseries
2364
+ if len(timeseries.columns) == 1:
2365
+ return timeseries[timeseries.columns[0]]
2366
+ else:
2367
+ return timeseries
2344
2368
  filter_document = {**filter_document, **kwargs}
2345
2369
  pipeline = [{"$match": filter_document}]
2346
2370
  if not compressed_ts_data:
@@ -2427,6 +2451,7 @@ class PandaHub:
2427
2451
  collection_name="timeseries",
2428
2452
  global_database=False,
2429
2453
  project_id=None,
2454
+ timestamp_range=None,
2430
2455
  ):
2431
2456
  """
2432
2457
  Returns a DataFrame, containing all metadata matching the provided filter.
@@ -2467,10 +2492,17 @@ class PandaHub:
2467
2492
  pipeline.append({"$match": document_filter})
2468
2493
  else:
2469
2494
  document_filter = {}
2495
+ if timestamp_range is not None:
2496
+ document_filter["timestamp"] = {
2497
+ "$gte": timestamp_range[0],
2498
+ "$lt": timestamp_range[1],
2499
+ }
2470
2500
  document = db[collection_name].find_one(
2471
2501
  document_filter, projection={"timestamp": 0, "_id": 0}
2472
2502
  )
2473
- value_fields = ["$%s" % field for field in document.keys()]
2503
+ if document is None:
2504
+ return pd.DataFrame()
2505
+ value_fields = ["$%s" % field for field in document.keys() if field != "metadata"]
2474
2506
  group_dict = {
2475
2507
  "_id": "$metadata._id",
2476
2508
  "max_value": {"$max": {"$max": value_fields}},
@@ -2595,27 +2627,30 @@ class PandaHub:
2595
2627
  document_filter,
2596
2628
  projection={"timestamp": 0, "metadata": 0, "_id": 0},
2597
2629
  )
2598
- meta_pipeline = []
2599
- meta_pipeline.append({"$match": document_filter})
2600
- value_fields = ["$%s" % field for field in document.keys()]
2601
- group_dict = {
2602
- "_id": "$metadata._id",
2603
- "max_value": {"$max": {"$max": value_fields}},
2604
- "min_value": {"$min": {"$min": value_fields}},
2605
- "first_timestamp": {"$min": "$timestamp"},
2606
- "last_timestamp": {"$max": "$timestamp"},
2607
- }
2608
- document = db[collection_name].find_one(document_filter)
2609
- metadata_fields = {
2610
- metadata_field: {"$first": "$metadata.%s" % metadata_field}
2611
- for metadata_field in document["metadata"].keys()
2612
- if metadata_field != "_id"
2613
- }
2614
- group_dict.update(metadata_fields)
2615
- meta_pipeline.append({"$group": group_dict})
2616
- meta_data = {
2617
- d["_id"]: d for d in db[collection_name].aggregate(meta_pipeline)
2618
- }
2630
+ if document is None:
2631
+ meta_data = {}
2632
+ else:
2633
+ meta_pipeline = []
2634
+ meta_pipeline.append({"$match": document_filter})
2635
+ value_fields = ["$%s" % field for field in document.keys()]
2636
+ group_dict = {
2637
+ "_id": "$metadata._id",
2638
+ "max_value": {"$max": {"$max": value_fields}},
2639
+ "min_value": {"$min": {"$min": value_fields}},
2640
+ "first_timestamp": {"$min": "$timestamp"},
2641
+ "last_timestamp": {"$max": "$timestamp"},
2642
+ }
2643
+ document = db[collection_name].find_one(document_filter)
2644
+ metadata_fields = {
2645
+ metadata_field: {"$first": "$metadata.%s" % metadata_field}
2646
+ for metadata_field in document["metadata"].keys()
2647
+ if metadata_field != "_id"
2648
+ }
2649
+ group_dict.update(metadata_fields)
2650
+ meta_pipeline.append({"$group": group_dict})
2651
+ meta_data = {
2652
+ d["_id"]: d for d in db[collection_name].aggregate(meta_pipeline)
2653
+ }
2619
2654
  timeseries = []
2620
2655
  ts_all = db[collection_name].aggregate_pandas_all(pipeline)
2621
2656
  if len(ts_all) == 0:
@@ -2961,7 +2996,9 @@ class PandaHub:
2961
2996
  """
2962
2997
  self.check_permission("write")
2963
2998
  db = self._get_project_database()
2964
-
2999
+ if self.collection_is_timeseries(collection_name):
3000
+ metadata = get_metadata_for_timeseries_collections(db, data_type, **kwargs)
3001
+ return db[collection_name].delete_many({"metadata._id": metadata["_id"]})
2965
3002
  filter_document = {"element_type": element_type, "data_type": data_type}
2966
3003
  if netname is not None:
2967
3004
  filter_document["netname"] = netname
@@ -3154,6 +3191,7 @@ class PandaHub:
3154
3191
  return self.get_net_collections(db, with_areas)
3155
3192
 
3156
3193
 
3194
+
3157
3195
  if __name__ == "__main__":
3158
3196
  self = PandaHub()
3159
3197
  project_name = "test_project"
@@ -478,3 +478,22 @@ def mongo_client(database: str | None = None, collection: str | None = None, con
478
478
  client.close()
479
479
 
480
480
 
481
+ def get_metadata_for_timeseries_collections(db, data_type=None, net_id=None, element_type=None, element_index=None, **kwargs):
482
+ if element_type is None:
483
+ raise ValueError("element_type needs to be defined for timeseries collections")
484
+ if element_index is None:
485
+ raise ValueError("element_index needs to be defined for timeseries collections")
486
+ if data_type is None:
487
+ raise ValueError("data_type needs to be defined for timeseries collections")
488
+ if net_id is None:
489
+ net_ids = db["_networks"].distinct("_id")
490
+ if len(net_ids) == 1:
491
+ net_id = net_ids[0]
492
+ else:
493
+ raise ValueError(
494
+ "No net_id was provided and multiple networks exist in the database. "
495
+ "Please provide a net_id."
496
+ )
497
+ metadata = {"data_type": data_type, "net_id": net_id, "element_type": element_type, "element_index": element_index, **kwargs}
498
+ metadata["_id"] = f"{net_id}_{element_type}_{element_index}_{data_type}"
499
+ return metadata
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pandahub
3
- Version: 0.3.13
3
+ Version: 0.3.15
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.13" # File format version '__format_version__' is tracked in __init__.py
7
+ version = "0.3.15" # 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" },
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