rtc-tools-interface 0.0.1b1__tar.gz → 0.0.1b2__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.
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/PKG-INFO +1 -1
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/rtc_tools_interface.egg-info/PKG-INFO +1 -1
- rtc-tools-interface-0.0.1b2/rtc_tools_interface.egg-info/SOURCES.txt +25 -0
- rtc-tools-interface-0.0.1b2/rtc_tools_interface.egg-info/top_level.txt +2 -0
- rtc-tools-interface-0.0.1b2/rtctools_interface/__init__.py +3 -0
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/rtctools_interface/_version.py +3 -3
- rtc-tools-interface-0.0.1b2/rtctools_interface/optimization/__init__.py +0 -0
- rtc-tools-interface-0.0.1b2/rtctools_interface/optimization/base_goal.py +126 -0
- rtc-tools-interface-0.0.1b2/rtctools_interface/optimization/base_optimization_problem.py +32 -0
- rtc-tools-interface-0.0.1b2/rtctools_interface/optimization/goal_generator_mixin.py +32 -0
- rtc-tools-interface-0.0.1b2/rtctools_interface/optimization/plot_goals_mixin.py +156 -0
- rtc-tools-interface-0.0.1b2/rtctools_interface/optimization/read_goals.py +25 -0
- rtc-tools-interface-0.0.1b2/rtctools_interface/optimization/read_plot_table.py +29 -0
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/setup.py +2 -1
- rtc-tools-interface-0.0.1b2/tests/__init__.py +0 -0
- rtc-tools-interface-0.0.1b2/tests/optimization/__init__.py +0 -0
- rtc-tools-interface-0.0.1b2/tests/optimization/get_test.py +21 -0
- rtc-tools-interface-0.0.1b2/tests/optimization/test_base_optimization_problem.py +23 -0
- rtc-tools-interface-0.0.1b2/tests/optimization/test_plot_goals_mixin.py +41 -0
- rtc-tools-interface-0.0.1b2/tests/optimization/test_read_goals.py +16 -0
- rtc-tools-interface-0.0.1b1/rtc_tools_interface.egg-info/SOURCES.txt +0 -11
- rtc-tools-interface-0.0.1b1/rtc_tools_interface.egg-info/top_level.txt +0 -1
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/COPYING.LESSER +0 -0
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/README.md +0 -0
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/rtc_tools_interface.egg-info/dependency_links.txt +0 -0
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/rtc_tools_interface.egg-info/requires.txt +0 -0
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/setup.cfg +0 -0
- {rtc-tools-interface-0.0.1b1 → rtc-tools-interface-0.0.1b2}/versioneer.py +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
COPYING.LESSER
|
|
2
|
+
README.md
|
|
3
|
+
setup.cfg
|
|
4
|
+
setup.py
|
|
5
|
+
versioneer.py
|
|
6
|
+
rtc_tools_interface.egg-info/PKG-INFO
|
|
7
|
+
rtc_tools_interface.egg-info/SOURCES.txt
|
|
8
|
+
rtc_tools_interface.egg-info/dependency_links.txt
|
|
9
|
+
rtc_tools_interface.egg-info/requires.txt
|
|
10
|
+
rtc_tools_interface.egg-info/top_level.txt
|
|
11
|
+
rtctools_interface/__init__.py
|
|
12
|
+
rtctools_interface/_version.py
|
|
13
|
+
rtctools_interface/optimization/__init__.py
|
|
14
|
+
rtctools_interface/optimization/base_goal.py
|
|
15
|
+
rtctools_interface/optimization/base_optimization_problem.py
|
|
16
|
+
rtctools_interface/optimization/goal_generator_mixin.py
|
|
17
|
+
rtctools_interface/optimization/plot_goals_mixin.py
|
|
18
|
+
rtctools_interface/optimization/read_goals.py
|
|
19
|
+
rtctools_interface/optimization/read_plot_table.py
|
|
20
|
+
tests/__init__.py
|
|
21
|
+
tests/optimization/__init__.py
|
|
22
|
+
tests/optimization/get_test.py
|
|
23
|
+
tests/optimization/test_base_optimization_problem.py
|
|
24
|
+
tests/optimization/test_plot_goals_mixin.py
|
|
25
|
+
tests/optimization/test_read_goals.py
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2023-06-
|
|
11
|
+
"date": "2023-06-27T15:41:22+0200",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.0.
|
|
14
|
+
"full-revisionid": "7ddd0961853c2359d2f270f2afa1e2291843689b",
|
|
15
|
+
"version": "0.0.1b2"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
File without changes
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Module for a basic Goal."""
|
|
2
|
+
import logging
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from rtctools.optimization.goal_programming_mixin import Goal
|
|
6
|
+
from rtctools.optimization.optimization_problem import OptimizationProblem
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger("rtctools")
|
|
9
|
+
|
|
10
|
+
GOAL_TYPES = [
|
|
11
|
+
"range",
|
|
12
|
+
"minimization",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
TARGET_DATA_TYPES = [
|
|
16
|
+
"value",
|
|
17
|
+
"parameter",
|
|
18
|
+
"timeseries",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BaseGoal(Goal):
|
|
23
|
+
"""
|
|
24
|
+
Basic optimization goal for a given state.
|
|
25
|
+
|
|
26
|
+
:cvar goal_type:
|
|
27
|
+
Type of goal ('range' or 'minimization').
|
|
28
|
+
:cvar target_data_type:
|
|
29
|
+
Type of target data ('value', 'parameter', 'timeseries').
|
|
30
|
+
If 'value', set the target bounds by value.
|
|
31
|
+
If 'parameter', set the bounds by a parameter. The target_min
|
|
32
|
+
and/or target_max are expected to be the name of the parameter.
|
|
33
|
+
If 'timeseries', set the bounds by a timeseries. The target_min
|
|
34
|
+
and/or target_max are expected to be the name of the timeseries.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
optimization_problem: OptimizationProblem,
|
|
40
|
+
state,
|
|
41
|
+
goal_type="minimization",
|
|
42
|
+
function_min=np.nan,
|
|
43
|
+
function_max=np.nan,
|
|
44
|
+
function_nominal=np.nan,
|
|
45
|
+
target_data_type="value",
|
|
46
|
+
target_min=np.nan,
|
|
47
|
+
target_max=np.nan,
|
|
48
|
+
priority=1,
|
|
49
|
+
weight=1.0,
|
|
50
|
+
order=2,
|
|
51
|
+
):
|
|
52
|
+
self.state = state
|
|
53
|
+
self.goal_type = None
|
|
54
|
+
self._set_goal_type(goal_type)
|
|
55
|
+
if goal_type == "range":
|
|
56
|
+
self._set_function_bounds(
|
|
57
|
+
optimization_problem=optimization_problem,
|
|
58
|
+
function_min=function_min,
|
|
59
|
+
function_max=function_max)
|
|
60
|
+
self._set_function_nominal(function_nominal)
|
|
61
|
+
if goal_type == "range":
|
|
62
|
+
self._set_target_bounds(
|
|
63
|
+
optimization_problem=optimization_problem,
|
|
64
|
+
target_data_type=target_data_type,
|
|
65
|
+
target_min=target_min,
|
|
66
|
+
target_max=target_max)
|
|
67
|
+
self.priority = priority if np.isfinite(priority) else 1
|
|
68
|
+
self.weight = weight if np.isfinite(weight) else 1.0
|
|
69
|
+
self.order = order if np.isfinite(order) else 2
|
|
70
|
+
|
|
71
|
+
def function(self, optimization_problem, ensemble_member):
|
|
72
|
+
del ensemble_member
|
|
73
|
+
return optimization_problem.state(self.state)
|
|
74
|
+
|
|
75
|
+
def _set_goal_type(
|
|
76
|
+
self,
|
|
77
|
+
goal_type,
|
|
78
|
+
):
|
|
79
|
+
"""Set the goal type."""
|
|
80
|
+
if goal_type in GOAL_TYPES:
|
|
81
|
+
self.goal_type = goal_type
|
|
82
|
+
else:
|
|
83
|
+
raise ValueError(f"goal_type should be one of {GOAL_TYPES}.")
|
|
84
|
+
|
|
85
|
+
def _set_function_bounds(
|
|
86
|
+
self,
|
|
87
|
+
optimization_problem: OptimizationProblem,
|
|
88
|
+
function_min=np.nan,
|
|
89
|
+
function_max=np.nan,
|
|
90
|
+
):
|
|
91
|
+
"""Set function bounds and nominal."""
|
|
92
|
+
self.function_range = [function_min, function_max]
|
|
93
|
+
if not np.isfinite(function_min):
|
|
94
|
+
self.function_range[0] = optimization_problem.bounds()[self.state][0]
|
|
95
|
+
if not np.isfinite(function_max):
|
|
96
|
+
self.function_range[1] = optimization_problem.bounds()[self.state][1]
|
|
97
|
+
|
|
98
|
+
def _set_function_nominal(self, function_nominal):
|
|
99
|
+
"""Set function nominal"""
|
|
100
|
+
self.function_nominal = function_nominal
|
|
101
|
+
if not np.isfinite(self.function_nominal):
|
|
102
|
+
if np.all(np.isfinite(self.function_range)):
|
|
103
|
+
self.function_nominal = np.sum(self.function_range) / 2
|
|
104
|
+
else:
|
|
105
|
+
self.function_nominal = 1.0
|
|
106
|
+
logger.warning("Function nominal not specified, nominal is set to 1.0")
|
|
107
|
+
|
|
108
|
+
def _set_target_bounds(
|
|
109
|
+
self,
|
|
110
|
+
optimization_problem: OptimizationProblem,
|
|
111
|
+
target_data_type="value",
|
|
112
|
+
target_min=np.nan,
|
|
113
|
+
target_max=np.nan,
|
|
114
|
+
):
|
|
115
|
+
"""Set the target bounds."""
|
|
116
|
+
if target_data_type not in TARGET_DATA_TYPES:
|
|
117
|
+
raise ValueError(f"target_data_type should be one of {TARGET_DATA_TYPES}.")
|
|
118
|
+
if target_data_type == "value":
|
|
119
|
+
self.target_min = float(target_min)
|
|
120
|
+
self.target_max = float(target_max)
|
|
121
|
+
elif target_data_type == "parameter":
|
|
122
|
+
self.target_min = optimization_problem.parameters(0)[target_min]
|
|
123
|
+
self.target_max = optimization_problem.parameters(0)[target_max]
|
|
124
|
+
elif target_data_type == "timeseries":
|
|
125
|
+
self.target_min = optimization_problem.get_timeseries(target_min)
|
|
126
|
+
self.target_max = optimization_problem.get_timeseries(target_max)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Module for a basic optimization problem."""
|
|
2
|
+
from rtctools.optimization.collocated_integrated_optimization_problem import (
|
|
3
|
+
CollocatedIntegratedOptimizationProblem,
|
|
4
|
+
)
|
|
5
|
+
from rtctools.optimization.csv_mixin import CSVMixin
|
|
6
|
+
from rtctools.optimization.goal_programming_mixin import GoalProgrammingMixin
|
|
7
|
+
from rtctools.optimization.modelica_mixin import ModelicaMixin
|
|
8
|
+
|
|
9
|
+
from rtctools_interface.optimization.goal_generator_mixin import GoalGeneratorMixin
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BaseOptimizationProblem(
|
|
13
|
+
GoalGeneratorMixin,
|
|
14
|
+
GoalProgrammingMixin,
|
|
15
|
+
CSVMixin,
|
|
16
|
+
ModelicaMixin,
|
|
17
|
+
CollocatedIntegratedOptimizationProblem,
|
|
18
|
+
):
|
|
19
|
+
"""
|
|
20
|
+
Basic optimization problem for a given state.
|
|
21
|
+
|
|
22
|
+
:cvar goal_table_file:
|
|
23
|
+
path to csv file containing a list of goals.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
goal_table_file,
|
|
29
|
+
**kwargs,
|
|
30
|
+
):
|
|
31
|
+
self.goal_table_file = goal_table_file
|
|
32
|
+
super().__init__(**kwargs)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
from rtctools_interface.optimization.read_goals import read_goals
|
|
7
|
+
from rtctools_interface.optimization.base_goal import BaseGoal
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger("rtctools")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GoalGeneratorMixin:
|
|
13
|
+
"""Add path goals as specified in the goal_table.
|
|
14
|
+
|
|
15
|
+
By default, the mixin looks for the csv in the in the default input
|
|
16
|
+
folder. One can also set the path to the goal_table_file manually
|
|
17
|
+
with the `goal_table_file` class variable.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, **kwargs):
|
|
21
|
+
super().__init__(**kwargs)
|
|
22
|
+
if not hasattr(self, "goal_table_file"):
|
|
23
|
+
self.goal_table_file = os.path.join(self._input_folder, "goal_table.csv")
|
|
24
|
+
|
|
25
|
+
def _goal_data_to_goal(self, goal_data: pd.Series):
|
|
26
|
+
"""Convert a series with goal data to a BaseGoal."""
|
|
27
|
+
return BaseGoal(optimization_problem=self, **goal_data.to_dict())
|
|
28
|
+
|
|
29
|
+
def path_goals(self):
|
|
30
|
+
goal_df = read_goals(self.goal_table_file)
|
|
31
|
+
goals = goal_df.apply(self._goal_data_to_goal, axis=1)
|
|
32
|
+
return goals
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import math
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import matplotlib.dates as mdates
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from rtctools_interface.optimization.read_plot_table import read_plot_table
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger("rtctools")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PlotGoalsMixin:
|
|
16
|
+
plot_max_rows = 4
|
|
17
|
+
|
|
18
|
+
def __init__(self, **kwargs):
|
|
19
|
+
super().__init__(**kwargs)
|
|
20
|
+
try:
|
|
21
|
+
plot_table_file = self.plot_table_file
|
|
22
|
+
except AttributeError:
|
|
23
|
+
plot_table_file = os.path.join(self._input_folder, "plot_table.csv")
|
|
24
|
+
self.plot_table = read_plot_table(plot_table_file, self.goal_table_file)
|
|
25
|
+
|
|
26
|
+
def pre(self):
|
|
27
|
+
super().pre()
|
|
28
|
+
self.intermediate_results = []
|
|
29
|
+
|
|
30
|
+
def plot_goal_results_from_dict(self, result_dict, results_dict_prev=None):
|
|
31
|
+
self.plot_goals_results(result_dict, results_dict_prev)
|
|
32
|
+
|
|
33
|
+
def plot_goal_results_from_self(self, priority=None):
|
|
34
|
+
result_dict = {
|
|
35
|
+
"extract_result": self.extract_results(),
|
|
36
|
+
"priority": priority,
|
|
37
|
+
}
|
|
38
|
+
self.plot_goals_results(result_dict)
|
|
39
|
+
|
|
40
|
+
def plot_goals_results(self, result_dict, results_dict_prev=None):
|
|
41
|
+
timeseries_import_times = self.io.datetimes
|
|
42
|
+
extract_result = result_dict["extract_result"]
|
|
43
|
+
all_goals = self.plot_table.to_dict("records")
|
|
44
|
+
range_goals = [goal for goal in all_goals if goal["goal_type"] == "range"]
|
|
45
|
+
min_q_goals = [goal for goal in all_goals if goal["goal_type"] == "minimization"]
|
|
46
|
+
priority = result_dict["priority"]
|
|
47
|
+
|
|
48
|
+
t = self.times()
|
|
49
|
+
t_datetime = np.array(timeseries_import_times)
|
|
50
|
+
results = extract_result
|
|
51
|
+
|
|
52
|
+
# Prepare the plot
|
|
53
|
+
n_plots = len(range_goals + min_q_goals)
|
|
54
|
+
n_cols = math.ceil(n_plots / self.plot_max_rows)
|
|
55
|
+
n_rows = math.ceil(n_plots / n_cols)
|
|
56
|
+
fig, axs = plt.subplots(nrows=n_rows, ncols=n_cols, figsize=(n_cols * 9, n_rows * 3), dpi=80, squeeze=False)
|
|
57
|
+
fig.suptitle("Results after optimizing until priority {}".format(priority), fontsize=14)
|
|
58
|
+
i_plot = -1
|
|
59
|
+
|
|
60
|
+
# Function to apply the general settings used by all goal types
|
|
61
|
+
def apply_general_settings():
|
|
62
|
+
"""Add line with the results for a particular goal. If previous results
|
|
63
|
+
are available, a line with the timeseries for those results is also plotted.
|
|
64
|
+
|
|
65
|
+
Note that this function does also determine the current row and column index
|
|
66
|
+
"""
|
|
67
|
+
i_c = math.ceil((i_plot + 1) / n_rows) - 1
|
|
68
|
+
i_r = i_plot - i_c * n_rows
|
|
69
|
+
|
|
70
|
+
goal_variable = g["state"]
|
|
71
|
+
axs[i_r, i_c].plot(t_datetime, results[goal_variable], label=goal_variable)
|
|
72
|
+
|
|
73
|
+
if results_dict_prev:
|
|
74
|
+
results_prev = results_dict_prev["extract_result"]
|
|
75
|
+
axs[i_r, i_c].plot(
|
|
76
|
+
t_datetime,
|
|
77
|
+
results_prev[goal_variable],
|
|
78
|
+
label=goal_variable + " at previous priority optimization",
|
|
79
|
+
color="gray",
|
|
80
|
+
linestyle="dotted",
|
|
81
|
+
)
|
|
82
|
+
return i_c, i_r
|
|
83
|
+
|
|
84
|
+
def apply_additional_settings(goal_settings):
|
|
85
|
+
"""Sets some additional settings, like additional variables to plot.
|
|
86
|
+
The second list of variables has a specific style, the first not.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
for var in goal_settings["variables_plot_1"]:
|
|
90
|
+
axs[i_row, i_col].plot(t_datetime, results[var], label=var)
|
|
91
|
+
for var in goal_settings["variables_plot_2"]:
|
|
92
|
+
axs[i_row, i_col].plot(t_datetime, results[var], linestyle="solid", linewidth="0.5", label=var)
|
|
93
|
+
axs[i_row, i_col].set_ylabel(goal_settings["y_axis_title"])
|
|
94
|
+
axs[i_row, i_col].legend()
|
|
95
|
+
axs[i_row, i_col].set_title(
|
|
96
|
+
"Goal for {} (active from priority {})".format(goal_settings["state"], goal_settings["priority"])
|
|
97
|
+
)
|
|
98
|
+
dateFormat = mdates.DateFormatter("%d%b%H")
|
|
99
|
+
axs[i_row, i_col].xaxis.set_major_formatter(dateFormat)
|
|
100
|
+
axs[i_row, i_col].grid(which="both", axis="x")
|
|
101
|
+
|
|
102
|
+
# Add plots needed for range goals
|
|
103
|
+
for g in sorted(range_goals, key=lambda goal: goal["priority"]):
|
|
104
|
+
i_plot += 1
|
|
105
|
+
|
|
106
|
+
i_col, i_row = apply_general_settings()
|
|
107
|
+
|
|
108
|
+
if g["target_data_type"] == "parameter":
|
|
109
|
+
target_min = np.full_like(t, 1) * self.parameters(0)[g["target_min"]]
|
|
110
|
+
target_max = np.full_like(t, 1) * self.parameters(0)[g["target_max"]]
|
|
111
|
+
elif g["target_data_type"] == "value":
|
|
112
|
+
target_min = np.full_like(t, 1) * g["target_min"]
|
|
113
|
+
target_max = np.full_like(t, 1) * g["target_max"]
|
|
114
|
+
elif g["target_data_type"] == "timeseries":
|
|
115
|
+
target_min = self.get_timeseries(g["target_min"]).values
|
|
116
|
+
target_max = self.get_timeseries(g["target_max"]).values
|
|
117
|
+
else:
|
|
118
|
+
message = "Target type {} not known.".format(g["target_data_type"])
|
|
119
|
+
logger.error(message)
|
|
120
|
+
raise ValueError(message)
|
|
121
|
+
|
|
122
|
+
if np.array_equal(target_min, target_max, equal_nan=True):
|
|
123
|
+
axs[i_row, i_col].plot(t_datetime, target_min, "r--", label="Target")
|
|
124
|
+
else:
|
|
125
|
+
axs[i_row, i_col].plot(t_datetime, target_min, "r--", label="Target min")
|
|
126
|
+
axs[i_row, i_col].plot(t_datetime, target_max, "r--", label="Target max")
|
|
127
|
+
|
|
128
|
+
apply_additional_settings(g)
|
|
129
|
+
|
|
130
|
+
# Add plots needed for minimization of discharge
|
|
131
|
+
for g in min_q_goals:
|
|
132
|
+
i_plot += 1
|
|
133
|
+
i_col, i_row = apply_general_settings()
|
|
134
|
+
apply_additional_settings(g)
|
|
135
|
+
|
|
136
|
+
# TODO: this should be expanded when there are more columns
|
|
137
|
+
for i in range(0, n_cols):
|
|
138
|
+
axs[n_rows - 1, i].set_xlabel("Time")
|
|
139
|
+
os.makedirs("goal_figures", exist_ok=True)
|
|
140
|
+
fig.tight_layout()
|
|
141
|
+
new_output_folder = os.path.join(self._output_folder, "goal_figures")
|
|
142
|
+
os.makedirs(new_output_folder, exist_ok=True)
|
|
143
|
+
fig.savefig(os.path.join(new_output_folder, "after_priority_{}.png".format(priority)))
|
|
144
|
+
|
|
145
|
+
def priority_completed(self, priority: int) -> None:
|
|
146
|
+
# Store results required for plotting
|
|
147
|
+
to_store = {"extract_result": self.extract_results(), "priority": priority}
|
|
148
|
+
self.intermediate_results.append(to_store)
|
|
149
|
+
super().priority_completed(priority)
|
|
150
|
+
|
|
151
|
+
def post(self):
|
|
152
|
+
super().post()
|
|
153
|
+
for intermediate_result_prev, intermediate_result in zip(
|
|
154
|
+
[None] + self.intermediate_results[:-1], self.intermediate_results
|
|
155
|
+
):
|
|
156
|
+
self.plot_goal_results_from_dict(intermediate_result, intermediate_result_prev)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Module for reading goals from a csv file."""
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
GOAL_PARAMETERS = [
|
|
6
|
+
'state',
|
|
7
|
+
'goal_type',
|
|
8
|
+
'function_min',
|
|
9
|
+
'function_max',
|
|
10
|
+
'function_nominal',
|
|
11
|
+
'target_data_type',
|
|
12
|
+
'target_min',
|
|
13
|
+
'target_max',
|
|
14
|
+
'priority',
|
|
15
|
+
'weight',
|
|
16
|
+
'order',
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def read_goals(file):
|
|
21
|
+
"""Read goals from a cvs file.
|
|
22
|
+
"""
|
|
23
|
+
goals = pd.read_csv(file, sep=",")
|
|
24
|
+
is_active = (goals['active'] == 1)
|
|
25
|
+
return goals.loc[is_active, GOAL_PARAMETERS]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Module for reading goals from a csv file."""
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
from rtctools_interface.optimization.read_goals import GOAL_PARAMETERS
|
|
5
|
+
|
|
6
|
+
PLOT_PARAMETERS = ["id", "y_axis_title", "variables_plot_1", "variables_plot_2"]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def string_to_list(string):
|
|
10
|
+
"""
|
|
11
|
+
Convert a string to a list of strings
|
|
12
|
+
"""
|
|
13
|
+
if string == "" or not isinstance(string, str):
|
|
14
|
+
return []
|
|
15
|
+
string_without_whitespace = string.replace(" ", "")
|
|
16
|
+
list_of_strings = string_without_whitespace.split(",")
|
|
17
|
+
return list_of_strings
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def read_plot_table(plot_table_file, goal_table_file):
|
|
21
|
+
"""Read plot table for PlotGoals and merge with goals table"""
|
|
22
|
+
plot_table = pd.read_csv(plot_table_file, sep=",")
|
|
23
|
+
plot_table[["variables_plot_1", "variables_plot_2"]] = plot_table[
|
|
24
|
+
["variables_plot_1", "variables_plot_2"]
|
|
25
|
+
].applymap(string_to_list)
|
|
26
|
+
goals = pd.read_csv(goal_table_file, sep=",")
|
|
27
|
+
joined_table = plot_table.merge(goals, on="id")
|
|
28
|
+
is_active = goals["active"] == 1
|
|
29
|
+
return joined_table.loc[is_active, PLOT_PARAMETERS + GOAL_PARAMETERS]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from setuptools import setup
|
|
1
|
+
from setuptools import find_packages, setup
|
|
2
2
|
|
|
3
3
|
import versioneer
|
|
4
4
|
|
|
@@ -7,6 +7,7 @@ setup(
|
|
|
7
7
|
name='rtc-tools-interface',
|
|
8
8
|
version=versioneer.get_version(),
|
|
9
9
|
maintainer='Deltares',
|
|
10
|
+
packages=find_packages("."),
|
|
10
11
|
author='Deltares',
|
|
11
12
|
description="Toolbox for user interfaces for RTC-Tools",
|
|
12
13
|
install_requires=["pandas",
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Module for getting optimization test data."""
|
|
2
|
+
import pathlib
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
DATA_DIR = pathlib.Path(__file__).parent.parent / "data"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_test_data(test: str):
|
|
11
|
+
tests_df = pd.read_csv(DATA_DIR / "optimization" / "tests.csv", sep=",")
|
|
12
|
+
tests_df.set_index("test", inplace=True)
|
|
13
|
+
test_data = tests_df.loc[test]
|
|
14
|
+
return {
|
|
15
|
+
"model_folder": DATA_DIR / "models" / test_data["model_folder"],
|
|
16
|
+
"model_name": test_data["model_name"],
|
|
17
|
+
"model_input_folder": DATA_DIR / "model_input" / test_data["model_input_folder"],
|
|
18
|
+
"goals_file": DATA_DIR / "goals" / test_data["goals_file"],
|
|
19
|
+
"plot_table_file": DATA_DIR / "plot_table" / test_data["plot_table_file"],
|
|
20
|
+
"output_folder": DATA_DIR / "optimization" / "output" / test_data["output_folder"],
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from rtctools_interface.optimization.base_optimization_problem import BaseOptimizationProblem
|
|
4
|
+
|
|
5
|
+
from .get_test import get_test_data
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestBaseOptimizationProblem(unittest.TestCase):
|
|
9
|
+
def run_test(self, test):
|
|
10
|
+
test_data = get_test_data(test)
|
|
11
|
+
problem = BaseOptimizationProblem(
|
|
12
|
+
goal_table_file=test_data["goals_file"],
|
|
13
|
+
model_folder=test_data["model_folder"],
|
|
14
|
+
model_name=test_data["model_name"],
|
|
15
|
+
input_folder=test_data["model_input_folder"],
|
|
16
|
+
output_folder=test_data["output_folder"],
|
|
17
|
+
)
|
|
18
|
+
problem.optimize()
|
|
19
|
+
|
|
20
|
+
# TODO: use pytest instead to parametrise tests.
|
|
21
|
+
def test_base_optimization_problem(self):
|
|
22
|
+
for test in ["basic", "target_bounds_as_parameters", "target_bounds_as_timeseries"]:
|
|
23
|
+
self.run_test(test)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from rtctools_interface.optimization.base_optimization_problem import (
|
|
4
|
+
BaseOptimizationProblem,
|
|
5
|
+
)
|
|
6
|
+
from rtctools_interface.optimization.plot_goals_mixin import PlotGoalsMixin
|
|
7
|
+
|
|
8
|
+
from .get_test import get_test_data
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BaseOptimizationProblemPlotting(PlotGoalsMixin, BaseOptimizationProblem):
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
plot_table_file,
|
|
15
|
+
goal_table_file,
|
|
16
|
+
**kwargs,
|
|
17
|
+
):
|
|
18
|
+
self.plot_table_file = plot_table_file
|
|
19
|
+
super().__init__(goal_table_file=goal_table_file, **kwargs)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TestPlotGoalsMixin(unittest.TestCase):
|
|
23
|
+
def run_test(self, test):
|
|
24
|
+
test_data = get_test_data(test)
|
|
25
|
+
problem = BaseOptimizationProblemPlotting(
|
|
26
|
+
goal_table_file=test_data["goals_file"],
|
|
27
|
+
plot_table_file=test_data["plot_table_file"],
|
|
28
|
+
model_folder=test_data["model_folder"],
|
|
29
|
+
model_name=test_data["model_name"],
|
|
30
|
+
input_folder=test_data["model_input_folder"],
|
|
31
|
+
output_folder=test_data["output_folder"],
|
|
32
|
+
)
|
|
33
|
+
problem.optimize()
|
|
34
|
+
|
|
35
|
+
def test_plot_goals_mixin(self):
|
|
36
|
+
for test in [
|
|
37
|
+
"basic",
|
|
38
|
+
"target_bounds_as_parameters",
|
|
39
|
+
"target_bounds_as_timeseries",
|
|
40
|
+
]:
|
|
41
|
+
self.run_test(test)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Test reading goals from a csv file."""
|
|
2
|
+
import pathlib
|
|
3
|
+
import unittest
|
|
4
|
+
|
|
5
|
+
from rtctools_interface.optimization.read_goals import read_goals
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
CSV_FILE = pathlib.Path(__file__).parent.parent / "data" / "goals" / "basic.csv"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestGoalReader(unittest.TestCase):
|
|
12
|
+
|
|
13
|
+
def test_read_csv(self):
|
|
14
|
+
goals = read_goals(CSV_FILE)
|
|
15
|
+
self.assertEqual(len(goals), 2)
|
|
16
|
+
pass
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
COPYING.LESSER
|
|
2
|
-
README.md
|
|
3
|
-
setup.cfg
|
|
4
|
-
setup.py
|
|
5
|
-
versioneer.py
|
|
6
|
-
rtc_tools_interface.egg-info/PKG-INFO
|
|
7
|
-
rtc_tools_interface.egg-info/SOURCES.txt
|
|
8
|
-
rtc_tools_interface.egg-info/dependency_links.txt
|
|
9
|
-
rtc_tools_interface.egg-info/requires.txt
|
|
10
|
-
rtc_tools_interface.egg-info/top_level.txt
|
|
11
|
-
rtctools_interface/_version.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|