zen-garden 2.7.19__tar.gz → 2.7.20__tar.gz

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 (42) hide show
  1. {zen_garden-2.7.19 → zen_garden-2.7.20}/PKG-INFO +1 -1
  2. {zen_garden-2.7.19 → zen_garden-2.7.20}/pyproject.toml +4 -4
  3. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/__init__.py +6 -1
  4. zen_garden-2.7.20/zen_garden/__main__.py +71 -0
  5. zen_garden-2.7.20/zen_garden/cli/zen_example.py +43 -0
  6. zen_garden-2.7.20/zen_garden/cli/zen_garden.py +165 -0
  7. zen_garden-2.7.20/zen_garden/cli/zen_visualization.py +24 -0
  8. zen_garden-2.7.20/zen_garden/preprocess/__init__.py +0 -0
  9. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/preprocess/unit_handling.py +1 -1
  10. zen_garden-2.7.19/zen_garden/_internal.py → zen_garden-2.7.20/zen_garden/runner.py +59 -13
  11. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/utils.py +133 -0
  12. zen_garden-2.7.19/zen_garden/__main__.py +0 -68
  13. zen_garden-2.7.19/zen_garden/dataset_examples.py +0 -186
  14. zen_garden-2.7.19/zen_garden/visualization.py +0 -4
  15. {zen_garden-2.7.19 → zen_garden-2.7.20}/LICENSE.txt +0 -0
  16. {zen_garden-2.7.19 → zen_garden-2.7.20}/README.md +0 -0
  17. {zen_garden-2.7.19/zen_garden/postprocess → zen_garden-2.7.20/zen_garden/cli}/__init__.py +0 -0
  18. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/default_config.py +0 -0
  19. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/__init__.py +0 -0
  20. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/carrier/__init__.py +0 -0
  21. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/carrier/carrier.py +0 -0
  22. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/component.py +0 -0
  23. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/element.py +0 -0
  24. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/energy_system.py +0 -0
  25. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/technology/__init__.py +0 -0
  26. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/technology/conversion_technology.py +0 -0
  27. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/technology/retrofitting_technology.py +0 -0
  28. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/technology/storage_technology.py +0 -0
  29. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/technology/technology.py +0 -0
  30. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/technology/transport_technology.py +0 -0
  31. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/model/time_steps.py +0 -0
  32. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/optimization_setup.py +0 -0
  33. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/postprocess/.gitkeep +0 -0
  34. {zen_garden-2.7.19/zen_garden/preprocess → zen_garden-2.7.20/zen_garden/postprocess}/__init__.py +0 -0
  35. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/postprocess/comparisons.py +0 -0
  36. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/postprocess/postprocess.py +0 -0
  37. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/postprocess/results/__init__.py +0 -0
  38. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/postprocess/results/results.py +0 -0
  39. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/postprocess/results/solution_loader.py +0 -0
  40. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/preprocess/extract_input_data.py +0 -0
  41. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/preprocess/parameter_change_log.py +0 -0
  42. {zen_garden-2.7.19 → zen_garden-2.7.20}/zen_garden/preprocess/time_series_aggregation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zen_garden
3
- Version: 2.7.19
3
+ Version: 2.7.20
4
4
  Summary: ZEN-garden is an optimization model of energy systems and value chains.
5
5
  Author: Alissa Ganter, Johannes Burger, Francesco De Marco, Lukas Kunz, Lukas Schmidt-Engelbertz, Christoph Funke, Paolo Gabrielli, Giovanni Sansavini
6
6
  Author-email: Jacob Mannhardt <zen-garden@ethz.ch>
@@ -16,7 +16,7 @@ authors = [
16
16
  {name = "Giovanni Sansavini"},
17
17
  ]
18
18
  # do not change version manually! Done by bump2version
19
- version = "2.7.19"
19
+ version = "2.7.20"
20
20
  requires-python= ">=3.11,<3.14"
21
21
  description="ZEN-garden is an optimization model of energy systems and value chains."
22
22
  readme = "README.md"
@@ -78,6 +78,6 @@ Zenodo = "https://zenodo.org/api/records/13385110"
78
78
  addopts = "-n auto"
79
79
 
80
80
  [project.scripts]
81
- zen-garden = "zen_garden.__main__:run_module"
82
- zen-visualization = "zen_garden.visualization:parse_arguments_and_run"
83
- zen-example = "zen_garden.dataset_examples:cli_download_example_dataset"
81
+ zen-garden = "zen_garden.cli.zen_garden:cli_zen_garden"
82
+ zen-visualization = "zen_garden.cli.zen_visualization:cli_zen_visualization"
83
+ zen-example = "zen_garden.cli.zen_example:cli_zen_example"
@@ -2,9 +2,14 @@ from . import model
2
2
  from . import postprocess
3
3
  from . import preprocess
4
4
  from .utils import get_inheritors
5
-
6
5
  from .model.element import Element
7
6
  from .optimization_setup import OptimizationSetup
