Quantum detectors Merlin Medipix reference

class libertem_live.detectors.merlin.MerlinAcquisition(conn: MerlinDetectorConnection, nav_shape: tuple[int, ...] | None = None, frames_per_partition: int | None = None, pending_aq: MerlinPendingAcquisition | None = None, controller: MerlinActiveController | None = None, hooks: Hooks | None = None)[source]

Acquisition from a Quantum Detectors Merlin camera.

Use libertem_live.api.LiveContext.make_acquisition() to create an instance!

Parameters:
  • conn – An existing MerlinDetectorConnection instance

  • nav_shape – The navigation shape as a tuple, for example (height, width) for a 2D STEM scan.

  • frames_per_partition – Number of frames to process before performing a merge operation. Decreasing this number increases the update rate, but can decrease performance.

  • pending_aq – A pending acquisition in passive mode, obtained from MerlinDetectorConnection.wait_for_acquisition(). If this is not provided, it’s assumed that the detector should be actively armed and triggered.

  • controller – A MerlinActiveController instance, which can be obtained from MerlinDetectorConnection.get_active_controller(). You can pass additional parameters to MerlinDetectorConnection.get_active_controller() in order to change detector settings. If no controller is passed in, and pending_aq is also not given, then the acquisition will be started in active mode, leaving all detector settings unchanged.

  • hooks – Acquisition hooks to react to certain events

property array_backends: Sequence[Literal['numpy', 'numpy.matrix', 'cuda', 'cupy', 'sparse.COO', 'sparse.GCXS', 'sparse.DOK', 'scipy.sparse.coo_matrix', 'scipy.sparse.csr_matrix', 'scipy.sparse.csc_matrix', 'scipy.sparse.coo_array', 'scipy.sparse.csr_array', 'scipy.sparse.csc_array', 'cupyx.scipy.sparse.coo_matrix', 'cupyx.scipy.sparse.csr_matrix', 'cupyx.scipy.sparse.csc_matrix']]

The array backends the dataset can return data as.

Defaults to only NumPy arrays

New in version 0.11.0.

property dtype

The “native” data type (either one matching the data on disk, or one that is closest)

property shape

The shape of the DataSet, as it makes sense for the application domain (for example, 4D for pixelated STEM)

class libertem_live.detectors.merlin.MerlinConnectionBuilder[source]

Builder class that can construct MerlinDetectorConnection instances.

Use the open() method to create a connection.

open(*, api_host: str = '127.0.0.1', api_port: int = 6341, data_host: str = '127.0.0.1', data_port: int = 6342, drain: bool = False, recovery_strategy: Literal['immediate_reconnect'] | Literal['drain_then_reconnect'] = 'immediate_reconnect', huge_pages: bool = False) MerlinDetectorConnection[source]

Connect to a Merlin Medipix detector system.

Parameters:
  • api_host – Hostname of the Merlin control server, default ‘127.0.0.1’ Should in most cases be the same as data_host.

  • api_port – Port of the Merlin control server, default 6341

  • data_host – Hostname of the Merlin data server, default ‘127.0.0.1’

  • data_port – Data port of the Merlin data server, default 6342

  • drain – Drain the socket before triggering. Enable this when using old versions of the Merlin software, but not when using an internal trigger.

  • recovery_strategy – What to do in case of errors - try to drain the socket or immediately reconnect.

  • huge_pages

    Set to True to allocate shared memory in huge pages. This can improve performance by reducing the page fault cost. Currently only available on Linux. Enabling this requires reserving huge pages, either at system start, or before connecting.

    For example, to reserve 10000 huge pages, you can run:

    echo 10000 | sudo tee /proc/sys/vm/nr_hugepages

    See also the hugeadm utility, especially hugeadm --explain can be useful to check your configuration.

Examples

Usually, this method is directly used together with libertem_live.api.LiveContext.make_connection():

>>> with ctx.make_connection('merlin').open(
...     api_host='127.0.0.1',
...     api_port=MERLIN_API_PORT,
...     data_host='127.0.0.1',
...     data_port=MERLIN_DATA_PORT,
... ) as conn:
...     aq = ctx.make_acquisition(conn=conn, nav_shape=(32, 32))
...     ctx.run_udf(dataset=aq, udf=SumUDF())
{'intensity': ...}
class libertem_live.detectors.merlin.MerlinControl(host='127.0.0.1', port=6341, timeout=1.0)[source]

