pept.processing.occupancy2d

pept.processing.occupancy2d(points, number_of_pixels, radius, xlim=None, ylim=None, omit_last=False, verbose=True)[source]

Compute the 2D occupancy / residence time distribution of a single circular particle moving along a trajectory.

This corresponds to the pixellisation of moving circular particles, such that for every two consecutive particle locations, a 2D cylinder (i.e. convex hull of two circles at the two particle positions), the fraction of its area that intersets a pixel is multiplied with the time between the two particle locations and saved in the input pixels.

You must specify the points (2D numpy array) recorded along a particle’s trajectory, formatted as [time, x, y] of each location, along with the number_of_pixels in each dimension ([nx, ny]) and particle radius.

The pixel area’s bounds can be specified in xlim and ylim. If unset, they will be computed automatically based on the minimum and maximum values found in points.

Parameters
points: (P, 3) numpy.ndarray

The particles’ 2D locations and corresponding timestamp, where each row is formatted as [time, x_coordinate, y_coordinate]. Must have at least two points.

number_of_pixels: (2,) list-like

The number of pixels in the x-dimension and y-dimension. Each dimension must have at least 2 pixels.

radius: float

The radius of the particle. It can be given in any system of units, as long as it is consistent with what is used for the particle locations.

xlim: (2,) list-like, optional

The limits of the system over which the pixels span in the x-dimension, formatted as [xmin, xmax]. If unset, they will be computed automatically based on the minimum and maximum values found in positions.

ylim: (2,) list-like, optional

The limits of the system over which the pixels span in the y-dimension, formatted as [ymin, ymax]. If unset, they will be computed automatically based on the minimum and maximum values found in positions.

omit_last: bool, default False

If true, omit the last circle in the particle positions. Useful if rasterizing the same trajectory piece-wise; if you split the trajectory and call this function multiple times, set omit_last = 0 to avoid considering the last particle location twice.

verbose: bool, default True

Time the pixellisation step and print it to the terminal.

Returns
pept.Pixels (numpy.ndarray subclass)

The created pixels, each cell containing the area covered by particles. The pept.Pixels class inherits all properties and methods from numpy.ndarray, so you can use it exactly like you would a numpy array. It just contains extra attributes (e.g. xlim, ylim) and some PEPT-oriented methods (e.g. pixels_trace).

Raises
ValueError

If positions is not a 2D array-like with exactly 3 columns, or number_of_pixels is not a 1D list-like with exactly 2 values or it contains a value smaller than 2. If xlim or ylim have max < min or there are particle positions falling outside the system defined by xlim and ylim, including the area.

Examples

Create ten random particle positions between 0-100 and radius 0.2:

>>> positions = np.random.random((10, 2)) * 100
>>> radius = 0.2

Now pixellise this trajectory over a grid of (20, 10) pixels:

>>> import pept.processing as pp
>>> num_pixels = (20, 10)
>>> pixels = pp.occupancy2d(positions, num_pixels, radius)

Alternatively, specify the system’s bounds explicitly:

>>> pixels = pp.occupancy2d(
>>>     positions, (20, 10), radius, xlim = [10, 90], ylim = [-5, 105]
>>> )

You can plot those pixels in two ways - using PlotlyGrapher (this plots a 3D “heatmap”, as a coloured surface):

>>> from pept.visualisation import PlotlyGrapher
>>> grapher = PlotlyGrapher()
>>> grapher.add_pixels(pixels)
>>> grapher.show()

Or using raw Plotly (this plots a “true” heatmap) - this is recommended:

>>> import plotly.graph_objs as go
>>> fig = go.Figure()
>>> fig.add_trace(pixels.heatmap_trace())
>>> fig.show()