Skip to content

Plot the carbon intensity time series #112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion cats/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .CI_api_query import get_CI_forecast # noqa: F401
from .configure import get_runtime_config
from .constants import CATS_ASCII_BANNER_COLOUR, CATS_ASCII_BANNER_NO_COLOUR
from .plotting import plotplan
from .forecast import CarbonIntensityAverageEstimate, WindowedForecast

__version__ = "1.0.0"
Expand Down Expand Up @@ -193,6 +194,13 @@ def positive_integer(string):
action="store_true",
help="Disable all terminal output colouring (alias to --no-colour)",
)
parser.add_argument(
"--plot",
help="Create a plot of the forecast and optimised plan for the job."
"This needs matplotlib to be installed, e.g. install with"
"\"pip install 'climate-aware-task-scheduler[plots]'\"",
action="store_true",
)

return parser

Expand Down Expand Up @@ -230,7 +238,7 @@ def __str__(self) -> str:
col_ee_opt = ""

out = f"""
Best job start time = {col_dt_opt}{self.carbonIntensityOptimal.start}{col_normal}
Best job start time = {col_dt_opt}{self.carbonIntensityOptimal.start:%Y-%m-%d %H:%M:%S}{col_normal}
Carbon intensity if job started now = {col_ci_now}{self.carbonIntensityNow.value:.2f} gCO2eq/kWh{col_normal}
Carbon intensity at optimal time = {col_ci_opt}{self.carbonIntensityOptimal.value:.2f} gCO2eq/kWh{col_normal}"""

Expand Down Expand Up @@ -383,6 +391,8 @@ def main(arguments=None) -> int:
print(output.to_json(dateformat, sort_keys=True, indent=2))
else:
print(output)
if args.plot:
plotplan(CI_forecast, output)
if args.command:
if args.scheduler == "at":
err = schedule_at(output, args.command.split())
Expand Down
56 changes: 56 additions & 0 deletions cats/plotting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
try:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
have_matplotlib = True
except ImportError:
have_matplotlib = False


def plotplan(CI_forecast, output):
"""
Plot the carbon intensity forecast and optimised plan
"""
if not have_matplotlib:
print("To plot graphs you must import matplotlib")
print("e.g. \"pip install 'climate-aware-task-scheduler[plots]'\"")
return None

# Just for now pull the CI forecast apart... probably belongs as method...
values = []
times = []
now_values = []
now_times = []
opt_values = []
opt_times = []
for point in CI_forecast:
values.append(point.value)
times.append(point.datetime)
if (point.datetime >= output.carbonIntensityOptimal.start and
point.datetime <= output.carbonIntensityOptimal.end):
opt_values.append(point.value)
opt_times.append(point.datetime)
if (point.datetime >= output.carbonIntensityNow.start and
point.datetime <= output.carbonIntensityNow.end):
now_values.append(point.value)
now_times.append(point.datetime)

# Make the plot (should probably take fig and ax as opt args...)
fig, ax = plt.subplots()
ax.fill_between(times, 0.0, values, alpha=0.2, color='b')
ax.fill_between(now_times, 0.0, now_values, alpha=0.6, color='r')
ax.fill_between(opt_times, 0.0, opt_values, alpha=0.6, color='g')

ax.text(0.125, 1.075, f"Mean carbon intensity if job started now: {output.carbonIntensityNow.value:.2f} gCO2eq/kWh",
transform=ax.transAxes, color='red')
ax.text(0.125, 1.025, f"Mean carbon intensity at optimal time: {output.carbonIntensityOptimal.value:.2f} gCO2eq/kWh",
transform=ax.transAxes, color='green')

ax.set_xlabel("Time (mm-dd hh)")
ax.xaxis.set_major_formatter(mdates.DateFormatter("%d-%m-%y %H:%M"))
ax.xaxis.set_minor_formatter(mdates.DateFormatter("%d-%m-%y %H:%M"))
ax.set_ylabel("Forecast carbon intensity (gCO2eq/kWh)")
ax.grid(True)
ax.label_outer()
fig.autofmt_xdate()
plt.show()
return None
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@
version = {attr = "cats.__version__"}

[project.optional-dependencies]
test = ["pytest", "numpy>=1.5.0", "pytest-subprocess==1.5.0", "pytest-cov"]
test = ["pytest", "numpy>=1.5.0", "pytest-subprocess==1.5.0", "pytest-cov", "matplotlib>=3.0"]
types = ["mypy", "types-PyYAML", "types-redis", "types-requests", "types-ujson"]
docs = ["sphinx==6.*", "sphinx-argparse", "ghp-import", "renku-sphinx-theme", "sphinx_copybutton"]
plots = ["matplotlib>=3.0"]

[project.urls]
Home = "https://github.com/GreenScheduler/cats"
Expand Down