Skip to content

Commit 79627ea

Browse files
committed
optimal time prediction now takes max percentage renewable
1 parent f2255c9 commit 79627ea

File tree

4 files changed

+57
-29
lines changed

4 files changed

+57
-29
lines changed

codegreen_core/tools/loadshift_time.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ def _get_energy_data(country, start, end):
2424
Check the country data file if models exists
2525
"""
2626
energy_mode = Config.get("default_energy_mode")
27-
2827
if Config.get("enable_energy_caching") == True:
2928
# check prediction is enabled : get cache or update prediction
3029
try:
@@ -43,6 +42,7 @@ def _get_energy_data(country, start, end):
4342
forecast = energy(country, start, end, "forecast")
4443
elif energy_mode == "public_data":
4544
forecast = energy(country, start, end, "forecast")
45+
# print(forecast)
4646
else:
4747
return None
4848
return forecast["data"]
@@ -53,8 +53,7 @@ def predict_now(
5353
estimated_runtime_hours: int,
5454
estimated_runtime_minutes: int,
5555
hard_finish_date: datetime,
56-
criteria: str = "percent_renewable",
57-
percent_renewable: int = 50,
56+
criteria: str = "percent_renewable"
5857
) -> tuple:
5958
"""
6059
Predicts optimal computation time in the given location starting now
@@ -69,8 +68,6 @@ def predict_now(
6968
:type hard_finish_date: datetime
7069
:param criteria: Criteria based on which optimal time is calculated. Valid value "percent_renewable" or "optimal_percent_renewable"
7170
:type criteria: str
72-
:param percent_renewable: The minimum percentage of renewable energy desired during the runtime
73-
:type percent_renewable: int
7471
:return: Tuple[timestamp, message, average_percent_renewable]
7572
:rtype: tuple
7673
"""
@@ -85,8 +82,7 @@ def predict_now(
8582
energy_data,
8683
estimated_runtime_hours,
8784
estimated_runtime_minutes,
88-
percent_renewable,
89-
hard_finish_date,
85+
hard_finish_date
9086
)
9187
else:
9288
return _default_response(Message.ENERGY_DATA_FETCHING_ERROR)
@@ -104,7 +100,6 @@ def predict_optimal_time(
104100
energy_data: pd.DataFrame,
105101
estimated_runtime_hours: int,
106102
estimated_runtime_minutes: int,
107-
percent_renewable: int,
108103
hard_finish_date: datetime,
109104
request_time: datetime = None,
110105
) -> tuple:
@@ -114,7 +109,6 @@ def predict_optimal_time(
114109
:param energy_data: A DataFrame containing the energy data including startTimeUTC, totalRenewable,total,percent_renewable,posix_timestamp
115110
:param estimated_runtime_hours: The estimated runtime in hours
116111
:param estimated_runtime_minutes: The estimated runtime in minutes
117-
:param percent_renewable: The minimum percentage of renewable energy desired during the runtime
118112
:param hard_finish_date: The latest possible finish time for the task.
119113
:param request_time: The time at which the prediction is requested. Defaults to None, then the current time is used. Assumed to be in local timezone
120114
@@ -123,7 +117,7 @@ def predict_optimal_time(
123117
"""
124118

125119
granularity = 60 # assuming that the granularity of time series is 60 minutes
126-
120+
# print(percent_renewable)
127121
# ============ data validation =========
128122
if not isinstance(hard_finish_date, datetime):
129123
raise ValueError("Invalid hard_finish_date. it must be a datetime object")
@@ -133,6 +127,7 @@ def predict_optimal_time(
133127
raise ValueError("Invalid request_time. it must be a datetime object")
134128
if energy_data is None:
135129
return _default_response(Message.NO_DATA, request_time)
130+
percent_renewable = int(energy_data["percent_renewable"].max()) #assuming we want the max possible percent renewable
136131
if percent_renewable <= 0:
137132
return _default_response(Message.NEGATIVE_PERCENT_RENEWABLE, request_time)
138133
if estimated_runtime_hours <= 0:

codegreen_core/utilities/config.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ class Config:
1313
config_data = None
1414
section_name = "codegreen"
1515
boolean_keys = {"enable_energy_caching", "enable_time_prediction_logging"}
16-
defaults = {"default_energy_mode": "public_data", "enable_energy_caching": False}
16+
defaults = {
17+
"default_energy_mode": "public_data",
18+
"enable_energy_caching": False,
19+
"enable_time_prediction_logging": False,
20+
"energy_redis_path": None,
21+
}
1722

1823
@classmethod
1924
def load_config(self, file_path=None):
@@ -34,6 +39,12 @@ def load_config(self, file_path=None):
3439
self.config_data = configparser.ConfigParser()
3540
self.config_data.read(file_path)
3641

42+
if self.section_name not in self.config_data:
43+
self.config_data[self.section_name] = {}
44+
for key, default_value in self.defaults.items():
45+
if not self.config_data.has_option(self.section_name, key):
46+
self.config_data.set(self.section_name, key, str(default_value))
47+
3748
if self.get("enable_energy_caching") == True:
3849
if self.get("energy_redis_path") is None:
3950
raise ConfigError(
@@ -42,6 +53,7 @@ def load_config(self, file_path=None):
4253
else:
4354
r = redis.from_url(self.get("energy_redis_path"))
4455
r.ping()
56+
# print(self.config_data["default_energy_mode"])
4557

4658
@classmethod
4759
def get(self, key):
@@ -60,4 +72,4 @@ def get(self, key):
6072
value = value.lower() == "true"
6173
return value
6274
except (configparser.NoSectionError, configparser.NoOptionError):
63-
return None
75+
return self.defaults.get(key) # Return default if key is missing

tests/test_loadshift_time.py

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ class TestOptimalTimeCore:
2525
def test_energy_data_blank(self):
2626
"""test if no energy data is provided, the result defaults to the request time"""
2727
timestamp, message, average_percent_renewable = ts.predict_optimal_time(
28-
None, 1, 1, 1, self.hard_finish_time_1, self.request_time_1
28+
None, 1, 1, self.hard_finish_time_1, self.request_time_1
2929
)
30+
# print(timestamp, message, average_percent_renewable)
3031
assert timestamp == int(self.request_time_1.timestamp())
3132
assert message == Message.NO_DATA
3233
assert average_percent_renewable == 0
@@ -37,9 +38,8 @@ def test_neg_hour(self):
3738
self.dummy_energy_data_1,
3839
-1,
3940
1,
40-
1,
4141
self.hard_finish_time_1,
42-
self.request_time_1,
42+
self.request_time_1
4343
)
4444
assert timestamp == int(self.request_time_1.timestamp())
4545
assert message == Message.INVALID_DATA
@@ -51,9 +51,8 @@ def test_zero_hour(self):
5151
self.dummy_energy_data_1,
5252
0,
5353
1,
54-
1,
5554
self.hard_finish_time_1,
56-
self.request_time_1,
55+
self.request_time_1
5756
)
5857
assert timestamp == int(self.request_time_1.timestamp())
5958
assert message == Message.INVALID_DATA
@@ -65,21 +64,26 @@ def test_neg_min(self):
6564
self.dummy_energy_data_1,
6665
1,
6766
-1,
68-
1,
6967
self.hard_finish_time_1,
70-
self.request_time_1,
68+
self.request_time_1
7169
)
7270
assert timestamp == int(self.request_time_1.timestamp())
7371
assert message == Message.INVALID_DATA
7472
assert average_percent_renewable == 0
7573

