Skip to content

Commit

Permalink
(PR #68) Implement pacifist monitoring
Browse files Browse the repository at this point in the history
* Implement pacifist monitoring
* Comment out not-yet-implemented protocol filters feature
  • Loading branch information
edan-bainglass authored Jan 30, 2024
1 parent f632906 commit aaf9fd2
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 16 deletions.
4 changes: 4 additions & 0 deletions aurora.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
" font-family: monospace;\n",
" }\n",
"\n",
" .select-min-height > select {\n",
" min-height: 200px;\n",
" }\n",
"\n",
" .info-logo {\n",
" display: inline-flex;\n",
" width: 25px;\n",
Expand Down
1 change: 1 addition & 0 deletions aurora/experiment/builder/settings/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def toggle_monitor_parameters(self, _=None) -> None:
self.view.check_type,
self.view.threshold,
self.view.consecutive,
self.view.keep_last,
]
else:
self.view.monitor_parameters.children = []
Expand Down
11 changes: 11 additions & 0 deletions aurora/experiment/builder/settings/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def current_state(self) -> dict:
"check_type": self.check_type.value,
"threshold": self.threshold.value,
"consecutive_cycles": self.consecutive.value,
"keep_last": self.keep_last.value,
}

return state
Expand Down Expand Up @@ -168,6 +169,16 @@ def __build_monitors_section(self) -> ipw.VBox:
)
self.defaults[self.consecutive] = self.consecutive.value

self.keep_last = ipw.BoundedIntText(
style=BOX_STYLE,
description="keep last:",
min=1,
max=50,
step=1,
value=10,
)
self.defaults[self.keep_last] = self.keep_last.value

self.monitor_parameters = ipw.VBox()

