Repository: PedestrianDynamics/PedPy

Issue:
Compute the individual velocity outside the mean functions
Same procedure as for the individual Voronoi polygons, it makes more sense to compute these data beforehand and then pass it to the mean functions to avoid unnecessary computations. 

Discussion:

Patch:
diff --git a/jpsreport.ipynb b/jpsreport.ipynb
index 5549b13..0f4a888 100644
--- a/jpsreport.ipynb
+++ b/jpsreport.ipynb
@@ -490,12 +490,16 @@
     "mean_area_speeds = {}\n",
     "\n",
     "for name, trajectory in trajectories.items():\n",
-    "    mean_area_speed, individual_speed_area = compute_mean_velocity_per_frame(\n",
+    "    individual_velocity = compute_individual_velocity(\n",
     "        traj_data=trajectory.data,\n",
-    "        measurement_area=measurement_area,\n",
     "        frame_rate=trajectory.frame_rate,\n",
     "        frame_step=5,\n",
     "    )\n",
+    "    mean_area_speed = compute_mean_velocity_per_frame(\n",
+    "        traj_data=trajectory.data,\n",
+    "        measurement_area=measurement_area,\n",
+    "        individual_velocity=individual_velocity,\n",
+    "    )\n",
     "\n",
     "    classic_density = compute_classic_density(\n",
     "        traj_data=trajectory.data, measurement_area=measurement_area\n",
@@ -670,12 +674,16 @@
     "        measurement_area=measurement_area,\n",
     "    )\n",
     "\n",
-    "    voronoi_velocity, individual_velocity = compute_voronoi_velocity(\n",
+    "    individual_velocity = compute_individual_velocity(\n",
     "        traj_data=trajectory.data,\n",
-    "        individual_voronoi_intersection=intersecting,\n",
     "        frame_rate=trajectory.frame_rate,\n",
     "        frame_step=5,\n",
+    "    )\n",
+    "    voronoi_velocity = compute_voronoi_velocity(\n",
+    "        traj_data=trajectory.data,\n",
+    "        individual_voronoi_intersection=intersecting,\n",
     "        measurement_area=measurement_area,\n",
+    "        individual_velocity=individual_velocity,\n",
     "    )\n",
     "\n",
     "    voronoi_densities[name] = voronoi_density\n",
@@ -716,20 +724,22 @@
     "        measurement_area=measurement_area,\n",
     "    )\n",
     "\n",
-    "    (\n",
-    "        voronoi_velocity_cutoff,\n",
-    "        individual_velocity_cutoff,\n",
-    "    ) = compute_voronoi_velocity(\n",
+    "    individual_velocity = compute_individual_velocity(\n",
     "        traj_data=trajectory.data,\n",
-    "        individual_voronoi_intersection=intersecting_cutoff,\n",
     "        frame_rate=trajectory.frame_rate,\n",
     "        frame_step=5,\n",
+    "    )\n",
+    "\n",
+    "    voronoi_velocity_cutoff = compute_voronoi_velocity(\n",
+    "        traj_data=trajectory.data,\n",
+    "        individual_voronoi_intersection=intersecting_cutoff,\n",
+    "        individual_velocity=individual_velocity,\n",
     "        measurement_area=measurement_area,\n",
     "    )\n",
     "\n",
     "    voronoi_densities_cutoff[name] = voronoi_density_cutoff\n",
     "    voronoi_velocities_cutoff[name] = voronoi_velocity_cutoff\n",
