Skip to content

Draft: Daiquiri

Stuart Fisher requested to merge daiquiri into main

Along with workflow/sidecar!56 (merged)

from blissoda.id13.daiquiri_xrpd_processor import DaiquiriXrpdProcessor as _XrpdProcessor
xrpd_processor = _XrpdProcessor(enable_plotter=False)

def loopscan_kmap(points, count_time, x_points, *detectors, datacollectionid=None):
    scan_info = {
        "daiquiri_datacollectionid": datacollectionid,
        "instrument": {
            "kmap_parameters": {
                "x_nb_points": int(x_points),
                "y_nb_points": int(points / x_points),
                "@NX_class": "NXcollection",
            }
        }
    }
    return loopscan(points, count_time, *detectors, scan_info=scan_info)

Along with ui/daiquiri!830 and ui/daiquiri-ui!796 (merged) you now get a generic object which can be connected to a blissoda "processor"

Screenshot 2024-10-23 at 15.59.50.png

In beacon you create a processor (say processor.yml), this is generic and can be used for any future type of processor:

- name: processor
  plugin: bliss
  package: blissoda.daiquiri.object
  class: DaiquiriProcessor
  processor_package: blissoda.id13.daiquiri_xrpd_processor
  processor_class: DaiquiriXrpdProcessor
  processor_class_options:
    enable_plotter: false

This wraps the blissoda processor and provides a consistent interface that daiquiri can use to provide a ui.

The blissoda processes needs to mixin DaiquiriProcessorMixin to provide the needed schema for the exposed parameters, each "parameter" should map to a property on the blissoda processor.

from marshmallow import fields

from ..daiquiri.mixin import DaiquiriProcessorMixin, ExposedParameter

def exists(value):
    if not os.path.exists(value):
        raise ValidationError(f"File `{value}` does not exist")


def exists_valid_json(value):
    exists(value)

    if value.endswith(".json"):
        try:
            with open(value) as f:
                json.load(f)
        except json.decoder.JSONDecodeError as ex:
            raise ValidationError(f"Could not decode JSON: {str(ex)}")

class DaiquiriXrpdProcessor(Id13XrpdProcessor, DaiquiriProcessorMixin):
    EXPOSED_PARAMETERS = [
        ExposedParameter(
            parameter="workflow_with_saving_diffmap",
            field_type=fields.Str,
            title="Workflow",
        ),
        ExposedParameter(
            parameter="pyfai_config",
            field_type=fields.Str,
            title="PyFAI Config File",
            field_options={"validate": exists_valid_json},
        ),
        ExposedParameter(
            parameter="integration_options",
            field_type=fields.Dict,
            field_options={"keys": fields.Str()},
            title="PyFAI Options",
        ),
        ...
    ]

    ...

Parameters can be picked off the processor with EXPOSED_PARAMETERS. This defines the parameter typing, UI title, and validation, which can do things like check a file exists, and check if the json is valid (useful for people manually modifying the poni json)

The high level bliss object then provides channels for each of the exposed parameters, so that daiquiri is aware of changes. Changes are bidirectioanlly reflected so modifications on the cli are sent to daiquiri and vice versa. The object also polls ewoksjob.client.get_workers() to tell you if the processor is ready to accept a job, it also looks at the active queue to tell you if the worker is processing.

Two outstanding questions:

  • Right now PersistentParameters are stored relative to the session name. In bliss generally speaking on an object, parameters are stored relative to their object name (which has to be unique, enforced by beacon). This allows objects and their parameters to be shared over sessions. So right now if you load the daiquiri bliss object in a different session to where you previously used your processor your parameters are not available. We do this sometimes when testing for example import an object into an empty bliss session.
  • Second because PersistentParameters are not a Cache there are no associated events, which essentially means that when the daiquiri bliss object wraps the processor it creates another copy of the parameters in redis. In use i dont think this is really a problem but it is duplicating data.
Edited by Stuart Fisher

Merge request reports

Loading