diff --git a/docs/source/_static/e4c-config.json b/docs/source/_static/e4c-config.json new file mode 100644 index 00000000..e1e8a4be --- /dev/null +++ b/docs/source/_static/e4c-config.json @@ -0,0 +1,199 @@ +{ + "name": "e4c", + "geometry": "E4CV", + "datetime": "2023-10-26 16:58:20.819009", + "class": "SimulatedE4CV", + "engine": "hkl", + "mode": "bissector", + "hklpy_version": "1.0.4+28.gd9a56a4.dirty", + "library": "gi.repository.Hkl", + "library_version": "v5.0.0.3001", + "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", + "lattice": { + "a": 1.54, + "b": 1.54, + "c": 1.54, + "alpha": 90.0, + "beta": 90.0, + "gamma": 90.0 + }, + "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 + ] + ] + }, + "vibranium": { + "name": "vibranium", + "lattice": { + "a": 6.283185307179586, + "b": 6.283185307179586, + "c": 6.283185307179586, + "alpha": 90.0, + "beta": 90.0, + "gamma": 90.0 + }, + "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": false + }, + { + "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 + }, + { + "reflection": { + "h": 0.0, + "k": 0.0, + "l": 4.0 + }, + "flag": 1, + "wavelength": 1.54, + "position": { + "omega": -145.451, + "chi": 90.0, + "phi": 0.0, + "tth": 69.0966 + }, + "orientation_reflection": true + } + ], + "U": [ + [ + 1.2217304763701863e-05, + -0.9999999999253688, + -1.8235863128158895e-15 + ], + [ + -1.4926257043558267e-10, + -9.139696455822134e-27, + -1.0000000000000002 + ], + [ + 0.9999999999253688, + 1.2217304763701863e-05, + -1.4926257042444305e-10 + ] + ], + "UB": [ + [ + 1.2217304763701863e-05, + -0.9999999999253688, + -1.7623547209572502e-15 + ], + [ + -1.4926257043558267e-10, + -1.4349296274686127e-42, + -1.0000000000000002 + ], + [ + 0.9999999999253688, + 1.221730476364063e-05, + -1.492626316575311e-10 + ] + ] + } + }, + "canonical_axes": [ + "omega", + "chi", + "phi", + "tth" + ], + "real_axes": [ + "omega", + "chi", + "phi", + "tth" + ], + "reciprocal_axes": [ + "h", + "k", + "l" + ] +} \ No newline at end of file diff --git a/docs/source/_static/e4c-config.yml b/docs/source/_static/e4c-config.yml new file mode 100644 index 00000000..9c7e3588 --- /dev/null +++ b/docs/source/_static/e4c-config.yml @@ -0,0 +1,143 @@ +canonical_axes: +- omega +- chi +- phi +- tth +class: SimulatedE4CV +constraints: + chi: + fit: true + high_limit: 180.0 + low_limit: -180.0 + value: 0.0 + omega: + fit: true + high_limit: 180.0 + low_limit: -180.0 + value: 0.0 + phi: + fit: true + high_limit: 180.0 + low_limit: -180.0 + value: 0.0 + tth: + fit: true + high_limit: 180.0 + low_limit: -180.0 + value: 0.0 +datetime: '2023-10-26 16:58:20.819891' +energy_keV: 8.050921974025975 +engine: hkl +geometry: E4CV +hklpy_version: 1.0.4+28.gd9a56a4.dirty +library: gi.repository.Hkl +library_version: v5.0.0.3001 +mode: bissector +name: e4c +real_axes: +- omega +- chi +- phi +- tth +reciprocal_axes: +- h +- k +- l +samples: + main: + 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 + lattice: + a: 1.54 + alpha: 90.0 + b: 1.54 + beta: 90.0 + c: 1.54 + gamma: 90.0 + name: main + reflections: [] + vibranium: + U: + - - 1.2217304763701863e-05 + - -0.9999999999253688 + - -1.8235863128158895e-15 + - - -1.4926257043558267e-10 + - -9.139696455822134e-27 + - -1.0000000000000002 + - - 0.9999999999253688 + - 1.2217304763701863e-05 + - -1.4926257042444305e-10 + UB: + - - 1.2217304763701863e-05 + - -0.9999999999253688 + - -1.7623547209572502e-15 + - - -1.4926257043558267e-10 + - -1.4349296274686127e-42 + - -1.0000000000000002 + - - 0.9999999999253688 + - 1.221730476364063e-05 + - -1.492626316575311e-10 + lattice: + a: 6.283185307179586 + alpha: 90.0 + b: 6.283185307179586 + beta: 90.0 + c: 6.283185307179586 + gamma: 90.0 + name: vibranium + reflections: + - flag: 1 + orientation_reflection: false + position: + chi: 0.0 + omega: -145.451 + phi: 0.0 + tth: 69.0966 + reflection: + h: 4.0 + k: 0.0 + l: 0.0 + wavelength: 1.54 + - flag: 1 + orientation_reflection: true + position: + chi: 0.0 + omega: -145.451 + phi: 90.0 + tth: 69.0966 + reflection: + h: 0.0 + k: 4.0 + l: 0.0 + wavelength: 1.54 + - flag: 1 + orientation_reflection: true + position: + chi: 90.0 + omega: -145.451 + phi: 0.0 + tth: 69.0966 + reflection: + h: 0.0 + k: 0.0 + l: 4.0 + wavelength: 1.54 +wavelength_angstrom: 1.54 diff --git a/docs/source/api.rst b/docs/source/api.rst index 338c498d..ec09a172 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -6,6 +6,7 @@ API Reference :glob: calc + configuration context diffract engine diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst new file mode 100644 index 00000000..ec6b9a73 --- /dev/null +++ b/docs/source/configuration.rst @@ -0,0 +1,148 @@ + +.. _configuration: + +configuration +------------- + +Record the configuration of the diffractometer so that it can be restored later. + +Users want to see a list of reflections, samples, etc. from their recent +session, even after the session stops. Multiple sessions could (optionally) access +the same list or use a different one. + +This code provides a core representation of a diffractometer's configuration and +methods to export and restore that configuration. User code could choose to +write the configuration to a file, an EPICS PV, or some other persistent +location. + +Configuration dictionary +++++++++++++++++++++++++ + +*Configuration* includes: + +* geometry +* current wavelength of the source +* soft limits (constraints) on the physical axes +* list [#axes.order]_ of reciprocal-space axes names +* list [#axes.order]_ of canonical (geometry-defined) real-space axes names +* list [#axes.order]_ of real-space axes names as the user has defined +* list of samples +* other general metadata about the diffractometer. + +.. [#axes.order] The axes names are listed in the order prescribed by the back-end library. + +Each sample includes: + +* name +* crystal lattice constants +* list of orientation reflections +* :math:`U` matrix +* :math:`UB` matrix + +Each reflection includes: + +* coordinates of the reciprocal-space axes +* coordinates of the real-space axes +* wavelength to be used for the reflection +* a flag indicating if the reflection is used to calculate the orientation +* a ``fit`` parameter used by the *libhkl* backend library + +To enable some generality when restoring reflections, the real-space coordinates +are recorded using the canonical (not user-defined) axis names defined by the +diffractometer geometry. + +The complete configuration list could be saved into a file, stored in the +current working directory or elsewhere. A session could load this file by +default, start a new one, or load from somewhere else. Or, the files could be +saved by time-stamp to compare as the configuration changes. + +Alternatively, the list could be saved as text into an EPICS PV (the PV would +need to handle text of several kilobytes in size). Or into a memory cache, such +as `redis `_. + +Export +++++++ + +The diffractometer configuration can be returned in any of the formats shown in +the table below. Assuming ``config`` is the object returned by calling +:class:`~hkl.DiffractometerConfiguration()`: + +=========================== ============================================================ +command returns +=========================== ============================================================ +``config.export()`` Defaults to JSON format. See below. +``config.export("json")`` `JSON string `_ +``config.export("dict")`` `Python dict `_ +``config.export("yaml")`` `YAML string `_ +=========================== ============================================================ + +Restore ++++++++ + +A single command is used to set a diffractometer's configuration from a Python object. +Assuming: + +* ``config`` is the object returned by calling :class:`~hkl.DiffractometerConfiguration()` +* ``settings`` is contains the configuration object (dict, json, or yaml) to be restored + +The same command is used to restore the configuration settings from either dict, +json string, or yaml string. The +:meth:`~hkl.DiffractometerConfiguration.restore` method will determine the +data type from its structure:: + + config.restore(settings) + +The example below demonstrates this process using a YAML file. + +Example ++++++++ + +Build a diffractometer (using E4CV geometry):: + + import numpy + from hkl import SimulatedE4CV + from hkl.configuration import DiffractometerConfiguration + from hkl.util import new_lattice + + e4c = SimulatedE4CV("", name="e4c") + config = DiffractometerConfiguration(e4c) + +Add a sample:: + + a0 = 2 * numpy.pi + cubic = new_lattice(a0) + e4c.calc.new_sample("vibranium", lattice=cubic) + +Define some reflections. Pick two of them to define its orientation:: + + _r400 = e4c.calc.sample.add_reflection(4, 0, 0, (-145.451, 0, 0, 69.0966)), + _r040 = e4c.calc.sample.add_reflection(0, 4, 0, (-145.451, 0, 90, 69.0966)) + _r004 = e4c.calc.sample.add_reflection(0, 0, 4, (-145.451, 90, 0, 69.0966)) + e4c.calc.sample.compute_UB(_r040, _r004) + +Save the orientation and other configuration:: + + settings = config.export() + with open("e4c-config.json", "w") as f: + f.write(settings) + +A :download:`JSON ` example of this file can be +downloaded. (Compare with :download:`YAML `.) This example +configuration can be restored to any diffractometer with matching ``"geometry": +"E4CV"``:: + + with open("e4c-config.json") as f: + settings = f.read() + config.restore(settings, clear=True) + +The extra keyword argument, ``clear=True`` (which is the default), means to +first remove any previous configuration of the diffractometer and reset it to +default values before restoring the configuration. + +API ++++ + +.. automodule:: hkl.configuration + :members: DiffractometerConfiguration + :exclude-members: Diffractometer + \ No newline at end of file