7
+ from .runner import run
8
+ from .postprocess.results.results import Results
9
+ from .utils import download_example_dataset
10
+
11
+ __all__ = ["run", "Results", "download_example_dataset"]
12
+
8
13
 
9
14
  # set the element classes of the EnergySystem class
10
15
  inheritors = get_inheritors(Element)
@@ -0,0 +1,71 @@
1
+ """
2
+ Runs the main function of ZEN-Garden.
3
+ Compilation of the optimization problem.
4
+ """
5
+ from .runner import run
6
+ from .cli.zen_garden import cli_zen_garden
7
+ import warnings
8
+
9
+ def run_module(config = "./config.py", dataset = None,
10
+ folder_output = None, job_index = None):
11
+ """
12
+ Deprecated wrapper for ``zen_garden.runner.run()``.
13
+
14
+ This function mirrors the behavior of
15
+ ``zen_garden.runner.run()`` and exists solely for backward
16
+ compatibility with older versions of ZEN_garden, where
17
+ ``zen_garden.__main__.run_module()`` served as the primary entry point.
18
+
19
+ This function is deprecated and will be removed in ZEN-garden v3.0.0.
20
+ Users should migrate to ``zen_garden.runner.run()``.
21
+
22
+ Args:
23
+ config (str): Path to the configuration file (e.g. ``config.json``).
24
+ If the file is located in the current working directory, the
25
+ filename alone may be specified. Defaults to ``"./config.py"``.
26
+ dataset (str): Path to the folder containing the input dataset
27
+ (e.g. ``"./1_base_case"``). If located in the current working
28
+ directory, the folder name alone may be used. Defaults to the
29
+ ``dataset`` value specified in the configuration file.
30
+ folder_output (str): Path to the folder where outputs will be saved.
31
+ Defaults to ``"./outputs"``.
32
+ job_index (list[int] | None): Indices of jobs (scenarios) to run.
33
+ For example, ``job_index=[1]`` runs only the first scenario.
34
+ Defaults to ``None`` (run all jobs).
35
+
36
+ Raises:
37
+ DeprecationWarning: This function will be removed in ZEN-garden v3.0.0.
38
+
39
+ Returns:
40
+ OptimizationSetup: The fully set up and solved optimization problem.
41
+
42
+ See Also:
43
+ zen_garden.runner.run: Replacement function.
44
+
45
+ Examples:
46
+ >>> from zen_garden import run, copy_example_dataset
47
+ >>> download_example_dataset("1_base_case")
48
+ >>> run("1_base_case")
49
+ """
50
+
51
+
52
+ # throw deprecation warning
53
+ warnings.warn(
54
+ "zen_garden.__main__.run_module() is deprecated and will be removed " \
55
+ "in ZEN-garden v3.0.0. Please use the new version " \
56
+ "zen_garden.runner.run() instead.",
57
+ DeprecationWarning,
58
+ stacklevel=2
59
+ )
60
+
61
+ # run new function
62
+ return run(
63
+ config = config,
64
+ dataset = dataset,
65
+ folder_output=folder_output,
66
+ job_index=job_index
67
+ )
68
+
69
+ if __name__ == "__main__":
70
+
71
+ cli_zen_garden()
@@ -0,0 +1,43 @@
1
+ import argparse
2
+ import sys
3
+ from zen_garden.utils import download_example_dataset
4
+
5
+ def cli_zen_example():
6
+ """
7
+ Entry point for the `zen-example` command-line interface.
8
+
9
+ Creates a command line interface for downloading the dataset examples.
10
+ The function parses a single required argument ``--dataset`` that
11
+ specifies the name of the dataset to be downloaded. It then invokes
12
+ the function function ``download_example_dataset`` with that argument.
13
+
14
+ The ``[project.scripts]`` section of the pyproject.toml declares that
15
+ this function will be called whenever a user enters ``zen-example`` into
16
+ the command prompt. This function is therefore creates the ``zen-example``
17
+ command line entry point.
18
+
19
+ Examples:
20
+ Basic usage in a command line prompt:
21
+
22
+ >>> zen-example --dataset="1_base_case"
23
+
24
+ """
25
+ # parse the args
26
+ description = "Downloads an example dataset for ZEN-garden to the current" \
27
+ "working directory"
28
+
29
+ parser = argparse.ArgumentParser(
30
+ description=description,
31
+ add_help=True,
32
+ usage="usage: zen-example [--dataset DATASET]")
33
+
34
+ parser.add_argument(
35
+ "--dataset",
36
+ required=True,
37
+ type=str,
38
+ help="Name of the dataset to download, e.g. '1_base_case'")
39
+
40
+ args = parser.parse_args(sys.argv[1:])
41
+
42
+ # download the example
43
+ download_example_dataset(args.dataset)
@@ -0,0 +1,165 @@
1
+ import argparse
2
+ from zen_garden.runner import run
3
+ import os
4
+
5
+ # ---------------------------------------------------------------------------
6
+ # Command-line interface
7
+ # ---------------------------------------------------------------------------
8
+
9
+ def build_parser() -> argparse.ArgumentParser:
10
+ """Build the command-line argument parser for ZEN-garden.
11
+
12
+ This function defines all supported command-line options for running
13
+ ZEN-garden. The parser handles configuration file selection, dataset and
14
+ output directory overrides, and job indexing for array or batch execution.
15
+
16
+ Command Line Flags:
17
+ --config (str, optional):
18
+ Path to a Python or JSON configuration file. If not provided, the
19
+ configuration is read from the current working directory.
20
+
21
+ --dataset (str, optional):
22
+ Path to the dataset directory. Overrides
23
+ ``config.analysis.dataset`` in the configuration file.
24
+
25
+ --folder_output (str, optional):
26
+ Path to the output directory. Overrides output-related settings in
27
+ the configuration file. If not specified, output is written to the
28
+ current working directory.
29
+
30
+ --job_index (str, optional):
31
+ Comma-separated list of scenario or job indices to execute. If not
32
+ provided, the value is read from the environment variable specified
33
+ by ``--job_index_var``.
34
+
35
+ --job_index_var (str, optional):
36
+ Name of the environment variable containing the job index.
37
+ Defaults to ``SLURM_ARRAY_TASK_ID``.
38
+
39
+ Returns:
40
+ argparse.ArgumentParser: An argument parser configured for the
41
+ ZEN-Garden command-line interface.
42
+ """
43
+
44
+ description = (
45
+ "Run ZEN-Garden with a given config file. By default, the config file "
46
+ "is read from the current working directory. You may specify a config "
47
+ "file with --config. Output is always written to the current working "
48
+ "directory unless overridden."
49
+ )
50
+
51
+ parser = argparse.ArgumentParser(
52
+ description=description,
53
+ add_help=True,
54
+ usage="zen_garden [options]"
55
+ )
56
+
57
+ parser.add_argument(
58
+ "--config", type=str, required=False, default=None,
59
+ help="Path to a Python or JSON config file."
60
+ )
61
+ parser.add_argument(
62
+ "--dataset", type=str, required=False, default=None,
63
+ help="Path to the dataset directory. Overrides config.analysis.dataset."
64
+ )
65
+ parser.add_argument(
66
+ "--folder_output", type=str, required=False, default=None,
67
+ help="Path to the output directory. Overrides output settings in config."
68
+ )
69
+ parser.add_argument(
70
+ "--job_index", type=str, required=False, default=None,
71
+ help="Comma-separated list of scenario indices. If omitted, the "
72
+ "environment variable specified by --job_index_var is used."
73
+ )
74
+ parser.add_argument(
75
+ "--job_index_var", type=str, required=False,
76
+ default="SLURM_ARRAY_TASK_ID",
77
+ help="Environment variable for job index."
78
+ )
79
+
80
+ return parser
81
+
82
+ def resolve_job_index(job_index:str, job_index_var:str) -> list[int]:
83
+ """
84
+ Resolves the job index when running ZEN-garden from the command line.
85
+
86
+ If the job index is directly specified using the ``job_index`` command-line
87
+ flag, those values are used. Otherwise, the job index is extracted from the
88
+ environment variable specified by the ``job_index_var`` command-line flag.
89
+ If neither is defined, ``None`` is returned.
90
+
91
+ Args:
92
+ job_index (str): Value of the ``job_index`` command-line flag provided
93
+ by the user.
94
+ job_index_var (str): Value of the ``job_index_var`` command-line flag
95
+ provided by the user.
96
+
97
+ Returns:
98
+ list[int] | None: List of job indices to run in the current instance of
99
+ ZEN-garden, or ``None`` if no job index is specified.
100
+ """
101
+
102
+ if job_index:
103
+ return [int(i) for i in job_index.split(",")]
104
+ elif ((env_value := os.environ.get(job_index_var)) is not None):
105
+ return [int(env_value)]
106
+ else:
107
+ return None
108
+
109
+
110
+ def cli_zen_garden():
111
+ """
112
+ Entry point for the `zen-garden` command-line interface.
113
+
114
+ This function creates the command-line interface for running ZEN-garden.
115
+ It first sets up an argument parser; extracts the job index (either from
116
+ the input flax directly or from an environment variable), and then
117
+ calls the ``zen_garden.run()`` function.
118
+
119
+ The ``[project.scripts]`` section of the pyproject.toml declares that
120
+ this function will be called whenever a user enters ``zen-garden`` into
121
+ the command prompt.
122
+
123
+ Command Line Flags:
124
+ --config (str, optional):
125
+ Path to a Python or JSON configuration file. If not provided, the
126
+ configuration is read from the current working directory.
127
+
128
+ --dataset (str, optional):
129
+ Path to the dataset directory. Overrides
130
+ ``config.analysis.dataset`` in the configuration file.
131
+
132
+ --folder_output (str, optional):
133
+ Path to the output directory. Overrides output-related settings in
134
+ the configuration file. If not specified, output is written to the
135
+ current working directory.
136
+
137
+ --job_index (str, optional):
138
+ Comma-separated list of scenario or job indices to execute. If not
139
+ provided, the value is read from the environment variable specified
140
+ by ``--job_index_var``.
141
+
142
+ --job_index_var (str, optional):
143
+ Name of the environment variable containing the job index.
144
+ Defaults to ``SLURM_ARRAY_TASK_ID``.
145
+ Examples:
146
+ Basic usage in a command line prompt:
147
+
148
+ >>> zen-garden --config=".\config.json" --dataset="1_base_case"
149
+
150
+ Returns:
151
+ None
152
+ """
153
+ # parse command line arguments
154
+ parser = build_parser()
155
+ args = parser.parse_args()
156
+
157
+ ### get the job index
158
+ job_index = resolve_job_index(args.job_index, args.job_index_var)
159
+
160
+ run(
161
+ config=args.config,
162
+ dataset = args.dataset,
163
+ folder_output = args.folder_output,
164
+ job_index = job_index,
165
+ )
@@ -0,0 +1,24 @@
1
+ from zen_temple.main import parse_arguments_and_run
2
+
3
+ def cli_zen_visualization():
4
+ """
5
+ Entry point for the `zen-visualization` command-line interface.
6
+
7
+ This function initializes and runs the command-line interface (CLI)
8
+ for the ZEN-garden visualization platform. It delegates argument parsing
9
+ and command execution to the `parse_arguments_and_run` command of
10
+ the ``ZEN-temple`` package.
11
+
12
+ The ``[project.scripts]`` section of the pyproject.toml declares that
13
+ this function will be called whenever a user enters ``zen-visualization``
14
+ into the command prompt.
15
+
16
+ Returns:
17
+ None
18
+
19
+ Examples:
20
+ Basic usage in a command line prompt:
21
+
22
+ >>> zen-visualization
23
+ """
24
+ parse_arguments_and_run()
File without changes
@@ -729,7 +729,7 @@ class Scaling:
729
729
 
