Skip to content

Commit

Permalink
Merge pull request #338 from bluesky/337-add-APS-POLAR
Browse files Browse the repository at this point in the history
add APS POLAR geometry

@padraic-shafer Thanks for the review
  • Loading branch information
prjemian authored Aug 7, 2024
2 parents 782b8ae + 3373261 commit cd32ae3
Show file tree
Hide file tree
Showing 18 changed files with 145 additions and 41 deletions.
14 changes: 9 additions & 5 deletions docs/make_geometry_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@
.. _geometry_tables:
=================================
=========================
Diffractometer Geometries
=================================
=========================
Tables are provided for the different geometries and then, for each
geometry, the calculation engines, pseudo axes required, modes of
operation, and any additional parameters required by the mode.
.. index:: mode
Tables are provided for the different geometries and then, for each geometry,
the calculation engines, pseudo axes required, modes of operation, and any
additional parameters required by the :ref:`mode <overview.mode>`. The mode
defines which axes will be computed, which will be held constant, and any
relationships between axes.
Geometries indexed by number of circles
---------------------------------------
Expand Down
51 changes: 33 additions & 18 deletions docs/source/diffract.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,46 @@ capabilities are also customized in a local subclass.
Examples are provided in the
:ref:`Geometries Examples <geometries.examples>` section.

.. _diffract.geometries.common:

Common Diffractometer Geometries
++++++++++++++++++++++++++++++++

These are the diffractometer geometries provided by the **libhkl**
library [#libhkl]_:

============================== ==========================
name description
============================== ==========================
:class:`~hkl.geometries.E4CH` Eulerian 4-circle, vertical scattering plane
:class:`~hkl.geometries.E4CV` Eulerian 4-circle, horizontal scattering plane
:class:`~hkl.geometries.E6C` Eulerian 6-circle
:class:`~hkl.geometries.K4CV` Kappa 4-circle, vertical scattering plane
:class:`~hkl.geometries.K6C` Kappa 6-circle
:class:`~hkl.geometries.Zaxis` Z-axis
============================== ==========================
.. autosummary::
:nosignatures:

~hkl.geometries.E4CH
~hkl.geometries.E4CV
~hkl.geometries.E6C
~hkl.geometries.K4CV
~hkl.geometries.K6C
~hkl.geometries.Zaxis

.. _diffract.geometries.special_use:

Special-use Diffractometer Geometries
+++++++++++++++++++++++++++++++++++++

These special-use geometries are also provided by the **libhkl**
library [#libhkl]_:

* :class:`~hkl.geometries.Petra3_p09_eh2`
* :class:`~hkl.geometries.SoleilMars`
* :class:`~hkl.geometries.SoleilSiriusKappa`
* :class:`~hkl.geometries.SoleilSiriusTurret`
* :class:`~hkl.geometries.SoleilSixsMed1p2`
* :class:`~hkl.geometries.SoleilSixsMed2p2`
* :class:`~hkl.geometries.SoleilSixsMed2p3`
* :class:`~hkl.geometries.SoleilSixsMed2p3v2`
.. autosummary::
:nosignatures:

~hkl.geometries.ApsPolar
~hkl.geometries.Petra3_p09_eh2
~hkl.geometries.Petra3_p23_4c
~hkl.geometries.Petra3_p23_6c
~hkl.geometries.SoleilMars
~hkl.geometries.SoleilSiriusKappa
~hkl.geometries.SoleilSiriusTurret
~hkl.geometries.SoleilSixsMed1p2
~hkl.geometries.SoleilSixsMed2p2
~hkl.geometries.SoleilSixsMed2p3
~hkl.geometries.SoleilSixsMed2p3v2

In all cases, see the **libhkl** documentation for further information
on these geometries.
Expand Down
38 changes: 33 additions & 5 deletions docs/source/geometry_tables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ Diffractometer Geometries

Tables are provided for the different geometries and then, for each geometry,
the calculation engines, pseudo axes required, modes of operation, and any
additional parameters required by the :ref:`mode <overview.mode>`. The mode defines
which axes will be computed, which will be held constant, and any relationships
between axes.
additional parameters required by the :ref:`mode <overview.mode>`. The mode
defines which axes will be computed, which will be held constant, and any
relationships between axes.

Geometries indexed by number of circles
---------------------------------------
Expand All @@ -37,6 +37,7 @@ used here in |hklpy|).
4 :ref:`ZAXIS <ZAXIS_table>` ``mu``, ``omega``, ``delta``, ``gamma``
5 :ref:`SOLEIL SIXS MED2+2 <SOLEIL_SIXS_MED2+2_table>` ``beta``, ``mu``, ``omega``, ``gamma``, ``delta``
5 :ref:`SOLEIL SIXS MED2+3 v2 <SOLEIL_SIXS_MED2+3_v2_table>` ``mu``, ``omega``, ``gamma``, ``delta``, ``eta_a``
6 :ref:`APS POLAR <APS_POLAR_table>` ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta``
6 :ref:`E6C <E6C_table>` ``mu``, ``omega``, ``chi``, ``phi``, ``gamma``, ``delta``
6 :ref:`K6C <K6C_table>` ``mu``, ``komega``, ``kappa``, ``kphi``, ``gamma``, ``delta``
6 :ref:`PETRA3 P09 EH2 <PETRA3_P09_EH2_table>` ``mu``, ``omega``, ``chi``, ``phi``, ``delta``, ``gamma``
Expand All @@ -54,8 +55,6 @@ used here in |hklpy|).
Tables for each geometry
------------------------

