Skip to content

Instrument management

Use the InstrumentManager() to start experiments and control your PalmSens instrument.

The most high-level way to start a measurement is to use the measure() function:

>>> import pypalmsens as ps

>>> method = ps.CyclicVoltammetry()
>>> ps.measure(method)

You can also manage the connection yourself, using connect(), for example:

>>> with ps.connect() as manager:
...    method = ps.ChronoAmperometry()
...    measurement = manager.measure(method)

Or using InstrumentManager() directly as a context manager:

>>> instruments = discover()

>>> with ps.InstrumentManager(instruments[0]) as manager:
...    measurement = manager.measure(method)

Or managing the instrument connection yourself:

>>> instruments = discover()

>>> manager = ps.InstrumentManager(instruments[0])
>>> manager.connect()
>>> # ...
>>> manager.disconnect()

For more information, see the measurement documentation.

pypalmsens.connect

connect(instrument: None | Instrument = None) -> InstrumentManager

Connect to instrument and return InstrumentManager.

Connects to any plugged-in PalmSens USB device. Error if multiple devices are plugged-in.

Parameters:

  • instrument

    (Instrument, default: None ) –

    Connect to a specific instrument. Use pypalmsens.discover() to discover instruments.

Returns:

  • manager ( InstrumentManager ) –

    Return instance of InstrumentManager connected to the given instrument.

Source code in src/pypalmsens/_instruments/instrument_manager.py
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def connect(
    instrument: None | Instrument = None,
) -> InstrumentManager:
    """Connect to instrument and return InstrumentManager.

    Connects to any plugged-in PalmSens USB device.
    Error if multiple devices are plugged-in.

    Parameters
    ----------
    instrument : Instrument, optional
        Connect to a specific instrument.
        Use `pypalmsens.discover()` to discover instruments.

    Returns
    -------
    manager : InstrumentManager
        Return instance of `InstrumentManager` connected to the given instrument.
    """
    if not instrument:
        available_instruments = discover(ignore_errors=True)

        if not available_instruments:
            raise ConnectionError('No instruments were discovered.')

        if len(available_instruments) > 1:
            raise ConnectionError('More than one device discovered.')

        instrument = available_instruments[0]

    manager = InstrumentManager(instrument)
    manager.connect()
    return manager

pypalmsens.discover

discover(ftdi: bool = True, usbcdc: bool = True, winusb: bool = True, bluetooth: bool = False, serial: bool = True, ignore_errors: bool = False) -> list[Instrument]

Discover instruments.

For a list of device interfaces, see: https://sdk.palmsens.com/python/latest//installation.html#compatibility

Parameters:

  • ftdi

    (bool, default: True ) –

    If True, discover ftdi devices

  • usbcdc

    (bool, default: True ) –

    If True, discover usbcdc devices (Windows only)

  • winusb

    (bool, default: True ) –

    If True, discover winusb devices (Windows only)

  • bluetooth

    (bool, default: False ) –

    If True, discover bluetooth devices (Windows only)

  • serial

    (bool, default: True ) –

    If True, discover serial devices

  • ignore_errors

    (False, default: False ) –

    Ignores errors in device discovery

Returns:

  • discovered ( list[Instrument] ) –

    List of dataclasses with discovered instruments.

Source code in src/pypalmsens/_instruments/instrument_manager.py
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def discover(
    ftdi: bool = True,
    usbcdc: bool = True,
    winusb: bool = True,
    bluetooth: bool = False,
    serial: bool = True,
    ignore_errors: bool = False,
) -> list[Instrument]:
    """Discover instruments.

    For a list of device interfaces, see:
        https://sdk.palmsens.com/python/latest//installation.html#compatibility

    Parameters
    ----------
    ftdi : bool
        If True, discover ftdi devices
    usbcdc : bool
        If True, discover usbcdc devices (Windows only)
    winusb : bool
        If True, discover winusb devices (Windows only)
    bluetooth : bool
        If True, discover bluetooth devices (Windows only)
    serial : bool
        If True, discover serial devices
    ignore_errors : False
        Ignores errors in device discovery

    Returns
    -------
    discovered : list[Instrument]
        List of dataclasses with discovered instruments.
    """
    return asyncio.run(
        discover_async(
            ftdi=ftdi,
            usbcdc=usbcdc,
            winusb=winusb,
            bluetooth=bluetooth,
            serial=serial,
            ignore_errors=ignore_errors,
        )
    )

