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

API evolution and performance improvements #74

Merged
merged 68 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
02fe9a5
Adapt for shm-enabled libertem-dectris-rs version
sk1p Jan 18, 2023
4b94948
dectris: allow the raw_tile to be a bit bigger than the tiling depth
sk1p Jan 19, 2023
e6fb948
Fix trigger setup: ext{e,s} needs nimages=1, ntrigger=X
sk1p Jan 23, 2023
84f1bbc
Don't leak shm slots, clean up in a finally block
sk1p Jan 25, 2023
dbcf737
WIP: active/passive control modes
sk1p Jan 25, 2023
37fb080
Tweak DECTRIS acquisition API for passive/active modes
sk1p Jan 27, 2023
f9e815a
add missing file
sk1p Jan 27, 2023
be45018
ensure header_detail is set to basic
sk1p Jan 27, 2023
eade30c
dectris sim: support for header_detail; fix number of frames
sk1p Jan 27, 2023
7669717
dectris: support for reconnecting
sk1p Jan 27, 2023
1e6c1d9
add passive api prototype notebook
sk1p Feb 15, 2023
7fa49f4
See if this fixes the tox issue with notebook tests
uellue Jan 13, 2023
896869c
Partition monitor UDF; native sparse processing
uellue Feb 23, 2023
b95f1a4
tweak partition signal monitor UDF
sk1p Feb 28, 2023
58ff8f6
dectris sim: hopefully fix trigger mode
sk1p Mar 14, 2023
3c52f6b
Adapt DectrisAcquisition to new libertem_dectris API
sk1p Mar 15, 2023
4b0ee48
Misc. cleanup for DECTRIS support and new APIs
sk1p Mar 21, 2023
86f5d6e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 21, 2023
ef59451
flake8 fixes
sk1p Mar 21, 2023
a9895a5
Remove duplicate `allowlist_externals`
sk1p Mar 21, 2023
b31d3af
WIP: documentation update
sk1p Mar 21, 2023
e3e7fac
WIP: docs
sk1p Mar 21, 2023
605dd3a
API tweaks and documentation
sk1p Mar 22, 2023
879bf18
Tweak `LiveContext` API
sk1p Mar 24, 2023
6dd561b
Implement context manager API for DectrisDetectorConnection
sk1p Mar 29, 2023
35e1a2d
Update the generic `DetectorConnection` interface
sk1p Mar 29, 2023
d26ab09
dectris sim: make debugging easier by propagating error msg to client
sk1p Mar 30, 2023
2af3e2b
tweak API: `LiveContext.make_acquisition` is now generic
sk1p Mar 30, 2023
98a2561
Update merlin active acquisition to new API
sk1p Mar 30, 2023
ce77fc8
Port the memory dataset to the new API
sk1p Mar 30, 2023
e5488d5
Fix example in docstring for memory acq
sk1p Mar 30, 2023
88c9913
tox.ini: full path in `allowlist_externals` for notebooks
sk1p Mar 30, 2023
2c894a4
Misc. fixes for various test failures
sk1p Mar 31, 2023
a1b99e9
Fixes: command order; get detector shape after setting
uellue Apr 3, 2023
97ef073
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 3, 2023
bcf7bee
Memory: add explicit tests for active and passive mode
sk1p Mar 31, 2023
ea0ec09
WIP: merlin updates, typing fixes, ...
sk1p Apr 3, 2023
981c6dd
Add comments for the command order
sk1p Apr 3, 2023
23fbebc
merlin: support for passive acquisition flow
sk1p Apr 3, 2023
3f30b17
Remove outdated testcase
sk1p Apr 3, 2023
cff360e
memory: fix inverted logic for calling `on_ready_for_data` hook
sk1p Apr 3, 2023
2918066
Typing improvements for `LiveContext.make_acquisition`
sk1p Apr 3, 2023
77ef45e
examples: update merlin-digital-micrograph.py
sk1p Apr 3, 2023
3e04c83
merlin: add a test for the timeout case of passive acquisition
sk1p Apr 3, 2023
f73a90a
merlin: sim: prime control sim with initial params
sk1p Apr 3, 2023
92ea41f
Update docstrings etc.
sk1p Apr 3, 2023
28e2c25
Update example notebooks
sk1p Apr 3, 2023
523f5c1
dectris: Add support for `mask_to_zero`; document ROI changes
sk1p Apr 4, 2023
4871fbb
merlin sim: provide COUNTERDEPTH from offline data
sk1p Apr 4, 2023
7170b41
Fix `Protocol` import for old-Python
sk1p Apr 4, 2023
1572ab2
Add an `autouse` fixture for numpy in doctests
sk1p Apr 4, 2023
d317334
WIP: documentation updates
sk1p Apr 4, 2023
3675e73
Let doctests run with data access
sk1p Apr 5, 2023
98e85b3
Fix `add_sims` autouse fixture in case of no data availability
sk1p Apr 5, 2023
986dfec
Misc. docs updates
sk1p Apr 6, 2023
6a5d88a
Documentation updates
sk1p Apr 6, 2023
f6fbf04
Include the dectris example notebook in the documentation
sk1p Apr 6, 2023
e34d33f
Update examples; add requirements sections etc.
sk1p Apr 6, 2023
e1d649e
Add some skipif conditions for doc test code
sk1p Apr 6, 2023
6967ee1
Implement `nav_shape` automatisms
sk1p Apr 11, 2023
9ba5b28
Update dectris example notebook
sk1p Apr 11, 2023
cf563c8
Fix intersphinx URL for numpy
sk1p Apr 11, 2023
12aebe8
Add and update changelog entries
sk1p Apr 11, 2023
071f177
Hooks `on_determine_nav_shape` docs; misc. fixes
sk1p Apr 11, 2023
bb48d2a
Make sure to pass TESTDATA_BASE_PATH in docs-check run
sk1p Apr 11, 2023
eb12fdb
codecov: fix `after_n_builds` config
sk1p Apr 11, 2023
bb6853e
Apply suggestions from code review
sk1p Apr 18, 2023
136898c
Documentation updates from review
sk1p Apr 18, 2023
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
2 changes: 1 addition & 1 deletion codecov.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
comment:
after_n_builds: 11
after_n_builds: 9
coverage:
status:
project:
Expand Down
88 changes: 87 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,38 @@
Global test configuration. Use this file to define fixtures to use
in both doctests and regular tests.
"""
import os
import importlib
from contextlib import contextmanager

from libertem.executor.inline import InlineJobExecutor
from libertem.executor.pipelined import PipelinedExecutor

import pytest
import numpy as np

from libertem.viz.base import Dummy2DPlot

from libertem_live.detectors.dectris.sim import DectrisSim
from libertem_live.detectors.merlin.sim import CameraSim
from libertem_live import api as ltl
# A bit of gymnastics to import the test utilities since this
# conftest.py file is shared between the doctests and unit tests
# and this file is outside the package
basedir = os.path.dirname(__file__)
location = os.path.join(basedir, "tests/utils.py")
spec = importlib.util.spec_from_file_location("utils", location)
utils = importlib.util.module_from_spec(spec)
spec.loader.exec_module(utils)


DECTRIS_TESTDATA_PATH = os.path.join(
utils.get_testdata_path(),
'dectris', 'zmqdump.dat.128x128-id34-exte-bslz4'
)
HAVE_DECTRIS_TESTDATA = os.path.exists(DECTRIS_TESTDATA_PATH)
MIB_TESTDATA_PATH = os.path.join(utils.get_testdata_path(), 'default.mib')
HAVE_MIB_TESTDATA = os.path.exists(MIB_TESTDATA_PATH)


@pytest.fixture
Expand Down Expand Up @@ -37,10 +62,71 @@ def ctx_pipelined():

@pytest.fixture()
def default_aq(ltl_ctx):
return ltl_ctx.prepare_acquisition('memory', trigger=None, datashape=[16, 16, 32, 32])
conn = ltl_ctx.make_connection('memory').open(
data=None, extra_kwargs={'datashape': [16, 16, 32, 32]}
)
return ltl_ctx.make_acquisition(conn=conn)


def pytest_collectstart(collector):
# nbval: ignore some output types
if collector.fspath and collector.fspath.ext == '.ipynb':
collector.skip_compare += 'text/html', 'application/javascript', 'stderr',


@pytest.fixture(autouse=True, scope='session')
def add_np(doctest_namespace):
doctest_namespace['np'] = np


@pytest.fixture(autouse=True, scope='session')
def add_helpers(doctest_namespace, ctx_pipelined):
from libertem.udf.sum import SumUDF
doctest_namespace['ctx'] = ctx_pipelined
doctest_namespace['SumUDF'] = SumUDF


@pytest.fixture(autouse=True, scope='session')
def add_sims(doctest_namespace):
if not HAVE_DECTRIS_TESTDATA or not HAVE_MIB_TESTDATA:
# FIXME: add some kind of proxy object that calls
# pytest.skip on access? is this possible somehow?
yield
return
path = DECTRIS_TESTDATA_PATH

sim = contextmanager(utils.run_camera_sim)

with sim(
cls=DectrisSim,
path=path,
port=0,
zmqport=0,
) as dectris_runner, sim(
cls=CameraSim,
host='127.0.0.1',
data_port=0,
control_port=0,
trigger_port=0,
path=MIB_TESTDATA_PATH,
nav_shape=(32, 32),
wait_trigger=False,
initial_params={
'IMAGEX': "256",
'IMAGEY': "256",
'COUNTERDEPTH': '12',
},
) as merlin_runner:
dectris_api_port, dectris_data_port = dectris_runner.port, dectris_runner.zmqport
merlin_api_port, merlin_data_port = (
merlin_runner.control_t.sockname[1],
merlin_runner.server_t.sockname[1]
)

doctest_namespace['DCU_API_PORT'] = dectris_api_port
doctest_namespace['DCU_DATA_PORT'] = dectris_data_port

doctest_namespace['MERLIN_API_PORT'] = merlin_api_port
doctest_namespace['MERLIN_DATA_PORT'] = merlin_data_port

yield
14 changes: 14 additions & 0 deletions docs/source/changelog/features/api-evolution.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[Feature] Update user-facing APIs
=================================

* Most operations are now reachable just by importing the :class:`libertem_live.api.LiveContext`,
no need to manually import detector-specific classes etc.
* Introduce :class:`libertem_live.hooks.Hooks` as a replacement
for the trigger function that is open for future enhancements.
* Generic interface :meth:`libertem_live.api.LiveContext.make_acquisition` for
creating acquisition objects; the detector specific parameters are now mostly
specified in :meth:`libertem_live.api.LiveContext.make_connection`. Connecting
and creating an acquisition object is now a two-step process.
* Support for a passive acquisition workflow using
:meth:`libertem_live.detectors.base.connection.DetectorConnection.wait_for_acquisition`
(:pr:`74`).
2 changes: 2 additions & 0 deletions docs/source/changelog/features/dectris.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[Feature] Support for DECTRIS detectors
=======================================
* Initial support for DECTRIS detectors, including QUADRO and ARINA (:pr:`51`).
* Updated to use shared memory as data transport to worker processes
for efficiency gains (:pr:`74`).
13 changes: 13 additions & 0 deletions docs/source/changelog/features/shape-auto.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Feature] Automatically determine :code:`nav_shape` if possible
===============================================================

* This is only possible in passive mode, as we have to know
the :code:`nav_shape` in active mode.
* If the automatic mode doesn't work for you, it's still possible to
manually specify the shape, or to override :meth:`libertem_live.hooks.Hooks.on_determine_nav_shape`
which takes precedence over the automatic detection.
* It's now possible to have placeholders in the :code:`nav_shape`,
which will be filled with the remainder of the shape. For example,
It's possible to specify :code:`(-1, -1)` and get a 2D shape, or
something like :code:`(128, -1)` to fill the last dimension automatically,
based on the number of frames in the acquisition (:pr:`74`).
7 changes: 6 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@
todo_include_todos = True

intersphinx_mapping = {
'numpy': ('http://docs.scipy.org/doc/numpy/', None),
'numpy': ('https://numpy.org/doc/stable/', None),
'python': ('https://docs.python.org/3.10', None),
'libertem': ('https://libertem.github.io/LiberTEM/', None),
}
Expand Down Expand Up @@ -237,4 +237,9 @@ def get_testdata_path():
'dectris', 'zmqdump.dat.128x128-id34-exte-bslz4'
)
HAVE_DECTRIS_TESTDATA = os.path.exists(DECTRIS_TESTDATA_PATH)

MERLIN_TESTDATA_PATH = os.path.join(
get_testdata_path(), 'default.mib',
)
HAVE_MERLIN_TESTDATA = os.path.exists(MERLIN_TESTDATA_PATH)
'''
3 changes: 3 additions & 0 deletions docs/source/dectris-acquisition-example.nblink
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"path": "../../examples/dectris-acquisition.ipynb"
}
153 changes: 11 additions & 142 deletions docs/source/detectors.rst
Original file line number Diff line number Diff line change
@@ -1,149 +1,18 @@
Supported Detectors
sk1p marked this conversation as resolved.
Show resolved Hide resolved
===================

.. _`dectris detectors`:
These are the different detectors and detector APIs supported in LiberTEM-live. Note
that level of support can vary between these, but the basic functionality
of receiving data and running UDFs on it works for each of these.

DECTRIS EIGER2-based
--------------------
Support for additional detectors is planned, please talk to us if you are
missing your detector in this list!

.. versionadded:: 0.2
In addition, there is also a :ref:`memory "detector" <memory detector>` available,
which is mostly useful for testing, and is not optimized for production use.

LiberTEM-live has support for all DECTRIS detectors that support
the `SIMPLON API <https://media.dectris.com/210607-DECTRIS-SIMPLON-API-Manual_EIGER2-chip-based_detectros.pdf>`_,
including QUADRO and ARINA.
.. toctree::
:maxdepth: 2
:glob:

.. note::
Python 3.7+ is required to use the DECTRIS-related features of
LiberTEM-live, and we recommend to use Python 3.10. Currently, Windows and
Linux on x86_64 are supported.

Installation
............

There are a few extra dependencies needed for DECTRIS support. You can easily
install them using:

.. code-block:: shell

(libertem) $ python -m pip install "libertem-live[dectris]"

Currently, at least LiberTEM 0.10 is required. Using LiberTEM master is
recommended until a number of stability fixes for the pipelined executor are
released in LiberTEM.

Usage example
.............

.. testsetup::
:skipif: not HAVE_DECTRIS_TESTDATA

from libertem_live.detectors.dectris.sim import DectrisSim
server = DectrisSim(path=DECTRIS_TESTDATA_PATH, port=0, zmqport=0, verbose=False)
server.start()
server.wait_for_listen()
DCU_API_PORT = server.port
DCU_DATA_PORT = server.zmqport

.. testoutput::
:hide:

RustedReplay listening on tcp://127.0.0.1:...
Waiting for arm

.. testcode::
:skipif: not HAVE_DECTRIS_TESTDATA

from libertem.executor.pipelined import PipelinedExecutor
from libertem.viz.bqp import BQLive2DPlot
from libertem_live.api import LiveContext
from libertem.udf.sum import SumUDF

executor = PipelinedExecutor(spec=PipelinedExecutor.make_spec(cpus=range(10), cudas=[]))
ctx = LiveContext(executor=executor, plot_class=BQLive2DPlot)

def trigger(aq):
"""
You can trigger the scan here, if you have a microscope control API
"""
# you can imagine something like:
# trigger_scan(shape=tuple(aq.shape.nav), dwelltime=67e-6)
pass

# prepare for acquisition, setting up scan parameters etc.
aq = ctx.prepare_acquisition(
'dectris',
api_host="127.0.0.1",
api_port=DCU_API_PORT,
data_host="127.0.0.1",
data_port=DCU_DATA_PORT,
nav_shape=(128, 128),
trigger_mode="exte",
trigger=trigger,
frames_per_partition=512,
)

# run one or more UDFs on the live data stream:
# (this can be run multiple times on the same `aq` object)
ctx.run_udf(dataset=aq, udf=SumUDF(), plots=True)

.. testoutput::
:hide:

...

.. testcleanup::
:skipif: not HAVE_DECTRIS_TESTDATA

ctx.close()
server.stop()
server.maybe_raise()

See the :ref:`DECTRIS reference section <dectris reference>` for a description of
the acquisition parameters.

.. _`merlin detector`:

Quantum Detectors Merlin
------------------------

No extra dependencies are needed for using Merlin detectors.

Supported are currently 1 bit, 6 bit and 12 bit :code:`COUNTERDEPTH` for both the "binary"
(:code:`FILEFORMAT 0`) and the "raw binary" format (:code:`FILEFORMAT 2`).

For testing, an acquisition with soft trigger (:code:`TRIGGERSTART 5`) is
recommended since internal trigger (:code:`TRIGGERSTART 0`) may cause issues
with finding the beginning of the data stream. For a real STEM acquisition a
hardware trigger setup that matches the given instrument is required. See the
MerlinEM User Manual from Quantum Detectors for details!

A simple simulator for testing live acquisition without the actual hardware is
included in LiberTEM-live. It replays an MIB dataset and accepts the following
parameters:

.. code-block:: shell

(libertem) $ libertem-live-mib-sim --help
Usage: libertem-live-mib-sim [OPTIONS] PATH

Options:
--nav-shape <INTEGER INTEGER>...
--continuous
--cached [NONE|MEM|MEMFD]
--host TEXT Address to listen on (data, control, and
trigger sockets)
--data-port INTEGER
--control-port INTEGER
--wait-trigger Wait for a SOFTTRIGGER command on the
control port, or a trigger signal on the
trigger socket
--garbage Send garbage before trigger. Implies --wait-
trigger
--max-runs INTEGER
--help Show this message and exit.

A suitable MIB dataset for testing can be downloaded at
https://zenodo.org/record/5113449.

See the :ref:`Merlin reference section <merlin reference>` for a description of
the acquisition parameters.
detectors/*
Loading