This class can be used to control a merlin medipix detector.

Parameters:
  • host (str) – The hostname to connect to

  • port (int) – The port to connect to

  • timeout (float) – The timeout, in seconds, after which a response is expected

close()[source]

Close the socket connection. Usually, instead of calling this function, you should use this class as a context manager.

cmd(cmd)[source]

Send a CMD command, and return the response

connect()[source]

Connect to the merlin control socket. Usually, you would instead use this class as a context manager.

get(param) bytes[source]

Send a GET command, and return the response

send_command_file(filename)[source]

Send the contents of filename, which should contain complete merlin command lines.

set(param, value)[source]

Send a SET command, and return the response

class libertem_live.detectors.merlin.MerlinDetectorConnection(*, api_host: str = '127.0.0.1', api_port: int = 6341, data_host: str = '127.0.0.1', data_port: int = 6342, drain: bool = False, recovery_strategy: Literal['immediate_reconnect'] | Literal['drain_then_reconnect'] = 'immediate_reconnect', huge_pages: bool = False)[source]

This class holds a permanent data connection to the merlin software.

Control connections are also possible to obtain from this class, but are created on demand and not kept open.

You can use the convenience function libertem_live.api.LiveContext.make_connection() to create an instance, instead of calling this constructor directly.

Parameters:
  • api_host – Hostname of the Merlin control server, default ‘127.0.0.1’ Should in most cases be the same as data_host.

  • api_port – Port of the Merlin control server, default 6341

  • data_host – Hostname of the Merlin data server, default ‘127.0.0.1’

  • data_port – Data port of the Merlin data server, default 6342

  • drain – Drain the socket before triggering. Enable this when using old versions of the Merlin software, but not when using an internal trigger.

  • recovery_strategy – What to do in case of errors - try to drain the socket or immediately reconnect. If an error on the LiberTEM-live side makes the Merlin software hang, try to switch to "drain_then_reconnect".

  • huge_pages

    Set to True to allocate shared memory in huge pages. This can improve performance by reducing the page fault cost. Currently only available on Linux. Enabling this requires reserving huge pages, either at system start, or before connecting.

    For example, to reserve 10000 huge pages, you can run:

    echo 10000 | sudo tee /proc/sys/vm/nr_hugepages

    See also the hugeadm utility, especially hugeadm --explain can be useful to check your configuration.

Examples

Usually, this class is instantiated using libertem_live.api.LiveContext.make_connection():

>>> with ctx.make_connection('merlin').open(
...     api_host='127.0.0.1',
...     api_port=MERLIN_API_PORT,
...     data_host='127.0.0.1',
...     data_port=MERLIN_DATA_PORT,
... ) as conn:
...     aq = ctx.make_acquisition(conn=conn, nav_shape=(32, 32))
...     ctx.run_udf(dataset=aq, udf=SumUDF())
{'intensity': ...}
close()[source]

Close the connection. It’s important to call this function once you don’t need the connection anymore, as an open connection might interfere with other software using the detector.

If possible, use this object as a context manager instead, using a with-statement.

wait_for_acquisition(timeout: float | None = None) PendingAcquisition | None[source]

Wait for at most timeout seconds for an acquisition to start. This does not perform any triggering itself and expects something external to arm and trigger the acquisition.

Once the detector is armed, this function returns a PendingAcquisition, which can be converted to a full Acquisition object using libertem_live.api.LiveContext.make_acquisition().

The function returns None on timeout.

Parameters:

timeout – Timeout in seconds. If None, wait indefinitely.

Examples

>>> with ctx.make_connection('merlin').open(
...     api_host='127.0.0.1',
...     api_port=MERLIN_API_PORT,
...     data_host='127.0.0.1',
...     data_port=MERLIN_DATA_PORT,
... ) as conn:
...     pending_aq = conn.wait_for_acquisition(timeout=1)
...     # at this point, something else is arming and triggering the
...     # detector:
...     aq = ctx.make_acquisition(
...         conn=conn,
...         nav_shape=(32, 32),
...         pending_aq=pending_aq,
...     )
...     ctx.run_udf(dataset=aq, udf=SumUDF())
{'intensity': ...}