Skip to content

Commit

Permalink
Enabled the catalog selection combobox in the run browser.
Browse files Browse the repository at this point in the history
  • Loading branch information
canismarko committed Jan 14, 2025
1 parent b2c706b commit 3c664a3
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 55 deletions.
6 changes: 3 additions & 3 deletions src/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ def filters(sim_registry):

mapping = {
"255id_testing": MapAdapter(bluesky_mapping),
"255bm_testing": MapAdapter(bluesky_mapping),
}

tree = MapAdapter(mapping)
Expand All @@ -389,13 +390,12 @@ def tiled_client():
app = build_app(tree)
with Context.from_app(app) as context:
client = from_context(context)
yield client["255id_testing"]
yield client


@pytest.fixture()
def catalog(tiled_client):
cat = Catalog(client=tiled_client)
# cat = mock.AsyncMock()
cat = Catalog(client=tiled_client["255id_testing"])
return cat


Expand Down
14 changes: 6 additions & 8 deletions src/firefly/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,15 @@ async def finalize_new_window(self, action):
# Send the current devices to the window
await action.window.update_devices(self.registry)

def finalize_run_browser_window(self, action):
"""Connect up signals that are specific to the run browser window."""
@asyncSlot(QAction)
async def finalize_run_browser_window(self, action):
"""Connect up run browser signals and load initial data."""
display = action.display
self.run_updated.connect(display.update_running_scan)
self.run_stopped.connect(display.update_running_scan)
# Set initial state for the run_browser
config = load_config()['database']['tiled']
await display.change_catalog(config['entry_node'])

def finalize_status_window(self, action):
"""Connect up signals that are specific to the voltmeters window."""
Expand Down Expand Up @@ -652,12 +656,6 @@ async def add_queue_item(self, item):
if getattr(self, "_queue_client", None) is not None:
await self._queue_client.add_queue_item(item)

@QtCore.Slot()
def show_sample_viewer_window(self):
return self.show_window(
FireflyMainWindow, ui_dir / "sample_viewer.ui", name="sample_viewer"
)

@QtCore.Slot(bool)
def set_open_environment_action_state(self, is_open: bool):
"""Update the readback value for opening the queueserver environment."""
Expand Down
29 changes: 25 additions & 4 deletions src/firefly/run_browser/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
import datetime as dt
import logging
import warnings
Expand All @@ -7,6 +8,7 @@
import numpy as np
import pandas as pd
from tiled import queries
from qasync import asyncSlot

from haven import exceptions
from haven.catalog import Catalog
Expand All @@ -16,13 +18,31 @@

class DatabaseWorker:
selected_runs: Sequence = []
catalog: Catalog = None

def __init__(self, catalog=None, *args, **kwargs):
if catalog is None:
catalog = Catalog()
self.catalog = catalog
def __init__(self, tiled_client, *args, **kwargs):
self.client = tiled_client
super().__init__(*args, **kwargs)

@asyncSlot(str)
async def change_catalog(self, catalog_name: str):
"""Change the catalog being used for pulling data.
*catalog_name* should be an entry in *worker.tiled_client()*.
"""
def get_catalog(name):
return Catalog(self.client[catalog_name])

loop = asyncio.get_running_loop()
self.catalog = await loop.run_in_executor(None, get_catalog, catalog_name)

async def catalog_names(self):
def get_names():
return list(self.client.keys())

loop = asyncio.get_running_loop()
return await loop.run_in_executor(None, get_names)

async def filtered_nodes(self, filters: Mapping):
case_sensitive = False
log.debug(f"Filtering nodes: {filters}")
Expand All @@ -49,6 +69,7 @@ async def filtered_nodes(self, filters: Mapping):
return runs

async def load_distinct_fields(self):

