Statistics API#

The statistics API consists of the statistics data structure, which is provided periodically to registered callbacks. The data structure contains the following top-level keys:

  • time: The time information which includes:

    • range: The (start, stop) time range for this data structure.

    • delta: The total duration which is equal to (stop - start).

    • samples: The total number of samples combined into this data.

  • signals: The signal values over the previous statistics time window. The keys include current, voltage, and power. Each key contains a map with keys:

    • µ: The mean (average) value.

    • σ2: The variance value.

    • min: The minimum value.

    • max: The maximum value.

    • p2p: The peak-to-peak value = (max - min)

    • ∫: The integrated value, only for current and power.

  • accumulators: The integrated charge and energy values.

  • source: Where the statistics were computed. The v1 backend provides sensor (on the instrument) or host (by the host driver from the full-rate sample stream). The legacy v0 backend provides sensor or stream_buffer.

Statistics source#

The model and the scan config select where the statistics are computed by default. Device.statistics_source reports the default source for a device.

Model

scan config

Default source

JS110

‘auto’, ‘ignore’, None

host: computed by the host driver from the 2 Msps sample stream, which requires streaming.

JS110

‘off’

sensor: computed on the instrument at 2 Hz, without the standard deviation.

JS220

any

sensor: computed on the instrument.

JS320

any

sensor: computed on the instrument.

The source argument of statistics_callback_register selects the source for that callback: ‘sensor’, ‘host’, or the legacy v0 name ‘stream_buffer’ for ‘host’. The JS110 supports both sources, even at the same time. The JS220 and JS320 only compute statistics on the instrument, so they ignore ‘host’ and issue a DeprecationWarning once.

Statistics on your thread#

Statistics callbacks run on the USB thread, so they must return quickly and must not call back into the device. Most scripts instead want the statistics on their own thread. Use Device.statistics_get or Device.statistics_iter, which block until the next value arrives:

import joulescope

with joulescope.scan_require_one(config='auto') as device:
    device.parameter_set('reduction_frequency', '2 Hz')
    for stats in device.statistics_iter(count=20):  # 10 seconds
        i = stats['signals']['current']['µ']['value']
        print(f'{i:.9f} A')

The first call starts buffering, so consecutive calls return consecutive values without gaps. Both wait 2 seconds for each value by default and raise TimeoutError if none arrives. statistics_iter without a count continues until the device closes.

Example#

Here is an example statistics data structure:

{
  "time": {
    "range": {"value": [29.975386, 29.999424], "units": "s"},
    "delta": {"value": 0.024038, "units": "s"},
    "samples": {"value": 48076, "units": "samples"}
  },
  "signals": {
    "current": {
      "µ": {"value": 0.000299379503657111, "units": "A"},
      "σ2": {"value": 2.2021878912979553e-12, "units": "A"},
      "min": {"value": 0.00029360855114646256, "units": "A"},
      "max": {"value": 0.0003051375679206103, "units": "A"},
      "p2p": {"value": 1.1529016774147749e-05, "units": "A"},
      "∫": {"value": 0.008981212667119223, "units": "C"}
    },
    "voltage": {
      "µ": {"value": 2.99890387873055,"units": "V"},
      "σ2": {"value": 1.0830626821348923e-06, "units": "V"},
      "min": {"value": 2.993824005126953, "units": "V"},
      "max": {"value": 3.002903699874878, "units": "V"},
      "p2p": {"value": 0.009079694747924805, "units": "V"}
    },
    "power": {
      "µ": {"value": 0.000897810357252683, "units": "W"},
      "σ2": {"value": 1.9910494110256852e-11, "units": "W"},
      "min": {"value": 0.0008803452947176993, "units": "W"},
      "max": {"value": 0.0009152597631327808, "units": "W"},
      "p2p": {"value": 3.49144684150815e-05, "units": "W"},
      "∫": {"value": 0.026933793578814716, "units": "J"}
    },
    "current_range": {
      "µ": {"value": 4.0, "units": ""},
      "σ2": {"value": 0.0, "units": ""},
      "min": {"value": 4.0, "units": ""},
      "max": {"value": 4.0, "units": ""},
      "p2p": {"value": 0.0, "units": ""}
    },
    "current_lsb": {
      "µ": {"value": 0.5333222397870035, "units": ""},
      "σ2": {"value": 0.24889270730539995, "units": ""},
      "min": {"value": 0.0, "units": ""},
      "max": {"value": 1.0, "units": ""},
      "p2p": {"value": 1.0, "units": ""}
    },
    "voltage_lsb": {
      "µ": {"value": 0.5333430401863711, "units": ""},
      "σ2": {"value": 0.24889309698100895, "units": ""},
      "min": {"value": 0.0, "units": ""},
      "max": {"value": 1.0, "units": ""},
      "p2p": {"value": 1.0, "units": ""}
    }
  },
  "accumulators": {
    "charge": {"value": 0.0, "units": "C"},
    "energy": {"value": 0.0, "units": "J"}
  },
  "source": "sensor"
}