API reference - A121#

This page provides an auto-generated summary of Acconeer Exploration Tool’s A121 API.

Configurations#

Session#

class acconeer.exptool.a121.SessionConfig(arg: Optional[Union[SensorConfig, dict[int, SensorConfig], list[dict[int, SensorConfig]]]] = None, *, extended: Optional[bool] = None, update_rate: Optional[float] = None)#

Session configuration

The session configuration defines the highest level of configuration available in Exploration Tool. It mainly consists of one or several sensor configurations (SensorConfig) for the server to run. It also sets the update rate for the server, and the data format (“extended”) returned from the client.

Mapping from sensor ID to sensor config is done here in the session config. For example, if you want to want to use sensor 2, you can do:

SessionConfig({2: SensorConfig(start_point=123)})

The default sensor ID is 1. Going further, you may run multiple sensors at the same time (in parallel) like this:

SessionConfig(
    {
        2: SensorConfig(start_point=123),
        3: SensorConfig(start_point=456),
    }
)

The dictionary shown above forms a group of sensor configs. Further extending upon this, you may specify multiple groups which are run in sequence, like this:

SessionConfig(
    [
        {
            2: SensorConfig(start_point=123),
            3: SensorConfig(start_point=456),
        },
        {
            2: SensorConfig(start_point=789),
        },
    ]
)

You may reuse the same sensor across groups. If a sensor is used multiple times, a reconfiguration will be done prior to each measurement.

A session config with multiple sensor configs (in a single group or multiple) is considered “extended”. This is reflected in the shape of some return types. A SessionConfig with a single SensorConfig is not extended, but the return values can be passed as extended with the keyword argument extended=True.

Parameters
  • arg – The sensor configuration(s).

  • extended – Forces whether to use the extended format or not. If not given (= None), the extended format will be used automatically if multiple sensor configs are given.

  • update_rate – The update rate limit on the server. Defaults to None, not limiting the rate.

Raises

ValueError – If the session config must be extended but extended=False.

property extended: bool#

Whether or not the extended format is used

property groups: list[dict[int, SensorConfig]]#

The sensor config groups of this session

property update_rate: Optional[float]#

The update rate limit in Hz

Must be > 0 or None, where None means unlimited.

validate() None#

Performs self-validation and validation of its sensor configs

Raises

ValidationError – If anything is invalid.

property sensor_id: int#

Retrieves the sole sensor ID

Raises

RuntimeError – If this session config is extended

property sensor_config: SensorConfig#

Retrieves the sole sensor config

Raises

RuntimeError – If this session config is extended

Sensor#

class acconeer.exptool.a121.SensorConfig(*, subsweeps: Optional[list[SubsweepConfig]] = None, num_subsweeps: Optional[int] = None, sweeps_per_frame: int = 1, sweep_rate: Optional[float] = None, frame_rate: Optional[float] = None, continuous_sweep_mode: bool = False, double_buffering: bool = False, inter_frame_idle_state: IdleState = IdleState.DEEP_SLEEP, inter_sweep_idle_state: IdleState = IdleState.READY, start_point: Optional[int] = None, num_points: Optional[int] = None, step_length: Optional[int] = None, profile: Optional[Profile] = None, hwaas: Optional[int] = None, receiver_gain: Optional[int] = None, enable_tx: Optional[bool] = None, enable_loopback: Optional[bool] = None, phase_enhancement: Optional[bool] = None, prf: Optional[PRF] = None)#

Sensor configuration

The sensor config represents a 1-1 mapping to the RSS service config.

By default, the sensor config holds a single SubsweepConfig. The parameters defined by the subsweep config, like start_point, can be accessed via the sensor config. If multiple subsweeps are used, those parameters must be accessed via their respective subsweep configs.

For example, a sensor config can be created like this:

SensorConfig(sweeps_per_frame=16, start_point=123)

Note that the start_point is implicitly set in the underlying subsweep config. If you want to explicitly set the subsweep config(s), you can do

SensorConfig(
    sweeps_per_frame=16,
    subsweeps=[
        SubsweepConfig(start_point=123),
    ],
)

Parameters can also be accessed via the class attributes:

sensor_config = SensorConfig()
sensor_config.sweeps_per_frame = 16
sensor_config.start_point = 123

If you want to use multiple subsweeps with this style of setting/getting the attributes, you can do like this:

