pyconvexity 0.4.8__py3-none-any.whl

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.

Potentially problematic release.


This version of pyconvexity might be problematic. Click here for more details.

Files changed (44) hide show
  1. pyconvexity/__init__.py +241 -0
  2. pyconvexity/_version.py +1 -0
  3. pyconvexity/core/__init__.py +60 -0
  4. pyconvexity/core/database.py +485 -0
  5. pyconvexity/core/errors.py +106 -0
  6. pyconvexity/core/types.py +400 -0
  7. pyconvexity/dashboard.py +265 -0
  8. pyconvexity/data/README.md +101 -0
  9. pyconvexity/data/__init__.py +17 -0
  10. pyconvexity/data/loaders/__init__.py +3 -0
  11. pyconvexity/data/loaders/cache.py +213 -0
  12. pyconvexity/data/schema/01_core_schema.sql +420 -0
  13. pyconvexity/data/schema/02_data_metadata.sql +120 -0
  14. pyconvexity/data/schema/03_validation_data.sql +507 -0
  15. pyconvexity/data/sources/__init__.py +5 -0
  16. pyconvexity/data/sources/gem.py +442 -0
  17. pyconvexity/io/__init__.py +26 -0
  18. pyconvexity/io/excel_exporter.py +1226 -0
  19. pyconvexity/io/excel_importer.py +1381 -0
  20. pyconvexity/io/netcdf_exporter.py +191 -0
  21. pyconvexity/io/netcdf_importer.py +1802 -0
  22. pyconvexity/models/__init__.py +195 -0
  23. pyconvexity/models/attributes.py +730 -0
  24. pyconvexity/models/carriers.py +159 -0
  25. pyconvexity/models/components.py +611 -0
  26. pyconvexity/models/network.py +503 -0
  27. pyconvexity/models/results.py +148 -0
  28. pyconvexity/models/scenarios.py +234 -0
  29. pyconvexity/solvers/__init__.py +29 -0
  30. pyconvexity/solvers/pypsa/__init__.py +30 -0
  31. pyconvexity/solvers/pypsa/api.py +446 -0
  32. pyconvexity/solvers/pypsa/batch_loader.py +296 -0
  33. pyconvexity/solvers/pypsa/builder.py +655 -0
  34. pyconvexity/solvers/pypsa/clearing_price.py +678 -0
  35. pyconvexity/solvers/pypsa/constraints.py +405 -0
  36. pyconvexity/solvers/pypsa/solver.py +1442 -0
  37. pyconvexity/solvers/pypsa/storage.py +2096 -0
  38. pyconvexity/timeseries.py +330 -0
  39. pyconvexity/validation/__init__.py +25 -0
  40. pyconvexity/validation/rules.py +312 -0
  41. pyconvexity-0.4.8.dist-info/METADATA +148 -0
  42. pyconvexity-0.4.8.dist-info/RECORD +44 -0
  43. pyconvexity-0.4.8.dist-info/WHEEL +5 -0
  44. pyconvexity-0.4.8.dist-info/top_level.txt +1 -0
