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

restore reflections to the proper sample #292

Merged
merged 7 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions hkl/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
DEFAULT_WAVELENGTH = 1.54 # angstrom
EXPORT_FORMATS = "dict json yaml".split()

EQUAL_TOLERANCE = 1.0e-7


# standard value checks, raise exception(s) when appropriate
def _check_key(key, biblio, intro):
Expand Down Expand Up @@ -254,12 +256,12 @@ def validate(self, dc_obj):

def write(self, diffractometer):
"""Write sample details to diffractometer."""
s = diffractometer.calc._samples.get(self.name)
sample = diffractometer.calc._samples.get(self.name)
lattice_parameters = list(self.lattice.values)
if s is None:
s = diffractometer.calc.new_sample(self.name, lattice=lattice_parameters)
if sample is None:
sample = diffractometer.calc.new_sample(self.name, lattice=lattice_parameters)
else:
s.lattice = lattice_parameters
sample.lattice = lattice_parameters

reflection_list = []
for reflection in self.reflections:
Expand All @@ -275,18 +277,18 @@ def write(self, diffractometer):
w1 = rdict["wavelength"]
try:
diffractometer.calc.wavelength = w1
r = diffractometer.calc.sample.add_reflection(*args)
r = sample.add_reflection(*args)
if rdict["orientation_reflection"]:
reflection_list.append(r)
except RuntimeError as exc:
raise RuntimeError(f"could not add reflection({args}, wavelength={w1})") from exc
finally:
diffractometer.calc.wavelength = w0

if rdict["orientation_reflection"]:
reflection_list.append(r)
# Remaining code will not be executed if exception was raised.

if len(reflection_list) > 1:
r1, r2 = reflection_list[0], reflection_list[1]
diffractometer.calc.sample.compute_UB(r1, r2)
sample.compute_UB(r1, r2)


@dataclass
Expand Down Expand Up @@ -543,6 +545,11 @@ def restore(self, data, clear=True, restore_constraints=True):
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.

Expand Down
14 changes: 8 additions & 6 deletions hkl/sample.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Sample on the diffractometer."""

import logging

import numpy as np
Expand Down Expand Up @@ -88,21 +90,19 @@ class HklSample(object):

.. autosummary::

~name
~add_reflection
~affine
~remove_reflection
~swap_orientation_reflections
~clear_reflections
~affine
~compute_UB
~hkl_calc
~hkl_sample
~lattice
~name
~reciprocal
~reflection_measured_angles
~reflection_theoretical_angles
~reflections
~reflections_details
~remove_reflection
~swap_orientation_reflections
~U
~UB
~ux
Expand All @@ -113,6 +113,8 @@ class HklSample(object):

.. autosummary::

~hkl_calc
~hkl_sample
~__repr__
~__str__
~_create_reflection
Expand Down
32 changes: 0 additions & 32 deletions hkl/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,32 +0,0 @@
import logging

import numpy

from ..util import new_lattice

logger = logging.getLogger("ophyd_session_test")

TARDIS_TEST_MODE = "lifting_detector_mu"
TWO_PI = 2 * numpy.pi


def new_sample(diffractometer, name, lattice):
diffractometer.calc.new_sample(name, lattice=lattice)


def sample_kryptonite(diffractometer):
triclinic = new_lattice(4, 5, 6, 75, 85, 95)
new_sample(diffractometer, "kryptonite", lattice=triclinic)


def sample_silicon(diffractometer):
from .. import SI_LATTICE_PARAMETER

cubic = new_lattice(SI_LATTICE_PARAMETER)
new_sample(diffractometer, "silicon", lattice=cubic)


def sample_vibranium(diffractometer):
a0 = TWO_PI
cubic = new_lattice(a0)
new_sample(diffractometer, "vibranium", lattice=cubic)
2 changes: 1 addition & 1 deletion hkl/tests/test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from ..configuration import DCSample
from ..util import Constraint
from ..util import new_lattice
from . import TWO_PI
from .tools import TWO_PI

TEST_CONFIG_FILE = "data/e4c-config.json"

Expand Down
61 changes: 61 additions & 0 deletions hkl/tests/test_restore_reflections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
Test that reflections from one sample are not restored to other samples.
"""

from .. import DiffractometerConfiguration
from .tools import sample_kryptonite
from .tools import sample_silicon
from .tools import sample_vibranium