sensor_config = SensorConfig(num_subsweeps=3)
sensor_config.sweeps_per_frame = 16
sensor_config.subsweeps[0].start_point = 123

Note

The sensor config does not control on which sensor it should be run. That is handled by the SessionConfig.

Parameters
  • subsweeps – The list of subsweeps to initialize with. May not be combined with num_subsweeps.

  • num_subsweeps – Initialize with a given number of subsweeps. May not be combined with subsweeps.

Raises
  • ValueError – If subsweeps and num_subsweeps are both given.

  • ValueError – If the given list of subsweeps is empty.

  • ValueError – If subsweeps parameters are both given implicitly and via subsweeps.

hwaas#

Hardware accelerated average samples (HWAAS)

Each data point can be sampled several times and the sensor hardware then produces an average value of those samples. The time needed to measure a sweep is roughly proportional to the number of averaged samples. Hence, if there is a need to obtain a higher update rate, HWAAS could be decreased but this leads to lower SNR.

HWAAS must be between 1 and 511 inclusive.

start_point#

Starting point of the sweep

The starting point of the sweep. The corresponding start in millimeter is approximately start_point * 2.5 mm.

num_points#

Number of data points to measure

The number of data points to measure in a sweep.

step_length#

Step length in a sweep

This sets the number of steps to have between each data point.

Sampling produces complex (IQ) data points with configurable distance spacing, starting from ~2.5mm.

profile#

Profile

Each profile consists of a number of settings for the sensor that configures the RX and TX paths. Lower profiles have higher depth resolution while higher profiles have higher radar loop gain.

See also Profile.

receiver_gain#

Receiver gain setting

Must be a value between 0 and 23 inclusive where 23 is the highest gain and 0 the lowest.

Lower gain gives higher SNR. However, too low gain may result in quantization, lowering SNR. Too high gain may result in saturation, corrupting the data.

enable_tx#

Enable or disable the transmitter

If set to True, TX is enabled. This will enable the radio transmitter. By turning the transmitter off the RX noise floor can be measured.

enable_loopback#

Enable or disable loopback

Note, loopback can’t be enabled together with profile 2.

phase_enhancement#

Enable or disable phase enhancement

If enabled, the data phase will be enhanced such that coherent distance filtering can be applied. Given a single reflection from an object, the phase will appear as “flat” around the amplitude peak.

Enabling the phase enhancement increases the processing execution time.

prf#

Pulse Repetition Frequency (PRF)

See PRF for details.

property subsweep: SubsweepConfig#

Retrieves the sole SubsweepConfig

Raises

AttributeError – If num_subsweeps > 1

property subsweeps: list[SubsweepConfig]#

The list of subsweep configs

property num_subsweeps: int#

The number of subsweep configs

validate() None#

Performs self-validation and validation of its subsweep configs

Raises

ValidationError – If anything is invalid.

property sweeps_per_frame: int#

Sweeps per frame (SPF)

The number of sweeps that will be captured in each frame (measurement).

Must be > 0.

property sweep_rate: Optional[float]#

Sweep rate

The sweep rate for sweeps in a frame (measurement).

In Hz. Must be > 0 or None, where None is interpreted as max sweep rate.

property frame_rate: Optional[float]#

Frame rate

Setting the frame rate to unlimited means that the rate is not limited by the sensor but the rate that the host acknowledge and reads out the measurement data.

In Hz. Must be > 0 or None, where None is interpreted as unlimited.

property continuous_sweep_mode: bool#

Continuous sweep mode

In continuous sweep mode the timing will be identical over all sweeps, not just the sweeps in a frame.

Constraints:

property double_buffering: bool#

Double buffering

If enabled, the sensor buffer will be split in two halves reducing the maximum number of samples. A frame can be read while sampling is done into the other buffer.

property inter_frame_idle_state: IdleState#

Inter frame idle state

The inter frame idle state is the state the sensor idles in between each frame.

See also config_enums.IdleState.

The inter_frame_idle_state of the frame must be deeper or the same as the inter_sweep_idle_state .

property inter_sweep_idle_state: IdleState#

Inter sweep idle state

The inter frame idle state is the state the sensor idles in between each sweep in a frame.

See also config_enums.IdleState.

Subsweep#

