Analysis Methods#
Core measurements#
Density#
Module containing functions to compute densities.
- compute_classic_density(*, traj_data, measurement_area)#
Compute the classic density per frame inside the given measurement area.
The classic density \(\rho_{classic}(t)\) is the number of pedestrians inside the given measurement area \(M\) at the time \(t\), divided by the area of that space \(A(M)\):
\[\rho_{classic} = {N \over A(M)},\]where \(N\) is the number of pedestrians inside the measurement area \(M\).
- Parameters:
traj_data (TrajectoryData) – trajectory data to analyze
measurement_area (MeasurementArea) – area for which the density is computed
- Returns:
DataFrame containing the columns ‘frame’ and ‘density’ in \(1/m^2\)
- Return type:
- compute_passing_density(*, density_per_frame, frames)#
Compute the individual density of the pedestrian who pass the area.
The passing density for each pedestrian \(\rho_{passing}(i)\) is the average number of pedestrian who are in the same measurement area \(M\) in the same time interval (\([t_{in}(i), t_{out}(i)]\)) as the pedestrian \(i\) divided by the area of that measurement area \(A(M)\).
Then the computation becomes:
\[\rho_{passing}(i) = {1 \over {t_{out}(i)-t_{in}(i)}} \int^{t_{out}(i)}_{t_{in}(i)} {{N(t)} \over A(M)} dt,\]where \(t_{in}(i) = f_{in}(i) / fps\) is the time the pedestrian crossed the first line and \(t_{out}(i) = f_{out}(i) / fps\) when they crossed the second line, where \(f_{in}\) and \(f_{out}\) are the frames where the pedestrian crossed the first line, and the second line respectively. And \(fps\) is the
frame_rate
of the trajectory data.- Parameters:
density_per_frame (pd.DataFrame) – density per frame, result from
compute_classic_density()
frames (pd.DataFrame) – information for each pedestrian in the area, result from
compute_frame_range_in_area()
- Returns:
DataFrame containing the columns ‘id’ and ‘density’ in \(1/m^2\)
- Return type:
- compute_voronoi_density(*, individual_voronoi_data, measurement_area)#
Compute the Voronoi density per frame inside the given measurement area.
The Voronoi density \(\rho_{voronoi}(t)\) is computed based on the individual Voronoi polygons \(V_i(t)\) from
compute_individual_voronoi_polygons()
. Pedestrians whose Voronoi polygon have an intersection with the measurement area are taken into account.The Voronoi density \(\rho_{voronoi}(t)\) is defined as
\[\rho_{voronoi}(t) = { \int\int \rho_{xy}(t) dxdy \over A(M)},\]where \(\rho_{xy}(t) = 1 / A(V_i(t))\) is the individual density of each pedestrian, whose \(V_i(t) \cap M\) and \(A(M)\) the area of the measurement area.
- Parameters:
individual_voronoi_data (pd.DataFrame) – individual voronoi data per frame, result from
method_utils.compute_individual_voronoi_polygon()
measurement_area (MeasurementArea) – area for which the density is computed
- Returns:
DataFrame containing the columns ‘id’ and ‘density’ in \(1/m^2\), DataFrame containing the columns: ‘id’, ‘frame’, ‘polygon’ which contains the Voronoi polygon of the pedestrian, ‘intersection’ which contains the intersection area of the Voronoi polygon and the given measurement area.
- Return type:
Tuple[pandas.DataFrame, pandas.DataFrame]
Speed#
Module containing functions to compute velocities.
- exception SpeedError(message)#
Class reflecting errors when computing speeds with PedPy.
Create SpeedError with the given message.
- Parameters:
message – Error message
- compute_individual_speed(*, traj_data, frame_step, movement_direction=None, compute_velocity=False, speed_calculation=SpeedCalculation.BORDER_EXCLUDE)#
Compute the individual speed for each pedestrian.
For computing the individuals speed at a specific frame \(v_i(t)\), a specific frame step (\(n\)) is needed. Together with the
frame_rate
of the trajectory data \(fps\) the time frame \(\Delta t\) for computing the speed becomes:\[\Delta t = 2 n / fps.\]This time step describes how many frames before and after the current position \(X_{current}\) are used to compute the movement. These positions are called \(X_{future}\), \(X_{past}\) respectively.
First computing the displacement between these positions \(\bar{X}\). This then can be used to compute the speed with:
\[\bar{X} = X_{future} - X_{past}.\]When getting closer to the start, or end of the trajectory data, it is not possible to use the full range of the frame interval for computing the speed. For these cases PedPy offers three different methods to compute the speed:
exclude these parts.
adaptively shrink the window in which the speed is computed.
switch to one-sided window.
Exclude border:
When not enough frames available to compute the speed at the borders, for these parts no speed can be computed and they are ignored. Use
speed_calculation=SpeedCalculation.BORDER_EXCLUDE
.Adaptive border window:
In the adaptive approach, it is checked how many frames \(n\) are available to from \(X_{current}\) to the end of the trajectory. This number is then used on both sides to create a smaller symmetric window, which yields \(X_{past}\) and \(X_{future}\). Now with the same principles as before the individual speed \(v_i(t)\) can be computed.
Use
speed_calculation=SpeedCalculation.BORDER_ADAPTIVE
.Important
As the time interval gets smaller to the ends of the individual trajectories, the oscillations in the speed increase here.
Single sided border window:
In these cases, one of the end points to compute the movement becomes the current position \(X_{current}\). When getting too close to the start of the trajectory, the movement is computed from \(X_{current}\) to \(X_{future}\). In the other case the movement is from \(X_{past}\) to \(X_{current}\).
\[v_i(t) = {|{X_{future} - X_{current}|}\over{ \frac{1}{2} \Delta t}}, \text{, or } v_i(t) = {|{X_{current} - X_{past}|}\over{ \frac{1}{2} \Delta t}}.\]Use
speed_calculation=SpeedCalculation.BORDER_SINGLE_SIDED
.Important
As at the edges of the trajectories the time interval gets halved, there may occur some jumps computed speeds at this point.
With movement direction:
It is also possible to compute the individual speed in a specific direction \(d\), for this the movement \(\bar{X}\) is projected onto the desired movement direction. \(\bar{X}\) and \(\Delta t\) are computed as described above. Hence, the speed then becomes:
\[v_i(t) = {{|\boldsymbol{proj}_d\; \bar{X}|} \over {\Delta t}}.\]Important
Using a movement direction may lead to negative speeds!
If
compute_velocity
is True also \(\bar{X}\) is returned.- Parameters:
traj_data (TrajectoryData) – trajectory data
frame_step (int) – gives the size of time interval for calculating the velocity.
movement_direction (np.ndarray) – main movement direction on which the actual movement is projected (default: None, when the un-projected movement should be used)
compute_velocity (bool) – compute the x and y components of the velocity
speed_calculation (method_utils.SpeedCalculation) – method used to compute the speed at the borders of the individual trajectories
- Returns:
DataFrame containing the columns ‘id’, ‘frame’, and ‘speed’ in m/s, ‘v_x’ and ‘v_y’ with the speed components in x and y direction if
compute_velocity
is True- Return type:
- compute_mean_speed_per_frame(*, traj_data, individual_speed, measurement_area)#
Compute mean speed per frame inside a given measurement area.
Computes the mean speed \(v_{mean}(t)\) inside the measurement area from the given individual speed data \(v_i(t)\) (see
compute_individual_speed()
for details of the computation). The mean speed \(v_{mean}\) is defined as\[v_{mean}(t) = {{1} \over {N}} \sum_{i \in P_M} v_i(t),\]where \(P_M\) are all pedestrians inside the measurement area, and \(N\) the number of pedestrians inside the measurement area ( \(|P_M|\)).
- Parameters:
traj_data (TrajectoryData) – trajectory data
individual_speed (pandas.DataFrame) – individual speed data from
compute_individual_speed()
measurement_area (MeasurementArea) – measurement area for which the speed is computed
- Returns:
DataFrame containing the columns ‘frame’ and ‘speed’ in m/s
- Return type:
Tuple[pandas.DataFrame, pandas.DataFrame]
- compute_passing_speed(*, frames_in_area, frame_rate, distance)#
Compute the individual speed of the pedestrian who pass the area.
Compute the individual speed \(v^i_{passing}\) at which the pedestrian traveled the given distance \(d\), which is defined as:
\[v^i_{passing} = {{d} \over{ \Delta t}},\]where \(\Delta t = (f_{out} - f_{in}) / fps\) is the time the pedestrian needed to cross the area, where \(f_{in}\) and \(f_{out}\) are the frames where the pedestrian crossed the first line, and the second line respectively. For details on the computation of the crossing frames, see
compute_frame_range_in_area()
. And \(fps\) is theframe_rate
of the trajectory data.- Parameters:
frames_in_area (pandas.DataFrame) – information for each pedestrian when they were in the area, result from
compute_frame_range_in_area()
frame_rate (float) – frame rate of the trajectory
distance (float) – distance between the two measurement lines
- Returns:
DataFrame containing the columns ‘id’ and ‘speed’ in m/s
- Return type:
- compute_voronoi_speed(*, traj_data, individual_speed, individual_voronoi_intersection, measurement_area)#
Compute the Voronoi speed per frame inside the measurement area.
Computes the Voronoi speed \(v_{voronoi}(t)\) inside the measurement area \(M\) from the given individual speed data \(v_i(t)\) (see
compute_individual_speed()
for details of the computation) and their individual Voronoi intersection data (fromcompute_voronoi_density()
). The individuals speed are weighted by the proportion of their Voronoi cell \(V_i\) and the intersection with the measurement area \(V_i \cap M\).The Voronoi speed \(v_{voronoi}(t)\) is defined as
\[v_{voronoi}(t) = { \int\int v_{xy}(t) dxdy \over A(M)},\]where \(v_{xy}(t) = v_i(t)\) is the individual speed of each pedestrian, whose \(V_i(t) \cap M\) and \(A(M)\) the area of the measurement area.
- Parameters:
traj_data (TrajectoryData) – trajectory data
individual_speed (pandas.DataFrame) – individual speed data from
compute_individual_speed()
individual_voronoi_intersection (pandas.DataFrame) – intersections of the individual with the measurement area of each pedestrian from
compute_intersecting_polygons()
measurement_area (MeasurementArea) – area in which the voronoi speed should be computed
- Returns:
DataFrame containing the columns ‘frame’ and ‘speed’ in m/s
- Return type:
Flow#
Module containing functions to compute flows.
- compute_flow(*, nt, crossing_frames, individual_speed, delta_frame, frame_rate)#
Compute the flow for the given the frame window from the nt information.
Computes the flow \(J\) in a frame interval of length
delta_frame
(\(\Delta frame\)). The first intervals starts, when the first person crossed the measurement, given bycrossing_frames
. The next interval always starts at the time when the last person in the previous frame interval crossed the line.In each of the time interval it is checked, if any person has crossed the line, if yes, a flow $J$ can be computed. From the first frame the line was crossed \(f^{\Delta frame}_1\), the last frame someone crossed the line \(f^{\Delta frame}_N\) the length of the frame interval \(\Delta f$\) can be computed:
\[\Delta f = f^{\Delta frame}_N - f^{\Delta frame}_1\]This directly together with the frame rate with
frame_rate
($fps$) gives the time interval $Delta t$:\[\Delta t = \Delta f / fps\]Given the number of pedestrian crossing the line is given by \(N^{\Delta frame}\), the flow \(J\) becomes:
\[J = \frac{N^{\Delta frame}}{\Delta t}\]At the same time also the mean speed of the pedestrian when crossing the line is computed from
individual_speed
.\[v_{crossing} = {1 \over N^{\Delta t} } \sum^{N^{\Delta t}}_{i=1} v_i(t)\]- Parameters:
nt (pd.DataFrame) – DataFrame containing the columns ‘frame’, ‘cumulative_pedestrians’, and ‘time’ (see result from
compute_n_t()
)crossing_frames (pd.DataFrame) – DataFrame containing the columns ‘ID’, and ‘frame’ (see result from
compute_n_t()
)individual_speed (pd.DataFrame) – DataFrame containing the columns ‘ID’, ‘frame’, and ‘speed’
delta_frame (int) – size of the frame interval to compute the flow
frame_rate (float) – frame rate of the trajectories
- Returns:
DataFrame containing the columns ‘flow’ in 1/s, and ‘mean_speed’ in m/s.
- Return type:
- compute_n_t(*, traj_data, measurement_line)#
Compute the frame-wise cumulative number of pedestrians passing the line.
Records the frames, when a pedestrian crossed the given measurement line. A frame counts as crossed when the movement is across the line, but does not end on it. Then the next frame when the movement starts on the line is counted as crossing frame.
Warning
For each pedestrian only the first passing of the line is considered!
- Parameters:
traj_data (TrajectoryData) – trajectory data
measurement_line (MeasurementLine) – line for which n-t is computed
- Returns:
DataFrame containing the columns ‘frame’, ‘cumulative_pedestrians’, and ‘time’ since frame 0, and DataFrame containing the columns ‘ID’, and ‘frame’ which gives the frame the pedestrian crossed the measurement line.
- Return type:
Tuple[pandas.DataFrame, pandas.DataFrame]
Acceleration#
Module containing functions to compute accelerations.
- exception AccelerationError(message)#
Class reflecting errors when computing accelerations with PedPy.
Create AccelerationError with the given message.
- Parameters:
message – Error message
- compute_individual_acceleration(*, traj_data, frame_step, movement_direction=None, compute_acceleration_components=False, acceleration_calculation=AccelerationCalculation.BORDER_EXCLUDE)#
Compute the individual acceleration for each pedestrian.
For computing the individuals’ acceleration at a specific frame \(a_i(t_k)\), a specific frame step (\(n\)) is needed. Together with the
frame_rate
of the trajectory data \(fps\) the time frame \(\Delta t\) for computing the speed becomes:\[\Delta t = 2 n / fps\]This time step describes how many frames before and after the current position \(X(t_k)\) are used to compute the movement. These positions are called \(X(t_{k+n})\), \(X(t_{k-n})\) respectively.
In order to compute the acceleration at time ‘t_k’, we first calculate the displacements \(\bar{X}\) around ‘t_{k+n}’ and ‘t_{k-n}’:
\[\bar{X}(t_{k+n}) = X(t_{k+2n}) - X(t_{k})\]\[\bar{X}(t_{k-n}) = X(t_{k}) - X(t_{k-2n})\]The acceleration is then calculated from the difference of the displacements
\[\Delta\bar{X}(t_k) = \bar{X}(t_{k+n}) - \bar{X}(t_{k-n})\]divided by the square of the time interval ‘Delta t’:
\[a_i(t_k) = \Delta\bar{X}(t_k) / \Delta t^{2}\]When getting closer to the start, or end of the trajectory data, it is not possible to use the full range of the frame interval for computing the acceleration. For these cases PedPy offers a method to compute the acceleration:
Exclude border:
When not enough frames available to compute the speed at the borders, for these parts no acceleration can be computed and they are ignored. Use
acceleration_calculation=AccelerationCalculation.BORDER_EXCLUDE
.With movement direction:
It is also possible to compute the individual acceleration in a specific direction \(d\), for this the movement \(\Delta\bar{X}\) is projected onto the desired movement direction. \(\Delta\bar{X}\) and \(\Delta t\) are computed as described above. Hence, the acceleration then becomes:
\[a_i(t) = {{|\boldsymbol{proj}_d\; \Delta\bar{X}|} \over {\Delta t^{2}}}\]If
compute_acceleration_components
is True also \(\Delta\bar{X}\) is returned.- Parameters:
traj_data (TrajectoryData) – trajectory data
frame_step (int) – gives the size of time interval for calculating the acceleration.
movement_direction (np.ndarray) – main movement direction on which the actual movement is projected (default: None, when the un-projected movement should be used)
compute_acceleration_components (bool) – compute the x and y components of the acceleration
acceleration_calculation (method_utils.AccelerationCalculation) – method used to compute the acceleration at the borders of the individual trajectories
- Returns:
DataFrame containing the columns ‘id’, ‘frame’, and ‘acceleration’ in ‘m/s^2’, ‘a_x’ and ‘a_y’ with the speed components in x and y direction if
compute_acceleration_components
is True- Return type:
- compute_mean_acceleration_per_frame(*, traj_data, individual_acceleration, measurement_area)#
Compute mean acceleration per frame inside a given measurement area.
Computes the mean acceleration \(a_{mean}(t)\) inside the measurement area from the given individual acceleration data \(a_i(t)\) (see
compute_individual_acceleration()
for details of the computation). The mean acceleration \(a_{mean}\) is defined as\[a_{mean}(t) = {{1} \over {N}} \sum_{i \in P_M} a_i(t),\]where \(P_M\) are all pedestrians inside the measurement area, and \(N\) the number of pedestrians inside the measurement area ( \(|P_M|\)).
- Parameters:
traj_data (TrajectoryData) – trajectory data
individual_acceleration (pandas.DataFrame) – individual acceleration data from
compute_individual_acceleration()
measurement_area (MeasurementArea) – measurement area for which the acceleration is computed
- Returns:
DataFrame containing the columns ‘frame’ and ‘acceleration’ in ‘m/s^2’
- Return type:
Tuple[pandas.DataFrame, pandas.DataFrame]
- compute_voronoi_acceleration(*, traj_data, individual_acceleration, individual_voronoi_intersection, measurement_area)#
Computes the Voronoi acceleration.
Computes the Voronoi acceleration \(a_{voronoi}(t)\) inside the measurement area \(M\) from the given individual acceleration data \(a_i(t)\) (see
compute_individual_acceleration()
for details of the computation) and their individual Voronoi intersection data (fromcompute_voronoi_density()
). The individuals’ accelerations are weighted by the proportion of their Voronoi cell \(V_i\) and the intersection with the measurement area \(V_i \cap M\).The Voronoi acceleration \(a_{voronoi}(t)\) is defined as
\[a_{voronoi}(t) = { \int\int a_{xy}(t) dxdy \over A(M)},\]where \(a_{xy}(t) = a_i(t)\) is the individual acceleration of each pedestrian, whose \(V_i(t) \cap M\) and \(A(M)\) the area of the measurement area.
- Parameters:
traj_data (TrajectoryData) – trajectory data
individual_acceleration (pandas.DataFrame) – individual acceleration data from
compute_individual_acceleration()
individual_voronoi_intersection (pandas.DataFrame) – intersections of the individual with the measurement area of each pedestrian from
compute_intersecting_polygons()
measurement_area (MeasurementArea) – area in which the voronoi acceleration should be computed
- Returns:
DataFrame containing the columns ‘frame’ and ‘acceleration’ in ‘m/s^2’
- Return type:
Further measurements#
Spatial Analysis#
Module containing functions to compute spatial analysis methods.
For example: the pair distribution function.
- compute_pair_distribution_function(*, traj_data, radius_bin_size, randomisation_stacking=1)#
Computes the pair distribution function g(r).
This function calculates the spatial distribution of positions \(g(r)\) \(g(r)\) here referred to the Euclidean distance between interacting pedestrians, i.e., pedestrians that are in the same walkable area at the same moment. The pdf is given by the probability that two pedestrians are separated by \(r\) normalized by the probability \(PNI(r)\) that two non-interacting pedestrians are separated by \(r\), specifically
\[g(r) = P(r)/PNI(r),\]- Parameters:
traj_data (pedpy.data.trajectory_data.TrajectoryData) – TrajectoryData, an object containing the trajectories.
radius_bin_size (float) – float, the size of the bins for the radial distribution function in the same units as the positions.
randomisation_stacking (int) – int, Number of time the dataset will be stacked before being randomly shuffled to exact distances of non-interacting pedestrians. Larger stacking number will lead to closer approximation of true pairwise distribution of non- interacting pedestrians but with also increase computation cost.
- Returns:
- A tuple of two numpy arrays. The first
array contains the bin edges (excluding the first bin edge), and the second array contains the values of the pair-distribution function \(g(r)\) for each bin.
- Return type:
Tuple[np.ndarray, np.ndarray]
Motion profiles#
Module containing functions to compute profiles.
For the computation of the profiles the given WalkableArea
is divided into square grid cells.
Each of these grid cells is then used as a MeasurementArea
in which the mean speed and density can be computed with different methods.
- class DensityMethod(*args, **kwds)#
Method used to compute the density profile.
- CLASSIC#
Classic density profile.
In each cell the density \(\rho_{classic}\) is defined by
\[\rho_{classic} = {N \over A(M)},\]where \(N\) is the number of pedestrians inside the grid cell \(M\) and the area of that grid cell (\(A(M)\)).
- GAUSSIAN#
Gaussian density profile.
In each cell the density \(\rho_{gaussian}\) is defined by
\[\rho_{gaussian} = \sum_{i=1}^{N}{\delta (\boldsymbol{r}_i - \boldsymbol{c})},\]where \(\boldsymbol{r}_i\) is the position of a pedestrian and \(\boldsymbol{c}\) is the center of the grid cell. Finally \(\delta(x)\) is approximated by a Gaussian
\[\delta(x) = \frac{1}{\sigma\sqrt{2\pi}}\exp[-x^2/2\sigma^2],\]where \(\sigma\) is the standard deviation.
- VORONOI#
Voronoi density profile.
In each cell the density \(\rho_{voronoi}\) is defined by
\[\rho_{voronoi} = { \int\int \rho_{xy} dxdy \over A(M)},\]where \(\rho_{xy} = 1 / A(V_i)\) is the individual density of each pedestrian, with the individual Voronoi polygons \(V_i\) where \(V_i \cap M\) and \(A(M)\) the area of the grid cell.
- class SpeedMethod(*args, **kwds)#
Method used to compute the speed profile.
- ARITHMETIC#
Compute arithmetic Voronoi speed profile.
In each cell \(M\) the arithmetic Voronoi speed \(v_{arithmetic}\) is defined as
\[v_{arithmetic} = \frac{1}{N} \sum_{i \in P_M} v_i,\]where \(P_M\) are the pedestrians, whose Voronoi cell \(V_i\) intersects with the grid cell \(M\) (\(V_i \cap M\)). Then \(N\) is the number of pedestrians in \(P_M\) (\(|P_M|\)).
- GAUSSIAN#
Compute Gaussian speed profile.
In each cell the weighted speed \(v_{c}\) is calculated as
\[v_{c} = \frac{\sum_{i=1}^{N}{\big(w_i\cdot v_i\big)}} {\sum_{i=1}^{N} w_i},\]where \(v_i\) is the speed of a pedestrian and \(w_i\) are weights depending on the pedestrian’s distance \(\delta\) from its position (\(\boldsymbol{r}_i\)) to the center of the grid (\(\boldsymbol{c}\)) cell:
\[\delta = \boldsymbol{r}_i - \boldsymbol{c}.\]The weights \(w_i\) are calculated by a Gaussian as follows:
\[w_i = \frac{1} {\sigma \cdot \sqrt{2\pi}} \exp\big(-\frac{\delta^2}{2\sigma^2}\big),\]where \(\sigma\) is derived from FWHM as:
\[\sigma = \frac{FWHM}{2\sqrt{2\ln(2)}}.\]
- MEAN#
Compute mean speed profile.
In each cell \(M\) the mean speed \(v_{mean}\) is defined as
\[v_{mean} = \frac{1}{N} \sum_{i \in P_M} v_i,\]where \(P_M\) are the pedestrians inside the grid cell. Then \(N\) is the number of pedestrians inside \(P_M\) (\(|P_M|\)).
- VORONOI#
Compute Voronoi speed profile.
In each cell \(M\) the Voronoi speed \(v_{voronoi}\) is defined as
\[v_{voronoi} = { \int\int v_{xy} dxdy \over A(M)},\]where \(v_{xy} = v_i\) is the individual speed of each pedestrian, whose \(V_i \cap M\) and \(A(M)\) the area the grid cell.
- compute_density_profile(*, data, walkable_area, grid_size, density_method, grid_intersections_area=None, gaussian_width=None)#
Compute the density profile.
- Parameters:
data (pandas.DataFrame) – Data from which the profiles are computes. The DataFrame must contain a frame column. It must contain a polygon column (from
compute_individual_voronoi_polygons()
) when using theDensityMethod.VORONOI
. When computing the classic density profile (DensityMethod.CLASSIC
) or Gaussian density profile (DensityMethod.GAUSSIAN
) the DataFrame needs to contain the columns ‘x’ and ‘y’. For getting a DataFrame containing all the needed data, you can merge the results of the different function on the ‘id’ and ‘frame’ columns (seepandas.DataFrame.merge()
andpandas.merge()
).walkable_area (WalkableArea) – geometry for which the profiles are computed
grid_size (float) – resolution of the grid used for computing the profiles
density_method (DensityMethod) – density method to compute the density profile
grid_intersections_area (Optional[numpy.typing.NDArray[numpy.float64]]) – intersection of grid cells with the Voronoi polygons (result from
compute_grid_cell_polygon_intersection_area()
)gaussian_width (Optional[float]) – full width at half maximum for Gaussian approximation of the density, only needed when using
DensityMethod.GAUSSIAN
.
- Returns:
List of density profiles
- Return type:
List[numpy.typing.NDArray[numpy.float64]]
- compute_grid_cell_polygon_intersection_area(*, data, grid_cells)#
Computes the intersection area of the grid with the Voronoi polygons.
Note
As this is a quite compute heavy operation, it is suggested to reduce limit the
data
to the most relevant frame interval.Note
If computing the speed/density profiles multiple times, e.g., with different methods it is of advantage to compute the grid cell polygon intersections before and then pass the result to the other functions.
Important
When passing the grid cell-polygon intersection, make sure to also pass the returned DataFrame as data, as it has the same ordering of rows as used for the grid cell-polygon intersection. Changing the order afterward will return wrong results!
- Parameters:
data (pandas.DataFrame) – DataFrame containing at least the columns ‘frame’ and ‘polygon’ (which should hold the result from
compute_individual_voronoi_polygons()
)grid_cells (numpy.typing.NDArray[shapely.Polygon]) – Grid cells used for computing the profiles, e.g., result from
get_grid_cells()
- Returns:
- Tuple containing first the grid cell-polygon intersection areas, and
second the reordered data by ‘frame’, which needs to be used in the next steps.
- Return type:
Tuple[numpy.typing.NDArray[numpy.float64], pandas.DataFrame]
- compute_profiles(*, data=None, walkable_area, grid_size, speed_method, density_method=DensityMethod.VORONOI, gaussian_width=None, **kwargs)#
Computes the density and speed profiles.
Note
As this is a quite compute heavy operation, it is suggested to reduce the geometry to the important areas and limit the
data
to the most relevant frame interval.- Parameters:
data (pandas.DataFrame) – Data from which the profiles are computes. The DataFrame must contain a frame and a speed (result from
compute_individual_speed()
) column. For computing density profiles, it must contain a polygon column (fromcompute_individual_voronoi_polygons()
) when using the DensityMethod.VORONOI. When computing the classic density profile (DensityMethod.CLASSIC) the DataFrame needs to contain the columns ‘x’ and ‘y’. Computing the speed profiles needs a polygon column (fromcompute_individual_voronoi_polygons()
) when using theSpeedMethod.VORONOI
orSpeedMethod.ARITHMETIC
. For getting a DataFrame containing all the needed data, you can merge the results of the different function on the ‘id’ and ‘frame’ columns (seepandas.DataFrame.merge()
andpandas.merge()
).walkable_area (WalkableArea) – geometry for which the profiles are computed
grid_size (float) – resolution of the grid used for computing the profiles
speed_method (SpeedMethod) – speed method used to compute the speed profile
density_method (DensityMethod) – density method to compute the density profile (default:
DensityMethod.VORONOI
)gaussian_width (Optional[float]) – full width at half maximum for Gaussian approximation of the density, only needed when using
DensityMethod.GAUSSIAN
.individual_voronoi_speed_data – deprecated alias for
data
. Please usedata
in the future.kwargs (Any) –
- Returns:
List of density profiles, List of speed profiles
- Return type:
Tuple[List[numpy.typing.NDArray[numpy.float64]], List[numpy.typing.NDArray[numpy.float64]]]
- compute_speed_profile(*, data, walkable_area, grid_size, speed_method, grid_intersections_area=None, fill_value=np.nan, gaussian_width=0.5)#
Computes the speed profile for pedestrians within an area.
This function calculates speed profiles based on pedestrian speed data across a grid within a walkable area. The method of computation can be selected among several options, including mean (
SpeedMethod.MEAN
), Gaussian (SpeedMethod.GAUSSIAN
), Voronoi (SpeedMethod.VORONOI
), and arithmetic mean methods (SpeedMethod.ARITHMETIC
), each suitable for different analysis contexts.- Parameters:
data (pandas.DataFrame) – A pandas DataFrame containing frame and pedestrian speed (result from
compute_individual_speed()
). Depending on speed_method, additional columns x, y, or polygon might be required. polygon column (fromcompute_individual_voronoi_polygons()
) is required when using theSpeedMethod.VORONOI
orSpeedMethod.ARITHMETIC
. When computing the Gaussian profile (SpeedMethod.GAUSSIAN
) the DataFrame needs to contain the columns x and y. For getting a DataFrame containing all the needed data, you can merge the results of the different function on the id and frame columns (seepandas.DataFrame.merge()
andpandas.merge()
).walkable_area (WalkableArea) – geometry for which the speed profiles are computed.
grid_size (float) – The resolution of the grid used for computing the profiles, expressed in the same units as the walkable_area.
speed_method (SpeedMethod) – The speed method used to compute the speed profile
grid_intersections_area (Optional[numpy.typing.NDArray[numpy.float64]]) – (Optional) intersection areas of grid cells with Voronoi polygons (result from
compute_grid_cell_polygon_intersection_area()
)fill_value (float) – fill value for cells with no pedestrians inside when using
SpeedMethod.MEAN
(default = np.nan)gaussian_width (float) – (Optional) The full width at half maximum (FWHM) for Gaussian weights, required when using
SpeedMethod.GAUSSIAN
(default = 0.5).
- Returns:
A list of NumPy arrays, each representing the speed profile per frame.
- Return type:
List[numpy.typing.NDArray[numpy.float64]]
Note
The choice of speed_method significantly impacts the required data format and the interpretation of results. Refer to the documentation of
SpeedMethod
for details on each method’s requirements and use cases.
- get_grid_cells(*, walkable_area, grid_size)#
Creates a list of square grid cells covering the geometry.
- Parameters:
walkable_area (WalkableArea) – geometry for which the profiles are computed.
grid_size (float) – resolution of the grid used for computing the profiles.
- Returns:
(List of grid cells, number of grid rows, number of grid columns)
- Return type:
Tuple[numpy.typing.NDArray[shapely.Polygon], int, int]
Utilities#
Helper functions for the analysis methods.
- class AccelerationCalculation(*args, **kwds)#
Method-identifier used to compute the movement at traj borders.
- BORDER_EXCLUDE#
- class Cutoff#
Maximal extend of a Voronoi polygon.
The maximal extend is an approximated circle with the given radius and number of line segments used to approximate a quarter circle.
- quad_segments = 3#
- radius#
- class SpeedCalculation(*args, **kwds)#
Method-identifier used to compute the movement at traj borders.
- BORDER_ADAPTIVE#
- BORDER_EXCLUDE#
- BORDER_SINGLE_SIDED#
- compute_crossing_frames(*, traj_data, measurement_line)#
Compute the frames at the pedestrians pass the measurement line.
As crossing we define a movement that moves across the measurement line. When the movement ends on the line, the line is not crossed. When it starts on the line, it counts as crossed. A visual representation is shown below, where the movement goes from left to right and each dot indicates the position at one frame. Red highlights where the person has crossed the measurement line.
Note
Due to oscillations, it may happen that a pedestrian crosses the measurement line multiple times in a small-time interval.
- Parameters:
traj_data (pandas.DataFrame) – trajectory data
measurement_line (MeasurementLine) – measurement line which is crossed
- Returns:
DataFrame containing the columns ‘id’, ‘frame’, where ‘frame’ is the frame where the measurement line is crossed.
- Return type:
- compute_frame_range_in_area(*, traj_data, measurement_line, width)#
Compute the frame ranges for each pedestrian inside the measurement area.
The measurement area is virtually created by creating a second measurement line parallel to the given one offsetting by the given width. The area between these line is the used measurement area.
For each pedestrians now the frames when they enter and leave the virtual measurement area is computed. In this frame interval they have to be inside the measurement area continuously. They also need to enter and leave the measurement area via different measurement lines. If leaving the area between the two lines, crossing the same line twice they will be ignored. For a better understanding, see the image below, where red parts of the trajectories are the detected ones inside the area. These frame intervals will be returned.
Note
As passing we define the frame, the pedestrians enter the area and then move through the complete area without leaving it. Hence, doing a closed analysis of the movement area with several measuring ranges underestimates the actual movement time.
- Parameters:
traj_data (TrajectoryData) – trajectory data
measurement_line (MeasurementLine) – measurement line
width (float) – distance to the second measurement line
- Returns:
DataFrame containing the columns ‘id’, ‘entering_frame’ describing the frame the pedestrian crossed the first or second line, ‘leaving_frame’ describing the frame the pedestrian crossed the second or first line, and the created measurement area
- Return type:
Tuple[pandas.DataFrame, MeasurementArea]
- compute_individual_voronoi_polygons(*, traj_data, walkable_area, cut_off=None, use_blind_points=True)#
Compute the individual Voronoi polygon for each person and frame.
The Voronoi cell will be computed based on the Voronoi tesselation of the pedestrians position. The resulting polygons will then be intersected with the walkable area.
Warning
In case of non-convex walkable areas it might happen that Voronoi cell will be cut at unexpected places.
The computed Voronoi cells will stretch all the way to the boundaries of the walkable area. As seen below:
In cases with only a few pedestrians not close to each other or large walkable areas this might not be desired behavior as the size of the Voronoi polygon is directly related to the individual density. In this case the size of the Voronoi polygon can be restricted by a
Cutoff
, where you give a radius and the number of line segments used to approximate a quarter circle. The differences the number of line segments has on the circle can be seen in the plot below:Using this cut off information, the resulting Voronoi polygons would like this:
For allowing the computation of the Voronoi polygons when less than 4 pedestrians are in the walkable area, 4 extra points will be added outside the walkable area with a significant distance. These will have no effect on the size of the computed Voronoi polygons. This behavior can be turned off by setting
use_blind_points = False
. When turned off no Voronoi polygons will be computed for frames with less than 4 persons, also pedestrians walking in a line can lead to issues in the computation of the Voronoi tesselation.- Parameters:
traj_data (TrajectoryData) – trajectory data
walkable_area (WalkableArea) – bounding area, where pedestrian are supposed to walk
cut_off (Cutoff) – cutoff information, which provide the largest possible extend of a single Voronoi polygon
use_blind_points (bool) – adds extra 4 points outside the walkable area to also compute voronoi cells when less than 4 peds are in the walkable area (default: on!)
- Returns:
DataFrame containing the columns ‘id’, ‘frame’,’polygon’ (
shapely.Polygon
), and ‘individual_density’ in \(1/m^2\).- Return type:
- compute_intersecting_polygons(*, individual_voronoi_data, measurement_area)#
Compute the intersection of the voronoi cells with the measurement area.
- Parameters:
individual_voronoi_data (pandas.DataFrame) – individual voronoi data, needs to contain a column ‘polygon’ (
shapely.Polygon
), result fromcompute_individual_voronoi_polygons()
measurement_area (MeasurementArea) – measurement area for which the intersection will be computed.
- Returns:
DataFrame containing the columns ‘id’, ‘frame’ and ‘intersection’ which is the intersection of the individual Voronoi polygon and the given measurement area as
shapely.Polygon
.- Return type:
- compute_neighbors(individual_voronoi_data)#
Compute the neighbors of each pedestrian based on the Voronoi cells.
Computation of the neighborhood of each pedestrian per frame. Every other pedestrian is a neighbor if the Voronoi cells of both pedestrian touch and some point. The threshold for touching is set to 1mm.
- Parameters:
individual_voronoi_data (pandas.DataFrame) – individual voronoi data, needs to contain a column ‘polygon’, which holds a
shapely.Polygon
(result fromcompute_individual_voronoi_polygons()
)- Returns:
DataFrame containing the columns ‘id’, ‘frame’ and ‘neighbors’, where neighbors are a list of the neighbor’s IDs
- Return type:
- compute_time_distance_line(*, traj_data, measurement_line)#
Compute the time and distance to the measurement line.
Compute the time (in frames) and distance to the first crossing of the measurement line for each pedestrian. For further information how the crossing frames are computed see
compute_crossing_frames()
. All frames after a pedestrian has crossed the line will be omitted in the results.- Parameters:
traj_data (TrajectoryData) – trajectory data
measurement_line (MeasurementLine) – line which is crossed
- Returns:
DataFrame containing ‘id’, ‘frame’, ‘time’ (seconds until crossing), and ‘distance’ (meters to measurement line)
- Return type:
- get_invalid_trajectory(*, traj_data, walkable_area)#
Returns all trajectory data points outside the given walkable area.
- Parameters:
traj_data (TrajectoryData) – trajectory data
walkable_area (WalkableArea) – walkable area in which the pedestrians should be
- Returns:
DataFrame showing all data points outside the given walkable area
- Return type:
- is_trajectory_valid(*, traj_data, walkable_area)#
Checks if all trajectory data points lie within the given walkable area.
- Parameters:
traj_data (TrajectoryData) – trajectory data
walkable_area (WalkableArea) – walkable area in which the pedestrians should be
- Returns:
All points lie within walkable area
- Return type: