pept.tracking.FPI#

class pept.tracking.FPI(w=3.0, r=0.4, lld_counts=0.0, verbose=False)[source]#

Bases: VoxelsFilter

FPI is a modern voxel-based tracer-location algorithm that can reliably work with unknown numbers of tracers in fast and noisy environments.

It was successfully used to track fast-moving radioactive tracers in pipe flows at the Virginia Commonwealth University. If you use this algorithm in your work, please cite the following paper:

Wiggins C, Santos R, Ruggles A. A feature point identification method for positron emission particle tracking with multiple tracers. Nuclear Instruments and Methods in Physics Research Section A: Accelerators, Spectrometers, Detectors and Associated Equipment. 2017 Jan 21; 843:22-8.

Permission was granted by Dr. Cody Wiggins in March 2021 to publish his code in the pept library under the GNU v3.0 license.

Two main methods are provided: fit_sample for tracking a single voxel space (i.e. a single pept.Voxels) and fit which tracks all the samples encapsulated in a pept.VoxelData class in parallel.

See also

pept.LineData

Encapsulate LoRs for ease of iteration and plotting.

pept.PointData

Encapsulate points for ease of iteration and plotting.

pept.utilities.read_csv

Fast CSV file reading into numpy arrays.

PlotlyGrapher

Easy, publication-ready plotting of PEPT-oriented data.

Examples

A typical workflow would involve reading LoRs from a file, creating a lazy VoxelData voxellised representation, instantiating an FPI class, tracking the tracer locations from the LoRs, and plotting them.

>>> import pept
>>>
>>> lors = pept.LineData(...)   # set sample_size and overlap appropriately
>>> voxels = pept.tracking.Voxelize((50, 50, 50)).fit(lors)
>>>
>>> fpi = pept.tracking.FPI(w = 3, r = 0.4)
>>> positions = fpi.fit(voxels) # this is a `pept.PointData` instance

A much more efficient approach would be to create a pept.Pipeline containing a voxelization step and then FPI:

>>> from pept.tracking import *
>>>
>>> pipeline = Voxelize((50, 50, 50)) + FPI() + Stack()
>>> positions = pipeline.fit(lors)

Finally, plotting results:

>>> from pept.plots import PlotlyGrapher
>>>
>>> grapher = PlotlyGrapher()
>>> grapher.add_points(positions)
>>> grapher.show()
>>> from pept.plots import PlotlyGrapher2D
>>> PlotlyGrapher2D().add_timeseries(positions).show()
Attributes
wdouble

Search range to be used in local maxima calculation. Typical values for w are 2 - 5 (lower number for more particles or smaller particle separation).

rdouble

Fraction of peak value used as threshold. Typical values for r are usually between 0.3 and 0.6 (lower for more particles, higher for greater background noise)

lld_countsdouble, default 0

A secondary lld to prevent assigning local maxima to voxels with very low values. The parameter lld_counts is not used much in practice - for most cases, it can be set to zero.

__init__(w=3.0, r=0.4, lld_counts=0.0, verbose=False)[source]#

FPI class constructor.

Parameters
wdouble

Search range to be used in local maxima calculation. Typical values for w are 2 - 5 (lower number for more particles or smaller particle separation).

rdouble

Fraction of peak value used as threshold. Typical values for r are usually between 0.3 and 0.6 (lower for more particles, higher for greater background noise)

lld_countsdouble, default 0

A secondary lld to prevent assigning local maxima to voxels with very low values. The parameter lld_counts is not used much in practice - for most cases, it can be set to zero.

verbosebool, default False

Show extra information on class instantiation.

Methods

__init__([w, r, lld_counts, verbose])

FPI class constructor.

copy([deep])

Create a deep copy of an instance of this class, including all inner attributes.

fit(voxels[, executor, max_workers, verbose])

Apply self.fit_sample (implemented by subclasses) according to the execution policy.

fit_sample(voxels)

Use the FPI algorithm to locate a tracer from a single voxellised space (i.e.

load(filepath)

Load a saved / pickled PEPTObject object from filepath.

save(filepath)

Save a PEPTObject instance as a binary pickle object.

fit_sample(voxels: Voxels)[source]#

Use the FPI algorithm to locate a tracer from a single voxellised space (i.e. from one sample of LoRs).

A sample of LoRs can be voxellised using the pept.Voxels.from_lines method before calling this function.

Parameters
voxelspept.Voxels

A single voxellised space (i.e. from a single sample of LoRs) for which the tracers’ locations will be found using the FPI method.

Returns
locationsnumpy.ndarray or pept.PointData

The tracked locations found; if as_array is True, they are returned as a NumPy array with columns [time, x, y, z, error_x, error_y, error_z]. If as_array is False, the points are returned in a pept.PointData for ease of visualisation.

Raises
TypeError

If voxels is not an instance of pept.Voxels (or subclass thereof).

copy(deep=True)#

Create a deep copy of an instance of this class, including all inner attributes.

fit(voxels, executor='joblib', max_workers=None, verbose=True)#

Apply self.fit_sample (implemented by subclasses) according to the execution policy. Simply return a list of processed samples. If you need a reduction step (e.g. stack all processed samples), apply it in the subclass.

static load(filepath)#

Load a saved / pickled PEPTObject object from filepath.

Most often the full object state was saved using the .save method.

Parameters
filepathfilename or file handle

If filepath is a path (rather than file handle), it is relative to where python is called.

Returns
pept.PEPTObject subclass instance

The loaded object.

Examples

Save a LineData instance, then load it back:

>>> lines = pept.LineData([[1, 2, 3, 4, 5, 6, 7]])
>>> lines.save("lines.pickle")
>>> lines_reloaded = pept.LineData.load("lines.pickle")
save(filepath)#

Save a PEPTObject instance as a binary pickle object.

Saves the full object state, including inner attributes, in a portable binary format. Load back the object using the load method.

Parameters
filepathfilename or file handle

If filepath is a path (rather than file handle), it is relative to where python is called.

Examples

Save a LineData instance, then load it back:

>>> lines = pept.LineData([[1, 2, 3, 4, 5, 6, 7]])
>>> lines.save("lines.pickle")
>>> lines_reloaded = pept.LineData.load("lines.pickle")