-    "    individual_velocities_cutoff[name] = individual_velocity_cutoff\n",
+    "    individual_velocities_cutoff[name] = individual_velocity\n",
     "    individual_cutoffs[name] = intersecting_cutoff"
    ],
    "metadata": {
@@ -924,18 +934,21 @@
     "    individual_voronoi_data=individual_voronoi,\n",
     "    measurement_area=measurement_area,\n",
     ")\n",
-    "voronoi_velocity_frames, individual_velocity_frames = compute_voronoi_velocity(\n",
+    "\n",
+    "individual_velocity = compute_individual_velocity(\n",
+    "    traj_data=trajectory.data, frame_rate=trajectory.frame_rate, frame_step=5\n",
+    ")\n",
+    "voronoi_velocity_frames = compute_voronoi_velocity(\n",
     "    traj_data=trajectory.data,\n",
     "    individual_voronoi_intersection=individual_frames,\n",
-    "    frame_rate=trajectory.frame_rate,\n",
-    "    frame_step=5,\n",
+    "    individual_velocity=individual_velocity,\n",
     "    measurement_area=measurement_area,\n",
     ")\n",
     "\n",
     "density_profiles, velocity_profiles = compute_profiles(\n",
     "    individual_voronoi_velocity_data=pd.merge(\n",
     "        individual_frames,\n",
-    "        individual_velocity_frames,\n",
+    "        individual_velocity,\n",
     "        on=[\"ID\", \"frame\"],\n",
     "        how=\"left\",\n",
     "    ),\n",
diff --git a/pedpy/methods/velocity_calculator.py b/pedpy/methods/velocity_calculator.py
index 7c901dc..197432b 100644
--- a/pedpy/methods/velocity_calculator.py
+++ b/pedpy/methods/velocity_calculator.py
@@ -51,37 +51,23 @@ def compute_individual_velocity(
 def compute_mean_velocity_per_frame(
     *,
     traj_data: pd.DataFrame,
+    individual_velocity: pd.DataFrame,
     measurement_area: Polygon,
-    frame_rate: float,
-    frame_step: int,
-    movement_direction: Optional[npt.NDArray[np.float64]] = None,
 ) -> Tuple[pd.DataFrame, pd.DataFrame]:
     """Compute mean velocity per frame.
 
     Note: when using a movement direction the velocity may be negative!
 
     Args:
-        traj_data (TrajectoryData): trajectory data
+        traj_data (pd.DataFrame): trajectory data
+        individual_velocity (pd.DataFrame): individual velocity data
         measurement_area (shapely.Polygon): measurement area for which the
             velocity is computed
-        frame_rate (float): frame rate of the trajectory
-        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)
 
     Returns:
         DataFrame containing the columns 'frame' and 'speed'
-        DataFrame containing the columns 'ID', 'frame', and 'speed'
     """
-    df_speed = compute_individual_velocity(
-        traj_data=traj_data,
-        frame_rate=frame_rate,
-        frame_step=frame_step,
-        movement_direction=movement_direction,
-    )
-    combined = traj_data.merge(df_speed, on=["ID", "frame"])
+    combined = traj_data.merge(individual_velocity, on=["ID", "frame"])
     df_mean = (
         combined[shapely.within(combined["points"], measurement_area)]
         .groupby("frame")["speed"]
@@ -91,47 +77,33 @@ def compute_mean_velocity_per_frame(
         list(range(traj_data.frame.min(), traj_data.frame.max() + 1)),
         fill_value=0.0,
     )
-    return df_mean, df_speed
+    return df_mean
 
 
 def compute_voronoi_velocity(
     *,
     traj_data: pd.DataFrame,
+    individual_velocity: pd.DataFrame,
     individual_voronoi_intersection: pd.DataFrame,
-    frame_rate: float,
-    frame_step: int,
     measurement_area: Polygon,
-    movement_direction: Optional[npt.NDArray[np.float64]] = None,
-) -> Tuple[pd.Series, pd.DataFrame]:
+) -> pd.Series:
     """Compute the voronoi velocity per frame.
 
     Note: when using a movement direction the velocity may be negative!
 
     Args:
-        traj_data (TrajectoryData): trajectory data
+        traj_data (pd.DataFrame): trajectory data
+        individual_velocity (pd.DataFrame): individual velocity data
         individual_voronoi_intersection (pd.DataFrame): intersections of the
             individual with the measurement area of each pedestrian
-        frame_rate (float): frame rate of the trajectory
-        frame_step (int): gives the size of time interval for calculating the
-            velocity
         measurement_area (shapely.Polygon): area in which the voronoi velocity
             should be computed
-        movement_direction (np.ndarray): main movement direction on which the
-            actual movement is projected (default: None, when the un-projected
-            movement should be used)
 
     Returns:
         DataFrame containing the columns 'frame' and 'voronoi speed'
-        DataFrame containing the columns 'ID', 'frame', and 'speed'
     """
-    df_speed = compute_individual_velocity(
-        traj_data=traj_data,
-        frame_rate=frame_rate,
-        frame_step=frame_step,
-        movement_direction=movement_direction,
-    )
     df_voronoi = pd.merge(
-        individual_voronoi_intersection, df_speed, on=["ID", "frame"]
+        individual_voronoi_intersection, individual_velocity, on=["ID", "frame"]
     )
     df_voronoi["voronoi speed"] = (
         shapely.area(df_voronoi["intersection voronoi"])
@@ -143,7 +115,32 @@ def compute_voronoi_velocity(
         list(range(traj_data.frame.min(), traj_data.frame.max() + 1)),
         fill_value=0.0,
     )
-    return pd.Series(df_voronoi_speed), df_speed
+    return pd.Series(df_voronoi_speed)
+
+
+def compute_passing_speed(
+    *, frames_in_area: pd.DataFrame, frame_rate: float, distance: float
+) -> pd.DataFrame:
+    """Compute the individual speed of the pedestrian who pass the area.
+
+    Args:
+        frames_in_area (pd.DataFrame): information for each pedestrian in the
+            area, need to contain the following columns: 'ID', 'start', 'end',
+            'frame_start', 'frame_end'
+        frame_rate (float): frame rate of the trajectory
+        distance (float): distance between the two measurement lines
+    Returns:
+        DataFrame containing the columns: 'ID', 'speed' which is the speed
+        in m/s
+
+    """
+    speed = pd.DataFrame(frames_in_area["ID"], columns=["ID", "speed"])
+    speed["speed"] = (
+        frame_rate
+        * distance
+        / (np.abs(frames_in_area.frame_end - frames_in_area.frame_start))
+    )
+    return speed
 
 
 def _compute_individual_speed(
@@ -206,28 +203,3 @@ def _compute_individual_speed(
         columns.append("v_y")
 
     return movement_data[columns]
-
-
-def compute_passing_speed(
-    *, frames_in_area: pd.DataFrame, frame_rate: float, distance: float
-) -> pd.DataFrame:
-    """Compute the individual speed of the pedestrian who pass the area.
-
-    Args:
-        frames_in_area (pd.DataFrame): information for each pedestrian in the
-            area, need to contain the following columns: 'ID', 'start', 'end',
-            'frame_start', 'frame_end'
-        frame_rate (float): frame rate of the trajectory
-        distance (float): distance between the two measurement lines
-    Returns:
-        DataFrame containing the columns: 'ID', 'speed' which is the speed
-        in m/s
-
-    """
-    speed = pd.DataFrame(frames_in_area["ID"], columns=["ID", "speed"])
-    speed["speed"] = (
-        frame_rate
-        * distance
-        / (np.abs(frames_in_area.frame_end - frames_in_area.frame_start))
-    )
-    return speed
diff --git a/usage.ipynb b/usage.ipynb
index 637d7ca..14dfce2 100644
--- a/usage.ipynb
+++ b/usage.ipynb
@@ -218,7 +218,7 @@
     "ax1 = fig.add_subplot(111, aspect=\"equal\")\n",
     "# ax1 = plot_geometry(geometry=geometry_faulty, ax=ax1) # remove comment to show the borders of the faulty geometry\n",
     "\n",
-    "ax1 = plot_measurement_setup(\n",
+    "plot_measurement_setup(\n",
     "    traj=traj,\n",
     "    geometry=geometry,\n",
     "    measurement_areas=[ma],\n",
@@ -230,6 +230,7 @@
     "    ma_color=\"g\",\n",
     "    ma_alpha=0.1,\n",
     "    ma_line_color=\"g\",\n",
+    "    ax=ax1,\n",
     ")\n",
     "plt.show()"
    ],
@@ -617,7 +618,7 @@
     "\n",
     "    ax1 = fig.add_subplot(121, aspect=\"equal\")\n",
     "    ax1.set_title(\"w/o cutoff\")\n",
-    "    ax1 = plot_voronoi_cells(\n",
+    "    plot_voronoi_cells(\n",
     "        data=df_frame,\n",
     "        geometry=geometry,\n",
     "        color_mode=\"id\",\n",
@@ -632,7 +633,7 @@
     "    ax2 = fig.add_subplot(122, aspect=\"equal\")\n",
     "    ax2.set_title(\"w cutoff\")\n",
     "\n",
-    "    ax2 = plot_voronoi_cells(\n",
+    "    plot_voronoi_cells(\n",
     "        data=df_frame_cutoff,\n",
     "        geometry=geometry,\n",
     "        color_mode=\"id\",\n",
@@ -770,11 +771,10 @@
    "source": [
     "from pedpy import compute_mean_velocity_per_frame\n",
     "\n",
-    "mean_speed, individual_speed = compute_mean_velocity_per_frame(\n",
+    "mean_speed = compute_mean_velocity_per_frame(\n",
     "    traj_data=traj.data,\n",
     "    measurement_area=ma,\n",
-    "    frame_rate=traj.frame_rate,\n",
-    "    frame_step=10,\n",
+    "    individual_velocity=individual_speed,\n",
     ")\n",
     "mean_speed"
    ],
@@ -798,7 +798,7 @@
    "execution_count": null,
    "outputs": [],
    "source": [
-    "mean_speed.reset_index().plot.scatter(x=\"frame\", y=\"speed\")"
+    "mean_speed.reset_index().plot.line(x=\"frame\", y=\"speed\")"
    ],
    "metadata": {
     "collapsed": false
@@ -809,15 +809,10 @@
    "execution_count": null,
    "outputs": [],
    "source": [
-    "(\n",
-    "    mean_speed_direction,\n",
-    "    individual_speed_direction,\n",
-    ") = compute_mean_velocity_per_frame(\n",
+    "mean_speed_direction = compute_mean_velocity_per_frame(\n",
     "    traj_data=traj.data,\n",
     "    measurement_area=ma,\n",
-    "    frame_rate=traj.frame_rate,\n",
-    "    frame_step=5,\n",
-    "    movement_direction=direction,\n",
+    "    individual_velocity=individual_speed_direction,\n",
     ")\n",
     "mean_speed_direction"
    ],
@@ -839,10 +834,7 @@
    "execution_count": null,
    "outputs": [],
    "source": [
-    "from pedpy import (\n",
-    "    compute_individual_velocity,\n",
-    "    compute_voronoi_velocity,\n",
-    ")"
+    "from pedpy import compute_voronoi_velocity"
    ],
    "metadata": {
     "collapsed": false
@@ -864,11 +856,10 @@
    "execution_count": null,
    "outputs": [],
    "source": [
-    "voronoi_velocity, individual_velocity = compute_voronoi_velocity(\n",
+    "voronoi_velocity = compute_voronoi_velocity(\n",
     "    traj_data=traj.data,\n",
     "    individual_voronoi_intersection=individual_voronoi,\n",
-    "    frame_rate=traj.frame_rate,\n",
-    "    frame_step=5,\n",
+    "    individual_velocity=individual_speed,\n",
     "    measurement_area=ma,\n",
     ")\n",
     "voronoi_velocity"
@@ -893,16 +884,11 @@
    "execution_count": null,
    "outputs": [],
    "source": [
-    "(\n",
-    "    voronoi_velocity_direction,\n",
-    "    individual_velocity_direction,\n",
-    ") = compute_voronoi_velocity(\n",
+    "voronoi_velocity_direction = compute_voronoi_velocity(\n",
     "    traj_data=traj.data,\n",
     "    individual_voronoi_intersection=individual_voronoi,\n",
-    "    frame_rate=traj.frame_rate,\n",
-    "    frame_step=5,\n",
+    "    individual_velocity=individual_speed_direction,\n",
     "    measurement_area=ma,\n",
-    "    movement_direction=direction,\n",
     ")\n",
     "voronoi_velocity_direction"
    ],
@@ -1140,8 +1126,8 @@
    "source": [
     "from pedpy import (\n",
     "    compute_profiles,\n",
-    "    compute_voronoi_velocity,\n",
-    "    compute_voronoi_density,\n",
+    "    compute_individual_voronoi_polygons,\n",
+    "    compute_individual_velocity,\n",
     "    VelocityMethod,\n",
     ")"
    ],


Test patch:
diff --git a/tests/reference_tests/reference_test.py b/tests/reference_tests/reference_test.py
index 7f1255c..26d97ed 100644
--- a/tests/reference_tests/reference_test.py
+++ b/tests/reference_tests/reference_test.py
@@ -147,12 +147,16 @@ def test_arithmetic_velocity(
         trajectory_file=folder / "traj.txt", default_unit=TrajectoryUnit.METER
     )
 
-    result, _ = compute_mean_velocity_per_frame(
+    individual_velocity = compute_individual_velocity(
         traj_data=trajectory.data,
-        measurement_area=measurement_area,
         frame_rate=trajectory.frame_rate,
         frame_step=velocity_frame,
     )
+    result = compute_mean_velocity_per_frame(
+        traj_data=trajectory.data,
+        measurement_area=measurement_area,
+        individual_velocity=individual_velocity,
+    )
     result = result.to_frame()
 
     assert (reference_result.index.values == result.index.values).all()
@@ -453,12 +457,16 @@ def test_voronoi_velocity(
     intersecting_voronoi = compute_intersecting_polygons(
         individual_voronoi, measurement_area
     )
-
-    result, _ = compute_voronoi_velocity(
+    individual_velocity = compute_individual_velocity(
         traj_data=trajectory.data,
-        individual_voronoi_intersection=intersecting_voronoi,
         frame_rate=trajectory.frame_rate,
         frame_step=velocity_frame,
+    )
+
+    result = compute_voronoi_velocity(
+        traj_data=trajectory.data,
+        individual_voronoi_intersection=intersecting_voronoi,
+        individual_velocity=individual_velocity,
         measurement_area=measurement_area,
     )
     result = result.to_frame()