class acconeer.exptool.a121.SubsweepConfig(*, start_point: int = 80, num_points: int = 160, step_length: int = 1, profile: Profile = Profile.PROFILE_3, hwaas: int = 8, receiver_gain: int = 16, enable_tx=True, enable_loopback=False, phase_enhancement=False, prf: PRF = PRF.PRF_13_0_MHz)#

Subsweep configuration

The subsweep config represents a 1-1 mapping to the RSS service subsweep config.

Normally used as a part of the SensorConfig.

validate() None#

Performs self-validation

Raises

ValidationError – If anything is invalid.

property start_point: int#

Starting point of the sweep

The starting point of the sweep. The corresponding start in millimeter is approximately start_point * 2.5 mm.

property num_points: int#

Number of data points to measure

The number of data points to measure in a sweep.

property step_length: int#

Step length in a sweep

This sets the number of steps to have between each data point.

Sampling produces complex (IQ) data points with configurable distance spacing, starting from ~2.5mm.

property profile: Profile#

Profile

Each profile consists of a number of settings for the sensor that configures the RX and TX paths. Lower profiles have higher depth resolution while higher profiles have higher radar loop gain.

See also Profile.

property hwaas: int#

Hardware accelerated average samples (HWAAS)

Each data point can be sampled several times and the sensor hardware then produces an average value of those samples. The time needed to measure a sweep is roughly proportional to the number of averaged samples. Hence, if there is a need to obtain a higher update rate, HWAAS could be decreased but this leads to lower SNR.

HWAAS must be between 1 and 511 inclusive.

property receiver_gain: int#

Receiver gain setting

Must be a value between 0 and 23 inclusive where 23 is the highest gain and 0 the lowest.

Lower gain gives higher SNR. However, too low gain may result in quantization, lowering SNR. Too high gain may result in saturation, corrupting the data.

property enable_tx: bool#

Enable or disable the transmitter

If set to True, TX is enabled. This will enable the radio transmitter. By turning the transmitter off the RX noise floor can be measured.

property enable_loopback: bool#

Enable or disable loopback

Note, loopback can’t be enabled together with profile 2.

property phase_enhancement: bool#

Enable or disable phase enhancement

If enabled, the data phase will be enhanced such that coherent distance filtering can be applied. Given a single reflection from an object, the phase will appear as “flat” around the amplitude peak.

Enabling the phase enhancement increases the processing execution time.

property prf: PRF#

Pulse Repetition Frequency (PRF)

See PRF for details.

Parameter enums#

Note

The configuration parameter enum values (e.g. 0, 1, 19500000, …) are not to be used directly. They are subject to change at any time.

class acconeer.exptool.a121.PRF(value)#

Pulse Repetition Frequency (PRF)

Pulse Repetition Frequency, PRF, is the frequency at which pulses are sent out from the radar system. The measurement time is approximately proportional to the PRF. The higher the PRF, the shorter the measurement time.

This parameter sets the Maximum Measurable Distance, MMD, that can be achieved. MMD is the maximum value for the end point, i.e., the start point + (number of points * step length). For example, an MMD of 7.0 m means that the range cannot be set further out than 7.0 m.

It also sets the Maximum Unambiguous Range, MUR, that can be achieved. MUR is the maximum distance at which an object can be located to guarantee that its reflection corresponds to the most recent transmitted pulse. Objects farther away than the MUR may fold into the measured range. For example, with a MUR of 11.5 m, an object at 13.5 m could become visible at 2 m.

PRF Setting

PRF

MMD

MUR

PRF_19_5_MHZ *

19.5 MHz

3.1 m

7.7 m

PRF_13_0_MHZ

13.0 MHz

7.0 m

11.5 m

PRF_8_7_MHZ

8.7 MHz

12.7 m

17.3 m

PRF_6_5_MHZ

6.5 MHz

18.5 m

23.1 m

*

19.5MHz is only available for profile 1.

PRF_19_5_MHz = 19500000#
PRF_13_0_MHz = 13000000#
PRF_8_7_MHz = 8700000#
PRF_6_5_MHz = 6500000#
property frequency: int#
class acconeer.exptool.a121.IdleState(value)#

Idle state

Idle state DEEP_SLEEP is the deepest state where as much of the sensor hardware as possible is shut down and idle state READY is the lightest state where most of the sensor hardware is kept on.

DEEP_SLEEP is the slowest to transition from while READY is the fastest.