730
730
  def run_scaling(self):
731
731
  """
732
- Runs the scaling algorithm. Function called in _internal.py.
732
+ Runs the scaling algorithm. Function called in runner.py.
733
733
  """
734
734
  logging.info(f"\n--- Start Scaling ---\n")
735
735
  t0 = time.perf_counter()
@@ -3,26 +3,52 @@ This function runs ZEN garden,it is executed in the __main__.py script.
3
3
  Compilation of the optimization problem.
4
4
  """
5
5
  import importlib.util
6
+ from pathlib import Path
6
7
  import logging
7
8
  import os
8
9
  import importlib
9
10
  from .optimization_setup import OptimizationSetup
10
11
  from .postprocess.postprocess import Postprocess
11
12
  from .utils import setup_logger, InputDataChecks, StringUtils, ScenarioUtils
13
+ import zen_garden.default_config as default_config
14
+ import json
15
+ import warnings
12
16
 
13
17
  # we setup the logger here
14
18
  setup_logger()
15
19
 
16
20
 
17
- def main(config, dataset_path=None, job_index=None, folder_output_path=None):
21
+ def run(config = "./config.json", dataset=None, job_index=None,
22
+ folder_output=None):
18
23
  """
19
- This function runs ZEN garden,
20
- it is executed in the __main__.py script
24
+ Run ZEN-garden.
21
25
 