"""Get distinct metadata fields for filterable metadata."""
new_fields = {}
target_fields = [
Expand Down
33 changes: 24 additions & 9 deletions src/firefly/run_browser/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from qtpy.QtGui import QStandardItem, QStandardItemModel
from ophyd_async.core import Device
from ophyd import Device as ThreadedDevice
from tiled.client.container import Container
from pydm import PyDMChannel

from firefly import display
Expand Down Expand Up @@ -60,16 +61,29 @@ class RunBrowserDisplay(display.FireflyDisplay):
# Counter for keeping track of UI hints for long DB hits
_busy_hinters: Counter

def __init__(self, root_node=None, args=None, macros=None, **kwargs):
def __init__(self, args=None, macros=None, **kwargs):
super().__init__(args=args, macros=macros, **kwargs)
self.selected_runs = []
self._running_db_tasks = {}
self._busy_hinters = Counter()
self.db = DatabaseWorker(catalog=root_node)
# Load the list of all runs for the selection widget
self.db_task(self.load_runs(), name="init_load_runs")
# Load the list of filters' field values into the comboboxes
self.db_task(self.update_combobox_items(), name="update_combobox_items")

async def setup_database(self, tiled_client: Container, catalog_name: str):
"""Prepare to use a set of databases accessible through *tiled_client*.
Parameters
==========
Each key in *tiled_client* should be """
self.db = DatabaseWorker(tiled_client)
self.ui.catalog_combobox.addItems(await self.db.catalog_names())
await self.change_catalog(catalog_name)

async def change_catalog(self, catalog_name: str):
"""Activate a different catalog in the Tiled server."""
await self.db_task(self.db.change_catalog(catalog_name), name="change_catalog")
await self.db_task(asyncio.gather(
self.load_runs(),
self.update_combobox_items()
), name="change_catalog")

def db_task(self, coro, name="default task"):
"""Executes a co-routine as a database task. Existing database
Expand Down Expand Up @@ -143,7 +157,6 @@ async def update_combobox_items(self):
""""""
with self.busy_hints(run_table=False, run_widgets=False, filter_widgets=True):
fields = await self.db.load_distinct_fields()
print(fields)
for field_name, cb in [
("plan_name", self.ui.filter_plan_combobox),
("sample_name", self.ui.filter_sample_combobox),
Expand Down Expand Up @@ -247,7 +260,8 @@ async def update_devices(self, registry):

def setup_bss_channels(self, bss: Device | ThreadedDevice):
"""Setup channels to update the proposal and ESAF ID boxes."""
self.proposal_channel.disconnect()
if getattr(self, "proposal_channel", None) is not None:
self.proposal_channel.disconnect()
self.proposal_channel = PyDMChannel(
address=f"haven://{bss.proposal.proposal_id.name}",
value_slot=partial(
Expand All @@ -256,7 +270,8 @@ def setup_bss_channels(self, bss: Device | ThreadedDevice):
checkbox=self.ui.filter_current_proposal_checkbox,
)
)
self.esaf_channel.disconnect()
if getattr(self, "esaf_channel", None) is not None:
self.esaf_channel.disconnect()
self.esaf_channel = PyDMChannel(
address=f"haven://{bss.esaf.esaf_id.name}",
value_slot=partial(
Expand Down
8 changes: 4 additions & 4 deletions src/firefly/run_browser/run_browser.ui
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@
<item>
<widget class="QLabel" name="label_18">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="text">
<string>Catalog:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_3">
<widget class="QComboBox" name="catalog_combobox">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
</widget>
</item>
Expand Down Expand Up @@ -223,7 +223,7 @@
<x>0</x>
<y>0</y>
<width>373</width>
<height>560</height>
<height>531</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
Expand Down
20 changes: 16 additions & 4 deletions src/firefly/run_browser/tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,35 @@
from firefly.run_browser.client import DatabaseWorker


@pytest.fixture()
async def worker(tiled_client):
worker = DatabaseWorker(tiled_client)
await worker.change_catalog("255id_testing")
return worker


@pytest.mark.asyncio
async def test_catalog_names(worker):
assert (await worker.catalog_names()) == ["255id_testing", "255bm_testing"]


@pytest.mark.asyncio
async def test_filter_runs(catalog):
worker = DatabaseWorker(catalog=catalog)
async def test_filter_runs(worker):
runs = await worker.load_all_runs(filters={"plan": "xafs_scan"})
# Check that the runs were filtered
assert len(runs) == 1


@pytest.mark.asyncio
async def test_distinct_fields(catalog):
worker = DatabaseWorker(catalog=catalog)
async def test_distinct_fields(worker):
distinct_fields = await worker.load_distinct_fields()
# Check that the dictionary has the right structure
for key in ["sample_name"]:
assert key in distinct_fields.keys()




# -----------------------------------------------------------------------------
# :author: Mark Wolfman
# :email: [email protected]
Expand Down
Loading

0 comments on commit 3c664a3

Please sign in to comment.