Skip to content

Commit

Permalink
Merge pull request #192 from spc-group/glados
Browse files Browse the repository at this point in the history
Provide support for the beamline manager (GLaDOS at 25-ID-C).

Got rid of the old BSS support since it was merged into the BeamlineManager class.
  • Loading branch information
canismarko authored Apr 9, 2024
2 parents 5727bce + efef422 commit 75ad122
Show file tree
Hide file tree
Showing 19 changed files with 1,262 additions and 389 deletions.
4 changes: 4 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ dependencies:
- pip
- psutil
- numba>=0.56 # Ensures 0.53 (broken) isn't installed
- # This version of networkx has an importlib bug in it
- networkx < 3.3

# --- testing and quality assurance
- black >=24
Expand Down Expand Up @@ -148,6 +150,8 @@ dependencies:
- xraydb >=4.5.0
- pytest-timeout # Get rid of this if tests are not hanging
- git+https://github.com/pcdshub/pcdsdevices
- git+https://github.com/BCDA-APS/apstools.git@a165d24b2ae272ba0db3fb73d9feba4416f40631
# - git+https://github.com/BCDA-APS/apstools.git@50a142f1cc761553f14570c6c5f7e799846a0ddf
# - https://github.com/BCDA-APS/adl2pydm/archive/main.zip
# --- optional Bluesky framework packages for evaluation
# - bluesky-webclient is NOT Python software, don't install it this way
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = [
]
description = "Tools and GUI for running the spectroscopy group beamlines at the Advanced Photon Source."
readme = "README.md"
requires-python = ">=3.7,<3.11"
requires-python = ">=3.7,<3.10"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
Expand Down
29 changes: 29 additions & 0 deletions src/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from haven.catalog import Catalog
from haven.instrument.aerotech import AerotechStage
from haven.instrument.aps import ApsMachine
from haven.instrument.beamline_manager import BeamlineManager, IOCManager
from haven.instrument.camera import AravisDetector
from haven.instrument.delay import EpicsSignalWithIO
from haven.instrument.dxp import DxpDetector
Expand Down Expand Up @@ -153,6 +154,34 @@ def blade_slits(sim_registry):
return slits


class SimpleBeamlineManager(BeamlineManager):
"""For a fake class, we need to un-override __new__ to just make
itself.
"""

iocs = DDC(
{
"ioc255idb": (IOCManager, "ioc255idb:", {}),
"ioc255idc": (IOCManager, "ioc255idc:", {}),
}
)

def __new__(cls, *args, **kwargs):
return object.__new__(cls)


@pytest.fixture()
def beamline_manager(sim_registry):
"""A fake set of slits using the 4-blade setup."""
FakeManager = make_fake_device(SimpleBeamlineManager)
manager = FakeManager(
prefix="companionCube:", name="companion_cube", labels={"beamline_manager"}
)
sim_registry.register(manager)
return manager


@pytest.fixture()
def aperture_slits(sim_registry):
"""A fake slit assembling using the rotary aperture design."""
Expand Down
42 changes: 29 additions & 13 deletions src/firefly/bss.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import logging
from functools import lru_cache

import qtawesome as qta
from apsbss import apsbss
from dm.common.exceptions.objectNotFound import ObjectNotFound
from qtpy.QtCore import Signal
from qtpy.QtGui import QStandardItem, QStandardItemModel

Expand Down Expand Up @@ -46,13 +46,25 @@ def customize_ui(self):
self.ui.update_proposal_button.clicked.connect(self.update_proposal)
self.ui.update_esaf_button.setIcon(icon)
self.ui.update_esaf_button.clicked.connect(self.update_esaf)
self.ui.refresh_models_button.clicked.connect(self.load_models)
# Icon for the refresh button
self.ui.refresh_models_button.setIcon(qta.icon("fa5s.sync"))

def customize_device(self):
self._device = haven.registry.find("beamline_manager")

@property
@lru_cache()
def proposals(self):
config = haven.load_config()
proposals = []
for proposal in self.api.getCurrentProposals(config["bss"]["beamline"]):
beamline = self._device.bss.proposal.beamline_name.get()
cycle = self._device.bss.esaf.aps_cycle.get()
# Get proposal data from the API
try:
api_result = self.api.listProposals(cycle, beamline)
except ObjectNotFound:
api_result = []
# Parse the API payload into the format for the BSS IOC
for proposal in api_result:
users = proposal["experimenters"]
proposals.append(
{
Expand All @@ -66,12 +78,18 @@ def proposals(self):
)
return proposals

@property
@lru_cache()
def esafs(self):
config = haven.load_config()
esafs_ = []
for esaf in self.api.getCurrentEsafs(config["bss"]["beamline"].split("-")[0]):
beamline = self._device.bss.proposal.beamline_name.get()
cycle = self._device.bss.esaf.aps_cycle.get()
# Retrieve current ESAFS from data management API
try:
api_result = self.api.listESAFs(cycle, beamline.split("-")[0])
except ObjectNotFound:
api_result = []
# Parse the API data into a format usable by the BSS IOC
for esaf in api_result:
users = esaf["experimentUsers"]
esafs_.append(
{
Expand All @@ -92,7 +110,7 @@ def load_models(self):
self.proposal_model = QStandardItemModel()
self.proposal_model.setHorizontalHeaderLabels(col_names)
# Load individual proposals
proposals = self.proposals
proposals = self.proposals()
for proposal in proposals:
items = [QStandardItem(str(proposal[col])) for col in col_names]
self.proposal_model.appendRow(items)
Expand All @@ -102,7 +120,7 @@ def load_models(self):
self.esaf_model = QStandardItemModel()
self.esaf_model.setHorizontalHeaderLabels(col_names)
# Load individual esafs
esafs = self.esafs
esafs = self.esafs()
for esaf in esafs:
items = [QStandardItem(str(esaf[col])) for col in col_names]
self.esaf_model.appendRow(items)
Expand All @@ -125,9 +143,8 @@ def select_proposal(self, current, previous):
def update_proposal(self):
new_id = self._proposal_id
# Change the proposal in the EPICS record
bss = haven.registry.find(name="bss")
bss = haven.registry.find("beamline_manager.bss")
bss.proposal.proposal_id.set(new_id).wait()
self.api.epicsUpdate(bss.prefix)
# Notify any interested parties that the proposal has been changed
self.proposal_changed.emit()

Expand All @@ -143,10 +160,9 @@ def select_esaf(self, current, previous):
def update_esaf(self):
new_id = self._esaf_id
# Change the esaf in the EPICS record
bss = haven.registry.find(name="bss")
bss = haven.registry.find("beamline_manager.bss")
bss.wait_for_connection()
bss.esaf.esaf_id.set(new_id).wait(timeout=5)
self.api.epicsUpdate(bss.prefix)
# Notify any interested parties that the esaf has been changed
self.esaf_changed.emit()

Expand Down
Loading

0 comments on commit 75ad122

Please sign in to comment.