DEEP_SLEEP = 0#
SLEEP = 1#
READY = 2#
is_deeper_than(other: IdleState) bool#
class acconeer.exptool.a121.Profile(value)#
PROFILE_1 = 1#
PROFILE_2 = 2#
PROFILE_3 = 3#
PROFILE_4 = 4#
PROFILE_5 = 5#

Entities#

RSS representations#

class acconeer.exptool.a121.Result(*, data_saturated: bool, frame_delayed: bool, calibration_needed: bool, temperature: int, frame: ndarray[Any, dtype[ScalarType]], tick: int, context: ResultContext)#

Represents the RSS processing_result.

data_saturated: bool#

Indication of sensor data being saturated, can cause data corruption. Lower the receiver gain if this indication is set.

frame_delayed: bool#

Indication of a delayed frame. The frame rate might need to be lowered if this indication is set.

calibration_needed: bool#

Indication of calibration needed. The sensor calibration needs to be redone if this indication is set.

temperature: int#

Temperature in sensor during measurement (in degree Celsius). Notice that this has poor absolute accuracy.

tick: int#

Server tick when the server got the interrupt from the sensor

property frame: numpy.ndarray[Any, numpy.dtype[numpy.complex128]]#

Frame data in a complex float data format

2-D with dimensions (sweep, distance).

property subframes: list[npt.NDArray[np.complex_]]#

Frame split up into subframes, one for every subsweep config used

property tick_time: float#

Tick converted to a time in seconds

class acconeer.exptool.a121.Metadata(*, frame_data_length: int, sweep_data_length: int, subsweep_data_offset: ndarray[Any, dtype[ScalarType]], subsweep_data_length: ndarray[Any, dtype[ScalarType]], calibration_temperature: int, tick_period: int, base_step_length_m: float, max_sweep_rate: float)#

Represents a superset of the RSS processing_metadata.

frame_data_length: int#

Number of elements in the frame

sweep_data_length: int#

Number of elements in the sweep

subsweep_data_offset: numpy.ndarray[Any, numpy.dtype[numpy._typing._generic_alias.ScalarType]]#

Offset to the subsweeps data

subsweep_data_length: numpy.ndarray[Any, numpy.dtype[numpy._typing._generic_alias.ScalarType]]#

Number of elements in the subsweeps

calibration_temperature: int#

Temperature during calibration

tick_period: int#

Target tick period if update rate is set, otherwise 0

base_step_length_m: float#

Base step length in meter

max_sweep_rate: float#

Maximum sweep rate that the sensor can provide for the given configuration

property frame_shape: Tuple[int, int]#

The frame shape this Metadata defines

to_dict() dict[str, Any]#
classmethod from_dict(d: dict) Metadata#
to_json() str#
classmethod from_json(json_str: str) Metadata#

System info#

class acconeer.exptool.a121.ClientInfo(*, ip_address: Optional[str] = None, serial_port: Optional[str] = None, usb_device: Optional[USBDevice] = None, override_baudrate: Optional[int] = None)#
ip_address: Optional[str]#
serial_port: Optional[str]#
usb_device: Optional[acconeer.exptool.utils.USBDevice]#
override_baudrate: Optional[int]#
to_dict() dict[str, Any]#
classmethod from_dict(d: dict) ClientInfo#
to_json() str#
classmethod from_json(json_str: str) ClientInfo#
class acconeer.exptool.a121.ServerInfo(*, rss_version: str, sensor_count: int, ticks_per_second: int, sensor_infos: dict[int, SensorInfo], hardware_name: Optional[str] = None, max_baudrate: Optional[int] = None)#
rss_version: str#
sensor_count: int#
ticks_per_second: int#
sensor_infos: dict[int, SensorInfo]#
hardware_name: Optional[str]#
max_baudrate: Optional[int]#
property parsed_rss_version: packaging.version.Version#
to_dict() dict[str, Any]#
classmethod from_dict(d: dict) ServerInfo#
to_json() str#
classmethod from_json(json_str: str) ServerInfo#
class acconeer.exptool.a121.SensorInfo(*, connected: bool, serial: Optional[str] = None)#

Holds information about a single sensor slot on a host.

connected: bool#
serial: Optional[str]#
to_dict() dict[str, Any]#
classmethod from_dict(d: dict[str, Any]) SensorInfo#
to_json() str#
classmethod from_json(json_str: str) SensorInfo#