7674
def test_zero_per_renew(self):
7775
"""test if 0 % renewable , the result defaults to the request time"""
76+
dummy_energy_data_2 = pd.DataFrame(
77+
{
78+
"startTimeUTC": [1, 2, 3],
79+
"totalRenewable": [1, 2, 3],
80+
"percent_renewable": [0, 0, 0],
81+
}
82+
)
7883
timestamp, message, average_percent_renewable = ts.predict_optimal_time(
79-
self.dummy_energy_data_1,
84+
dummy_energy_data_2,
8085
1,
8186
0,
82-
-10,
8387
self.hard_finish_time_1,
8488
self.request_time_1,
8589
)
@@ -89,13 +93,19 @@ def test_zero_per_renew(self):
8993

9094
def test_neg_per_renew(self):
9195
"""test if negative -ve % renew is provided, the result defaults to the request time"""
96+
dummy_energy_data_3 = pd.DataFrame(
97+
{
98+
"startTimeUTC": [1, 2, 3],
99+
"totalRenewable": [1, 2, 3],
100+
"percent_renewable": [-1, -4, -5],
101+
}
102+
)
92103
timestamp, message, average_percent_renewable = ts.predict_optimal_time(
93-
self.dummy_energy_data_1,
104+
dummy_energy_data_3,
94105
1,
95106
0,
96-
0,
97107
self.hard_finish_time_1,
98-
self.request_time_1,
108+
self.request_time_1
99109
)
100110
assert timestamp == int(self.request_time_1.timestamp())
101111
assert message == Message.NEGATIVE_PERCENT_RENEWABLE
@@ -107,9 +117,8 @@ def test_less_energy_data(self):
107117
self.dummy_energy_data_1,
108118
20,
109119
0,
110-
10,
111120
self.hard_finish_time_1,
112-
self.request_time_1,
121+
self.request_time_1
113122
)
114123
assert timestamp == int(self.request_time_1.timestamp())
115124
assert message == Message.RUNTIME_LONGER_THAN_DEADLINE_ALLOWS
@@ -118,7 +127,7 @@ def test_if_incorrect_data_provided(self):
118127
"""this is to test if energy data provided does not contain the data for the request time"""
119128
data = pd.read_csv("tests/data/DE_forecast1.csv")
120129
timestamp, message, average_percent_renewable = ts.predict_optimal_time(
121-
data, 20, 0, 10, self.hard_finish_time_2, self.request_time_2
130+
data, 20, 0, self.hard_finish_time_2, self.request_time_2
122131
)
123132
assert timestamp == int(self.request_time_2.timestamp())
124133
assert message == Message.NO_DATA
@@ -225,7 +234,7 @@ def test_multiple(self):
225234
def test_data_validation_country(self):
226235
timestamp1 = int(datetime.now(timezone.utc).timestamp())
227236
timestamp, message, average_percent_renewable = ts.predict_now(
228-
"UFO", 10, 0, datetime(2024, 9, 7), "percent_renewable", 30
237+
"UFO", 10, 0, datetime(2024, 9, 7), "percent_renewable"
229238
)
230239
print(timestamp1, timestamp, message)
231240
assert timestamp - timestamp1 <= 10
@@ -269,7 +278,6 @@ def test_all_country():
269278
energy_data,
270279
row["runtime_hour"],
271280
row["runtime_min"],
272-
row["percent_renewable"],
273281
end,
274282
start,
275283
)

tests/use_tools.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from codegreen_core.utilities.message import CodegreenDataError, Message
2+
from datetime import datetime, timezone, timedelta
3+
import codegreen_core.tools.loadshift_time as ts
4+
import pandas as pd
5+
import pytz
6+
7+
try:
8+
a,b,c, = ts.predict_now("DE",12,0,datetime(2024,10,30,23,00,00))
9+
except Exception as e:
10+
print(e)
11+
12+
13+
#print(a,b,c)

0 commit comments

Comments
 (0)