strip — Strip charts#

This module provides a StripChart class representing a sliding strip chart, that is, a scatter plot where the number of points is limited to a maximum, so that the thing acts essentially as a sliding window, typically in time. This is mainly meant to represent the time history of a signal over a reasonable span—a long-term acquisition might go on for weeks, and it would not make sense to try and plot on the screen millions of points, but the last segment of the acquisition is the most important part when we want to monitor what is happening.

Internally the class uses two distinct collections.deque objects to store the data points, and the public interface is fairly simple:

  • you use put() to add one or more data points (x and y coordinates) to the strip chart;

  • you use clear() to clear the contents of the strip chart;

  • you use set_max_length() to change the maximum length of the strip chart.

from aptapy.strip import StripChart

chart = StripChart(max_length=1000, label='Signal')

# add a single point
chart.put(0., 0.)

# add multiple points
chart.put([1., 2., 3.], [4., 5., 6.])

# plot the current contents of the strip chart
chart.plot()

See also

Have a look at the Simple strip chart and Interactive cursor examples.

Strip charts and wall time#

A fairly common use case for strip charts is to plot the time history of a signal against wall time. In this case, the x-axis represents time in seconds since the epoch (i.e., POSIX timestamps), e.g., from a call to time.time(). In order to facilitate this use case, the module provides the EpochStripChart class.

Note

time.time() always returns a floating-point number, representing seconds since the Unix epoch (January 1, 1970, 00:00:00 UTC). Note the UTC part: time.time() is not affected by the local time zone or daylight saving time (not even mentioning leap seconds), and we do nothing clever internally to this module to even try and keep track of any of that.

Internally, the class converts the seconds-since-epoch values to numpy datetime64 objects at plotting time. We support s, ms, us, and ns resolutions, with the default being ms (milliseconds), see the EpochStripChart documentation.

Note

datetime64 is the numpy native timestamp data type. Unlike Python’s datetime.datetime, which stores a full object per entry, datetime64 is a compact numeric type that stores timestamps as integer counts since the Unix epoch (1970-01-01) with a fixed time unit. That time unit is specified in brackets, e.g., datetime64[s] (second precision), datetime64[ms] (millisecond precision) and datetime64[ns] (nanosecond precision).

In order to convert from POSIX timestamps (i.e., floating-point seconds since epoch) to datetime64, numpy simply multiplies the floating-point number by the appropriate factor (1 for seconds, 1000 for milliseconds and so on and so forth) and then casts to integer. This is all done internally to the EpochStripChart class. Good for you.

The class does its best to format the x-axis labels in a human-friendly way, so that the appearance is sensible regardless of the time span represented in the strip chart. Open an issue if you do run into an edge case!

See also

Have a look at the Epoch strip chart example.

Module documentation#

Strip charts.

class aptapy.strip.StripChart(max_length: int = None, label: str = None, xlabel: str = None, ylabel: str = None)[source]#

Class describing a sliding strip chart, that is, a scatter plot where the number of points is limited to a maximum, so that the thing acts essentially as a sliding window, typically in time.

Arguments#

max_lengthint, optional

the maximum number of points to keep in the strip chart. If None (the default), the number of points is unlimited.

labelstr, optional

a text label for the data series (default is None).

xlabelstr, optional

the label for the x axis.

ylabelstr, optional

the label for the y axis.

set_max_length(max_length: int) None[source]#

Set the maximum length of the strip chart.

Arguments#

max_lengthint

the new maximum number of points to keep in the strip chart.

Note this creates two new deque objects under the hood but labels are preserved. There is no attempt to preserve existing data points.

clear() None[source]#

Reset the strip chart.

static _is_numerical_scalar(value) bool[source]#

Return whether the given value is a numerical scalar.

This is more tricky than one would expect as, while np.int32(1) and alike are instances of Number, 0-dim numpy arrays, e.g., numpy.array(1), are not.

put(x: float | ndarray, y: float | ndarray) StripChart[source]#

Append data points to the strip chart.

This is supposed to correctly interoperate with all the data types we will be typically deal with: numbers, numpy scalars, and iterables, including numpy arrays.

Note this returns the strip chart itself in order to allow for chaining operations.

Arguments#

xarray-like

The x value(s) to append to the strip chart.

yarray-like

The y value(s) to append to the strip chart.

Returns#

StripChart

The strip chart itself

spline(k: int = 1, ext: str = 'raise') InterpolatedUnivariateSpline[source]#

Return an interpolating spline through all the underlying data points. This is useful, e.g., when adding a vertical cursor to the strip chart.

Note that, by default, the spline will raise a ValueError exception when asked to extrapolate outside the data range. (This plays well with the VerticalCursor class, as in that case the marker and associated text will be hidden.)

Arguments#

kint

The order of the spline (default 1).

extstr

The behavior when extrapolating outside the data range. Valid values are: extrapolate (return the extrapolated value), zeros (return 0), raise (raise a ValueError), and const (return the boundary value).

Returns#

InterpolatedUnivariateSpline

The interpolating spline.

_render(axes: Axes = None, **kwargs) None[source]#

Plot the strip chart.

_abc_impl = <_abc._abc_data object>#
class aptapy.strip.EpochStripChart(max_length: int = None, label: str = '', xlabel: str = 'Date and Time (UTC)', ylabel: str = None, resolution: str = 'ms')[source]#

Class describing a sliding strip chart with epoch time on the x axis.

Operationally, this assumes that the values on the x axis are seconds since the Unix epoch (January 1st, 1970), e.g., from a time.time() call. These are then converted into NumPy datetime64 values (with the desired resolution) at plot time.

Arguments#

max_lengthint, optional

the maximum number of points to keep in the strip chart. If None (the default), the number of points is unlimited.

labelstr, optional

a text label for the data series (default is None).

xlabelstr, optional

the label for the x axis.

ylabelstr, optional

the label for the y axis.

resolutionstr, optional

the resolution for the x axis. Supported values are “s” (seconds), “ms” (milliseconds), “us” (microseconds), and “ns” (nanoseconds). Default is “ms”.

_RESOLUTION_MULTIPLIER_DICT = {'ms': 1000, 'ns': 1000000000, 's': 1, 'us': 1000000}#
_render(axes: Axes = None, **kwargs) None[source]#

Plot the strip chart.

This is more tricky than one would expect, as NumPy’s datetime64 type stores timestamps as integer counts of a specific unit (like seconds, milliseconds, or nanoseconds) from the epoch. Assuming that we are using seconds since the epoch as input, we need to convert those into the appropriate integer counts. This boils down to using a multiplier depending on the desired resolution.

_abc_impl = <_abc._abc_data object>#