Client#

class acconeer.exptool.a121.Client(ip_address: Optional[str] = None, serial_port: Optional[str] = None, usb_device: Optional[Union[str, bool, USBDevice]] = None, override_baudrate: Optional[int] = None, _override_protocol: Optional[Type[CommunicationProtocol]] = None)#
connect() None#

Connects to the specified host.

Raises

Exception if the host cannot be connected to.

Raises

ClientError if server has wrong sensor generation (e.g. “a111”)

disconnect() None#

Disconnects the client from the host.

get_next() Union[Result, list[dict[int, Result]]]#

Gets results from the server.

Returns

A Result if the setup SessionConfig.extended is False, list[dict[int, Result]] otherwise.

Raises

ClientError if Client’s session is not started.

setup_session(config: Union[SensorConfig, SessionConfig], calibrations: Optional[dict[int, SensorCalibration]] = None) Union[Metadata, list[dict[int, Metadata]]]#

Sets up the session specified by config.

If the Client is not already connected, it will connect before setting up the session.

Parameters
  • config – The session to set up.

  • calibrations – An optional dict with SensorCalibration for the session.

Raises

ValueError if the config is invalid.

Returns

Metadata if config.extended is False, list[dict[int, Metadata]] otherwise.

start_session(recorder: Optional[Recorder] = None) None#

Starts the already set up session.

After this call, the server starts streaming data to the client.

Parameters

recorder – An optional Recorder, which samples every get_next()

Raises

ClientError if Client’s session is not set up.

stop_session() Any#

Stops an on-going session

Returns

The return value of the passed Recorder.stop() passed in start_session.

Raises

ClientError if Client’s session is not started.

property calibrations: dict[int, SensorCalibration]#

Returns a dict with a SensorCalibration per used sensor for the current session:

For example, if session_setup was called with

client.setup_session(
    SessionConfig({1: SensorConfig(), 3: SensorConfig()}),
)

this attribute will return {1: SensorCalibration(…), 3: SensorCalibration(…)}

property calibrations_provided: dict[int, bool]#

Returns whether a calibration was provided for each sensor in setup_session. For example, if setup_session was called with

client.setup_session(
    SessionConfig({1: SensorConfig(), 2: SensorConfig()}),
    calibrations={2: SensorCalibration(...)},
)

this attribute will return {1: False, 2: True}

property client_info: ClientInfo#

The ClientInfo.

property connected: bool#

Whether this Client is connected.

property extended_metadata: list[dict[int, Metadata]]#

The extended Metadata for the current session

property server_info: ServerInfo#

The ServerInfo.

property session_config: SessionConfig#

The SessionConfig for the current session

property session_is_setup: bool#

Whether this Client has a session set up.

property session_is_started: bool#

Whether this Client’s session is started.

Recording#

Recorders#

class acconeer.exptool.a121.H5Recorder(path_or_file: Union[str, PathLike, File], mode: str = 'x', *, _chunk_size: Optional[int] = None, _lib_version: Optional[str] = None, _timestamp: Optional[str] = None, _uuid: Optional[str] = None)#

Recorder writing directly to an HDF5 file

Parameters
  • path_or_file

    If a path-like object, by default (depending on mode below) an HDF5 file is created at that path. When stopping, the file is closed.

    If an h5py.File, that file is used as-is. In this case, the file is not closed when stopping.

  • mode – The file mode to use if a path-like object was given for path_or_file. Default value is ‘x’, meaning that we open for exclusive creation, failing if the file already exists.

  • _chunk_size

    If given, data will be written to file every _chunk_size samples.

    If not given, data will be written at least every 512:th sample, or at least once per second, whichever comes first.

    Setting a small chunk size (e.g. 1) may degrade performance for high sample rates.

    Internal parameter, subject to change.

file: h5py.File#

The h5py.File.

owns_file: bool#

Whether H5Recorder opened and owns the file, i.e., if a path-like object was given for path_or_file. If it does, the file is closed when stopping.

path: Optional[os.PathLike]#

The file path, if a path-like object was given for path_or_file.

require_algo_group(key: str) Group#

Creates/gets the algo group with a given key.

Raises

Exception if the key does not match the file content

Records#

class acconeer.exptool.a121.Record#