@@ -0,0 +1,191 @@
1
+ """
2
+ NetCDF exporter for PyConvexity energy system models.
3
+ Exports networks to PyPSA NetCDF format using existing PyPSA infrastructure.
4
+ """
5
+
6
+ from typing import Dict, Any, Optional, Callable
7
+ from pathlib import Path
8
+
9
+ # Import existing PyPSA functionality from pyconvexity
10
+ from pyconvexity.solvers.pypsa import build_pypsa_network
11
+
12
+
13
+ class NetCDFModelExporter:
14
+ """Export network model to PyPSA NetCDF format"""
15
+
16
+ def __init__(self):
17
+ pass
18
+
19
+ def export_to_netcdf(
20
+ self,
21
+ db_path: str,
22
+ output_path: str,
23
+ scenario_id: Optional[int] = None,
24
+ progress_callback: Optional[Callable[[int, str], None]] = None,
25
+ ) -> Dict[str, Any]:
26
+ """
27
+ Export network from database to PyPSA NetCDF format (single network per database).
28
+
29
+ This method leverages the existing pyconvexity PyPSA infrastructure to build
30
+ a network from the database and then export it to NetCDF format.
31
+
32
+ Args:
33
+ db_path: Path to the database file
34
+ output_path: Path where to save the NetCDF file
35
+ scenario_id: Optional scenario ID (NULL for base network)
36
+ progress_callback: Optional callback for progress updates
37
+
38
+ Returns:
39
+ Dictionary with export results and statistics
40
+ """
41
+ try:
42
+ if progress_callback:
43
+ progress_callback(0, "Starting NetCDF export...")
44
+
45
+ # Build PyPSA network from database using existing infrastructure
46
+ if progress_callback:
47
+ progress_callback(10, "Building PyPSA network from database...")
48
+
49
+ network = build_pypsa_network(
50
+ db_path=db_path,
51
+ scenario_id=scenario_id,
52
+ progress_callback=self._wrap_progress_callback(
53
+ progress_callback, 10, 80
54
+ ),
55
+ )
56
+
57
+ if progress_callback:
58
+ progress_callback(80, "Exporting to NetCDF...")
59
+
60
+ # Export to NetCDF using PyPSA's built-in method
61
+ network.export_to_netcdf(output_path)
62
+
63
+ if progress_callback:
64
+ progress_callback(100, "NetCDF export completed")
65
+
66
+ # Get statistics
67
+ stats = self._get_network_stats(network)
68
+
69
+ return {
70
+ "success": True,
71
+ "message": f"Network exported to NetCDF: {output_path}",
72
+ "output_path": output_path,
73
+ "stats": stats,
74
+ }
75
+
76
+ except Exception as e:
77
+ if progress_callback:
78
+ progress_callback(None, f"Export failed: {str(e)}")
79
+ raise
80
+
81
+ def export_to_csv(
82
+ self,
83
+ db_path: str,
84
+ output_directory: str,
85
+ scenario_id: Optional[int] = None,
86
+ progress_callback: Optional[Callable[[int, str], None]] = None,
87
+ ) -> Dict[str, Any]:
88
+ """
89
+ Export network from database to PyPSA CSV format (single network per database).
90
+
91
+ Args:
92
+ db_path: Path to the database file
93
+ output_directory: Directory where to save CSV files
94
+ scenario_id: Optional scenario ID (NULL for base network)
95
+ progress_callback: Optional callback for progress updates
96
+
97
+ Returns:
98
+ Dictionary with export results and statistics
99
+ """
100
+ try:
101
+ if progress_callback:
102
+ progress_callback(0, "Starting CSV export...")
103
+
104
+ # Ensure output directory exists
105
+ Path(output_directory).mkdir(parents=True, exist_ok=True)
106
+
107
+ # Build PyPSA network from database using existing infrastructure
108
+ if progress_callback:
109
+ progress_callback(10, "Building PyPSA network from database...")
110
+
111
+ network = build_pypsa_network(
112
+ db_path=db_path,
113
+ scenario_id=scenario_id,
114
+ progress_callback=self._wrap_progress_callback(
115
+ progress_callback, 10, 80
116
+ ),
117
+ )
118
+
119
+ if progress_callback:
120
+ progress_callback(80, "Exporting to CSV...")
121
+
122
+ # Export to CSV using PyPSA's built-in method
123
+ network.export_to_csv_folder(output_directory)
124
+
125
+ if progress_callback:
126
+ progress_callback(100, "CSV export completed")
127
+
128
+ # Get statistics
129
+ stats = self._get_network_stats(network)
130
+
131
+ return {
132
+ "success": True,
133
+ "message": f"Network exported to CSV: {output_directory}",
134
+ "output_directory": output_directory,
135
+ "stats": stats,
136
+ }
137
+
138
+ except Exception as e:
139
+ if progress_callback:
140
+ progress_callback(None, f"Export failed: {str(e)}")
141
+ raise
142
+
143
+ def _wrap_progress_callback(
144
+ self,
145
+ callback: Optional[Callable[[int, str], None]],
146
+ start_percent: int,
147
+ end_percent: int,
148
+ ) -> Optional[Callable[[int, str], None]]:
149
+ """
150
+ Wrap a progress callback to map progress from one range to another
151
+
152
+ Args:
153
+ callback: Original callback function
154
+ start_percent: Starting percentage for the wrapped range
155
+ end_percent: Ending percentage for the wrapped range
156
+
157
+ Returns:
158
+ Wrapped callback function or None if original callback is None
159
+ """
160
+ if callback is None:
161
+ return None
162
+
163
+ def wrapped_callback(progress: Optional[int], message: Optional[str]):
164
+ if progress is not None:
165
+ # Map progress from 0-100 to start_percent-end_percent
166
+ mapped_progress = start_percent + (
167
+ progress * (end_percent - start_percent) // 100
168
+ )
169
+ callback(mapped_progress, message)
170
+ else:
171
+ callback(progress, message)
172
+
173
+ return wrapped_callback
174
+
175
+ def _get_network_stats(self, network: "pypsa.Network") -> Dict[str, int]:
176
+ """Get component counts from the network"""
177
+ return {
178
+ "buses": len(network.buses),
179
+ "generators": (
180
+ len(network.generators) if hasattr(network, "generators") else 0
181
+ ),
182
+ "loads": len(network.loads) if hasattr(network, "loads") else 0,
183
+ "lines": len(network.lines) if hasattr(network, "lines") else 0,
184
+ "links": len(network.links) if hasattr(network, "links") else 0,
185
+ "storage_units": (
186
+ len(network.storage_units) if hasattr(network, "storage_units") else 0
187
+ ),
188
+ "stores": len(network.stores) if hasattr(network, "stores") else 0,
189
+ "carriers": len(network.carriers) if hasattr(network, "carriers") else 0,
190
+ "snapshots": len(network.snapshots) if hasattr(network, "snapshots") else 0,
191
+ }