From 532c403ada62c3a55097b5da6ef0b8ad43de23e3 Mon Sep 17 00:00:00 2001 From: David McDonagh <60879630+toastisme@users.noreply.github.com> Date: Fri, 31 May 2024 10:52:57 +0100 Subject: [PATCH] Add Laue experiment type (#733) * Add Laue experiment type --- newsfragments/733.misc | 1 + src/dxtbx/model/__init__.py | 4 + src/dxtbx/model/boost_python/experiment.cc | 3 +- src/dxtbx/model/experiment.h | 11 ++- tests/model/test_experiment_list.py | 88 ++++++++++++++++++++++ 5 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 newsfragments/733.misc diff --git a/newsfragments/733.misc b/newsfragments/733.misc new file mode 100644 index 000000000..bb62d39f2 --- /dev/null +++ b/newsfragments/733.misc @@ -0,0 +1 @@ +Add Laue experiment type. diff --git a/src/dxtbx/model/__init__.py b/src/dxtbx/model/__init__.py index 0cfbc0711..d1e5e384b 100644 --- a/src/dxtbx/model/__init__.py +++ b/src/dxtbx/model/__init__.py @@ -615,6 +615,10 @@ def all_tof(self): """Check if all the experiments are time-of-flight""" return all(exp.get_type() == ExperimentType.TOF for exp in self) + def all_laue(self): + """Check if all the experiments are Laue experiments""" + return all(exp.get_type() == ExperimentType.LAUE for exp in self) + def to_dict(self): """Serialize the experiment list to dictionary.""" diff --git a/src/dxtbx/model/boost_python/experiment.cc b/src/dxtbx/model/boost_python/experiment.cc index abe15a5a4..7a84f30a4 100644 --- a/src/dxtbx/model/boost_python/experiment.cc +++ b/src/dxtbx/model/boost_python/experiment.cc @@ -77,7 +77,8 @@ namespace dxtbx { namespace model { namespace boost_python { enum_("ExperimentType") .value("STILL", STILL) .value("ROTATION", ROTATION) - .value("TOF", TOF); + .value("TOF", TOF) + .value("LAUE", LAUE); class_("Experiment") .def(init, diff --git a/src/dxtbx/model/experiment.h b/src/dxtbx/model/experiment.h index 60adbe861..dc31457e6 100644 --- a/src/dxtbx/model/experiment.h +++ b/src/dxtbx/model/experiment.h @@ -28,7 +28,7 @@ namespace dxtbx { namespace model { - enum ExperimentType { ROTATION = 1, STILL = 2, TOF = 3 }; + enum ExperimentType { ROTATION = 1, STILL = 2, TOF = 3, LAUE = 4 }; /** * A class to represent what's in an experiment. @@ -156,6 +156,15 @@ namespace dxtbx { namespace model { if (scan_ && scan_->contains("time_of_flight")) { return TOF; } + + if (beam_) { + dxtbx::model::BeamBase &beam_base_ref = *beam_; + PolychromaticBeam *beam = dynamic_cast(&beam_base_ref); + if (beam != nullptr) { + return LAUE; + } + } + if (!goniometer_ || !scan_ || scan_->is_still()) { return STILL; } else { diff --git a/tests/model/test_experiment_list.py b/tests/model/test_experiment_list.py index b1ccead06..0e9643c22 100644 --- a/tests/model/test_experiment_list.py +++ b/tests/model/test_experiment_list.py @@ -17,6 +17,7 @@ from dxtbx.imageset import ImageSetFactory from dxtbx.model import ( Beam, + BeamFactory, Crystal, Detector, Experiment, @@ -26,6 +27,11 @@ Scan, ScanFactory, ) + +try: + from ..dxtbx_model_ext import Probe +except ModuleNotFoundError: + from dxtbx_model_ext import Probe # type: ignore from dxtbx.model.experiment_list import ExperimentListDict, ExperimentListFactory @@ -786,10 +792,22 @@ def test_experiment_type(): # Specifically test the bug from dxtbx#4 triggered by ending on 0° experiment.scan = Scan((1, 1800), (-90, 0.05)) assert experiment.get_type() == ExperimentType.ROTATION + + experiment.beam = BeamFactory.make_polychromatic_beam( + direction=(0, 0, -1), + sample_to_source_distance=(100), + probe=Probe.xray, + wavelength_range=(1, 10), + ) + + assert experiment.get_type() == ExperimentType.LAUE + experiment.scan = ScanFactory.make_scan_from_properties( (1, 10), properties={"time_of_flight": list(range(10))} ) assert experiment.get_type() == ExperimentType.TOF + + experiment.beam = Beam() experiment.scan = ScanFactory.make_scan_from_properties( (1, 10), properties={"other_property": list(range(10))} ) @@ -1184,3 +1202,73 @@ def test_from_templates(dials_data): assert len(expts) == 1 assert expts[0].imageset.get_template() == str(template) assert len(expts[0].imageset) == 45 + + +def test_experiment_list_all(): + experiments = ExperimentList() + for i in range(3): + experiments.append(Experiment()) + + assert experiments.all_stills() + experiments[0].goniometer = Goniometer() + assert experiments.all_stills() + experiments[1].goniometer = Goniometer() + experiments[2].goniometer = Goniometer() + assert experiments.all_stills() + + experiments[0].beam = BeamFactory.make_polychromatic_beam( + direction=(0, 0, -1), + sample_to_source_distance=(100), + probe=Probe.xray, + wavelength_range=(1, 10), + ) + assert not experiments.all_stills() + experiments[1].beam = BeamFactory.make_polychromatic_beam( + direction=(0, 0, -1), + sample_to_source_distance=(100), + probe=Probe.xray, + wavelength_range=(1, 10), + ) + experiments[2].beam = BeamFactory.make_polychromatic_beam( + direction=(0, 0, -1), + sample_to_source_distance=(100), + probe=Probe.xray, + wavelength_range=(1, 10), + ) + assert experiments.all_laue() + + experiments[0].beam = Beam() + assert not experiments.all_laue() + experiments[1].beam = Beam() + experiments[2].beam = Beam() + assert experiments.all_stills() + + experiments[0].scan = Scan((1, 1000), (0, 0.05)) + assert not experiments.all_stills() + experiments[1].scan = Scan((1, 1000), (0, 0.05)) + experiments[2].scan = Scan((1, 1000), (0, 0.05)) + assert experiments.all_rotations() + + experiments[0].scan = ScanFactory.make_scan_from_properties( + (1, 10), properties={"time_of_flight": list(range(10))} + ) + assert not experiments.all_rotations() + experiments[1].scan = ScanFactory.make_scan_from_properties( + (1, 10), properties={"time_of_flight": list(range(10))} + ) + experiments[2].scan = ScanFactory.make_scan_from_properties( + (1, 10), properties={"time_of_flight": list(range(10))} + ) + assert experiments.all_tof() + + experiments[0].scan = ScanFactory.make_scan_from_properties( + (1, 10), properties={"other_property": list(range(10))} + ) + assert not experiments.all_tof() + experiments[1].scan = ScanFactory.make_scan_from_properties( + (1, 10), properties={"other_property": list(range(10))} + ) + experiments[2].scan = ScanFactory.make_scan_from_properties( + (1, 10), properties={"other_property": list(range(10))} + ) + assert experiments.all_stills()