bluesky / ophyd

hardware abstraction in Python with an emphasis on EPICS
https://blueskyproject.io/ophyd
BSD 3-Clause "New" or "Revised" License
48 stars 77 forks source link

BUG: Windows write path with AD file writer plugins #960

Open prjemian opened 3 years ago

prjemian commented 3 years ago

A problem occurred when staging an area detector HDF file writing plugin and the IOC is running on Windows.

One feature of any of the AD file writers is the ability to control the directory where the file will be written. When the file_path attribute is written, the EPICS IOC will append a / directory separator to the given file path if it does not have one already. The choice of / even happens for Windows IOCs!

The problem in ophyd is two-fold:

  1. these are the lines that strip any supplied directory separator if it is the last item in the given file path: https://github.com/bluesky/ophyd/blob/1b9e91be7483d94636ae0bfa14bf13702e07b969/ophyd/areadetector/filestore_mixins.py#L417-L418
  2. the ophyd .set() to this signal waits at this line (with no timeout): https://github.com/bluesky/ophyd/blob/1b9e91be7483d94636ae0bfa14bf13702e07b969/ophyd/areadetector/filestore_mixins.py#L432 since the return value will be different than the expected.

Here is the code that fixes the problem for one detector, by making a custom HDF5 Plugin for a Windows IOC (the other support code is added):

class MyHDF5Plugin(FileStoreHDF5IterativeWrite, HDF5Plugin_V34):

    def make_filename(self):
        """Override from ophyd.areadetector.filestore_mixins.FileStorePluginBase"""
        filename = new_short_uid()
        formatter = datetime.datetime.now().strftime
        write_path = formatter(self.write_path_template) + "\\"  # the FIX!
        read_path = formatter(self.read_path_template)
        return filename, read_path, write_path

class MyProcessPlugin(ProcessPlugin):

    pool_max_buffers = None

class MyDexelaDetector(SingleTrigger, DexelaDetector):
    """Dexela detector(s) as used by 9-ID-C USAXS."""

    hdf1 = ADComponent(
        MyHDF5Plugin,
        "HDF1:",
        write_path_template="W:\\USAXS_data\\test\\dexela\\%Y\\%m\\%d\\",
        read_path_template="/share1/USAXS_data/test/dexela/%Y/%m/%d/",
        path_semantics="windows",
    )
    image = ADComponent(ImagePlugin, "image1:")
    proc1 = ADComponent(MyProcessPlugin, "Proc1:")

dexela_det = MyDexelaDetector("9idcDEX:", name="dexela_det")
mrakitin commented 3 years ago

MyProcessPlugin can be replaced by https://github.com/bluesky/ophyd/blob/03585f0b02752d5975da393a889e5c5cecd06fd7/ophyd/areadetector/plugins.py#L1504-L1507

That removes pool_max_buffers via https://github.com/bluesky/ophyd/blob/03585f0b02752d5975da393a889e5c5cecd06fd7/ophyd/areadetector/plugins.py#L1025-L1028

klauer commented 3 years ago

EpicsPathSignal may need some updating to fix this? https://github.com/bluesky/ophyd/blob/03585f0b02752d5975da393a889e5c5cecd06fd7/ophyd/areadetector/paths.py#L87

prjemian commented 3 years ago

On slack.com, it was suggested that #749 might address this directly with a resolution.