Record representing all data needed to recreate a session

abstract property client_info: ClientInfo#

Client info

abstract property extended_metadata: list[dict[int, Metadata]]#

Extended metadata

property metadata: Metadata#

Retrieves the sole metadata entry in the record

Raises

ValueError if there are multiple entries in the extended_metadata

abstract property extended_results: Iterator[list[dict[int, Result]]]#

The sequence of extended results

Retrieves an iterator over all extended results in the record, which may be useful to replay a session.

Tip

If your record only has one entry in the session, and you want to retrieve the results for that one entry, you can use results.

If you desire to get, for example, all frames in the sequence of results stacked in one array, use extended_stacked_results. Similar to results, there is also stacked_results which retrieves the one and only entry.

property results: Iterator[Result]#

Retrieves the sole sequence of results in the record

Raises

ValueError if there are multiple entries in the extended_results

abstract property extended_stacked_results: list[dict[int, StackedResults]]#

The extended stacked results

property stacked_results: StackedResults#

Retrieves the sole stacked results in the record

Raises

ValueError if there are multiple entries in the extended_stacked_results

property frames: numpy.ndarray[Any, numpy.dtype[numpy.complex128]]#

Retrieves the sole stack of frames in the record

Alias for Record.stacked_results.frame.

Raises

ValueError if there are multiple entries in the extended_stacked_results

abstract property lib_version: str#

The version of the acconeer.exptool library which created the record

abstract property num_frames: int#

The number of frames in the record

abstract property server_info: ServerInfo#

Server info

abstract property session_config: SessionConfig#

Session config

abstract property sensor_id: int#

The sole sensor ID

Raises

ValueError if there are multiple entries in the session_config

abstract property timestamp: str#

Creation timestamp

abstract property uuid: str#

UUID

abstract property calibrations: dict[int, SensorCalibration]#

The calibrations in the record

abstract property calibrations_provided: dict[int, bool]#

The calibrations provided in the record

class acconeer.exptool.a121.PersistentRecord#

Record that wraps a file on disk

Data is lazily loaded from the underlying file on demand.

abstract close() None#

Close the underlying file

class acconeer.exptool.a121.StackedResults(*, data_saturated: ndarray[Any, dtype[bool_]], frame_delayed: ndarray[Any, dtype[bool_]], calibration_needed: ndarray[Any, dtype[bool_]], temperature: ndarray[Any, dtype[bool_]], frame: ndarray[Any, dtype[ScalarType]], tick: ndarray[Any, dtype[int64]], context: ResultContext)#

Stacked results

For loading/processing data.

Representation of multiple Result stacked together. Scalar values, like Result.data_saturated, become 1-D arrays of the same type. The Result.frame, which is originally a 2-D array, becomes a 3-D array where the frames are stacked in the first dimension.

See Result for details on the attributes/properties.

data_saturated: numpy.ndarray[Any, numpy.dtype[numpy.bool_]]#
frame_delayed: numpy.ndarray[Any, numpy.dtype[numpy.bool_]]#
calibration_needed: numpy.ndarray[Any, numpy.dtype[numpy.bool_]]#
temperature: numpy.ndarray[Any, numpy.dtype[numpy.bool_]]#
tick: numpy.ndarray[Any, numpy.dtype[numpy.int64]]#
property frame: numpy.ndarray[Any, numpy.dtype[numpy.complex128]]#
property subframes: list[npt.NDArray[np.complex_]]#
property tick_time: numpy.ndarray[Any, numpy.dtype[numpy.float64]]#

Open/load/save functions#

acconeer.exptool.a121.load_record(path_or_file: Union[str, PathLike, File]) Record#

Load a record from file

Unlike open_record(), this functions loads the data into memory immediately. The file handle is not kept open.

Returns

A Record with the content of the given file

acconeer.exptool.a121.open_record(path_or_file: Union[str, PathLike, File]) PersistentRecord#

Open a record from file

Since this function returns a PersistentRecord, data is not immediately loaded into memory. Rather, data is lazily loaded from the underlying file on demand.

Either a path or an opened file (h5py.File) may be given. If a path is given, the file will be opened by this function, and must be closed again by the user. The recommended way to do this is by using the context manager of the returned persistent record, like:

with a121.open_record("path/to/my/file.h5") as record:
    record.timestamp

Tip

Unless you’re dealing with very large files, use load_record() instead.

Returns

A PersistentRecord wrapping the given file

acconeer.exptool.a121.save_record(path_or_file: Union[str, PathLike, File], record: Record) None#

Alias for save_record_to_h5()

acconeer.exptool.a121.save_record_to_h5(path_or_file: Union[str, PathLike, File], record: Record) None#

Save a record to a HDF5 file

Utility functions#

acconeer.exptool.a121.complex_array_to_int16_complex(array: ndarray[Any, dtype[complex128]]) ndarray[Any, dtype[ScalarType]]#

Converts an array with plain complex dtype (non-structured) into an array with dtype = INT_16_COMPLEX (structured with parts “real” and “imag”) using numpy.round.

acconeer.exptool.a121.iterate_extended_structure(structure: list[dict[int, ValueT]]) Iterator[Tuple[int, int, ValueT]]#

Iterates over the elements of the extended structure.

Returns

Iterator of (<group id>, <sensor id>, <element>)

acconeer.exptool.a121.iterate_extended_structure_values(structure: list[dict[int, ValueT]]) Iterator[ValueT]#

Iterates like iterate_extended_structure but throws away group id and sensor id.

acconeer.exptool.a121.zip_extended_structures(structure_a: list[dict[int, S]], structure_b: list[dict[int, T]]) list[dict[int, Tuple[S, T]]]#

Zip structures according to group id and sensor id.

Typical use case is reordering extended structures before iterating.

Example:

structure_a = [{1: a_1, 2: a_2}, {1: a_3}]

structure_b = [{1: b_1, 2: b_2}, {1: b_3}]

result: [{1: (a_1, b_1), 2: (a_2, b_2)}, 1: {(a_3, b_3)}]

acconeer.exptool.a121.zip3_extended_structures(structure_a: list[dict[int, S]], structure_b: list[dict[int, T]], structure_c: list[dict[int, U]]) list[dict[int, Tuple[S, T, U]]]#

Zip structures according to group id and sensor id.

Typical use case is reordering extended structures before iterating.

Example:

structure_a = [{1: a_1, 2: a_2}, {1: a_3}]

structure_b = [{1: b_1, 2: b_2}, {1: b_3}]

structure_c = [{1: c_1, 2: c_2}, {1: c_3}]

result: [{1: (a_1, b_1, c_1), 2: (a_2, b_2, c_2)}, {1: (a_3, b_3, c_3)}]

Algo#

Warning

The acconeer.exptool.a121.algo package is currently an unstable API and may change at any time.

Utility functions#

acconeer.exptool.a121.algo.find_peaks(abs_sweep: npt.NDArray[np.float_], threshold: npt.NDArray[np.float_]) list[int]#

Identifies peaks above threshold.

A peak is defined as a point with greater value than its two neighbouring points and all three points are above the threshold.

Parameters
  • abs_sweep – Absolute value of mean sweep.

  • threshold – Array of values, defining the threshold throughout the sweep.

acconeer.exptool.a121.algo.get_distance_filter_coeffs(profile: Profile, step_length: int) Any#

Calculates the iir coefficients corresponding to a matched filter, based on the profile and the step length.

acconeer.exptool.a121.algo.get_distance_filter_edge_margin(profile: Profile, step_length: int) int#

Calculates the number of points required for filter initialization when performing distance filtering, using the filter coefficients supplied by the function get_distance_filter_coeffs.

acconeer.exptool.a121.algo.get_temperature_adjustment_factors(temperature_diff: int, profile: Profile) Tuple[float, float]#

Calculate temperature compensation for mean sweep and background noise(tx off) standard deviation.

The signal adjustment model is follows 2 ** (temperature_diff / model_parameter), where model_parameter reflects the temperature difference relative the reference temperature, required for the amplitude to double/halve.

The noise adjustment is a linear function of the temperature difference, calibrated using noise-normalized data, generalizing to different sensor configurations.

acconeer.exptool.a121.algo.interpolate_peaks(abs_sweep: npt.NDArray[np.float_], peak_idxs: list[int], start_point: int, step_length: int, step_length_m: float) Tuple[list[float], list[float]]#

Quadratic interpolation around a peak using the amplitudes of the peak and its two neghbouring points.

Derivation: https://math.stackexchange.com/questions/680646/get-polynomial-function-from-3-points

Parameters
  • abs_sweep – Absolute value of mean sweep.

  • peak_idxs – List containing indexes of identified peaks.

  • start_point – Start point.

  • step_length – Step length in points.

  • step_length_m – Step length in meters.

acconeer.exptool.a121.algo.select_prf(breakpoint: int, profile: Profile) PRF#

Calculates the highest possible PRF for the given breakpoint.

Parameters
  • breakpoint – Distance in the unit of points.

  • profile – Profile.

Distance (under development)#

class acconeer.exptool.a121.algo.distance.Processor(*, sensor_config: SensorConfig, metadata: Metadata, processor_config: ProcessorConfig, subsweep_indexes: Optional[list[int]] = None, context: Optional[ProcessorContext] = None)#

Distance processor

For all used subsweeps, the profile and step_length must be the same.

Parameters
  • sensor_config – Sensor configuration

  • metadata – Metadata yielded by the sensor config

  • processor_config – Processor configuration

  • subsweep_indexes – The subsweep indexes to be processed. If None, all subsweeps will be used.

  • context – Context

CFAR_GUARD_LENGTH_ADJUSTMENT = 4#
CFAR_WINDOW_LENGTH_ADJUSTMENT = 0.25#
PHASE_JITTER_RESTART_STD = 0.05#
CLOSE_RANGE_LOOPBACK_IDX = 0#
CLOSE_RANGE_DIST_IDX = 1#
process(result: Result) ProcessorResult#
classmethod calc_cfar_margin(profile: Profile, step_length: int) int#
update_config(config: ProcessorConfig) None#
class acconeer.exptool.a121.algo.distance.ProcessorConfig(*, processor_mode=ProcessorMode.DISTANCE_ESTIMATION, threshold_method=ThresholdMethod.CFAR, measurement_type=MeasurementType.FAR_RANGE, threshold_sensitivity: float = 0.5, fixed_threshold_value: float = 100.0)#
processor_mode: acconeer.exptool.a121.algo.distance._processors.ProcessorMode#
threshold_method: ThresholdMethod#
measurement_type: acconeer.exptool.a121.algo.distance._processors.MeasurementType#
threshold_sensitivity: float#
fixed_threshold_value: float#
class acconeer.exptool.a121.algo.distance.ProcessorContext(*, direct_leakage: Optional[ndarray[Any, dtype[complex128]]] = None, phase_jitter_comp_ref: Optional[ndarray[Any, dtype[float64]]] = None, recorded_threshold_mean_sweep: Optional[ndarray[Any, dtype[float64]]] = None, recorded_threshold_noise_std: Optional[List[float64]] = None, bg_noise_std: Optional[List[float]] = None, reference_temperature: Optional[int] = None, loopback_peak_location_m: Optional[float] = None)#
direct_leakage: Optional[numpy.ndarray[Any, numpy.dtype[numpy.complex128]]]#
phase_jitter_comp_ref: Optional[numpy.ndarray[Any, numpy.dtype[numpy.float64]]]#
recorded_threshold_mean_sweep: Optional[numpy.ndarray[Any, numpy.dtype[numpy.float64]]]#
recorded_threshold_noise_std: Optional[List[numpy.float64]]#
bg_noise_std: Optional[List[float]]#
reference_temperature: Optional[int]#
loopback_peak_location_m: Optional[float]#
class acconeer.exptool.a121.algo.distance.ProcessorResult(*, estimated_distances: Optional[list[float]] = None, estimated_amplitudes: Optional[list[float]] = None, recorded_threshold_mean_sweep: Optional[npt.NDArray[np.float_]] = None, recorded_threshold_noise_std: Optional[list[np.float_]] = None, direct_leakage: Optional[npt.NDArray[np.complex_]] = None, phase_jitter_comp_reference: Optional[npt.NDArray[np.float_]] = None, extra_result: ProcessorExtraResult = NOTHING)#
estimated_distances: Optional[list[float]]#
estimated_amplitudes: Optional[list[float]]#
recorded_threshold_mean_sweep: Optional[npt.NDArray[np.float_]]#
recorded_threshold_noise_std: Optional[list[np.float_]]#
direct_leakage: Optional[npt.NDArray[np.complex_]]#
phase_jitter_comp_reference: Optional[npt.NDArray[np.float_]]#
extra_result: ProcessorExtraResult#