pypalmsens.measure

measure(method: BaseTechnique, instrument: None | Instrument = None, callback: Callback | None = None) -> Measurement

Run measurement.

Executes the given method on any plugged-in PalmSens USB device. Error if multiple devices are plugged-in.

Parameters:

  • instrument

    (Instrument, default: None ) –

    Connect to and meassure on a specific instrument. Use pypalmsens.discover() to discover instruments.

  • callback

    (Callback | None, default: None ) –

    If specified, call this function on every new set of data points. New data points are batched, and contain all points since the last time it was called. Each point is a dictionary containing frequency, z_re, z_im for impedimetric techniques and index, x, x_unit, x_type, y, y_unit and y_type for non-impedimetric techniques.

Returns:

  • measurement ( Measurement ) –

    Finished measurement.

Source code in src/pypalmsens/_instruments/instrument_manager.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
def measure(
    method: BaseTechnique,
    instrument: None | Instrument = None,
    callback: Callback | None = None,
) -> Measurement:
    """Run measurement.

    Executes the given method on any plugged-in PalmSens USB device.
    Error if multiple devices are plugged-in.

    Parameters
    ----------
    instrument : Instrument, optional
        Connect to and meassure on a specific instrument.
        Use `pypalmsens.discover()` to discover instruments.
    callback: Callback, optional
        If specified, call this function on every new set of data points.
        New data points are batched, and contain all points since the last
        time it was called. Each point is a dictionary containing
        `frequency`, `z_re`, `z_im` for impedimetric techniques and
        `index`, `x`, `x_unit`, `x_type`, `y`, `y_unit` and `y_type` for
        non-impedimetric techniques.

    Returns
    -------
    measurement : Measurement
        Finished measurement.
    """
    with connect(instrument=instrument) as manager:
        measurement = manager.measure(method, callback=callback)

    assert measurement

    return measurement

pypalmsens.InstrumentManager

InstrumentManager(instrument: Instrument)

              flowchart TD
              pypalmsens.InstrumentManager[InstrumentManager]
              pypalmsens._instruments.instrument_manager_async.SupportedMixin[SupportedMixin]

                              pypalmsens._instruments.instrument_manager_async.SupportedMixin --> pypalmsens.InstrumentManager
                


              click pypalmsens.InstrumentManager href "" "pypalmsens.InstrumentManager"
              click pypalmsens._instruments.instrument_manager_async.SupportedMixin href "" "pypalmsens._instruments.instrument_manager_async.SupportedMixin"
            

Instrument manager for PalmSens instruments.

Parameters:

  • instrument

    (Instrument) –

    Instrument to connect to, use discover() to find connected instruments.

Methods:

Attributes:

  • instrument (Instrument) –

    Instrument to connect to.

Source code in src/pypalmsens/_instruments/instrument_manager.py
156
157
158
159
160
def __init__(self, instrument: Instrument):
    self.instrument: Instrument = instrument
    """Instrument to connect to."""

    self._comm: CommManager

instrument instance-attribute

instrument: Instrument = instrument

Instrument to connect to.

abort

abort() -> None

Abort measurement.

Source code in src/pypalmsens/_instruments/instrument_manager.py
379
380
381
382
def abort(self) -> None:
    """Abort measurement."""
    with self._lock():
        self._comm.Abort()

connect

connect() -> None

Connect to instrument.

Source code in src/pypalmsens/_instruments/instrument_manager.py
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
def connect(self) -> None:
    """Connect to instrument."""
    if self.is_connected():
        return

    async def _connect(psinstrument: PalmSens.Devices.Device) -> CommManager:
        try:
            await create_future(psinstrument.OpenAsync())
        except System.UnauthorizedAccessException as err:
            raise ConnectionError(
                f'Cannot open instrument connection (reason: {err.Message}). Check if the device is already in use.'
            ) from err

        return await create_future(CommManager.CommManagerAsync(psinstrument))

    # The comm manager needs to open async, because the measurement is handled async.
    # Opening the comm manager in async sets some handlers in ClientConnection
    # that are sync or async specific. This affects the measurement,
    # receive status, and device state change events.
    self._comm = asyncio.run(_connect(self.instrument.device))

    firmware_warning(self._comm.Capabilities)

