Module: 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.

Note

New in v1.1.

Configuration dictionary#

Configuration includes:

  • geometry

  • current wavelength of the source

  • soft limits (constraints) on the physical axes

  • list [1] of reciprocal-space axes names

  • list [1] of canonical (geometry-defined) real-space axes names

  • list [1] of real-space axes names as the user has defined

  • list of samples

  • other general metadata about the diffractometer.

Each sample includes:

  • name

  • crystal lattice constants

  • list of orientation reflections

  • \(U\) matrix

  • \(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 exported to any of the formats shown in the table below. Assuming config is the object returned by calling 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

config.export(path_obj)

JSON string, JSON written to file identified by path_obj.

Restore#

A single command is used to set a diffractometer’s configuration from a Python object. Assuming:

  • config is the object returned by calling DiffractometerConfiguration()

  • settings 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 or from a file (where the file is specified as a pathlib.Path object). The 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 to file "e4c-config.json" in the present working directory:

settings = config.export()
with open("e4c-config.json", "w") as f:
    f.write(settings)

A JSON example of this file can be downloaded. (Compare with YAML.) This example configuration can be restored to any diffractometer with matching "geometry": "E4CV" and engine "engine": "hkl":

import pathlib

config.restore(pathlib.Path("e4c-config.json"), 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. The file name is described using the pathlib library.

Alternatively, the export() method accepts a pathlib object such as:

import pathlib

config_file = pathlib.Path("e4c-config.json")
config.export(config_file, clear=True)

API#

Save and restore Diffractometer Configuration.

PUBLIC API

DiffractometerConfiguration(diffractometer)

Save and restore Diffractometer Configuration.

PRIVATE API

note: DC classes: Diffractometer Configuration

_check_key(key, biblio, intro)

(internal) Raise KeyError if key is not in biblio.

_check_not_value(actual, avoid, intro)

(internal) Raise ValueError if actual IS equal to expected.

_check_range(value, low, high, intro)

(internal) Raise ValueError if value is not between low & high.

_check_type(actual, expected, intro)

(internal) Raise TypeError if actual is not an instance of expected.

_check_value(actual, expected, intro)

(internal) Raise ValueError if actual is not equal to expected.

DCConstraint(low_limit, high_limit, value[, fit])

(internal) Configuration of one diffractometer axis constraint.

DCLattice(a, b, c, alpha, beta, gamma)

(internal) Configuration of one crystal lattice.

DCReflection(reflection, position, ...[, flag])

(internal) Configuration of one orientation reflection.

DCSample(name, lattice, reflections, UB, U)

(internal) Configuration of one crystalline sample with a lattice.

DCConfiguration(geometry, engine, library, ...)

(internal) Full structure of the diffractometer configuration.

Note

New in v1.1.

class hkl.configuration.DiffractometerConfiguration(diffractometer)[source]#

Save and restore Diffractometer Configuration.

export([fmt])

Export configuration in a recognized format (dict, JSON, YAML, file).

preview(data[, show_constraints, ...])

List the samples in the configuration.

restore(data[, clear, restore_constraints])

Restore configuration from a recognized format (dict, JSON, YAML, file).

model

Return validated diffractometer configuration object.

reset_diffractometer()

Reset the diffractometer to the default configuration.

reset_diffractometer_constraints()

Reset the diffractometer constraints to defaults.

reset_diffractometer_samples()

Reset the diffractometer sample dict to defaults.

from_dict(data[, clear, restore_constraints])

Load diffractometer configuration from Python dictionary.

from_json(data[, clear, restore_constraints])

Load diffractometer configuration from JSON text.

from_yaml(data[, clear, restore_constraints])

Load diffractometer configuration from YAML text.

to_dict()

Report diffractometer configuration as Python dictionary.

to_json([indent])

Report diffractometer configuration as JSON text.

to_yaml([indent])

Report diffractometer configuration as YAML text.

canonical_axes_names

Names of the real-space axes, defined by the back-end library.

real_axes_names

Names of the real-space axes, defined by the user.

reciprocal_axes_names

Names of the reciprocal-space axes, defined by the back-end library.

_preview(data, show_constraints=False, show_reflections=False)[source]#
property canonical_axes_names#

Names of the real-space axes, defined by the back-end library.

export(fmt='json')[source]#

Export configuration in a recognized format (dict, JSON, YAML, file).

PARAMETERS

fmt str or pathlib.Path object:

One of these: None, "dict", "json", "yaml". If None (or empty string or no argument at all), then JSON will be the default.

from_dict(data, clear=True, restore_constraints=True)[source]#

Load diffractometer configuration from Python dictionary.

PARAMETERS

data dict:

structure (dict) with diffractometer configuration

clear bool:

If True (default), remove any previous configuration of the diffractometer and reset it to default values before restoring the configuration.

from_json(data, clear=True, restore_constraints=True)[source]#

Load diffractometer configuration from JSON text.

PARAMETERS

data str (JSON):

structure (JSON string) with diffractometer configuration

clear bool:

If True (default), remove any previous configuration of the diffractometer and reset it to default values before restoring the configuration.

from_yaml(data, clear=True, restore_constraints=True)[source]#

Load diffractometer configuration from YAML text.

PARAMETERS

data str (YAML):

structure (YAML string) with diffractometer configuration

clear bool:

If True (default), remove any previous configuration of the diffractometer and reset it to default values before restoring the configuration.

property model: DCConfiguration#

Return validated diffractometer configuration object.

preview(data, show_constraints=False, show_reflections=False)[source]#

List the samples in the configuration.

PARAMETERS

data dict or str pathlib.Path object:

Structure (dict, json, or yaml) with diffractometer configuration or pathlib object referring to a file with one of these formats.

show_constraints bool:

If True (default: False), will also show any constraints in a separate table.

show_reflections bool:

If True (default: False), will also show reflections, if any, in a separate table for each sample.

property real_axes_names#

Names of the real-space axes, defined by the user.

property reciprocal_axes_names#

Names of the reciprocal-space axes, defined by the back-end library.

reset_diffractometer()[source]#

Reset the diffractometer to the default configuration.

reset_diffractometer_constraints()[source]#

Reset the diffractometer constraints to defaults.

reset_diffractometer_samples()[source]#

Reset the diffractometer sample dict to defaults.

restore(data, clear=True, restore_constraints=True)[source]#

Restore configuration from a recognized format (dict, JSON, YAML, file).

Instead of guessing, recognize the kind of config data by its structure.

PARAMETERS

data dict or str pathlib.Path object:

Structure (dict, json, or yaml) with diffractometer configuration or pathlib object referring to a file with one of these formats.

clear bool:

If True (default), remove any previous configuration of the diffractometer and reset it to default values before restoring the configuration.

If False, sample reflections will be append with all reflections included in the configuration data for that sample. Existing reflections will not be changed. The user may need to edit the list of reflections after restore(clear=False).

restore_constraints bool:

If True (default), restore any constraints provided.

Note: Can’t name this method “import”, it’s a reserved Python word.

to_dict()[source]#

Report diffractometer configuration as Python dictionary.

to_json(indent=2)[source]#

Report diffractometer configuration as JSON text.

to_yaml(indent=2)[source]#

Report diffractometer configuration as YAML text.

Order of appearance may be important for some entries, such as the list of reflections. Use sort_keys=False here. Don’t make sort_keys a keyword argument that could be changed.

hkl.configuration._check_key(key, biblio, intro)[source]#

(internal) Raise KeyError if key is not in biblio.

hkl.configuration._check_not_value(actual, avoid, intro)[source]#

(internal) Raise ValueError if actual IS equal to expected.

hkl.configuration._check_range(value, low, high, intro)[source]#

(internal) Raise ValueError if value is not between low & high.

hkl.configuration._check_type(actual, expected, intro)[source]#

(internal) Raise TypeError if actual is not an instance of expected.

hkl.configuration._check_value(actual, expected, intro)[source]#

(internal) Raise ValueError if actual is not equal to expected.

class hkl.configuration.DCConfiguration(geometry: str, engine: str, library: str, mode: str, canonical_axes: ~typing.List[str], real_axes: ~typing.List[str], reciprocal_axes: ~typing.List[str], constraints: ~typing.Dict[str, ~hkl.configuration.DCConstraint], samples: ~typing.Dict[str, ~hkl.configuration.DCSample], name: str = '', datetime: str = '', wavelength_angstrom: float = <factory>, energy_keV: float = <factory>, hklpy_version: str = '', library_version: str = '', python_class: str = '', other: ~typing.Dict[str, ~typing.Any] = <factory>)[source]#

(internal) Full structure of the diffractometer configuration.

Optional (keyword) attributes are not used to restore a diffractometer’s configuration.

Required (non-optional) attributes are used by restore() to either match the diffractometer or restore the configuration.

geometry: str#

Name of the diffractometer geometry as provided by the back-end computation library. MUST match diffractometer to restore.

engine: str#

Name of the computational support for the reciprocal-space (pseudo) axes. MUST match in the list provided by the diffractometer geometry to restore. The engine defines the list of the reciprocal-space (pseudo) axes.

library: str#

Name of the back-end computation library. MUST match diffractometer to restore.

mode: str#

Diffractometer calculation mode. Chosen from list provided by the back-end computation library. MUST match in the list provided by the diffractometer to restore.

canonical_axes: List[str]#

List of the diffractometer real-space axis names. Both the exact spelling and order are defined by the back-end computation library. MUST match diffractometer to restore.

real_axes: List[str]#

User-defined real-space axis names. MUST match diffractometer to restore. The length and order of this list must be the same as the canonical_axes. It is used to resolve any (real-space) positioner names in this file.

reciprocal_axes: List[str]#

List of names of the diffractometer reciprocal-space (pseudo) axes. Both the exact spelling and order are defined by the back-end computation library engine. MUST match diffractometer to restore.

samples: Dict[str, DCSample]#

Crystalline samples (lattice and orientation reflections). The sample name is used as the key in the dictionary.

name: str = ''#

Name of this diffractometer. (optional)

datetime: str = ''#

Date and time this configuration was recorded. (optional)

wavelength_angstrom: float#

Wavelength (angstrom) of the incident radiation. (optional)

energy_keV: float#

Energy (keV) of the incident beam. Useful for synchrotron X-ray instruments. (optional)

hklpy_version: str = ''#

Version of the hklpy Python package used to create this diffractometer configuration content. (optional)

library_version: str = ''#

Version information of the back-end computation library. (optional)

python_class: str = ''#

Name of the Python class that defines this diffractometer. (optional)

other: Dict[str, Any]#

Any other content goes into this dictionary (comments, unanticipated keys, …) (optional)

validate(dc_obj)[source]#

Check this configuration has values the diffractometer can accept.

PARAMETERS

dc_obj DiffractometerConfiguration:

The DiffractometerConfiguration object.

write(diffractometer, restore_constraints=True)[source]#

Update diffractometer with configuration.

class hkl.configuration.DCConstraint(low_limit: float, high_limit: float, value: float, fit: bool = True)[source]#

(internal) Configuration of one diffractometer axis constraint.

low_limit: float#

Lowest acceptable value for this axis when computing real-space solutions from given reciprocal-space positions.

high_limit: float#

Highest acceptable value for this axis when computing real-space solutions from given reciprocal-space positions.

value: float#

Constant value used (on condition) for forward(hkl) calculation.

Implemented by diffractometer mode.

The diffractometer engine’s mode (such as E4CV’s constant_phi mode) controls whether or not the axis is to be held constant.

fit: bool = True#

(deprecated) Not used as a constraint. Value is ignored. See Constraint.

validate(cname)[source]#

Check this constraint has values the diffractometer can accept.

Assumes diffractometer real axis limits of AX_MIN to AX_MAX degrees.

property values#

Return the list of values in order.

class hkl.configuration.DCLattice(a: float, b: float, c: float, alpha: float, beta: float, gamma: float)[source]#

(internal) Configuration of one crystal lattice.

a: float#

unit cell length \(a\) (angstrom)

b: float#

unit cell length \(b\) (angstrom)

c: float#

unit cell length \(c\) (angstrom)

alpha: float#

unit cell angle alpha (degrees)

beta: float#

unit cell angle beta (degrees)

gamma: float#

unit cell angle gamma (degrees)

validate(*_args)[source]#

Check this lattice has values the diffractometer can accept.

property values#

Return the list of values in order.

class hkl.configuration.DCReflection(reflection: Dict[str, float], position: Dict[str, float], wavelength: float, orientation_reflection: bool, flag: int = 1)[source]#

(internal) Configuration of one orientation reflection.

reflection: Dict[str, float]#

Reciprocal-space axis positions. Keys must match in the list of reciprocal_axes.

position: Dict[str, float]#

Real-space axis positions. Keys must match in the list of canonical_axes.

wavelength: float#

Wavelength (angstroms) at which this reflection was measured.

orientation_reflection: bool#

Use this reflection for calculating \(UB\) matrix?

flag: int = 1#

(only used by libhkl)

validate(dc_obj)[source]#

Check this reflection has values the diffractometer can accept.

class hkl.configuration.DCSample(name: str, lattice: DCLattice, reflections: List[DCReflection], UB: List[List[float]], U: List[List[float]])[source]#

(internal) Configuration of one crystalline sample with a lattice.

name: str#

Name of this crystalline sample.

lattice: DCLattice#

Crystal lattice parameters (angstroms and degrees)

reflections: List[DCReflection]#

List of orientation reflections.

UB: List[List[float]]#

Orientation matrix (3 x 3). U is the crystal orientation matrix relative to the diffractometer and B is the transition matrix of a non-orthonormal (the reciprocal of the crystal) in an orthonormal system.

U: List[List[float]]#

Orientation matrix (3 x 3) of the crystal relative to the diffractometer. (optional)

validate(dc_obj)[source]#

Check this sample has values the diffractometer can accept.

write(diffractometer)[source]#

Write sample details to diffractometer.