Class: Particle

class pykitPIV.particle.ParticleSpecs(n_images=1, size=(512, 512), size_buffer=10, diameters=(3, 6), distances=(0.5, 2), densities=(0.05, 0.1), diameter_std=(0, 0.1), min_diameter=0.01, seeding_mode='random', dtype=<class 'numpy.float64'>, random_seed=None)

Configuration object for the Particle class.

Example:

from pykitPIV import ParticleSpecs

# Instantiate an object of ParticleSpecs class:
particle_spec = ParticleSpecs()

# Change one field of particle_spec:
particle_spec.diameters = (2, 2)

# You can print the current values of all attributes:
print(particle_spec)
class pykitPIV.particle.Particle(n_images, size=(512, 512), size_buffer=10, diameters=(3, 6), distances=(0.5, 2), densities=(0.05, 0.1), diameter_std=(0, 0.1), min_diameter=0.01, seeding_mode='random', dtype=<class 'numpy.float64'>, random_seed=None)

Generates tracer particles with specified properties for a set of \(N\) image pairs. This class generates the starting positions for tracer particles, i.e., the ones used for \(I_1\).

Example:

from pykitPIV import Particle
import numpy as np

# We are going to generate 10 PIV image pairs:
n_images = 10

# Specify size in pixels for each image:
image_size = (128, 512)

# Initialize a particle object:
particles = Particle(n_images=n_images,
                     size=image_size,
                     size_buffer=10,
                     diameters=(2, 4),
                     distances=(1, 2),
                     densities=(0.01, 0.05),
                     diameter_std=(0, 0.1),
                     min_diameter=0.1,
                     seeding_mode='random',
                     dtype=np.float32,
                     random_seed=100)

# Access particle coordinates on the first image:
(height_coordinates, width_coordinates) = particles.particle_coordinates[0]

Alternatively, all particle properties can also be made fixed across all \(N\) image pairs by passing integers or floats instead of tuples:

# Initialize a particle object:
particles = Particle(n_images=n_images,
                     size=image_size,
                     size_buffer=10,
                     diameters=2,
                     distances=1,
                     densities=0.1,
                     diameter_std=0.1,
                     min_diameter=0.1,
                     seeding_mode='random',
                     dtype=np.float32,
                     random_seed=100)
../_images/Particle-setting-spectrum.png
Parameters:
  • n_imagesint specifying the number of image pairs, \(N\), to create.

  • size – (optional) tuple of two int elements specifying the size of images in pixels \([\text{px}]\). The first number is the image height, \(H\), the second number is the image width, \(W\).

  • size_buffer – (optional) int specifying the buffer, \(b\), in pixels \([\text{px}]\) to add to the image size in the width and height direction. This number should be approximately equal to the maximum displacement that particles are subject to in order to allow new particles to arrive into the image area and prevent spurious disappearance of particles near image boundaries.

  • diameters – (optional) tuple of two numerical elements specifying the minimum (first element) and maximum (second element) particle diameter in pixels \([\text{px}]\) to randomly sample from across all generated image pairs. Note, that one image pair will be associated with one (fixed) particle diameter, but the random sample between minimum and maximum diameter will generate variation in diameters across \(N\) image pairs. It can also be set to int or float to generate a fixed diameter value across all \(N\) image pairs. You can steer the deviation from that diameter within each single image pair using the diameter_std parameter.

  • distances – (optional) tuple of two numerical elements specifying the minimum (first element) and maximum (second element) particle distances in pixels \([\text{px}]\) to randomly sample from. Only used when seeding_mode is 'poisson'. It can also be set to int or float to generate fixed distances across all \(N\) image pairs.

  • densities – (optional) tuple of two numerical elements specifying the minimum (first element) and maximum (second element) particle seeding density on an image in particle per pixel \([\text{ppp}]\) to randomly sample from. Only used when seeding_mode is 'random'. It can also be set to int or float to generate a fixed densities value across all \(N\) image pairs.

  • diameter_std – (optional) tuple of two numerical elements specifying the minimum (first element) and maximum (second element) standard deviation in pixels \([\text{px}]\) for the distribution of particle diameters within each image pair. If set to zero, all particles in an image pair will have diameters exactly equal. If the choice of the diameter_std causes any diameters to be negative, the diameters will be clipped such that the minimum diameter is min_diameter. It can also be set to int or float to generate a fixed standard deviation value across all \(N\) image pairs.

  • min_diameter – (optional) float or int specifying the minimum particle diameter that will be used if the standard deviation (diameter_std) causes any diameters to be negative.

  • seeding_mode

    (optional) str specifying the seeding mode for initializing particles in the image domain. It can be one of the following: 'random', 'poisson', or 'user'.

    • 'random' seeding generates random locations of particles on the available image area.

    • 'poisson' seeding is also random, but makes sure that particles are kept at minimum distances from one another. This is particularly useful when generating BOS images.

    • 'user' seeding allows for particle coordinates to be provided by the user. This provides an interesting functionality where the user can chain movement of particles and create time-resolved sequence of images.

  • dtype – (optional) numpy.dtype specifying the data type for particle coordinates. To reduce memory, you can switch from the default numpy.float64 to numpy.float32.

  • random_seed – (optional) int specifying the random seed for random number generation in numpy. If specified, all operations are reproducible.

