Skip to content

Commit 79f420b

Browse files
committed
Improve profile computation memory efficiency
Profile functions (compute_density_profile, compute_speed_profile, compute_profiles) no longer require pre-computed grid intersections. When grid_intersections_area is not provided, intersections are computed per frame internally, avoiding the allocation of the full (grid_cells × pedestrians) matrix. - Add _compute_frame_grid_intersection helper for single-frame intersection - Change _compute_grid_polygon_intersection to process frame-by-frame using NumPy instead of a single broadcast - Make grid_intersections_area optional in compute_density_profile and compute_speed_profile (on-the-fly when omitted) - Simplify compute_profiles to delegate to _compute_density_for_frame and _compute_speed_for_frame per frame with shared intersection - Extract _compute_density_for_frame and _compute_speed_for_frame as single-dispatch helpers; compute_density_profile and compute_speed_profile also delegate here, eliminating duplicated method branches - Move frame-invariant quantities (bounds, grid centers) out of the per-frame loop to avoid redundant recomputation - Update user guide to use the simpler API without compute_grid_cell_polygon_intersection_area
1 parent f70f08d commit 79f420b

3 files changed

Lines changed: 860 additions & 195 deletions

File tree

notebooks/user_guide.ipynb

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3499,25 +3499,12 @@
34993499
"metadata": {},
35003500
"outputs": [],
35013501
"source": [
3502-
"from pedpy import (\n",
3503-
" compute_grid_cell_polygon_intersection_area,\n",
3504-
" get_grid_cells,\n",
3505-
")\n",
3506-
"\n",
35073502
"grid_size = 0.4\n",
3508-
"grid_cells, _, _ = get_grid_cells(walkable_area=walkable_area, grid_size=grid_size)\n",
35093503
"\n",
3510-
"min_frame_profiles = 250 # We use here just an excerpt of the\n",
3511-
"max_frame_profiles = 400 # trajectory data to reduce compute time\n",
3504+
"min_frame_profiles = 500 # We use here just an excerpt of the\n",
3505+
"max_frame_profiles = 1000 # trajectory data to reduce compute time\n",
35123506
"\n",
3513-
"profile_data = profile_data[profile_data.frame.between(min_frame_profiles, max_frame_profiles)]\n",
3514-
"\n",
3515-
"# Compute the grid intersection area for the resorted profile data (they have the same sorting)\n",
3516-
"# for usage in multiple calls to not run the compute heavy operation multiple times\n",
3517-
"(\n",
3518-
" grid_cell_intersection_area,\n",
3519-
" resorted_profile_data,\n",
3520-
") = compute_grid_cell_polygon_intersection_area(data=profile_data, grid_cells=grid_cells)"
3507+
"profile_data = profile_data[profile_data.frame.between(min_frame_profiles, max_frame_profiles)]"
35213508
]
35223509
},
35233510
{
@@ -3567,14 +3554,29 @@
35673554
},
35683555
"outputs": [],
35693556
"source": [
3570-
"from pedpy import plot_measurement_setup\n",
3557+
"from pedpy import PEDPY_ORANGE, get_grid_cells, plot_measurement_setup\n",
35713558
"\n",
3572-
"plot_measurement_setup(\n",
3559+
"ax = plot_measurement_setup(\n",
35733560
" walkable_area=walkable_area,\n",
35743561
" measurement_areas=[profile_measurement_area],\n",
35753562
" ma_line_width=2,\n",
35763563
" ma_alpha=0.2,\n",
35773564
").set_aspect(\"equal\")\n",
3565+
"\n",
3566+
"grid_size = 0.4\n",
3567+
"grid_cells_measurement_area, _, _ = get_grid_cells(\n",
3568+
" axis_aligned_measurement_area=profile_measurement_area,\n",
3569+
" grid_size=grid_size,\n",
3570+
")\n",
3571+
"grid_cells = [MeasurementArea(cell) for cell in grid_cells_measurement_area]\n",
3572+
"plot_measurement_setup(\n",
3573+
" measurement_areas=grid_cells,\n",
3574+
" ma_line_color=PEDPY_ORANGE,\n",
3575+
" ma_line_width=0.3,\n",
3576+
" ma_alpha=0,\n",
3577+
" axes=ax,\n",
3578+
").set_aspect(\"equal\")\n",
3579+
"\n",
35783580
"plt.show()"
35793581
]
35803582
},
@@ -3667,17 +3669,15 @@
36673669
"from pedpy import SpeedMethod, compute_speed_profile\n",
36683670
"\n",
36693671
"voronoi_speed_profile = compute_speed_profile(\n",
3670-
" data=resorted_profile_data,\n",
3672+
" data=profile_data,\n",
36713673
" walkable_area=walkable_area,\n",
3672-
" grid_intersections_area=grid_cell_intersection_area,\n",
36733674
" grid_size=grid_size,\n",
36743675
" speed_method=SpeedMethod.VORONOI,\n",
36753676
")\n",
36763677
"\n",
36773678
"arithmetic_speed_profile = compute_speed_profile(\n",
3678-
" data=resorted_profile_data,\n",
3679+
" data=profile_data,\n",
36793680
" walkable_area=walkable_area,\n",
3680-
" grid_intersections_area=grid_cell_intersection_area,\n",
36813681
" grid_size=grid_size,\n",
36823682
" speed_method=SpeedMethod.ARITHMETIC,\n",
36833683
")\n",
@@ -3770,19 +3770,17 @@
37703770
"from pedpy import AxisAlignedMeasurementArea, SpeedMethod, compute_speed_profile\n",
37713771
"\n",
37723772
"voronoi_speed_profile = compute_speed_profile(\n",
3773-
" data=resorted_profile_data_measurement_area,\n",
3773+
" data=profile_data,\n",
37743774
" walkable_area=walkable_area,\n",
37753775
" axis_aligned_measurement_area=profile_measurement_area,\n",
3776-
" grid_intersections_area=grid_cell_intersection_area_measurement_area,\n",
37773776
" grid_size=grid_size,\n",
37783777
" speed_method=SpeedMethod.VORONOI,\n",
37793778
")\n",
37803779
"\n",
37813780
"arithmetic_speed_profile = compute_speed_profile(\n",
3782-
" data=resorted_profile_data_measurement_area,\n",
3781+
" data=profile_data,\n",
37833782
" walkable_area=walkable_area,\n",
37843783
" axis_aligned_measurement_area=profile_measurement_area,\n",
3785-
" grid_intersections_area=grid_cell_intersection_area_measurement_area,\n",
37863784
" grid_size=grid_size,\n",
37873785
" speed_method=SpeedMethod.ARITHMETIC,\n",
37883786
")\n",
@@ -3916,16 +3914,13 @@
39163914
"source": [
39173915
"from pedpy import DensityMethod, compute_density_profile\n",
39183916
"\n",
3919-
"# here it is important to use the resorted data, as it needs to be in the same ordering as \"grid_cell_intersection_area\"\n",
39203917
"voronoi_density_profile = compute_density_profile(\n",
3921-
" data=resorted_profile_data,\n",
3918+
" data=profile_data,\n",
39223919
" walkable_area=walkable_area,\n",
3923-
" grid_intersections_area=grid_cell_intersection_area,\n",
39243920
" grid_size=grid_size,\n",
39253921
" density_method=DensityMethod.VORONOI,\n",
39263922
")\n",
39273923
"\n",
3928-
"# here the unsorted data can be used\n",
39293924
"classic_density_profile = compute_density_profile(\n",
39303925
" data=profile_data,\n",
39313926
" walkable_area=walkable_area,\n",
@@ -4005,17 +4000,14 @@
40054000
"source": [
40064001
"from pedpy import DensityMethod, compute_density_profile\n",
40074002
"\n",
4008-
"# here it is important to use the resorted data, as it needs to be in the same ordering as \"grid_cell_intersection_area\"\n",
40094003
"voronoi_density_profile = compute_density_profile(\n",
4010-
" data=resorted_profile_data_measurement_area,\n",
4004+
" data=profile_data,\n",
40114005
" walkable_area=walkable_area,\n",
40124006
" axis_aligned_measurement_area=profile_measurement_area,\n",
4013-
" grid_intersections_area=grid_cell_intersection_area_measurement_area,\n",
40144007
" grid_size=grid_size,\n",
40154008
" density_method=DensityMethod.VORONOI,\n",
40164009
")\n",
40174010
"\n",
4018-
"# here the unsorted data can be used\n",
40194011
"classic_density_profile = compute_density_profile(\n",
40204012
" data=profile_data,\n",
40214013
" walkable_area=walkable_area,\n",

0 commit comments

Comments
 (0)