disconnect

disconnect()

Disconnect from the instrument.

Source code in src/pypalmsens/_instruments/instrument_manager.py
474
475
476
477
478
479
480
481
def disconnect(self):
    """Disconnect from the instrument."""
    if not self.is_connected():
        return

    self._comm.Disconnect()

    del self._comm

ensure_connection

ensure_connection()

Raises connection error if the instrument is not connected.

Source code in src/pypalmsens/_instruments/instrument_manager.py
205
206
207
208
def ensure_connection(self):
    """Raises connection error if the instrument is not connected."""
    if not self.is_connected():
        raise ConnectionError('Not connected to an instrument')

get_instrument_serial

get_instrument_serial() -> str

Return instrument serial number.

Returns:

  • serial ( str ) –

    Instrument serial.

Source code in src/pypalmsens/_instruments/instrument_manager.py
301
302
303
304
305
306
307
308
309
310
311
312
def get_instrument_serial(self) -> str:
    """Return instrument serial number.

    Returns
    -------
    serial : str
        Instrument serial.
    """
    with self._lock():
        serial = self._comm.DeviceSerial.ToString()

    return serial

initialize_multiplexer

initialize_multiplexer(mux_model: int) -> int

Initialize the multiplexer.

Parameters:

  • mux_model

    (int) –

    The model of the multiplexer. - 0 = 8 channel - 1 = 16 channel - 2 = 32 channel

Returns:

  • channels ( int ) –

    Number of available multiplexes channels

Source code in src/pypalmsens/_instruments/instrument_manager.py
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
def initialize_multiplexer(self, mux_model: int) -> int:
    """Initialize the multiplexer.

    Parameters
    ----------
    mux_model: int
        The model of the multiplexer.
        - 0 = 8 channel
        - 1 = 16 channel
        - 2 = 32 channel

    Returns
    -------
    channels : int
        Number of available multiplexes channels
    """
    with self._lock():
        model = MuxModel(mux_model)

        if model == MuxModel.MUX8R2 and (
            self._comm.ClientConnection.GetType().Equals(
                clr.GetClrType(PalmSens.Comm.ClientConnectionPS4)
            )
            or self._comm.ClientConnection.GetType().Equals(
                clr.GetClrType(PalmSens.Comm.ClientConnectionMS)
            )
        ):
            self._comm.ClientConnection.ReadMuxInfo()

        self._comm.Capabilities.MuxModel = model

        if self._comm.Capabilities.MuxModel == MuxModel.MUX8:
            self._comm.Capabilities.NumMuxChannels = 8
        elif self._comm.Capabilities.MuxModel == MuxModel.MUX16:
            self._comm.Capabilities.NumMuxChannels = 16
        elif self._comm.Capabilities.MuxModel == MuxModel.MUX8R2:
            self._comm.ClientConnection.ReadMuxInfo()

    channels = self._comm.Capabilities.NumMuxChannels
    return channels

is_connected

is_connected() -> bool

Return True if an instrument connection exists.

Source code in src/pypalmsens/_instruments/instrument_manager.py
196
197
198
199
200
201
202
203
def is_connected(self) -> bool:
    """Return True if an instrument connection exists."""
    try:
        self._comm
    except AttributeError:
        return False
    else:
        return True

is_measuring

is_measuring() -> bool

Return True if device is measuring.

Source code in src/pypalmsens/_instruments/instrument_manager.py
176
177
178
def is_measuring(self) -> bool:
    """Return True if device is measuring."""
    return int(self._comm.State) == CommManager.DeviceState.Measurement

measure

measure(method: BaseTechnique, *, callback: Callback | None = None) -> Measurement

Start measurement using given method parameters.

