Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store operational information locally for use outside of bluesky #256

Closed
prjemian opened this issue Sep 25, 2023 · 13 comments · Fixed by #279
Closed

Store operational information locally for use outside of bluesky #256

prjemian opened this issue Sep 25, 2023 · 13 comments · Fixed by #279
Assignees
Milestone

Comments

@prjemian
Copy link
Contributor

Users want to see a list of reflections, samples, etc. from their recent session, even after bluesky stops. Multiple sessions could (optionally) access the same list or use a different one.

This would be a local file, stored in the pwd. A session could load this file by default, start a new one, or load from somewhere else.

@strempfer : Thanks for the suggestion!

@prjemian
Copy link
Contributor Author

@rodolakis - You described an implementation of this idea that uses EPICS PVs. It was useful for when the bluesky session needed to be restarted. (So that any session info could be restored.)

@prjemian
Copy link
Contributor Author

prjemian commented Oct 3, 2023

One way is to generalize the support so it is easy and consistent to call. Consider this class:

from dataclasses import dataclass

from hkl.diffract import Diffractometer


@dataclass
class DiffractometerPreservation:
    """Preserve Diffractometer Configuration."""

    meter: Diffractometer

    def export_dict(self):
        me = self.meter

        d = {
            "name": me.name,
            "geometry": me.calc._geometry.name_get(),
            "class": me.__class__.__name__,
            "engine": me.calc.engine.name,
            "mode": me.calc.engine.mode,
            "class": me.__class__.__name__,
            "hklpy_version": me._hklpy_version_,
            "energy_keV": me.calc.energy,
            "wavelength_angstrom": me.calc.wavelength,
            # fmt: off
            "constraints": {
                k: {
                    nm: getattr(v, nm)
                    for nm in "low_limit high_limit value fit".split()
                }
                for k, v in me._constraints_dict.items()
            },
            "samples": {
                sname: {
                    "name": sample.name,
                    "reflections": sample.reflections_details,
                    "U": sample.reflections_details,
                    "UB": sample.reflections_details,
                }
                for sname, sample in me.calc._samples.items()
            },
            # fmt: on
            "real_axes": list(me.RealPosition._fields),
            "reciprocal_axes": list(me.PseudoPosition._fields),
        }
        return d

    def export_json(self):
        import json

        return json.dumps(self.export_dict())

    def export_yaml(self):
        import yaml

        return yaml.dump(self.export_dict())

An agent could be created: agent = DiffractometerPreservation(e4cv). The default configuration could be exported as JSON by calling agent.export_json():

{"name": "e4cv", "geometry": "E4CV", "class": "SimulatedE4CV", "engine": "hkl", "mode": "bissector", "hklpy_version": "1.0.3", "energy_keV": 8.050921974025975, "wavelength_angstrom": 1.54, "constraints": {"omega": {"low_limit": -180.0, "high_limit": 180.0, "value": 0.0, "fit": true}, "chi": {"low_limit": -180.0, "high_limit": 180.0, "value": 0.0, "fit": true}, "phi": {"low_limit": -180.0, "high_limit": 180.0, "value": 0.0, "fit": true}, "tth": {"low_limit": -180.0, "high_limit": 180.0, "value": 0.0, "fit": true}}, "samples": {"main": {"name": "main", "reflections": [], "U": [], "UB": []}}, "real_axes": ["omega", "chi", "phi", "tth"], "reciprocal_axes": ["h", "k", "l"]}

When orientation info exists for a sample (sample and reflections are added and UB matrix is computed):

