diff --git a/README.md b/README.md index 7bd9e16e..27ee14f2 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,6 @@ item | description ## See also * https://github.com/BCDA-APS/bluesky_training -* https://BCDA-APS.github.io/apsbss * https://blueskyproject.io/ * https://github.com/bluesky/bluesky * https://github.com/bluesky/ophyd diff --git a/apstools/devices/aps_cycle.py b/apstools/devices/aps_cycle.py index 83c8ad59..98d51f14 100644 --- a/apstools/devices/aps_cycle.py +++ b/apstools/devices/aps_cycle.py @@ -9,12 +9,14 @@ import datetime import json +import logging import pathlib import time import yaml from ophyd.sim import SynSignalRO +logger = logging.getLogger(__name__) _PATH = pathlib.Path(__file__).parent YAML_CYCLE_FILE = _PATH / "aps_cycle_info.yml" @@ -70,17 +72,22 @@ def iso2ts(isodatetime): } return db - def _write_cycle_data(self): + def _write_cycle_data(self, output_file: str = None): """ Write the list of APS run cycles to a local file. - The file is formatted exactly as received from the - APS Data Management package (*aps-dm-api*). This allows + The content of this file is received from the APS Data Management + package (*aps-dm-api*) and reformatted here for readbility. This allows automatic updates as needed. - To update the LOCAL_FILE, run this code (on a workstation at the APS):: + MANUAL UPDATE OF CYCLE YAML FILE - from apstools._devices.aps_cycle import cycle_db + To update the LOCAL_FILE, run this code (on a workstation at the APS + configured to use the DM tools):: + + from apstools.devices.aps_cycle import cycle_db + from apstools.utils import dm_setup + dm_setup("/path/to/dm.setup.sh") cycle_db._write_cycle_data() """ runs = self._bss_list_runs @@ -98,16 +105,28 @@ def sorter(line): } for line in sorted(cycles, key=sorter) } - with YAML_CYCLE_FILE.open("w") as f: + + if output_file is None: + output_file = YAML_CYCLE_FILE + else: + # Allow caller to override default location. + output_file = pathlib.Path(output_file) + with output_file.open("w") as f: f.write(yaml.dump(db)) @property def _bss_list_runs(self): - try: - import apsbss + """Get the full list of APS runs via a Data Management API or 'None'.""" + from dm import ApsDbApiFactory + from dm.common.exceptions.dmException import DmException - return str(apsbss.api_bss.listRuns()) - except ModuleNotFoundError: + api = ApsDbApiFactory.getBssApsDbApi() + + # Only succeeds on workstations with DM tools installed. + try: + return api.listRuns() + except (DmException, ValueError) as reason: + logger.info(reason) return None @@ -129,9 +148,9 @@ class ApsCycleDM(SynSignalRO): def get(self): self._cycle_name = cycle_db.get_cycle_name() if datetime.datetime.now().isoformat(sep=" ") >= self._cycle_ends: - self._cycle_ends = datetime.datetime.fromtimestamp(cycle_db.db[self._cycle_name]["end"]).isoformat( - sep=" " - ) + ts_cycle_end = cycle_db.db[self._cycle_name]["end"] + dt_cycle_ends = datetime.datetime.fromtimestamp(ts_cycle_end) + self._cycle_ends = dt_cycle_ends.isoformat(sep=" ") return self._cycle_name diff --git a/apstools/devices/aps_cycle_info.yml b/apstools/devices/aps_cycle_info.yml index 63e4865b..d8adce57 100644 --- a/apstools/devices/aps_cycle_info.yml +++ b/apstools/devices/aps_cycle_info.yml @@ -130,10 +130,20 @@ 2023-1: begin: '2023-01-09 08:00:00-06:00' end: '2023-05-01 08:00:00-05:00' -# next entries are unofficial but allow the ophyd tool to work properly +# next entry is unofficial but allows the ophyd tool to work properly APS-U: begin: '2023-05-01 08:00:00-05:00' end: '2024-05-01 08:00:00-05:00' +# back to official entries 2024-2: - begin: '2024-05-01 08:00:00-05:00' + begin: '2024-05-06 08:00:00-05:00' end: '2024-10-01 00:00:00-05:00' +2024-3: + begin: '2024-10-01 00:00:00-05:00' + end: '2025-01-01 00:00:00-06:00' +2025-1: + begin: '2025-01-01 00:00:00-06:00' + end: '2025-05-01 00:00:00-05:00' +2025-2: + begin: '2025-05-01 00:00:00-05:00' + end: '2025-10-01 00:00:00-05:00'