return ipw.VBox(
Expand Down
4 changes: 2 additions & 2 deletions aurora/experiment/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ def __build_inputs(
inputs["control_settings"][step] = settings_node

monitors = self.builder.get_monitors(step)
monitors_node = self.__build_monitors_input(deepcopy(monitors))
inputs["monitor_settings"][step] = monitors_node
monitors_dict = self.__build_monitors_input(deepcopy(monitors))
inputs["monitor_settings"][step] = monitors_dict

return inputs

Expand Down
2 changes: 1 addition & 1 deletion aurora/inventory/protocols/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def __init__(self, protocols_model: ProtocolsModel):
layout={},
children=[
self.editor,
self.filters,
# self.filters,
ipw.HBox(
layout={},
children=[
Expand Down
67 changes: 60 additions & 7 deletions aurora/results/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from datetime import datetime, timedelta

import pandas as pd
from aiida.orm import Group, QueryBuilder
from aiida.orm import CalcJobNode, Group, QueryBuilder, load_node
from aiida_aurora.calculations import BatteryCyclerExperiment
from traitlets import HasTraits, Unicode

Expand Down Expand Up @@ -87,11 +87,16 @@ def reset_weights(self) -> None:
self.weights.clear()
self.weights_file = ""

def update_experiments(self, group: str, last_days: int) -> None:
def update_experiments(
self,
group: str,
last_days: int,
active_only: bool,
) -> None:
"""docstring"""

group_label = f"{EXPERIMENTS_GROUP_PREFIX}/{group}"
if experiments := query_jobs(group_label, last_days):
if experiments := query_jobs(group_label, last_days, active_only):
df = pd.DataFrame(experiments).sort_values("id")
ctime = df["ctime"].dt.strftime(r"%Y-%m-%d %H:%m:%S")
df["ctime"] = ctime
Expand Down Expand Up @@ -140,10 +145,37 @@ def create_new_group(label: str, members: list[int]) -> None:
group = Group.collection.get_or_create(label)[0]
group.add_nodes(nodes)

def schedule_monitor_kill_order(self, eid: int):
"""docstring"""
node: CalcJobNode = load_node(eid)
flag: str = node.base.extras.get("flag", "")
if "🍅" in flag and "❌" not in flag:
node.base.extras.set_many({
"flag": f"{flag}❌",
"marked_for_death": True,
})

def cancel_monitor_kill_order(self, eid: int):
"""docstring"""
node: CalcJobNode = load_node(eid)
flag: str = node.base.extras.get("flag", "")
if "❌" in flag:
node.base.extras.set_many({
"flag": flag.replace("❌", ""),
"marked_for_death": False,
})

def get_experiment_extras(self, eid: int, field: str) -> str:
"""docstring"""
query = f"id == {eid}"
column = f"extras.{field}"
return self.experiments.query(query)[column].values[0]


def query_jobs(
group: str,
last_days: int,
active_only: bool,
) -> list[BatteryCyclerExperiment]:
"""docstring"""

Expand All @@ -159,10 +191,10 @@ def query_jobs(
"id",
"label",
"ctime",
"attributes.process_label",
"attributes.state",
"attributes.status",
"attributes.process_state",
"extras.monitored",
"extras.flag",
"extras.status",
],
)

Expand All @@ -175,7 +207,28 @@ def query_jobs(
},
)

qb.add_filter("jobs", {"attributes.process_state": "finished"})
qb.add_filter(
"jobs",
{
"and": [
{
"attributes.process_state": "waiting",
},
{
"extras.monitored": True,
},
],
} if active_only else {
"or": [
{
"attributes.process_state": "finished"
},
{
"extras.monitored": True,
},
],
},
)

qb.order_by({"jobs": {"ctime": "desc"}})

Expand Down
34 changes: 28 additions & 6 deletions aurora/results/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def update_view_experiments(self, _=None) -> None:
self.model.update_experiments(
group=self.view.group_selector.value,
last_days=self.view.last_days.value,
active_only=self.view.active_check.value,
)

options = self._build_experiment_selector_options()
Expand Down Expand Up @@ -143,11 +144,26 @@ def toggle_widgets(self, _=None) -> None:
self.toggle_plot_button()
self.update_group_name_state()

def schedule_monitor_kill_order(self, _=None) -> None:
"""docstring"""
for eid in self.view.experiment_selector.value:
self.model.schedule_monitor_kill_order(eid)
self.update_view_experiments()

def cancel_monitor_kill_order(self, _=None) -> None:
"""docstring"""
for eid in self.view.experiment_selector.value:
self.model.cancel_monitor_kill_order(eid)
self.update_view_experiments()

def _set_event_handlers(self) -> None:
"""docstring"""
self.view.on_displayed(self.update_view_experiments)
self.view.plot_button.on_click(self.on_plot_button_clicked)
self.view.update_button.on_click(self.update_view_experiments)
self.view.thumb_down.on_click(self.schedule_monitor_kill_order)
self.view.thumb_up.on_click(self.cancel_monitor_kill_order)
self.view.active_check.observe(self.update_view_experiments, "value")
self.view.group_selector.observe(self.update_view_experiments, "value")
self.view.last_days.observe(self.update_view_experiments, "value")
self.view.experiment_selector.observe(self.toggle_widgets, "value")
Expand All @@ -166,9 +182,20 @@ def reset_weights_file(self, _=None) -> None:

def _build_experiment_selector_options(self) -> list[tuple]:
"""Returns a (option_string, battery_id) list."""
return [(as_option(row), row["id"])
return [(self._cast_row_as_option(row), row["id"])
for _, row in self.model.experiments.iterrows()]

def _cast_row_as_option(self, row: dict) -> str:
"""docstring"""
pk = row["id"]
flag = self.model.get_experiment_extras(pk, "flag") or "❓"
label = row["label"] or "Experiment"
timestamp = row["ctime"]
option = f" {flag} {pk} : {label} : {timestamp}"
return option + f" : {status}" \
if (status := self.model.get_experiment_extras(pk, "status")) \
else option

def _has_valid_selection(self) -> bool:
"""docstring"""

Expand All @@ -182,8 +209,3 @@ def _has_valid_selection(self) -> bool:
return False

return True


def as_option(row: dict) -> str:
"""docstring"""
return f"{row['id']:5} : {row['ctime']} : {row['label'] or 'Experiment'}"
31 changes: 31 additions & 0 deletions aurora/results/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
"width": "fit-content",
}

ACTIVE_CHECK_STYLE = {
"description_width": "5px",
}


class ResultsView(ipw.VBox):
"""
Expand Down Expand Up @@ -70,6 +74,7 @@ def __init__(self) -> None:
"width": "auto",
},
min=0,
max=999,
value=10,
description="Last days:",
)
Expand All @@ -86,6 +91,7 @@ def __init__(self) -> None:
)

self.experiment_selector.add_class("select-monospace")
self.experiment_selector.add_class("select-min-height")

self.plot_type_selector = ipw.Dropdown(
layout={},
Expand All @@ -107,10 +113,32 @@ def __init__(self) -> None:

self.update_button = ipw.Button(
layout=BUTTON_LAYOUT,
button_style="warning",
tooltip="Update experiments",
icon="refresh",
)

self.thumb_down = ipw.Button(
layout=BUTTON_LAYOUT,
button_style="danger",
tooltip="Schedule monitor kill order",
icon="thumbs-down",
)

self.thumb_up = ipw.Button(
layout=BUTTON_LAYOUT,
button_style="success",
tooltip="Cancel monitor kill order",
icon="thumbs-up",
)

self.active_check = ipw.Checkbox(
layout=BUTTON_LAYOUT,
style=ACTIVE_CHECK_STYLE,
description="active jobs only",
value=False,
)

self.group_name = ipw.Text(
layout={},
placeholder="Enter group name",
Expand Down Expand Up @@ -141,6 +169,9 @@ def __init__(self) -> None:
self.plot_type_selector,
self.plot_button,
self.update_button,
self.thumb_down,
self.thumb_up,
self.active_check,
],
),
ipw.HBox(
Expand Down

0 comments on commit aaf9fd2

Please sign in to comment.