Source code for pedpy.methods.flow_calculator
"""Module containing functions to compute flows."""
from typing import Tuple
import pandas as pd
from shapely import LineString
from pedpy.methods.method_utils import _compute_crossing_frames
[docs]def compute_n_t(
*,
traj_data: pd.DataFrame,
measurement_line: LineString,
frame_rate: float,
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""Compute the framewise cumulative number of pedestrians passing the line.
Warnings:
For each pedestrian only the first passing of the line is considered!
Args:
traj_data (TrajectoryData): trajectory data
measurement_line (shapely.LineString): line for which n-t is computed
frame_rate (float): frame rate of the trajectory data
Returns:
DataFrame containing the columns 'frame', 'Cumulative pedestrians',
and 'Time [s]' and DataFrame containing the columns 'ID', and 'frame'.
"""
crossing_frames = _compute_crossing_frames(traj_data, measurement_line)
crossing_frames = (
crossing_frames.groupby("ID")["frame"].min().sort_values().reset_index()
)
nt = (
crossing_frames.groupby("frame")["frame"]
.size()
.cumsum()
.rename("Cumulative pedestrians")
)
# add missing values, to get values for each frame. First fill everything
# with the previous valid value (fillna('ffill')). When this is done only
# the frame at the beginning where no one has passed the line yet area
# missing (fillna(0)).
nt = (
nt.reindex(
list(range(traj_data.frame.min(), traj_data.frame.max() + 1))
)
.fillna(method="ffill")
.fillna(0)
)
nt = nt.to_frame()
nt["Cumulative pedestrians"] = nt["Cumulative pedestrians"].astype(int)
# frame number is the index
nt["Time [s]"] = nt.index / frame_rate
return nt, crossing_frames
[docs]def compute_flow(
*,
nt: pd.DataFrame,
crossing_frames: pd.DataFrame,
individual_speed: pd.DataFrame,
delta_t: int,
frame_rate: float,
) -> pd.DataFrame:
"""Compute the flow for the given crossing_frames and nt.
Args:
nt (pd.DataFrame): DataFrame containing the columns 'frame',
'Cumulative pedestrians', and 'Time [s]' (see result from
compute_nt)
crossing_frames (pd.DataFrame): DataFrame containing the columns
'ID', and 'frame' (see result from compute_nt)
individual_speed (pd.DataFrame): DataFrame containing the columns
'ID', 'frame', and 'speed'
delta_t (int): size of the time interval to compute the flow
frame_rate (float): frame rate of the trajectories
Returns:
DataFrame containing the columns 'Flow rate(1/s)', and 'Mean
velocity(m/s)'
"""
crossing_speeds = pd.merge(
crossing_frames, individual_speed, on=["ID", "frame"]
)
# Get frame where the first person passes the line
num_passed_before = 0
passed_frame_before = nt[nt["Cumulative pedestrians"] > 0].index.min()
rows = []
for frame in range(passed_frame_before + delta_t, nt.index.max(), delta_t):
passed_num_peds = nt.loc[frame]["Cumulative pedestrians"]
passed_frame = (
nt[nt["Cumulative pedestrians"] == passed_num_peds].index.min() + 1
)
if passed_num_peds != num_passed_before:
num_passing_peds = passed_num_peds - num_passed_before
t = passed_frame - passed_frame_before
flow_rate = num_passing_peds / t * frame_rate
v = crossing_speeds[
crossing_speeds.frame.between(
passed_frame_before, passed_frame, inclusive="both"
)
]["speed"].mean()
num_passed_before = passed_num_peds
passed_frame_before = passed_frame
rows.append(
{"Flow rate(1/s)": flow_rate, "Mean velocity(m/s)": v},
)
return pd.DataFrame(rows)