Skip to content
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

Fix/638/remove job selection #849

Merged
merged 8 commits into from
Oct 9, 2024
Merged
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
11 changes: 6 additions & 5 deletions qe.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,14 @@
"url = urlparse.urlsplit(jupyter_notebook_url) # noqa F821\n",
"query = urlparse.parse_qs(url.query)\n",
"\n",
"app_with_work_chain_selector = App(qe_auto_setup=True)\n",
"# if a pk is provided in the query string, set it as the value of the work_chain_selector\n",
"app = App(qe_auto_setup=True)\n",
"# if a pk is provided in the query string, set it as the process of the app\n",
"if \"pk\" in query:\n",
" pk = int(query[\"pk\"][0])\n",
" app_with_work_chain_selector.work_chain_selector.value = pk\n",
" pk = query[\"pk\"][0]\n",
" app.process = pk\n",
"\n",
"view.main.children = [app_with_work_chain_selector]"
"view.main.children = [app]\n",
"view.app = app"
]
},
{
Expand Down
33 changes: 21 additions & 12 deletions src/aiidalab_qe/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,23 @@
"""

import ipywidgets as ipw
import traitlets as tl
from IPython.display import Javascript, display

from aiida.orm import load_node
from aiidalab_qe.app.configuration import ConfigureQeAppWorkChainStep
from aiidalab_qe.app.result import ViewQeAppWorkChainStatusAndResultsStep
from aiidalab_qe.app.structure import StructureSelectionStep
from aiidalab_qe.app.submission import SubmitQeAppWorkChainStep
from aiidalab_qe.common import QeAppWorkChainSelector
from aiidalab_widgets_base import WizardAppWidget, WizardAppWidgetStep


class App(ipw.VBox):
"""The main widget that combines all the application steps together."""

# The PK or UUID of the work chain node.
process = tl.Union([tl.Unicode(), tl.Int()], allow_none=True)

def __init__(self, qe_auto_setup=True):
# Create the application steps
self.structure_step = StructureSelectionStep(auto_advance=True)
Expand Down Expand Up @@ -64,23 +68,27 @@ def __init__(self, qe_auto_setup=True):
("Status & Results", self.results_step),
]
)
# hide the header
self._wizard_app_widget.children[0].layout.display = "none"
self._wizard_app_widget.observe(self._observe_selected_index, "selected_index")

# Add process selection header
self.work_chain_selector = QeAppWorkChainSelector(
layout=ipw.Layout(width="auto")
# Add a button to start a new calculation
self.new_work_chains_button = ipw.Button(
description="Start New Calculation",
tooltip="Open a new page to start a separate calculation",
button_style="success",
icon="plus-circle",
layout=ipw.Layout(width="30%"),
)
self.work_chain_selector.observe(self._observe_process_selection, "value")

ipw.dlink(
(self.submit_step, "process"),
(self.work_chain_selector, "value"),
transform=lambda node: None if node is None else node.pk,
)
def on_button_click(_):
display(Javascript("window.open('./qe.ipynb', '_blank')"))

self.new_work_chains_button.on_click(on_button_click)

super().__init__(
children=[
self.work_chain_selector,
self.new_work_chains_button,
self._wizard_app_widget,
]
)
Expand Down Expand Up @@ -119,7 +127,8 @@ def _observe_selected_index(self, change):
)
self.submit_step.external_submission_blockers = blockers

def _observe_process_selection(self, change):
@tl.observe("process")
def _observe_process(self, change):
from aiida.orm.utils.serialize import deserialize_unsafe

if change["old"] == change["new"]:
Expand Down
24 changes: 16 additions & 8 deletions src/aiidalab_qe/app/utils/search_jobs.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import ipywidgets as ipw
import pandas as pd
from IPython.display import display

from aiida.orm import QueryBuilder
from aiidalab_qe.workflows import QeAppWorkChain


class QueryInterface:
def __init__(self):
pass

def setup_table(self):
import ipywidgets as ipw

self.df = self.load_data()
self.table = ipw.HTML()
self.setup_widgets()

def load_data(self):
import pandas as pd

from aiida.orm import QueryBuilder
from aiidalab_qe.workflows import QeAppWorkChain

projections = [
"id",
"extras.structure",
Expand Down Expand Up @@ -70,6 +72,8 @@ def load_data(self):
]

def setup_widgets(self):
import ipywidgets as ipw

AndresOrtegaGuerrero marked this conversation as resolved.
Show resolved Hide resolved
self.css_style = """
<style>
.df { border: none; }
Expand Down Expand Up @@ -151,6 +155,8 @@ def get_table_value(self, display_df):
)

