diff --git a/docs/changelog.md b/docs/changelog.md index fbb3d26..1fba928 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -16,6 +16,10 @@ pip install git+https://github.com/European-XFEL/EXtra.git ``` +Added: + +- [JF4MHalfMotors][extra.components.JF4MHalfMotors] to access positions of motors moving halfs of Jungfrau detector (!224). + Fixed: - Karabacon 3.0.10 is now supported by the [Scantool][extra.components.Scantool] diff --git a/docs/components/detector-motors.md b/docs/components/detector-motors.md index be20369..182ea68 100644 --- a/docs/components/detector-motors.md +++ b/docs/components/detector-motors.md @@ -1 +1,3 @@ ::: extra.components.AGIPD1MQuadrantMotors + +::: extra.components.JF4MHalfMotors diff --git a/docs/components/index.md b/docs/components/index.md index 714308a..a801dba 100644 --- a/docs/components/index.md +++ b/docs/components/index.md @@ -24,3 +24,4 @@ Component index: - [AdqRawChannel][extra.components.AdqRawChannel] - [Detector motors](detector-motors.md) - [AGIPD1MQuadrantMotors][extra.components.AGIPD1MQuadrantMotors] + - [JF4MHalfMotors][extra.components.JF4MHalfMotors] diff --git a/src/extra/components/__init__.py b/src/extra/components/__init__.py index 0ee3f33..49a7e4d 100644 --- a/src/extra/components/__init__.py +++ b/src/extra/components/__init__.py @@ -7,4 +7,4 @@ from .dld import DelayLineDetector # noqa from .las import OpticalLaserDelay # noqa from .adq import AdqRawChannel # noqa -from .detector_motors import AGIPD1MQuadrantMotors # noqa +from .detector_motors import AGIPD1MQuadrantMotors, JF4MHalfMotors # noqa diff --git a/src/extra/components/detector_motors.py b/src/extra/components/detector_motors.py index 23d804f..20177a6 100644 --- a/src/extra/components/detector_motors.py +++ b/src/extra/components/detector_motors.py @@ -196,7 +196,10 @@ def find_motors(dc, pattern, position_key, data_selectors=None, **coordinates): src = pattern.format(**args) label = ''.join(f"{n}{v}" for n, v in args.items()) - if src in dc.control_sources and position_key in dc[src].keys(): + if ( + src in dc.control_sources and + position_key in dc[src].keys(inc_timestamps=False) + ): motors[label] = (src, position_key) continue @@ -244,7 +247,7 @@ def __init__(self, dc, detector_id=None): dc (extra_data.DataCollection): The data detector_id (str): - The detector ID, e.g. SPB_IRU_AGIPD1M or SPB_IRU_AGIPD1M + The detector ID, e.g. SPB_IRU_AGIPD1M or MID_EXP_AGIPD1M Raises: ValueError: @@ -278,3 +281,64 @@ def __init__(self, dc, detector_id=None): detector_id, detector_motors = all_motors.popitem() super().__init__(dc, detector_id, detector_motors, q=groups, m=motors) + + +class JF4MHalfMotors(DetectorMotors): + """Interface to Jungfrau 4M half motors. + + Example usage in a Jupyter notebook: + ```python + ----------------------------------------------------------- + In [1]: |motors = JF4MHalfMotors(run) | + |motors | + ----------------------------------------------------------- + Out[1]: + ``` + """ + # SPB + # SPB_IRDA_JF4M/MOTOR/X{q+1} + # SPB_IRDA_JF4M/MOTOR/Z + + KNOWN_DETECTORS = ["SPB_IRDA_JF4M"] + + def __init__(self, dc, detector_id=None): + """ + Args: + dc (extra_data.DataCollection): + The data + detector_id (str): + The detector ID, e.g. SPB_IRDA_JF4M + + Raises: + ValueError: + If motors are not found or multiple motor groups are found + """ + pattern = "{detector_id}/MOTOR/X{q}" + + num_groups = 2 + num_motors = 1 + groups = list(range(1, num_groups + 1)) + motors = list(range(1, num_motors + 1)) + + data_selectors = sources_by_class(dc) + + all_motors = {} + detectors = ( + self.KNOWN_DETECTORS if detector_id is None else [detector_id]) + for det_id in detectors: + pattern = det_id + "/MOTOR/X{q}" + det_motors = find_motors(dc, pattern, self._position_key, + data_selectors, q=groups, m=motors) + if det_motors: + all_motors[det_id] = det_motors + + if len(all_motors) == 0: + raise ValueError("Motors are not found") + elif len(all_motors) > 1: + raise ValueError( + "Many detector found: {', '.join(det_motors.keys())}. " + "Please specify 'detector_id'") + + detector_id, detector_motors = all_motors.popitem() + super().__init__(dc, detector_id, detector_motors, q=groups, m=motors)