bluesky / hklpy

Diffractometer computation library with ophyd pseudopositioner support
https://blueskyproject.io/hklpy
BSD 3-Clause "New" or "Revised" License
4 stars 12 forks source link

add Sync_UB_Matrix #340

Open prjemian opened 2 months ago

prjemian commented 2 months ago

Is there a way motor positions (and UB matrices) of the two engines can be synchronized automatically?

class Sync_UB_Matrix:
    """Copy the UB matrix from source to target diffractometers."""

    def __init__(self, source: Diffractometer, target: Diffractometer):
        self.source = source
        self.target = target
        self.source.UB.subscribe(self.sync_callback)

        # initialize
        self.sync_callback(self.source.UB.get())

    def cleanup(self, *args, **kwargs):
        """Remove all our subscriptions to ophyd objects."""
        self.source.UB.clear_sub(self.sync_callback)

    def sync_callback(self, value=None, **kwargs):
        if value is None:
            raise RuntimeError(f"sync_callback: {value=!r}  {kwargs=!r}")
        ub_source = value
        print(f"Copy UB={ub_source=} from {self.source.name} to {self.source.name}")
        self.target.UB.put(ub_source)

        for axis in self.source.real_positioners._fields:
            ptarget = getattr(self.target, axis)
            if isinstance(ptarget, SoftPositioner):
                # If the target is a simulated motor, sync it with the source.
                psource = getattr(self.source, axis)
                ptarget.move(psource.position)
                print(f"Sync {self.target.name}.{axis}={ptarget.position}")

try:
    sync_UB.cleanup()
except Exception:
    pass
sync_UB = Sync_UB_Matrix(polar, polar_psi)

@strempfer - Thanks for the suggestion!

prjemian commented 2 months ago

The __init__() method should raise if the two diffractometers do not have the same geometry.