Attributes:

  • n_images - (read-only) as per user input.

  • size - (read-only) as per user input.

  • size_buffer - (read-only) as per user input.

  • diameters - (read-only) as per user input.

  • distances - (read-only) as per user input.

  • densities - (read-only) as per user input.

  • diameter_std - (read-only) as per user input.

  • min_diameter - (read-only) as per user input.

  • seeding_mode - (read-only) as per user input.

  • dtype - (read-only) as per user input.

  • random_seed - (read-only) as per user input.

  • size_with_buffer - (read-only) tuple specifying the size of each image in pixels with buffer added.

  • diameter_per_image - (read-only) numpy.ndarray specifying the template for the particle diameters in pixels \([\text{px}]\) for each image. Template diameters are random numbers between diameters[0] and diameters[1].

  • distance_per_image - (read-only) numpy.ndarray specifying the template for the particle distances in pixels \([\text{px}]\) for each image. Template distances are random numbers between distances[0] and distances[1].

  • density_per_image - (read-only) numpy.ndarray specifying the template for the particle densities in particle per pixel \([\text{ppp}]\) for each image. Template densities are random numbers between densities[0] and densities[1].

  • n_of_particles - (read-only) list specifying the number of particles created for each image, \(n_i\), based on each template density.

  • particle_coordinates - (read-only) list of tuple of two numpy.ndarray specifying the absolute coordinates of all particle centers for each image. The positions are computed based on the seeding_mode. Each tuple refers to one PIV image pair. The first element in each tuple are the coordinates along the image height, and the second element are the coordinates along the image width.

  • particle_positions - (read-only) numpy.ndarray specifying the per-pixel starting positions of all particles’ centers for each image pair; these positions will later populate the first image frame, \(I_1\). The positions are computed based on the seeding_mode. If a particle’s position falls into a specific pixel coordinate, this pixel’s value is increased by one. Zero entry indicates that no particles are present inside that pixel. This array has size \((N, C_{in}, H+2b, W+2b)\), where \(N\) is the number of image pairs, \(C_{in}\) is the number of channels (one channel, greyscale, is supported at the moment), \(H\) is the height and \(W\) the width of each image, and \(b\) is an optional image buffer. This array has type numpy.int16.

  • particle_diameters - (read-only) list of numpy.ndarray, each specifying the diameters of all seeded particles in pixels \([\text{px}]\) for each image based on each template diameter. Each array in this list has length \(n_i\).

pykitPIV.particle.Particle.upload_particle_coordinates(self, particle_coordinates)