22
- :param config: A config instance used for the run
23
- :param dataset_path: If not None, used to overwrite the config.analysis.dataset
24
- :param job_index: The index of the scenario to run or a list of indices, if None, all scenarios are run in sequence
25
- :param folder_output_path: If not None, used to overwrite the config.analysis.folder_output
26
+ This function is the primary programmatic entry point for running
27
+ ZEN-garden. When called, it reads the configuration, loads the model
28
+ input data, constructs and solves the optimization problem, and saves
29
+ the results.
30
+
31
+ Args:
32
+ config (str): Path to the configuration file (e.g. ``config.json``).
33
+ If the file is located in the current working directory, the
34
+ filename alone may be specified. Defaults to ``"./config.json"``.
35
+ dataset (str): Path to the folder containing the input dataset
36
+ (e.g. ``"./1_base_case"``). If located in the current working
37
+ directory, the folder name alone may be used. Defaults to the
38
+ ``dataset`` value specified in the configuration file.
39
+ folder_output (str): Path to the folder where outputs will be saved.
40
+ Defaults to ``"./outputs"``.
41
+ job_index (list[int] | None): Indices of jobs (scenarios) to run.
42
+ For example, ``job_index=[1]`` runs only the first scenario.
43
+ Defaults to ``None`` (run all jobs).
44
+
45
+ Returns:
46
+ OptimizationSetup: The fully set up and solved optimization problem.
47
+
48
+ Examples:
49
+ >>> from zen_garden import run, download_example_dataset
50
+ >>> download_example_dataset("1_base_case")
51
+ >>> run("1_base_case")
26
52
  """
27
53
 
28
54
  # print the version
@@ -32,13 +58,33 @@ def main(config, dataset_path=None, job_index=None, folder_output_path=None):
32
58
  # prevent double printing
33
59
  logging.propagate = False
34
60
 
61
+ ### import the config
62
+ if not os.path.exists(config):
63
+ config = config.replace(".py", ".json")
64
+ config_path, config_file = os.path.split(os.path.abspath(config))
65
+ if config_file.endswith(".py"):
66
+ spec = importlib.util.spec_from_file_location("module", Path(config_path) / config_file)
67
+ module = importlib.util.module_from_spec(spec)
68
+ spec.loader.exec_module(module)
69
+ config = module.config
70
+ warnings.warn(
71
+ "Use of the `config.py` file is deprecated and will be removed " \
72
+ "in ZEN-garden v3.0.0. Please switch to using a `config.json` " \
73
+ "file instead.",
74
+ DeprecationWarning,
75
+ stacklevel=2
76
+ )
77
+ else:
78
+ with open(Path(config_path) / config_file, "r") as f:
79
+ config = default_config.Config(**json.load(f))
80
+
35
81
  # overwrite the path if necessary
36
- if dataset_path is not None:
82
+ if dataset is not None:
37
83
  # logging.info(f"Overwriting dataset to: {dataset_path}")
38
- config.analysis.dataset = dataset_path
39
- if folder_output_path is not None:
40
- config.analysis.folder_output = os.path.abspath(folder_output_path)
41
- config.solver.solver_dir = os.path.abspath(folder_output_path)
84
+ config.analysis.dataset = dataset
85
+ if folder_output is not None:
86
+ config.analysis.folder_output = os.path.abspath(folder_output)
87
+ config.solver.solver_dir = os.path.abspath(folder_output)
42
88
  logging.info(f"Optimizing for dataset {config.analysis.dataset}")
43
89
  # get the abs path to avoid working dir stuff
44
90
  config.analysis.dataset = os.path.abspath(config.analysis.dataset)
@@ -101,4 +147,4 @@ def main(config, dataset_path=None, job_index=None, folder_output_path=None):
101
147
  Postprocess(optimization_setup, scenarios=config.scenarios, subfolder=subfolder,
102
148
  model_name=model_name, scenario_name=scenario_name, param_map=param_map)
103
149
  logging.info("--- Optimization finished ---")
104
- return optimization_setup
150
+ return optimization_setup
@@ -17,6 +17,10 @@ import shutil
17
17
  from copy import deepcopy
18
18
  from pathlib import Path
19
19
  from zen_garden.default_config import Subscriptable
20
+ import requests
21
+ from importlib.metadata import metadata
22
+ import zipfile
23
+ import io
20
24
 
21
25
  def setup_logger(level=logging.INFO):
22
26
  """ set up logger
@@ -45,6 +49,135 @@ def get_inheritors(klass):
45
49
  work.append(child)
46
50
  return subclasses
47
51
 
52
+ def download_example_dataset(dataset):
53
+ """
54
+ Downloads a dataset example to the current working directory. The function
55
+ downloads the ZEN-garden dataset examples from the ZEN-garden Zenodo
56
+ repository. It then extracts the dataset specified by the user and saves
57
+ it to the current working directory. In addition, it also downloads a
58
+ ``config.json`` file and a Jupyter notebook demonstrating how to analyze
59
+ the results of a model.
60
+
61
+ Args:
62
+ dataset (str): Name of the dataset to be downloaded. The following
63
+ options are currently available: "1_base_case",
64
+ "2_multi_year_optimization", "3_reduced_import_availability",
65
+ "4_PWA_nonlinear_capex", "5_multiple_time_steps_per_year",
66
+ "6_reduced_import_availability_yearly", "7_time_series_aggregation",
67
+ "8_yearly_variation", "9_myopic_foresight", "10_brown_field",
68
+ "11_multi_scenario", "12_multiple_in_output_carriers_conversion",
69
+ "13_yearly_interpolation", "14_retrofitting_and_fuel_substitution",
70
+ "15_unit_consistency_expected_error"
71
+
72
+ Returns:
73
+ tuple:
74
+ str: The local path of the copied example
75
+ str: The local path of the copied config.json
76
+
77
+ Raises:
78
+ FileNotFoundError: If either the dataset or the config file could not
79
+ be found in the Zenodo repository.
80
+
81
+ Examples:
82
+ Basic usage example:
83
+
84
+ >>> from zen_garden.dataset_examples import download_dataset_example
85
+ >>> download_dataset_example("1_base_case")
86
+
87
+ """
88
+
89
+ # retrieve Zenodo metadata
90
+ url = metadata("zen_garden").get_all("Project-URL")
91
+ url = [u.split(", ")[1] for u in url if u.split(", ")[0] == "Zenodo"][0]
92
+
93
+ # fetch Zenodo metadata
94
+ zenodo_meta = requests.get(url, allow_redirects=True)
95
+ zenodo_meta.raise_for_status()
96
+ zenodo_data = zenodo_meta.json()
97
+ zenodo_zip_url = zenodo_data["files"][0]["links"]["self"]
98
+
99
+ # download ZIP file from Zenodo
100
+ zenodo_zip = requests.get(zenodo_zip_url)
101
+ zenodo_zip = zipfile.ZipFile(io.BytesIO(zenodo_zip.content))
102
+
103
+ # define relevant paths
104
+ base_path = zenodo_zip.filelist[0].filename
105
+ example_path = f"{base_path}docs/dataset_examples/{dataset}/"
106
+ config_path = f"{base_path}docs/dataset_examples/config.json"
107
+ notebook_path = f"{base_path}docs/dataset_examples/example_notebook.ipynb"
108
+
109
+ # create local directories
110
+ local_dataset_path = os.getcwd()
111
+ if not os.path.exists(local_dataset_path):
112
+ os.mkdir(local_dataset_path)
113
+ local_example_path = os.path.join(local_dataset_path, dataset)
114
+ if not os.path.exists(local_example_path):
115
+ os.mkdir(local_example_path)
116
+
117
+ # initialize flags for extracting files
118
+ example_found = False
119
+ config_found = False
120
+ notebook_found = False
121
+
122
+ # search for example within ZIP file
123
+ for file in zenodo_zip.filelist:
124
+
125
+ # download all files in dataset example
126
+ if file.filename.startswith(example_path):
127
+ filename_ending = file.filename.split(example_path)[1]
128
+ local_folder_path = os.path.join(
129
+ local_example_path, filename_ending)
130
+ if file.is_dir():
131
+ if not os.path.exists(local_folder_path):
132
+ os.mkdir(os.path.join(local_example_path, filename_ending))
133
+ else:
134
+ local_file_path = os.path.join(
135
+ local_example_path, filename_ending)
136
+ with open(local_file_path, "wb") as f:
137
+ f.write(zenodo_zip.read(file))
138
+ example_found = True
139
+
140
+ # download config.json
141
+ elif file.filename == config_path:
142
+ with open(os.path.join(local_dataset_path, "config.json"), "wb") as f:
143
+ f.write(zenodo_zip.read(file))
144
+ config_found = True
145
+
146
+ # download jupyter notebook
147
+ elif file.filename == notebook_path:
148
+ notebook_path_local = os.path.join(
149
+ local_dataset_path, "example_notebook.ipynb")
150
+ notebook = json.loads(zenodo_zip.read(file))
151
+ for cell in notebook['cells']:
152
+ if cell['cell_type'] == 'code': # Check only code cells
153
+ for i, line in enumerate(cell['source']):
154
+ if "<dataset_name>" in line:
155
+ cell['source'][i] = line.replace(
156
+ "<dataset_name>", dataset)
157
+ with open(notebook_path_local, "w") as f:
158
+ json.dump(notebook, f)
159
+ notebook_found = True
160
+
161
+ # display status, errors, and warnings
162
+ if not example_found:
163
+ raise FileNotFoundError(
164
+ f"Example {dataset} could not be found in the dataset examples!"
165
+ )
166
+ if not config_found:
167
+ raise FileNotFoundError(
168
+ "Config.json file could not be downloaded from the dataset "
169
+ "examples!"
170
+ )
171
+ if not notebook_found:
172
+ warnings.warn(
173
+ "Example jupyter notebook could not be downloaded from the "
174
+ "dataset examples!")
175
+
176
+ # print output
177
+ print(f"Example dataset {dataset} downloaded to {local_example_path}")
178
+
179
+ # return
180
+ return local_example_path, os.path.join(local_dataset_path, "config.json")
48
181
 
