Skip to content

Commit

Permalink
Setup PandA writer to set create directory depth PV on open (#503)
Browse files Browse the repository at this point in the history
* Add support for directory creation feature in PandA

* Update tests to reflect create_directory changes

* Make sure create_dir_depth is set before directory_path

* Adding test case for when directory does not exist panda writer

* Directory exists record should be a bool

* Cast dir path to string to avoid p4p error

* Fix failing test

* Fix typo leftover from merge conflict resolution
  • Loading branch information
jwlodek authored Aug 15, 2024
1 parent d5da999 commit 6b5f2b2
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/ophyd_async/fastcs/panda/_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class DataBlock(Device):
hdf_file_name: SignalRW[str]
num_capture: SignalRW[int]
num_captured: SignalR[int]
create_directory: SignalRW[int]
directory_exists: SignalR[bool]
capture: SignalRW[bool]
flush_period: SignalRW[float]
datasets: SignalR[DatasetTable]
Expand Down
16 changes: 13 additions & 3 deletions src/ophyd_async/fastcs/panda/_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,27 @@ async def open(self, multiplier: int = 1) -> Dict[str, DataKey]:

self._file = None
info = self._path_provider(device_name=self._name_provider())

# Set create dir depth first to guarantee that callback when setting
# directory path has correct value
await self.panda_data_block.create_directory.set(info.create_dir_depth)

# Set the initial values
await asyncio.gather(
self.panda_data_block.hdf_directory.set(info.directory_path),
self.panda_data_block.hdf_directory.set(str(info.directory_path)),
self.panda_data_block.hdf_file_name.set(
f"{info.filename}.h5",
),
self.panda_data_block.num_capture.set(0),
# TODO: Set create_dir_depth once available
# https://github.com/bluesky/ophyd-async/issues/317
)

# Make sure that directory exists or has been created.
if not await self.panda_data_block.directory_exists.get_value() == 1:
raise OSError(
f"Directory {info.directory_path} does not exist or "
"is not writable by the PandABlocks-ioc!"
)

# Wait for it to start, stashing the status that tells us when it finishes
await self.panda_data_block.capture.set(True)
if multiplier > 1:
Expand Down
7 changes: 7 additions & 0 deletions tests/fastcs/panda/test_hdf_panda.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from typing import Dict
from unittest.mock import ANY

Expand Down Expand Up @@ -41,7 +42,13 @@ class CaptureBlock(Device):
def link_function(value, **kwargs):
set_mock_value(mock_hdf_panda.pcap.active, value)

# Mimic directory exists check that happens normally in the PandA IOC
def check_dir_exits(value, **kwargs):
if os.path.exists(value):
set_mock_value(mock_hdf_panda.data.directory_exists, 1)

callback_on_mock_put(mock_hdf_panda.pcap.arm, link_function)
callback_on_mock_put(mock_hdf_panda.data.hdf_directory, check_dir_exits)

set_mock_value(
mock_hdf_panda.data.datasets,
Expand Down
1 change: 1 addition & 0 deletions tests/fastcs/panda/test_panda_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ async def test_save_panda(mock_save_to_yaml, mock_panda, RE: RunEngine):
},
{
"data.capture": False,
"data.create_directory": 0,
"data.flush_period": 0.0,
"data.hdf_directory": "",
"data.hdf_file_name": "",
Expand Down
33 changes: 31 additions & 2 deletions tests/fastcs/panda/test_writer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from pathlib import Path
from unittest.mock import ANY

Expand All @@ -14,6 +15,9 @@
StaticPathProvider,
set_mock_value,
)
from ophyd_async.core._mock_signal_utils import (
callback_on_mock_put,
)
from ophyd_async.epics.pvi import create_children_from_annotations, fill_pvi_entries
from ophyd_async.fastcs.panda import (
CommonPandaBlocks,
Expand Down Expand Up @@ -84,6 +88,14 @@ async def mock_panda(panda_t):
async with DeviceCollector(mock=True):
mock_panda = panda_t("mock_PANDA", name="mock_panda")

# Mimic directory exists check that happens normally in the PandA IOC
def check_dir_exits(value, **kwargs):
if os.path.exists(os.path.abspath(os.path.dirname(value))):
set_mock_value(mock_panda.data.directory_exists, 1)

# Assume directory exists
callback_on_mock_put(mock_panda.data.hdf_directory, check_dir_exits)

set_mock_value(
mock_panda.data.datasets,
DatasetTable(
Expand All @@ -98,7 +110,7 @@ async def mock_panda(panda_t):
@pytest.fixture
async def mock_writer(tmp_path, mock_panda) -> PandaHDFWriter:
fp = StaticFilenameProvider("data")
dp = StaticPathProvider(fp, tmp_path / mock_panda.name)
dp = StaticPathProvider(fp, tmp_path / mock_panda.name, create_dir_depth=-1)
async with DeviceCollector(mock=True):
writer = PandaHDFWriter(
prefix="TEST-PANDA",
Expand Down Expand Up @@ -146,7 +158,7 @@ async def test_open_close_sets_capture(mock_writer: PandaHDFWriter):
async def test_open_sets_file_path_and_name(mock_writer: PandaHDFWriter, tmp_path):
await mock_writer.open()
path = await mock_writer.panda_data_block.hdf_directory.get_value()
assert path == tmp_path / mock_writer._name_provider()
assert path == str(tmp_path / mock_writer._name_provider())
name = await mock_writer.panda_data_block.hdf_file_name.get_value()
assert name == "data.h5"

Expand Down Expand Up @@ -204,3 +216,20 @@ def assert_resource_document(name, resource_doc):
assert_resource_document(name=name, resource_doc=resource_doc)

assert resource_doc["data_key"] == name


async def test_oserror_when_hdf_dir_does_not_exist(tmp_path, mock_panda):
fp = StaticFilenameProvider("data")
dp = StaticPathProvider(
fp, tmp_path / mock_panda.name / "extra" / "dirs", create_dir_depth=-1
)
async with DeviceCollector(mock=True):
writer = PandaHDFWriter(
prefix="TEST-PANDA",
path_provider=dp,
name_provider=lambda: "test-panda",
panda_data_block=mock_panda.data,
)

with pytest.raises(OSError):
await writer.open()

0 comments on commit 6b5f2b2

Please sign in to comment.