.. index:: mode

A table is provided for each diffractometer geometry listing the calculation
engines, pseudo axes required, modes of operation, and any additional parameters
required by the mode.
Expand All @@ -71,6 +70,35 @@ required by the mode.
* *axes written* : Axes computed by the ``forward()`` computation.
* *extra parameters* : Any necessary additional parameters.

.. index:: APS_POLAR, geometry; APS_POLAR

.. _APS_POLAR_table:

Geometry: ``APS POLAR``
+++++++++++++++++++++++

* real axes: ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta``
* pseudo axes: depends on the engine

====== =================== ================================= ======================================================= ===================================== ===============================
engine pseudo axes mode axes read axes written extra parameters
====== =================== ================================= ======================================================= ===================================== ===============================
hkl ``h``, ``k``, ``l`` 4-circles bissecting horizontal ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``mu``, ``chi``, ``phi``, ``gamma``
hkl ``h``, ``k``, ``l`` 4-circles constant chi horizontal ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``mu``, ``phi``, ``gamma``
hkl ``h``, ``k``, ``l`` 4-circles constant mu horizontal ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``chi``, ``phi``, ``gamma``
hkl ``h``, ``k``, ``l`` 4-circles constant phi horizontal ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``mu``, ``chi``, ``gamma``
hkl ``h``, ``k``, ``l`` lifting detector chi ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``chi``, ``gamma``, ``delta``
hkl ``h``, ``k``, ``l`` lifting detector mu ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``tau``, ``gamma``, ``delta``
hkl ``h``, ``k``, ``l`` lifting detector mu ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``tau``, ``gamma``, ``delta``
hkl ``h``, ``k``, ``l`` lifting detector phi ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``phi``, ``gamma``, ``delta``
hkl ``h``, ``k``, ``l`` psi constant horizontal ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``mu``, ``chi``, ``phi``, ``gamma`` ``h2``, ``k2``, ``l2``, ``psi``
hkl ``h``, ``k``, ``l`` psi constant vertical ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``tau``, ``chi``, ``phi``, ``delta`` ``h2``, ``k2``, ``l2``, ``psi``
hkl ``h``, ``k``, ``l`` zaxis + alpha-fixed ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``mu``, ``gamma``, ``delta``
hkl ``h``, ``k``, ``l`` zaxis + alpha=beta ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``tau``, ``mu``, ``gamma``, ``delta``
hkl ``h``, ``k``, ``l`` zaxis + beta-fixed ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``tau``, ``gamma``, ``delta``
psi ``psi`` psi_vertical ``tau``, ``mu``, ``chi``, ``phi``, ``gamma``, ``delta`` ``mu``, ``chi``, ``phi``, ``delta`` ``h2``, ``k2``, ``l2``
====== =================== ================================= ======================================================= ===================================== ===============================

.. index:: E4CH, geometry; E4CH

.. _E4CH_table:
Expand Down
5 changes: 3 additions & 2 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ dependencies:
- python >=3.8,<3.12
- apischema
- bluesky
- databroker
- databroker <=1.999
- hkl
- numpy
- numpy <=1.999
- ophyd
- orjson
- packaging
- pint
- pip
Expand Down
1 change: 1 addition & 0 deletions hkl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from .geometries import E6C
from .geometries import K4CV
from .geometries import K6C
from .geometries import ApsPolar
from .geometries import Petra3_p09_eh2
from .geometries import Petra3_p23_4c
from .geometries import Petra3_p23_6c
Expand Down
9 changes: 9 additions & 0 deletions hkl/calc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
.. autosummary::
~CalcApsPolar
~CalcE4CH
~CalcE4CV
~CalcE6C
Expand Down Expand Up @@ -47,6 +48,7 @@

__all__ = """
A_KEV
CalcApsPolar
CalcE4CH
CalcE4CV
CalcE6C
Expand Down Expand Up @@ -806,6 +808,13 @@ def _cfg_reciprocal(self):
return tuple(list(self.sample.reciprocal))


class CalcApsPolar(CalcRecip):
"""Geometry: APS POLAR"""

def __init__(self, **kwargs):
super().__init__("APS POLAR", **kwargs)


class CalcE4CH(CalcRecip):
"""Geometry: E4CH"""

Expand Down
2 changes: 1 addition & 1 deletion hkl/diffract.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"""


import logging

import pint
Expand Down Expand Up @@ -113,6 +112,7 @@ class (using `calc_kw`) to instantiate a new one.
See Also
--------
:class:`~hkl.geometries.ApsPolar
:class:`~hkl.geometries.E4CH`
:class:`~hkl.geometries.E4CV`
:class:`~hkl.geometries.E6C`
Expand Down
8 changes: 8 additions & 0 deletions hkl/geometries.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
.. autosummary::
~ApsPolar
~Petra3_p09_eh2
~Petra3_p23_4c
~Petra3_p23_6c
Expand All @@ -54,6 +55,7 @@
from .diffract import Diffractometer

__all__ = """
ApsPolar
E4CH
E4CV
E6C
Expand All @@ -80,6 +82,12 @@
logger = logging.getLogger(__name__)


class ApsPolar(Diffractometer):
"""APS POLAR 6-circle diffractometer."""

calc_class = calc.CalcApsPolar


class E4CH(Diffractometer):
"""Eulerian 4-circle, horizontal scattering plane"""

Expand Down
2 changes: 1 addition & 1 deletion hkl/tests/test_diffract.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


class Fourc(SimulatedE4CV):
...
"""4-circle for testing."""


@pytest.fixture(scope="function")
Expand Down
2 changes: 1 addition & 1 deletion hkl/tests/test_extra_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class Fourc(SimulatedE4CV):
...
"""4-circle for testing."""


FOURC_SETUP_CODE = """
Expand Down
2 changes: 1 addition & 1 deletion hkl/tests/test_fourc.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


class Fourc(SimulatedE4CV):
...
"""4-circle for testing."""


def check_hkl(diffractometer, h, k, l):
Expand Down
1 change: 1 addition & 0 deletions hkl/tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
[
("calc", "A_KEV"),
("calc", "UnreachableError"),
("geometries", "ApsPolar"),
("geometries", "E4CH"),
("geometries", "E4CV"),
("geometries", "E6C"),
Expand Down
2 changes: 1 addition & 1 deletion hkl/tests/test_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class Fourc(SimulatedE4CV):
...
"""4-circle for testing."""


@pytest.fixture(scope="function")
Expand Down
4 changes: 2 additions & 2 deletions hkl/tests/test_save_restore_UB.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@


class Fourc(SimulatedE4CV):
...
"""4-circle for testing."""


class Kappa(SimulatedK4CV):
...
"""Kappa 4-circle for testing."""


@pytest.fixture
Expand Down
2 changes: 1 addition & 1 deletion hkl/tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


class Fourc(SimulatedE4CV):
...
"""4-circle for testing."""


@pytest.fixture(scope="function")
Expand Down
2 changes: 1 addition & 1 deletion hkl/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
from bluesky import plans as bp
from bluesky.run_engine import RunEngine
from packaging import version
from tiled.utils import safe_json_dump

from .. import util
from .tools import DocsCollector
from .tools import safe_json_dump
from .tools import validate_descriptor_doc_content

NO_SUCH_PACKAGE_NAME = "no-such-package"
Expand Down
37 changes: 36 additions & 1 deletion hkl/tests/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from pathlib import Path # noqa

import numpy
from tiled.utils import safe_json_dump

from ..util import new_lattice

Expand Down Expand Up @@ -90,3 +89,39 @@ def validate_descriptor_doc_content(gname, descriptor):
]
for attr, struct in attrs:
assert isinstance(data.get(f"{gname}_{attr}"), struct), f"{attr=!r} {list(data)=!r}"


def safe_json_dump(content):
"""
Vendored from tiled.utils
https://github.com/bluesky/tiled/blob/15abbc98df9bfd25f8c713656f664a558136e26f/tiled/utils.py#L526
Base64-encode raw bytes, and provide a fallback if orjson numpy handling fails.
"""
import base64
import sys

import orjson

def default(content):
if isinstance(content, bytes):
content = f"data:application/octet-stream;base64,{base64.b64encode(content).decode('utf-8')}"
return content
if isinstance(content, Path):
return str(content)
# No need to import numpy if it hasn't been used already.
numpy = sys.modules.get("numpy", None)
if numpy is not None:
if isinstance(content, numpy.ndarray):
# If we make it here, OPT_NUMPY_SERIALIZE failed because we have hit some edge case.
# Give up on the numpy fast-path and convert to Python list.
# If the items in this list aren't serializable (e.g. bytes) we'll recurse on each item.
return content.tolist()
elif isinstance(content, (bytes, numpy.bytes_)):
return content.decode("utf-8")
raise TypeError

# Not all numpy dtypes are supported by orjson.
# Fall back to converting to a (possibly nested) Python list.
return orjson.dumps(content, option=orjson.OPT_SERIALIZE_NUMPY, default=default)
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ docs = [
]
tests = [
"bluesky",
"tiled",
"databroker <=1.999",
"numpy <=1.999",
"orjson",
"packaging",
]
all = ["hklpy[docs,tests]"]
Expand Down

0 comments on commit cd32ae3

Please sign in to comment.