49
182
  # linopy helpers
50
183
  # --------------
@@ -1,68 +0,0 @@
1
- """
2
- Runs the main function of ZEN-Garden.
3
- Compilation of the optimization problem.
4
- """
5
- from ._internal import main
6
- import importlib.util
7
- import argparse
8
- import sys
9
- import os
10
- import zen_garden.default_config as default_config
11
- import json
12
- from pathlib import Path
13
-
14
- def run_module(args=None, config = "./config.py", dataset = None,
15
- folder_output = None, job_index = None, job_index_var = "SLURM_ARRAY_TASK_ID"):
16
- """
17
- Runs the main function of ZEN-Garden
18
-
19
- :param args: Arguments to parse
20
- """
21
- if args is None:
22
- args = sys.argv[1:]
23
-
24
- # parse the args
25
- description = "Run ZEN garden with a given config file. Per default, the config file will be read out from the " \
26
- "current working directory. You can specify a config file with the --config argument. However, " \
27
- "note that the output directory will always be the current working directory, independent of the " \
28
- "dataset specified in the config file."
29
- parser = argparse.ArgumentParser(description=description, add_help=True, usage="usage: zen-garden [-h] [--config CONFIG] [--dataset DATASET] [--job_index JOB_INDEX] [--job_index_var JOB_INDEX_VAR]")
30
- # TODO make json config default
31
- parser.add_argument("--config", required=False, type=str, default=config, help="Path to the config file used to run the pipeline (e.g., `./config.json`). Alternatively, if the config file is located in the current working directory, then the file name is alone is also acceptable (e.g. `config.json`).")
32
- parser.add_argument("--dataset", required=False, type=str, default=dataset, help="Path to the dataset (e.g. `./<dataset_name>`). Alternatively, if the dataset is located in the current working directory, then the folder name alone is also acceptable (e.g. `<dataset_name>`). IMPORTANT: This will overwrite the config.analysis.dataset attribute of the config file!")
33
- parser.add_argument("--folder_output", required=False, type=str, default=folder_output, help="Path to the folder where results of the run are stored. IMPORTANT: This will overwrite the "
34
- "config.analysis.folder_output attribute and the config.solver.solver_dir attribute of the config file!")
35
- parser.add_argument("--job_index", required=False, type=str, default=job_index, help="A comma separated list (no spaces) of indices of the scenarios to run, if None, all scenarios are run in sequence")
36
- parser.add_argument("--job_index_var", required=False, type=str, default=job_index_var, help="Try to read out the job index from the environment variable specified here. "
37
- "If both --job_index and --job_index_var are specified, --job_index will be used.")
38
- args = parser.parse_args(args)
39
-
40
- if not os.path.exists(args.config):
41
- args.config = args.config.replace(".py", ".json")
42
-
43
- ### import the config
44
- config_path, config_file = os.path.split(os.path.abspath(args.config))
45
- if config_file.endswith(".py"):
46
- spec = importlib.util.spec_from_file_location("module", Path(config_path) / config_file)
47
- module = importlib.util.module_from_spec(spec)
48
- spec.loader.exec_module(module)
49
- config = module.config
50
- else:
51
- with open(Path(config_path) / config_file, "r") as f:
52
- config = default_config.Config(**json.load(f))
53
-
54
- ### get the job index
55
- job_index = args.job_index
56
- if job_index is None:
57
- if (job_index := os.environ.get(args.job_index_var)) is not None:
58
- job_index = int(job_index)
59
- else:
60
- job_index = [int(i) for i in job_index.split(",")]
61
-
62
- ### run
63
- main(config=config, dataset_path=args.dataset, job_index=job_index, folder_output_path=args.folder_output)
64
-
65
-
66
- if __name__ == "__main__":
67
-
68
- run_module()
@@ -1,186 +0,0 @@
1
- """
2
- This module contains code the coding for downloading the ZEN-garden
3
- dataset examples. It defines a command line interface as well as a python
4
- function for this purpose.
5
- """
6
-
7
- import argparse
8
- import sys
9
- import json
10
- import warnings
11
- import os
12
- import sys
13
- import requests
14
- from importlib.metadata import metadata
15
- import zipfile
16
- import io
17
-
18
-
19
- def download_example_dataset(dataset):
20
- """
21
- Downloads a dataset example to the current working directory. The function
22
- downloads the ZEN-garden dataset examples from the ZEN-garden Zenodo
23
- repository. It then extracts the dataset specified by the user and saves
24
- it to the current working directory. In addition, it also downloads a
25
- ``config.json`` file and a Jupyter notebook demonstrating how to analyze
26
- the results of a model.
27
-
28
- Args:
29
- dataset (str): Name of the dataset to be downloaded. The following
30
- options are currently available: "1_base_case",
31
- "2_multi_year_optimization", "3_reduced_import_availability",
32
- "4_PWA_nonlinear_capex", "5_multiple_time_steps_per_year",
33
- "6_reduced_import_availability_yearly", "7_time_series_aggregation",
34
- "8_yearly_variation", "9_myopic_foresight", "10_brown_field",
35
- "11_multi_scenario", "12_multiple_in_output_carriers_conversion",
36
- "13_yearly_interpolation", "14_retrofitting_and_fuel_substitution",
37
- "15_unit_consistency_expected_error"
38
-
39
- Returns:
40
- tuple:
41
- str: The local path of the copied example
42
- str: The local path of the copied config.json
43
-
44
- Raises:
45
- FileNotFoundError: If either the dataset or the config file could not
46
- be found in the Zenodo repository.
47
-
48
- Examples:
49
- Basic usage example:
50
-
51
- >>> from zen_garden.dataset_examples import download_dataset_example
52
- >>> download_dataset_example("1_base_case")
53
-
54
- """
55
-
56
- # retrieve Zenodo metadata
57
- url = metadata("zen_garden").get_all("Project-URL")
58
- url = [u.split(", ")[1] for u in url if u.split(", ")[0] == "Zenodo"][0]
59
-
60
- # fetch Zenodo metadata
61
- zenodo_meta = requests.get(url, allow_redirects=True)
62
- zenodo_meta.raise_for_status()
63
- zenodo_data = zenodo_meta.json()
64
- zenodo_zip_url = zenodo_data["files"][0]["links"]["self"]
65
-
66
- # download ZIP file from Zenodo
67
- zenodo_zip = requests.get(zenodo_zip_url)
68
- zenodo_zip = zipfile.ZipFile(io.BytesIO(zenodo_zip.content))
69
-
70
- # define relevant paths
71
- base_path = zenodo_zip.filelist[0].filename
72
- example_path = f"{base_path}docs/dataset_examples/{dataset}/"
73
- config_path = f"{base_path}docs/dataset_examples/config.json"
74
- notebook_path = f"{base_path}docs/dataset_examples/example_notebook.ipynb"
75
-
76
- # create local directories
77
- local_dataset_path = os.getcwd()
78
- if not os.path.exists(local_dataset_path):
79
- os.mkdir(local_dataset_path)
80
- local_example_path = os.path.join(local_dataset_path, dataset)
81
- if not os.path.exists(local_example_path):
82
- os.mkdir(local_example_path)
83
-
84
- # initialize flags for extracting files
85
- example_found = False
86
- config_found = False
87
- notebook_found = False
88
-
89
- # search for example within ZIP file
90
- for file in zenodo_zip.filelist:
91
-
92
- # download all files in dataset example
93
- if file.filename.startswith(example_path):
94
- filename_ending = file.filename.split(example_path)[1]
95
- local_folder_path = os.path.join(
96
- local_example_path, filename_ending)
97
- if file.is_dir():
98
- if not os.path.exists(local_folder_path):
99
- os.mkdir(os.path.join(local_example_path, filename_ending))
100
- else:
101
- local_file_path = os.path.join(
102
- local_example_path, filename_ending)
103
- with open(local_file_path, "wb") as f:
104
- f.write(zenodo_zip.read(file))
105
- example_found = True
106
-
107
- # download config.json
108
- elif file.filename == config_path:
109
- with open(os.path.join(local_dataset_path, "config.json"), "wb") as f:
110
- f.write(zenodo_zip.read(file))
111
- config_found = True
112
-
113
- # download jupyter notebook
114
- elif file.filename == notebook_path:
115
- notebook_path_local = os.path.join(
116
- local_dataset_path, "example_notebook.ipynb")
117
- notebook = json.loads(zenodo_zip.read(file))
118
- for cell in notebook['cells']:
119
- if cell['cell_type'] == 'code': # Check only code cells
120
- for i, line in enumerate(cell['source']):
121
- if "<dataset_name>" in line:
122
- cell['source'][i] = line.replace(
123
- "<dataset_name>", dataset)
124
- with open(notebook_path_local, "w") as f:
125
- json.dump(notebook, f)
126
- notebook_found = True
127
-
128
- # display status, errors, and warnings
129
- if not example_found:
130
- raise FileNotFoundError(
131
- f"Example {dataset} could not be found in the dataset examples!"
132
- )
133
- if not config_found:
134
- raise FileNotFoundError(
135
- "Config.json file could not be downloaded from the dataset "
136
- "examples!"
137
- )
138
- if not notebook_found:
139
- warnings.warn(
140
- "Example jupyter notebook could not be downloaded from the "
141
- "dataset examples!")
142
-
143
- # print output
144
- print(f"Example dataset {dataset} downloaded to {local_example_path}")
145
-
146
- # return
147
- return local_example_path, os.path.join(local_dataset_path, "config.json")
148
-
149
-
150
- def cli_download_example_dataset():
151
- """
152
- Creates a command line interface for downloading the dataset examples.
153
- The function parses a single required argument ``--dataset`` that
154
- specifies the name of the dataset to be downloaded. It then invokes
155
- the function function ``download_example_dataset`` with that argument.
156
-
157
- The ``[project.scripts]`` section of the pyproject.toml declares that
158
- this function will be called whenever a user enters ``zen-example`` into
159
- the command prompt. This function is therefore creates the ``zen-example``
160
- command line entry point.
161
-
162
- Examples:
163
- Basic usage in a command line prompt:
164
-
165
- >>> zen-example --dataset="1_base_case"
166
-
167
- """
168
- # parse the args
169
- description = "Downloads an example dataset for ZEN-garden to the current" \
170
- "working directory"
171
-
172
- parser = argparse.ArgumentParser(
173
- description=description,
174
- add_help=True,
175
- usage="usage: zen-example [--dataset DATASET]")
176
-
177
- parser.add_argument(
178
- "--dataset",
179
- required=True,
180
- type=str,
181
- help="Name of the dataset to download, e.g. '1_base_case'")
182
-
183
- args = parser.parse_args(sys.argv[1:])
184
-
185
- # download the example
186
- download_example_dataset(args.dataset)
@@ -1,4 +0,0 @@
1
- from zen_temple.main import parse_arguments_and_run
2
-
3
- if __name__ == "__main__":
4
- parse_arguments_and_run()
File without changes
File without changes