def apply_filters(self, _):
import pandas as pd

selected_properties = [
cb.description for cb in self.properties_box.children if cb.value
]
Expand Down Expand Up @@ -184,5 +190,7 @@ def apply_filters(self, _):
self.get_table_value(filtered_df)

def display(self):
from IPython.display import display

display(self.filters_layout)
display(self.table)
32 changes: 32 additions & 0 deletions src/aiidalab_qe/app/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,42 @@ def enable_toggles(self) -> None:
"""Enable the toggle buttons."""
self._view.guide_toggle.disabled = False
self._view.about_toggle.disabled = False
self._view.job_history_toggle.disabled = False

@without_triggering("about_toggle")
def _on_guide_toggle(self, change: dict):
"""Toggle the guide section."""
if change["new"]:
self._view.job_history_toggle.value = False
self._view.info_container.children = [self._view.guide] if change["new"] else []
self._view.info_container.layout.display = "flex" if change["new"] else "none"

@without_triggering("guide_toggle")
def _on_about_toggle(self, change: dict):
"""Toggle the about section."""
if change["new"]:
self._view.job_history_toggle.value = False
self._view.info_container.children = [self._view.about] if change["new"] else []
self._view.info_container.layout.display = "flex" if change["new"] else "none"

def _on_job_history_toggle(self, change: dict):
"""Toggle the job list section."""
if change["new"]:
self._view.about_toggle.value = False
self._view.guide_toggle.value = False
self._view.job_history.setup_table()
self._view.main.children = [
self._view.job_history.filters_layout,
self._view.job_history.table,
]
else:
self._view.main.children = [self._view.app]

def _set_event_handlers(self) -> None:
"""Set up event handlers."""
self._view.guide_toggle.observe(self._on_guide_toggle, "value")
self._view.about_toggle.observe(self._on_about_toggle, "value")
self._view.job_history_toggle.observe(self._on_job_history_toggle, "value")


class AppWrapperModel(traitlets.HasTraits):
Expand All @@ -89,6 +108,7 @@ def __init__(self) -> None:
from jinja2 import Environment

from aiidalab_qe.app.static import templates
from aiidalab_qe.app.utils.search_jobs import QueryInterface
from aiidalab_qe.common.infobox import InfoBox
from aiidalab_qe.version import __version__

Expand Down Expand Up @@ -125,10 +145,21 @@ def __init__(self) -> None:
disabled=True,
)

self.job_history_toggle = ipw.ToggleButton(
button_style="",
icon="list",
value=False,
description="Job History",
tooltip="View all jobs run with this app",
disabled=True,
layout=ipw.Layout(width="auto"),
)

info_toggles = ipw.HBox(
children=[
self.guide_toggle,
self.about_toggle,
self.job_history_toggle,
]
)
info_toggles.add_class("info-toggles")
Expand All @@ -141,6 +172,7 @@ def __init__(self) -> None:
self.about = ipw.HTML(env.from_string(about_template).render())

self.info_container = InfoBox()
self.job_history = QueryInterface()

header = ipw.VBox(
children=[
Expand Down
4 changes: 2 additions & 2 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def test_reload_and_reset(submit_app_generator, generate_qeapp_workchain):
)
app = submit_app_generator()
# select the pk
app.work_chain_selector.value = wkchain.node.pk
app.process = wkchain.node.pk
# check if the value are reload correctly
assert app.configure_step.workchain_settings.relax_type.value == "positions"
assert app.configure_step.workchain_settings.spin_type.value == "collinear"
Expand All @@ -30,7 +30,7 @@ def test_reload_and_reset(submit_app_generator, generate_qeapp_workchain):
app._wizard_app_widget.selected_index = 2
assert app.configure_step.state == app.configure_step.State.SUCCESS
# new workflow, this will reset the GUI
app.work_chain_selector.value = None
app.process = None
# check if the value are reload correctly
assert app.structure_step.manager.structure is None
assert app.configure_step.workchain_settings.relax_type.value == "positions_cell"
Expand Down
Loading