Parameters:

  • method

    (BaseTechnique) –

    Method parameters for measurement

  • callback

    (Callback | None, default: None ) –

    If specified, call this function on every new set of data points. New data points are batched, and contain all points since the last time it was called. Each point is an instance of ps.data.CallbackData for non-impedimetric or ps.data.CallbackDataEIS for impedimetric measurments.

Returns:

  • measurement ( Measurement ) –

    Finished measurement.

Source code in src/pypalmsens/_instruments/instrument_manager.py
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
def measure(
    self,
    method: BaseTechnique,
    *,
    callback: Callback | None = None,
) -> Measurement:
    """Start measurement using given method parameters.

    Parameters
    ----------
    method: Method parameters
        Method parameters for measurement
    callback: Callback, optional
        If specified, call this function on every new set of data points.
        New data points are batched, and contain all points since the last
        time it was called. Each point is an instance of `ps.data.CallbackData`
        for non-impedimetric or  `ps.data.CallbackDataEIS`
        for impedimetric measurments.

    Returns
    -------
    measurement : Measurement
        Finished measurement.
    """
    psmethod = method._to_psmethod()

    self.ensure_connection()

    self.validate_method(psmethod)

    # note that the comm manager must be opened async so it sets the
    # correct async event handlers
    measurement_manager = MeasurementManagerAsync(comm=self._comm)

    return asyncio.run(measurement_manager.measure(psmethod, callback=callback))

read_current

read_current() -> float

Read the current in µA.

Returns:

  • current ( float ) –

    Current in µA.

Source code in src/pypalmsens/_instruments/instrument_manager.py
274
275
276
277
278
279
280
281
282
283
284
285
def read_current(self) -> float:
    """Read the current in µA.

    Returns
    -------
    current : float
        Current in µA.
    """
    with self._lock():
        current = self._comm.Current

    return current

read_potential

read_potential() -> float

Read the potential in V.

Returns:

  • potential ( float ) –

    Potential in V.

Source code in src/pypalmsens/_instruments/instrument_manager.py
287
288
289
290
291
292
293
294
295
296
297
298
299
def read_potential(self) -> float:
    """Read the potential in V.

    Returns
    -------
    potential : float
        Potential in V.
    """

    with self._lock():
        potential = self._comm.Potential

    return potential

set_cell

set_cell(cell_on: bool)

Turn the cell on or off.

Parameters:

  • cell_on

    (bool) –

    If true, turn on the cell

Source code in src/pypalmsens/_instruments/instrument_manager.py
240
241
242
243
244
245
246
247
248
249
def set_cell(self, cell_on: bool):
    """Turn the cell on or off.

    Parameters
    ----------
    cell_on : bool
        If true, turn on the cell
    """
    with self._lock():
        self._comm.CellOn = cell_on

set_current_range

set_current_range(current_range: AllowedCurrentRanges)

Set the current range for the cell.

Parameters:

  • current_range

    (AllowedCurrentRanges) –

    Set the current range as a string. See pypalmsens.settings.AllowedCurrentRanges for options.

Source code in src/pypalmsens/_instruments/instrument_manager.py
262
263
264
265
266
267
268
269
270
271
272
def set_current_range(self, current_range: AllowedCurrentRanges):
    """Set the current range for the cell.

    Parameters
    ----------
    current_range: AllowedCurrentRanges
        Set the current range as a string.
        See `pypalmsens.settings.AllowedCurrentRanges` for options.
    """
    with self._lock():
        self._comm.CurrentRange = cr_string_to_enum(current_range)

set_multiplexer_channel

set_multiplexer_channel(channel: int)

Sets the multiplexer channel.

Parameters:

  • channel

    (int) –

    Index of the channel to set.

Source code in src/pypalmsens/_instruments/instrument_manager.py
463
464
465
466
467
468
469
470
471
472
def set_multiplexer_channel(self, channel: int):
    """Sets the multiplexer channel.

    Parameters
    ----------
    channel : int
        Index of the channel to set.
    """
    with self._lock():
        self._comm.ClientConnection.SetMuxChannel(channel)

set_mux8r2_settings

Set the settings for the Mux8R2 multiplexer.