{"name": "e4cv", "geometry": "E4CV", "class": "SimulatedE4CV", "engine": "hkl", "mode": "bissector", "hklpy_version": "1.0.3", "energy_keV": 8.050921974025975, "wavelength_angstrom": 1.54, "constraints": {"omega": {"low_limit": -180.0, "high_limit": 180.0, "value": 0.0, "fit": true}, "chi": {"low_limit": -180.0, "high_limit": 180.0, "value": 0.0, "fit": true}, "phi": {"low_limit": -180.0, "high_limit": 180.0, "value": 0.0, "fit": true}, "tth": {"low_limit": -180.0, "high_limit": 180.0, "value": 0.0, "fit": true}}, "samples": {"main": {"name": "main", "reflections": [], "U": [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], "UB": [[4.079990459207523, -2.4982736282101165e-16, -2.4982736282101165e-16], [0.0, 4.079990459207523, -2.4982736282101165e-16], [0.0, 0.0, 4.079990459207523]]}, "silicon": {"name": "silicon", "reflections": [{"reflection": {"h": 4.0, "k": 0.0, "l": 0.0}, "flag": 1, "wavelength": 1.54, "position": {"omega": -145.451, "chi": 0.0, "phi": 0.0, "tth": 69.0966}, "orientation_reflection": true}, {"reflection": {"h": 0.0, "k": 4.0, "l": 0.0}, "flag": 1, "wavelength": 1.54, "position": {"omega": -145.451, "chi": 0.0, "phi": 90.0, "tth": 69.0966}, "orientation_reflection": true}], "U": [[-1.2217304763832569e-05, -0.9999999999253688, 0.0], [0.0, 0.0, 1.0], [-0.9999999999253688, 1.2217304763832569e-05, 0.0]], "UB": [[-1.4134284639502065e-05, -1.1569069374686927, 7.084098436944218e-17], [0.0, 0.0, 1.156906937555034], [-1.1569069374686927, 1.4134284639572905e-05, 7.083925341879798e-17]]}}, "real_axes": ["omega", "chi", "phi", "tth"], "reciprocal_axes": ["h", "k", "l"]}

Export as YAML is demonstrated, above. Could add exporters to file, EPICS PV (CA or PVA), or other.

Importers would have to match the geometry of the diffractometer object first. Basically a reverse of the export steps. Convert from incoming format to a standard dict, then a single code that takes the standard dict and updates the diffractometer object.

@prjemian
Copy link
Contributor Author

prjemian commented Oct 4, 2023

The export_dict() method (above) could be part of the Diffractometer() class.

@prjemian prjemian self-assigned this Oct 4, 2023
@prjemian prjemian added this to the v1.0.4 milestone Oct 4, 2023
@prjemian
Copy link
Contributor Author

prjemian commented Oct 6, 2023

While hklpy should not design how to persist such information outside the package, it can provide an easy way to import & export. The export_dict() method above is an example.

@prjemian prjemian modified the milestones: v1.0.4, v1.1 Oct 6, 2023
@prjemian
Copy link
Contributor Author

prjemian commented Oct 6, 2023

Not necessary for the 1.0.4 release.

@prjemian
Copy link
Contributor Author

The dictionary stored as a run's configuration: diffractometer.read_configuration() but this dict only contains a single sample.

prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 26, 2023
prjemian added a commit that referenced this issue Oct 31, 2023
prjemian added a commit that referenced this issue Oct 31, 2023
prjemian added a commit that referenced this issue Oct 31, 2023
prjemian added a commit that referenced this issue Oct 31, 2023
prjemian added a commit that referenced this issue Nov 1, 2023
prjemian added a commit that referenced this issue Nov 1, 2023
prjemian added a commit that referenced this issue Nov 1, 2023
prjemian added a commit that referenced this issue Nov 1, 2023
prjemian added a commit that referenced this issue Nov 1, 2023
prjemian added a commit that referenced this issue Nov 1, 2023
prjemian added a commit that referenced this issue Nov 2, 2023
prjemian added a commit that referenced this issue Nov 2, 2023
prjemian added a commit that referenced this issue Nov 2, 2023
prjemian added a commit that referenced this issue Nov 2, 2023
prjemian added a commit that referenced this issue Nov 2, 2023
prjemian added a commit that referenced this issue Nov 2, 2023
prjemian added a commit that referenced this issue Nov 2, 2023
prjemian added a commit that referenced this issue Nov 2, 2023
prjemian added a commit that referenced this issue Nov 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants