Skip to content

Commit

Permalink
Merge pull request #429 from BCDA-APS/426-simulated-diffractometers
Browse files Browse the repository at this point in the history
add simulated diffractometers: 4-circle, kappa, 6-circle
  • Loading branch information
prjemian committed Sep 27, 2020
2 parents ea78787 + 9aac10b commit 59c3145
Show file tree
Hide file tree
Showing 7 changed files with 453 additions and 14 deletions.
4 changes: 2 additions & 2 deletions apstools/beamtime/apsbss.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,9 +706,9 @@ def cmd_esaf(args):
esaf = getEsaf(args.esafId)
print(yaml.dump(esaf))
except DmRecordNotFound as exc:
print(exc)
print(f"DmRecordNotFound reported: {exc}")
except dm.DmException as exc:
print("dm reported: {exc}")
print(f"dm reported: {exc}")


def cmd_proposal(args):
Expand Down
11 changes: 8 additions & 3 deletions apstools/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -1748,10 +1748,10 @@ def AD_plugin_primed(detector_plugin):
Since Area Detector release 2.1 (2014-10-14).
The *prime* process is not needed if you select the
The *prime* process is not needed if you select the
*LazyOpen* feature with *Stream* mode for the file plugin.
*LazyOpen* defers file creation until the first frame arrives
in the plugin. This removes the need to initialize the plugin
*LazyOpen* defers file creation until the first frame arrives
in the plugin. This removes the need to initialize the plugin
with a dummy frame before starting capture.
"""
old_capture = detector_plugin.capture.get()
Expand All @@ -1772,15 +1772,20 @@ def AD_prime_plugin(detector, detector_plugin):
Prime this area detector's file writer plugin.
Collect and push an NDarray to the file writer plugin.
Works with HDF and JPEG file writers, maybe others.
PARAMETERS
detector
*obj* :
area detector (such as ``detector``)
detector_plugin
*obj* :
area detector plugin to be *primed* (such as ``detector.hdf1``)
EXAMPLE::
AD_prime_plugin(detector, detector.hdf1)
"""
old_enable = detector_plugin.enable.get()
old_mode = detector_plugin.file_write_mode.get()
Expand Down
160 changes: 157 additions & 3 deletions apstools/diffractometer.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
"""
add to capabilities of any diffractometer
diffractometer support
.. autosummary::
~Constraint
~DiffractometerMixin
~SoftE4CV
~SoftE6C
~SoftK4CV
~SoftK6C
"""

Expand All @@ -21,15 +25,24 @@
__all__ = [
'Constraint',
'DiffractometerMixin',
'SoftE4CV',
'SoftE6C',
'SoftK4CV',
'SoftK6C',
]

from ophyd import Component, Device, PseudoSingle, SoftPositioner
import collections
import gi
import logging
from ophyd import Component, Device, PseudoSingle
import pyRestTable

logger = logging.getLogger(__file__)

gi.require_version('Hkl', '5.0') # MUST come before `import hkl`
import hkl.diffract


Constraint = collections.namedtuple(
"Constraint",
("low_limit", "high_limit", "value", "fit"))
Expand All @@ -47,7 +60,7 @@ class DiffractometerMixin(Device):
~showConstraints
~undoLastConstraints
~wh
"""
"""

h = Component(PseudoSingle, '', labels=("hkl",), kind="hinted")
k = Component(PseudoSingle, '', labels=("hkl",), kind="hinted")
Expand Down Expand Up @@ -154,6 +167,7 @@ def wh(self, printing=True):
table.labels = "term value".split()
table.addRow(("diffractometer", self.name))
table.addRow(("mode", self.calc.engine.mode))
table.addRow(("sample name", self.calc.sample.name))
table.addRow(("wavelength (angstrom)", self.calc.wavelength))

for k, v in self.calc.pseudo_axes.items():
Expand All @@ -168,3 +182,143 @@ def wh(self, printing=True):
print(table)

return table


class SoftE4CV(DiffractometerMixin, hkl.diffract.E4CV):
"""
E4CV: Simulated (soft) 4-circle diffractometer, vertical scattering
EXAMPLE::
sim4c = SoftE4CV('', name='sim4c')
"""

omega = Component(SoftPositioner,
labels=("motor", "sim4c"), kind="hinted")
chi = Component(SoftPositioner,
labels=("motor", "sim4c"), kind="hinted")
phi = Component(SoftPositioner,
labels=("motor", "sim4c"), kind="hinted")
tth = Component(SoftPositioner,
labels=("motor", "sim4c"), kind="hinted")

def __init__(self, *args, **kwargs):
"""
start the SoftPositioner objects with initial values
Since this diffractometer uses simulated motors,
prime the SoftPositioners (motors) with initial values.
Otherwise, with position == None, then describe(), and
other functions get borked.
"""
super().__init__(*args, **kwargs)