Parameters:

  • connect_sense_to_working_electrode

    (bool, default: False ) –

    Connect the sense electrode to the working electrode. Default is False.

  • combine_reference_and_counter_electrodes

    (bool, default: False ) –

    Combine the reference and counter electrodes. Default is False.

  • use_channel_1_reference_and_counter_electrodes

    (bool, default: False ) –

    Use channel 1 reference and counter electrodes for all working electrodes. Default is False.

  • set_unselected_channel_working_electrode

    (int, default: 0 ) –

    Set the unselected channel working electrode to disconnected/floating (0), ground (1), or standby potential (2). Default is 0.

Source code in src/pypalmsens/_instruments/instrument_manager.py
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
def set_mux8r2_settings(
    self,
    connect_sense_to_working_electrode: bool = False,
    combine_reference_and_counter_electrodes: bool = False,
    use_channel_1_reference_and_counter_electrodes: bool = False,
    set_unselected_channel_working_electrode: int = 0,
):
    """Set the settings for the Mux8R2 multiplexer.

    Parameters
    ---------
    connect_sense_to_working_electrode: float
        Connect the sense electrode to the working electrode. Default is False.
    combine_reference_and_counter_electrodes: float
        Combine the reference and counter electrodes. Default is False.
    use_channel_1_reference_and_counter_electrodes: float
        Use channel 1 reference and counter electrodes for all working electrodes. Default is False.
    set_unselected_channel_working_electrode: float
        Set the unselected channel working electrode to disconnected/floating (0), ground (1), or standby potential (2). Default is 0.
    """
    self.ensure_connection()

    if self._comm.Capabilities.MuxModel != MuxModel.MUX8R2:
        raise ValueError(
            f"Incompatible mux model: {self._comm.Capabilities.MuxModel}, expected 'MUXR2'."
        )

    mux_settings = PSMethod.MuxSettings(False)
    mux_settings.ConnSEWE = connect_sense_to_working_electrode
    mux_settings.ConnectCERE = combine_reference_and_counter_electrodes
    mux_settings.CommonCERE = use_channel_1_reference_and_counter_electrodes
    mux_settings.UnselWE = PSMethod.MuxSettings.UnselWESetting(
        set_unselected_channel_working_electrode
    )

    with self._lock():
        self._comm.ClientConnection.SetMuxSettings(MuxType(1), mux_settings)

set_potential

set_potential(potential: float)

Set the potential of the cell.

Parameters:

  • potential

    (float) –

    Potential in V

Source code in src/pypalmsens/_instruments/instrument_manager.py
251
252
253
254
255
256
257
258
259
260
def set_potential(self, potential: float):
    """Set the potential of the cell.

    Parameters
    ----------
    potential : float
        Potential in V
    """
    with self._lock():
        self._comm.Potential = potential

status

status() -> Status

Get status.

Source code in src/pypalmsens/_instruments/instrument_manager.py
233
234
235
236
237
238
def status(self) -> Status:
    """Get status."""
    return Status(
        self._comm.get_Status(),
        device_state=str(self._comm.get_State()),  # type:ignore
    )

supported_applied_current_ranges

supported_applied_current_ranges() -> list[AllowedCurrentRanges]

List applied current ranges supported by this device.

Returns:

Source code in src/pypalmsens/_instruments/instrument_manager_async.py
251
252
253
254
255
256
257
258
259
260
261
def supported_applied_current_ranges(self: HasCommProtocol) -> list[AllowedCurrentRanges]:
    """List applied current ranges supported by this device.

    Returns
    -------
    current_ranges: list[AllowedCurrentRanges]
    """
    self.ensure_connection()
    capabilities = self._comm.Capabilities

    return [cr_enum_to_string(cr) for cr in capabilities.SupportedAppliedRanges]

supported_bipot_ranges

supported_bipot_ranges() -> list[AllowedCurrentRanges]

List applied current ranges supported by this device.

Returns:

Source code in src/pypalmsens/_instruments/instrument_manager_async.py
263
264
265
266
267
268
269
270
271
272
273
def supported_bipot_ranges(self: HasCommProtocol) -> list[AllowedCurrentRanges]:
    """List applied current ranges supported by this device.

    Returns
    -------
    current_ranges: list[AllowedCurrentRanges]
    """
    self.ensure_connection()
    capabilities = self._comm.Capabilities

    return [cr_enum_to_string(cr) for cr in capabilities.SupportedBipotRanges]

supported_current_ranges

supported_current_ranges() -> list[AllowedCurrentRanges]

List current ranges supported by this device.

Returns:

Source code in src/pypalmsens/_instruments/instrument_manager_async.py
239
240
241
242
243
244
245
246
247
248
249
def supported_current_ranges(self: HasCommProtocol) -> list[AllowedCurrentRanges]:
    """List current ranges supported by this device.

    Returns
    -------
    current_ranges: list[AllowedCurrentRanges]
    """
    self.ensure_connection()
    capabilities = self._comm.Capabilities

    return [cr_enum_to_string(cr) for cr in capabilities.SupportedRanges]

supported_methods

supported_methods() -> list[str]

List methods supported by this device.

Returns:

Source code in src/pypalmsens/_instruments/instrument_manager_async.py
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
def supported_methods(self: HasCommProtocol) -> list[str]:
    """List methods supported by this device.

    Returns
    -------
    methods: list[str]
    """
    self.ensure_connection()
    capabilities = self._comm.Capabilities
    numbers = list(capabilities.SupportedMethods)
    method_ids = []

    for number in numbers:
        try:
            id = PalmSens.Method.FromTechniqueNumber(number).MethodID
        except Exception:
            pass
        else:
            method_ids.append(id)

    return method_ids

supported_potential_ranges

supported_potential_ranges() -> list[AllowedPotentialRanges]

List applied potential ranges supported by this device.

Returns:

Source code in src/pypalmsens/_instruments/instrument_manager_async.py
275
276
277
278
279
280
281
282
283
284
285
def supported_potential_ranges(self: HasCommProtocol) -> list[AllowedPotentialRanges]:
    """List applied potential ranges supported by this device.

    Returns
    -------
    potential_ranges: list[AllowedPotentialRanges]
    """
    self.ensure_connection()
    capabilities = self._comm.Capabilities

    return [pr_enum_to_string(pr) for pr in capabilities.SupportedPotentialRanges]

validate_method

validate_method(method: Method | BaseTechnique) -> None

Validate method.

Raise ValueError if the method cannot be validated.

Source code in src/pypalmsens/_instruments/instrument_manager.py
314
315
316
317
318
319
320
321
322
323
324
325
326
327
def validate_method(self, method: PSMethod | BaseTechnique) -> None:
    """Validate method.

    Raise ValueError if the method cannot be validated."""
    self.ensure_connection()

    if not isinstance(method, PSMethod):
        method = method._to_psmethod()

    errors = method.Validate(self._comm.Capabilities)

    if any(error.IsFatal for error in errors):
        message = '\n'.join([error.Message for error in errors])
        raise ValueError(f'Method not compatible:\n{message}')

wait_digital_trigger

wait_digital_trigger(wait_for_high: bool)

Wait for digital trigger.

Parameters:

  • wait_for_high

    (bool) –

    Wait for digital line high before starting

Source code in src/pypalmsens/_instruments/instrument_manager.py
365
366
367
368
369
370
371
372
373
374
375
376
377
def wait_digital_trigger(self, wait_for_high: bool):
    """Wait for digital trigger.

    Parameters
    ----------
    wait_for_high: bool
        Wait for digital line high before starting
    """
    with self._lock():
        while True:
            if self._comm.DigitalLineD0 == wait_for_high:
                break
            sleep(0.05)

pypalmsens.InstrumentPool

InstrumentPool(devices_or_managers: Sequence[Instrument | InstrumentManagerAsync])

Manages a set of instrument.

Most calls are run asynchronously in the background, which means that measurements are running in parallel.

This is a thin wrapper around the InstrumentManagerAsync.

Parameters:

Methods:

  • add

    Open and add manager to the pool.

  • connect

    Connect all instrument managers in the pool.

  • disconnect

    Disconnect all instrument managers in the pool.

  • is_connected

    Return true if all managers in the pool are connected.

  • is_disconnected

    Return true if all managers in the pool are disconnected.

  • measure

    Concurrently run measurement on all managers in the pool.

  • remove

    Close and remove manager from pool.

Attributes:

Source code in src/pypalmsens/_instruments/instrument_pool.py
30
31
32
33
34
35
36
37
38
def __init__(
    self,
    devices_or_managers: Sequence[Instrument | InstrumentManagerAsync],
):
    self._async: InstrumentPoolAsync = InstrumentPoolAsync(devices_or_managers)
    self._loop = asyncio.new_event_loop()

    self.managers: list[InstrumentManagerAsync] = self._async.managers
    """List of instruments managers in the pool."""

managers instance-attribute

managers: list[InstrumentManagerAsync] = managers

List of instruments managers in the pool.

add

Open and add manager to the pool.

Parameters:

Source code in src/pypalmsens/_instruments/instrument_pool.py
76
77
78
79
80
81
82
83
84
def add(self, manager: InstrumentManagerAsync) -> None:
    """Open and add manager to the pool.

    Parameters
    ----------
    manager : InstrumentManagerAsync
        Instance of an instrument manager.
    """
    self._loop.run_until_complete(self._async.add(manager))

connect

connect() -> None

Connect all instrument managers in the pool.

Source code in src/pypalmsens/_instruments/instrument_pool.py
50
51
52
def connect(self) -> None:
    """Connect all instrument managers in the pool."""
    self._loop.run_until_complete(self._async.connect())

disconnect

disconnect() -> None

Disconnect all instrument managers in the pool.

Source code in src/pypalmsens/_instruments/instrument_pool.py
54
55
56
def disconnect(self) -> None:
    """Disconnect all instrument managers in the pool."""
    self._loop.run_until_complete(self._async.disconnect())

is_connected

is_connected() -> bool

Return true if all managers in the pool are connected.

Source code in src/pypalmsens/_instruments/instrument_pool.py
58
59
60
def is_connected(self) -> bool:
    """Return true if all managers in the pool are connected."""
    return self._async.is_connected()

is_disconnected

is_disconnected() -> bool

Return true if all managers in the pool are disconnected.

Source code in src/pypalmsens/_instruments/instrument_pool.py
62
63
64
def is_disconnected(self) -> bool:
    """Return true if all managers in the pool are disconnected."""
    return self._async.is_disconnected()

measure

measure(method: BaseTechnique, **kwargs) -> list[Measurement]

Concurrently run measurement on all managers in the pool.

For hardware synchronization, set use_hardware_sync on the method. In addition, the pool must contain: - channels from a single multi-channel instrument only - the first channel of the multi-channel instrument - at least two channels

All instruments are prepared and put in a waiting state. The measurements are started via a hardware sync trigger on channel 1.

Parameters:

  • method

    (MethodSettings) –

    Method parameters for measurement.

  • **kwargs

    These keyword arguments are passed to the measure method.

Source code in src/pypalmsens/_instruments/instrument_pool.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def measure(self, method: BaseTechnique, **kwargs) -> list[Measurement]:
    """Concurrently run measurement on all managers in the pool.

    For hardware synchronization, set `use_hardware_sync` on the method.
    In addition, the pool must contain:
    - channels from a single multi-channel instrument only
    - the first channel of the multi-channel instrument
    - at least two channels

    All instruments are prepared and put in a waiting state.
    The measurements are started via a hardware sync trigger on channel 1.

    Parameters
    ----------
    method : MethodSettings
        Method parameters for measurement.
    **kwargs
        These keyword arguments are passed to the measure method.
    """
    return self._loop.run_until_complete(self._async.measure(method=method, **kwargs))

remove

Close and remove manager from pool.

Parameters:

Source code in src/pypalmsens/_instruments/instrument_pool.py
66
67
68
69
70
71
72
73
74
def remove(self, manager: InstrumentManagerAsync) -> None:
    """Close and remove manager from pool.

    Parameters
    ----------
    manager : InstrumentManagerAsync
        Instance of an instrument manager.
    """
    self._loop.run_until_complete(self._async.remove(manager))