Uploads user-specified starting particle coordinates.

Note

Note that only the \(x\) and \(y\) coordinates get uploaded to the current Particle class object and particle diameters (Particle.particle_diameters) get computed for the user-specified particles from the class attribute diameters that was given during Particle class object generation.

The number of particles per image (Particle.n_of_particles) is computed directly from the user-specified particle_coordinates argument, so is Particle.particle_positions.

Example:

from pykitPIV import Particle

# We are going to generate 10 PIV image pairs:
n_images = 10

# Specify size in pixels for each image:
image_size = (128, 512)

# Initialize the first particle object:
particles_1 = Particle(n_images,
                       size=image_size,
                       diameters=(2, 4),
                       diameter_std=(0, 1),
                       densities=(0.1, 0.1),
                       seeding_mode='random')

# Initialize the second particle object:
particles_2 = Particle(n_images,
                       size=image_size,
                       densities=(0.1, 0.1),
                       seeding_mode='random')

# Overwrite the coordinates in the first particle object with the second one:
particles_1.upload_particle_coordinates(particles_2.particle_coordinates)

Alternatively, you can instantiate an object of the Particle class with the seeding_mode='user', which will initially make all the particle parameters empty. Those parameters get populated the moment you call the upload_particle_coordinates() function.

# Initialize the first particle object:
particles_1 = Particle(n_images,
                       size=image_size,
                       diameters=(2, 4),
                       diameter_std=(0, 1),
                       seeding_mode='user')

# Initially, all of these attributes will be None:
particles_1.particle_coordinates
particles_1.particle_positions
particles_1.particle_diameters
particles_1.n_of_particles

# Initialize the second particle object:
particles_2 = Particle(n_images,
                       size=image_size,
                       densities=(0.1, 0.1),
                       seeding_mode='random')

# Overwrite the coordinates in the first particle object with the second one:
particles_1.upload_particle_coordinates(particles_2.particle_coordinates)
Parameters:

particle_coordinateslist of tuple specifying the coordinates of particles in image \(I_1\). The first element in each tuple are the coordinates along the image height, and the second element are the coordinates along the image width. It can be obtained directly from an object of the Motion class by accessing the attribute Motion.particle_coordinates_I1. This allows to have starting particle coordinates with a more irregular pattern.

pykitPIV.particle.Particle.plot_properties(self, idx=None, c_hist='k', c_scatter='b', s=4, figsize=(5, 5), dpi=300, filename=None)

Plots statistical properties of the generated particles across all n_images images or a subset of those.

Example:

from pykitPIV import Particle

# We are going to generate 100 PIV image pairs:
n_images = 100

# Initialize a particle object:
particles = Particle(n_images,
                     size=(200, 200),
                     size_buffer=10,
                     diameters=(1, 4),
                     distances=(1, 2),
                     densities=(0.05, 0.1),
                     diameter_std=(0, 0.1),
                     seeding_mode='random',
                     random_seed=100)

# Visualize properties on images indexed from 0 to 40:
particles.plot_properties(idx=(0, 40),
                          c_hist='k',
                          c_scatter='b',
                          s=30,
                          figsize=(15, 10),
                          dpi=300,
                          filename='Particle_plot_properties.png')

The code above will produce a figure like below:

../_images/Particle_plot_properties.png
Parameters:
  • idx – (optional) tuple or int specifying the slice or the index of images whose properties to plot. If set to None, properties of all n_images will be plotted.

  • c_hist – (optional) str specifying the color of the histogram bars.

  • c_scatter – (optional) str specifying the color of the scatter plots.

  • s – (optional) int or float specifying the size of scatter points

  • figsize – (optional) tuple of two numerical elements specifying the figure size as per matplotlib.pyplot.

  • dpi – (optional) int specifying the dpi for the image.

  • filename – (optional) str specifying the path and filename to save an image. If set to None, the image will not be saved.

Returns:

  • plt - matplotlib.pyplot image handle.