for axis in self.real_positioners:
axis.move(0)


class SoftE6C(DiffractometerMixin, hkl.diffract.E6C):
"""
E6C: Simulated (soft) 6-circle diffractometer
EXAMPLE::
sim6c = SoftE6C('', name='sim6c')
"""

mu = Component(SoftPositioner,
labels=("motor", "sim6c"), kind="hinted")
omega = Component(SoftPositioner,
labels=("motor", "sim6c"), kind="hinted")
chi = Component(SoftPositioner,
labels=("motor", "sim6c"), kind="hinted")
phi = Component(SoftPositioner,
labels=("motor", "sim6c"), kind="hinted")
gamma = Component(SoftPositioner,
labels=("motor", "sim6c"), kind="hinted")
delta = Component(SoftPositioner,
labels=("motor", "sim6c"), kind="hinted")

def __init__(self, *args, **kwargs):
"""
start the SoftPositioner objects with initial values
Since this diffractometer uses simulated motors,
prime the SoftPositioners (motors) with initial values.
Otherwise, with position == None, then describe(), and
other functions get borked.
"""
super().__init__(*args, **kwargs)

for axis in self.real_positioners:
axis.move(0)


class SoftK4CV(DiffractometerMixin, hkl.diffract.K4CV):
"""
K4CV: Simulated (soft) kappa as 4-circle diffractometer
EXAMPLE::
simk4c = SoftK4CV('', name='simk4c')
"""

komega = Component(SoftPositioner,
labels=("motor", "simk4c"), kind="hinted")
kappa = Component(SoftPositioner,
labels=("motor", "simk4c"), kind="hinted")
kphi = Component(SoftPositioner,
labels=("motor", "simk4c"), kind="hinted")
tth = Component(SoftPositioner,
labels=("motor", "simk4c"), kind="hinted")

def __init__(self, *args, **kwargs):
"""
start the SoftPositioner objects with initial values
Since this diffractometer uses simulated motors,
prime the SoftPositioners (motors) with initial values.
Otherwise, with position == None, then describe(), and
other functions get borked.
"""
super().__init__(*args, **kwargs)

for axis in self.real_positioners:
axis.move(0)


class SoftK6C(DiffractometerMixin, hkl.diffract.K6C):
"""
K6C: Simulated (soft) kappa 6-circle diffractometer
EXAMPLE::
simk6c = SoftK6C('', name='simk6c')
"""

mu = Component(SoftPositioner,
labels=("motor", "simk6c"), kind="hinted")
komega = Component(SoftPositioner,
labels=("motor", "simk6c"), kind="hinted")
kappa = Component(SoftPositioner,
labels=("motor", "simk6c"), kind="hinted")
kphi = Component(SoftPositioner,
labels=("motor", "simk6c"), kind="hinted")
gamma = Component(SoftPositioner,
labels=("motor", "simk6c"), kind="hinted")
delta = Component(SoftPositioner,
labels=("motor", "simk6c"), kind="hinted")

def __init__(self, *args, **kwargs):
"""
start the SoftPositioner objects with initial values
Since this diffractometer uses simulated motors,
prime the SoftPositioners (motors) with initial values.
Otherwise, with position == None, then describe(), and
other functions get borked.
"""
super().__init__(*args, **kwargs)

for axis in self.real_positioners:
axis.move(0)
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies:
- bluesky>=1.6.2
- databroker>=1.0.6
- h5py
- hklpy
- ophyd>=1.5.1
- pip
- pyEpics>=3.4.2
Expand Down
4 changes: 2 additions & 2 deletions packaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ Build and upload::

Builds of this package are uploaded to these conda channels:

* `aps-anl-tag` production releases
* `aps-anl-dev` anything else, such as: pre-release, release candidates, or testing purposes
* [*aps-anl-tag*](https://anaconda.org/aps-anl-tag) : production releases
* [*aps-anl-dev*](https://anaconda.org/aps-anl-dev) : anything else, such as: pre-release, release candidates, or testing purposes
10 changes: 6 additions & 4 deletions tests/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
def suite(*args, **kw):

from tests import test_apsbss
from tests import test_simple
from tests import test_filewriter
from tests import test_export_json
from tests import test_exceltable
from tests import test_commandlist
from tests import test_diffractometer
from tests import test_exceltable
from tests import test_export_json
from tests import test_filewriter
from tests import test_simple
from tests import test_utils
test_list = [
test_simple,
Expand All @@ -27,6 +28,7 @@ def suite(*args, **kw):
test_commandlist,
test_utils,
test_apsbss,
test_diffractometer,
]

test_suite = unittest.TestSuite()
Expand Down

0 comments on commit 59c3145

Please sign in to comment.