DiamondLightSource/dodal

Standard way to define device once that is shared between multiple end statations

Open

#1,530 opened on Sep 15, 2025

View on GitHub
 (21 comments) (0 reactions) (0 assignees)Python (12 forks)auto 404
DesignDeveloper Experiencedocumentationhelp wantedstandarisation

Repository metrics

Stars
 (4 stars)
PR merge metrics
 (PR metrics pending)

Description

It is common for branched beamlines to have shared components, e.g PGM is used by I06 and I06-1.

In dodal, we don't seem to have a standard way of doing this as of yet. At the moment, we have dodal/beamlines/i05.py, dodal/beamlines/i05_1.py and dodal/beamlines/beamline_specific_util/i05_shared.py. However, i05.py and i05_1.py both redefine the pgm which defeats the purpose were trying to achieve.

from dodal.beamline_specific_utils.i05_shared import pgm as i05_pgm

@device_factory()
def pgm() -> PGM:
    return i05_pgm()

In other situations, we have I09 defined DCM in two different places when it's the same device i09.py and i09_1.py.

This should be defined once in it's own module. This seems to be what I19 have done with i19_1.py, i19_2.py and i19_optics.py, though I think this is slightly different use case as this is a way for access control and has its own BlueAPI service. However, I believe all beamlines, if has shared endstations, should have devices defined once in a shared module. This way, we get BlueAPI to pull devices from beamline iXX and iXX_shared to be into a single environment e.g

worker:
    env:
      sources:
        - kind: planFunctions
          module: sm_bluesky.beamlines.i05.plans
        - kind: planFunctions
          module: sm_bluesky.common.plan_stubs
        - kind: planFunctions
          module: sm_bluesky.common.plans
        - kind: planFunctions
          module: dodal.plans
        - kind: dodal
          module: "dodal.beamlines.i05"
        - kind: dodal
          module: "dodal.beamlines.i05_shared"

I think we can also go further and maybe define a dodal/beamlines/core.py as well because almost every beamline defines Synchrotron device, we can remove this duplication.

Finally, as this makes beamlines more modular and we want to test using dodal connect iXX for a whole beamline, I suggest the following change be made to dodal connect:

We define some config in dodal e.g

_BEAMLINE_SHARED = {
    "i09": ["i09", "i09_1_shared", "i09_2_shared"]
    ...
}

This config defines the whole beamline so when running dodal connect i09, we get:

(venv) root ➜ /workspaces/dodal (fix_test_motor_limits_with_new_ophyd_async ✗) 
$ dodal connect i09 -s
====================================================================================================
Attempting connection to i09 (using dodal.beamlines.i09)
2 devices connected (sim mode):
        analyser_driver
        synchrotron
====================================================================================================
Attempting connection to i09_1_shared (using dodal.beamlines.i09_1_shared)
1 devices connected (sim mode):
        dcm
====================================================================================================
Attempting connection to i09_2_shared (using dodal.beamlines.i09_2_shared)
1 devices connected (sim mode):
        pgm

We can also add a flag to test the individual beamline only

(venv) root ➜ /workspaces/dodal (fix_test_motor_limits_with_new_ophyd_async ✗) 
$ dodal connect i09 -s -i
====================================================================================================
Attempting connection to i09 (using dodal.beamlines.i09)
2 devices connected (sim mode):
        analyser_driver
        synchrotron

Acceptance Criteria

  • Documentation added on standard for shared modules
  • Beamlines conform to standard.
  • Dodal connect command adjusted

Contributor guide