def test_issue289(e4cv):
assert e4cv is not None

# setup four samples with reflections, all of them different
main = e4cv.calc.sample # the default sample
assert len(main.reflections) == 0
m_100 = main.add_reflection(1, 0, 0, (-45, 0, 0, 0))
m_010 = main.add_reflection(0, 1, 0, (45, 0, 0, 0))
main.compute_UB(m_100, m_010)

kryptonite = sample_kryptonite(e4cv)
assert len(kryptonite.reflections) == 0
k_200 = kryptonite.add_reflection(2, 0, 0, (30, 0, 10, 60))
k_020 = kryptonite.add_reflection(0, 2, 0, (30, 90, 10, 60))
kryptonite.compute_UB(k_200, k_020)

vibranium = sample_vibranium(e4cv)
assert len(vibranium.reflections) == 0
v_003 = vibranium.add_reflection(0, 0, 3, (20.33, 4.33, 8.33, 40.33))
v_033 = vibranium.add_reflection(0, 3, 3, (20.33, -94.33, 8.33, 40.33))
vibranium.compute_UB(v_003, v_033)

silicon = sample_silicon(e4cv)
assert len(silicon.reflections) == 0
s_440 = silicon.add_reflection(4, 4, 0, (34, 44, 54, 64))
s_444 = silicon.add_reflection(4, 4, 4, (34, 134, 54, 64))
silicon.compute_UB(s_440, s_444)

n_saved_reflections = 2
assert len(main.reflections) == n_saved_reflections
assert len(kryptonite.reflections) == n_saved_reflections
assert len(silicon.reflections) == n_saved_reflections
assert len(vibranium.reflections) == n_saved_reflections
# same test, using diffractometer sample dictionary now.
for sample in e4cv.calc._samples.values():
assert len(sample.reflections) == n_saved_reflections, f"{sample.name=}"
assert len(e4cv.calc._samples) == 4

agent = DiffractometerConfiguration(e4cv)
assert agent is not None
config = agent.export()
assert isinstance(config, str)

# Restore the configuration without clearing the diffractometer first.
# This should not change the number of samples or the number of
# reflections for any of the samples.
agent.restore(config, clear=False)

assert len(e4cv.calc._samples) == 4
for sample in e4cv.calc._samples.values():
assert len(sample.reflections) == 2 * n_saved_reflections
6 changes: 3 additions & 3 deletions hkl/tests/test_tardis.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

@pytest.fixture(scope="function")
def kcf_sample(tardis):
from . import new_sample
from .tools import new_sample

# note: orientation matrix (below) was pre-computed with this wavelength
# wavelength units must match lattice unit cell length units
Expand Down Expand Up @@ -90,7 +90,7 @@ def test_params(tardis):
"""
Make sure the parameters are set correctly
"""
from . import TARDIS_TEST_MODE
from .tools import TARDIS_TEST_MODE

calc = tardis.calc
assert calc.pseudo_axis_names == "h k l".split()
Expand Down Expand Up @@ -319,7 +319,7 @@ def test_sample1(sample1, tardis):

def test_sample1_calc_only():
"""Comparisons start with the Tardis' calc support (no Diffractometer object)."""
from . import TARDIS_TEST_MODE
from .tools import TARDIS_TEST_MODE

tardis_calc = hkl_calc.CalcE6C()

Expand Down
38 changes: 38 additions & 0 deletions hkl/tests/tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""
Common code, setups, constants, ... for these tests.

Avoids direct imports of __init__.py.
"""

import logging

import numpy

from ..util import new_lattice

logger = logging.getLogger("ophyd_session_test")

TARDIS_TEST_MODE = "lifting_detector_mu"
TWO_PI = 2 * numpy.pi


def new_sample(diffractometer, name, lattice):
return diffractometer.calc.new_sample(name, lattice=lattice)


def sample_kryptonite(diffractometer):
triclinic = new_lattice(4, 5, 6, 75, 85, 95)
return new_sample(diffractometer, "kryptonite", lattice=triclinic)


def sample_silicon(diffractometer):
from .. import SI_LATTICE_PARAMETER

cubic = new_lattice(SI_LATTICE_PARAMETER)
return new_sample(diffractometer, "silicon", lattice=cubic)


def sample_vibranium(diffractometer):
a0 = TWO_PI
cubic = new_lattice(a0)
return new_sample(diffractometer, "vibranium", lattice=cubic)
Loading