streetlos 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. streetlos-0.1.0/CHANGELOG.md +19 -0
  2. streetlos-0.1.0/CITATION.cff +20 -0
  3. streetlos-0.1.0/LICENSE +21 -0
  4. streetlos-0.1.0/MANIFEST.in +9 -0
  5. streetlos-0.1.0/PKG-INFO +298 -0
  6. streetlos-0.1.0/README.md +263 -0
  7. streetlos-0.1.0/examples/quickstart.py +54 -0
  8. streetlos-0.1.0/examples/segments.csv +5 -0
  9. streetlos-0.1.0/pyproject.toml +107 -0
  10. streetlos-0.1.0/setup.cfg +4 -0
  11. streetlos-0.1.0/src/streetlos/__init__.py +68 -0
  12. streetlos-0.1.0/src/streetlos/__main__.py +7 -0
  13. streetlos-0.1.0/src/streetlos/_version.py +1 -0
  14. streetlos-0.1.0/src/streetlos/batch.py +328 -0
  15. streetlos-0.1.0/src/streetlos/cli.py +93 -0
  16. streetlos-0.1.0/src/streetlos/comfort.py +140 -0
  17. streetlos-0.1.0/src/streetlos/py.typed +0 -0
  18. streetlos-0.1.0/src/streetlos/segment.py +249 -0
  19. streetlos-0.1.0/src/streetlos/tables.py +194 -0
  20. streetlos-0.1.0/src/streetlos/timespace.py +149 -0
  21. streetlos-0.1.0/src/streetlos/units.py +44 -0
  22. streetlos-0.1.0/src/streetlos/walkway.py +193 -0
  23. streetlos-0.1.0/src/streetlos.egg-info/PKG-INFO +298 -0
  24. streetlos-0.1.0/src/streetlos.egg-info/SOURCES.txt +32 -0
  25. streetlos-0.1.0/src/streetlos.egg-info/dependency_links.txt +1 -0
  26. streetlos-0.1.0/src/streetlos.egg-info/entry_points.txt +2 -0
  27. streetlos-0.1.0/src/streetlos.egg-info/requires.txt +6 -0
  28. streetlos-0.1.0/src/streetlos.egg-info/top_level.txt +1 -0
  29. streetlos-0.1.0/tests/test_batch_cli.py +179 -0
  30. streetlos-0.1.0/tests/test_comfort.py +61 -0
  31. streetlos-0.1.0/tests/test_segment.py +215 -0
  32. streetlos-0.1.0/tests/test_tables.py +116 -0
  33. streetlos-0.1.0/tests/test_timespace.py +78 -0
  34. streetlos-0.1.0/tests/test_walkway.py +109 -0
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [0.1.0] - 2026-11-09
8
+ ### Added
9
+ - Walkway LOS by space per pedestrian and unit flow rate, with average-flow and
10
+ platoon-adjusted criteria (FHWA-RD-98-107; HCM 2000 walkway tables).
11
+ - Effective sidewalk width with building and curb shy distances and street furniture.
12
+ - Corner and crosswalk circulation area with the time-space method.
13
+ - Pedestrian and bicycle segment (link) LOS score models of NCHRP Report 616 in the
14
+ HCM 2010 form, returning every factor.
15
+ - Pedestrian comfort and bicycle facility indicators with configurable thresholds
16
+ (PROWAG clear-width minimum).
17
+ - Overridable, cited `LosTable` threshold tables.
18
+ - `streetlos` command line tool: CSV of segments in, LOS table out, US or SI units,
19
+ JSON table overrides.
@@ -0,0 +1,20 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it as below."
3
+ authors:
4
+ - family-names: "Eminoğlu"
5
+ given-names: "Yusuf"
6
+ email: "geospacephilo@gmail.com"
7
+ orcid: "https://orcid.org/0009-0005-6000-2934"
8
+ title: "streetlos"
9
+ version: "0.1.0"
10
+ date-released: "2026-11-09"
11
+ license: "MIT"
12
+ repository-code: "https://gitlab.com/geophilo1/streetlos_sdk"
13
+ url: "https://pypi.org/project/streetlos/"
14
+ abstract: "Multimodal street level-of-service screening: walkway LOS by flow and space (average and platoon-adjusted), corner and crosswalk circulation area, NCHRP Report 616 / HCM 2010 pedestrian and bicycle segment LOS scores, and comfort indicators, with a CSV command line tool."
15
+ keywords:
16
+ - level of service
17
+ - pedestrian
18
+ - bicycle
19
+ - complete streets
20
+ - transportation planning
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yusuf Eminoğlu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,9 @@
1
+ include LICENSE
2
+ include README.md
3
+ include CHANGELOG.md
4
+ include CITATION.cff
5
+ include pyproject.toml
6
+ include src/streetlos/py.typed
7
+ recursive-include src/streetlos *.py
8
+ recursive-include tests *.py
9
+ recursive-include examples *.py *.csv
@@ -0,0 +1,298 @@
1
+ Metadata-Version: 2.4
2
+ Name: streetlos
3
+ Version: 0.1.0
4
+ Summary: Multimodal street level-of-service screening: walkway LOS by flow and space (average and platoon-adjusted), corner and crosswalk circulation area, NCHRP 616 / HCM 2010 pedestrian and bicycle segment LOS scores, and comfort indicators, with a CSV command line tool.
5
+ Author-email: Yusuf Eminoğlu <geospacephilo@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://gitlab.com/geophilo1/streetlos_sdk
8
+ Project-URL: Repository, https://gitlab.com/geophilo1/streetlos_sdk
9
+ Project-URL: Issues, https://gitlab.com/geophilo1/streetlos_sdk/-/work_items
10
+ Project-URL: Changelog, https://gitlab.com/geophilo1/streetlos_sdk/-/blob/main/CHANGELOG.md
11
+ Keywords: level-of-service,multimodal-los,pedestrian,bicycle,walkability,sidewalk,complete-streets,highway-capacity-manual,nchrp-616,transportation-planning,urban-planning,gis
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Environment :: Console
21
+ Classifier: Topic :: Scientific/Engineering :: GIS
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Classifier: Intended Audience :: Science/Research
24
+ Classifier: Intended Audience :: Developers
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
31
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
32
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
33
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
34
+ Dynamic: license-file
35
+
36
+ # streetlos
37
+
38
+ [![PyPI version](https://img.shields.io/pypi/v/streetlos.svg?color=3b82f6)](https://pypi.org/project/streetlos/)
39
+ [![Python version support](https://img.shields.io/pypi/pyversions/streetlos.svg?color=10b981)](https://pypi.org/project/streetlos/)
40
+ [![pipeline](https://gitlab.com/geophilo1/streetlos_sdk/badges/main/pipeline.svg)](https://gitlab.com/geophilo1/streetlos_sdk/-/pipelines)
41
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitlab.com/geophilo1/streetlos_sdk/-/blob/main/LICENSE)
42
+
43
+ **Multimodal street level-of-service screening for walking and cycling.**
44
+
45
+ `streetlos` scores street segments for pedestrians and cyclists from a plain CSV
46
+ of street attributes. It is written for planners and researchers who need a
47
+ transparent, reproducible screening (which streets look poor, and why) rather
48
+ than a black box. Every threshold table is cited and can be overridden.
49
+
50
+ - **Walkway LOS** by space per pedestrian and unit flow rate, with the
51
+ average-flow and the **platoon-adjusted** criteria.
52
+ - **Effective sidewalk width** after shy distances and street furniture.
53
+ - **Corner and crosswalk circulation area** with the time-space method.
54
+ - **Pedestrian and bicycle segment LOS scores** from NCHRP Report 616
55
+ (Dowling et al. 2008), in the form adopted by HCM 2010.
56
+ - **Comfort indicators**: clear width against the PROWAG minimum, buffer,
57
+ traffic speed and volume per lane, bike lane width and door-zone exposure.
58
+ - **CLI**: CSV of segments in, LOS table out. US (ft, mph) or SI (m, km/h) units.
59
+
60
+ No runtime dependencies: the standard library is enough.
61
+
62
+ ```bash
63
+ pip install streetlos
64
+ ```
65
+
66
+ Requires Python 3.9 or newer.
67
+
68
+ > **About the HCM.** The *Highway Capacity Manual* is a copyrighted publication
69
+ > of the Transportation Research Board. `streetlos` does not reproduce its text.
70
+ > It implements published equations and numeric thresholds, cites the openly
71
+ > accessible documents they were checked against, and lets you replace every
72
+ > table (for example with the values of the HCM edition your agency uses).
73
+
74
+ ---
75
+
76
+ ## Quickstart
77
+
78
+ ```python
79
+ import streetlos as sl
80
+
81
+ # Walkway: 8.5 ft effective width, 600 pedestrians in the peak 15 minutes
82
+ w = sl.walkway_los(8.5, 600)
83
+ print(w.unit_flow_p_min_ft, w.space_ft2_p, w.los) # 4.71 56.1 'B'
84
+ print(sl.walkway_los(8.5, 600, platoon=True).los) # 'C'
85
+
86
+ # Effective width: 10 ft sidewalk, building facade, no buffer, a light pole
87
+ sl.effective_walkway_width(10, building_edge="building", obstructions=["light_pole"]) # 3.5
88
+
89
+ # Pedestrian segment LOS score for one side of the street
90
+ p = sl.pedestrian_link_score(
91
+ outside_lane_ft=12, bike_lane_ft=5, shoulder_ft=8, parking_occupancy=0.5,
92
+ buffer_ft=4, sidewalk_ft=6, volume_vph=800, through_lanes=2, running_speed_mph=30,
93
+ )
94
+ print(round(p.score, 3), p.los) # 1.997 'A'
95
+
96
+ # Bicycle segment LOS score for one direction
97
+ b = sl.bicycle_link_score(
98
+ outside_lane_ft=12, bike_lane_ft=5, volume_vph=800, through_lanes=2,
99
+ running_speed_mph=35, heavy_vehicle_pct=2, pavement_rating=4,
100
+ )
101
+ print(round(b.score, 3), b.los) # 2.232 'B'
102
+
103
+ # Corner circulation area (time-space)
104
+ c = sl.corner_circulation(10, 12, 15, cycle_s=90, circulating_peds_per_cycle=120,
105
+ waiting=[(20, 60), (25, 55)])
106
+ print(round(c.space_ft2_p, 2), c.los) # 4.9 'F'
107
+ ```
108
+
109
+ ### Command line
110
+
111
+ ```bash
112
+ streetlos segments.csv -o segments_los.csv # US units (ft, mph)
113
+ streetlos segments.csv --units si # metres, km/h -> segments_los.csv
114
+ streetlos segments.csv --platoon # platoon-adjusted walkway criteria
115
+ streetlos segments.csv --tables my_tables.json # override breakpoints
116
+ streetlos --list-tables # print tables and sources
117
+ ```
118
+
119
+ One row per segment side (pedestrian) or direction (bicycle). Recognised columns
120
+ (all optional; a model runs only when its inputs are present, and `notes` says
121
+ what was skipped):
122
+
123
+ | column | meaning | unit (us / si) |
124
+ |---|---|---|
125
+ | `segment_id` | identifier, copied through | |
126
+ | `outside_lane` | outside through lane width | ft / m |
127
+ | `bike_lane` | bicycle lane width | ft / m |
128
+ | `shoulder` | paved shoulder or parking lane width | ft / m |
129
+ | `curb` | curb present (yes/no, default yes) | |
130
+ | `parking_occupancy` | share of on-street parking occupied, 0-1 | |
131
+ | `parking_striped` | parking spaces striped (yes/no) | |
132
+ | `buffer` | buffer between sidewalk and road | ft / m |
133
+ | `barrier` | continuous barrier at least 3 ft high in the buffer | |
134
+ | `sidewalk_width` | sidewalk width, excluding the buffer | ft / m |
135
+ | `building_edge` | `none`, `building`, `window_display`, `fence`, `low_wall` | |
136
+ | `obstructions` | `;`-separated names or widths in the walking path | ft / m |
137
+ | `volume_vph` | motor vehicle flow in this direction | veh/h |
138
+ | `through_lanes` | through lanes in this direction | |
139
+ | `speed` | motor vehicle running speed | mph / km/h |
140
+ | `heavy_vehicle_pct` | heavy vehicles | % |
141
+ | `pavement_rating` | pavement condition, 0.5-5 (default 4) | |
142
+ | `divided` | divided street (yes/no) | |
143
+ | `ped_volume_15min` / `ped_volume_hour` + `phf` | two-way pedestrian volume | p |
144
+ | `walk_speed` | walking speed (default 4.4 ft/s) | ft/s / m/s |
145
+ | `facility` | `none`, `shared`, `bike_lane`, `buffered_lane`, `separated`, `path` | |
146
+ | `bike_buffer` | buffer beside the bike lane | ft / m |
147
+
148
+ Output columns: effective width, unit flow, space per pedestrian, walkway LOS
149
+ (space, flow, overall), pedestrian score and LOS, bicycle score and LOS,
150
+ `ped_flags`, `bike_flags`, `notes`. See `examples/segments.csv`.
151
+
152
+ Override file format (`--tables`): `{"walkway_flow": [5, 7, 10, 15, 23]}`, i.e.
153
+ five A-E breakpoints per table name (`streetlos --list-tables` shows the names).
154
+
155
+ ---
156
+
157
+ ## API overview
158
+
159
+ | function | purpose |
160
+ |---|---|
161
+ | `walkway_los(width, peds_15min, platoon=False)` | walkway LOS by space and flow; worse governs |
162
+ | `effective_walkway_width(total, building_edge, has_buffer, obstructions)` | effective width W_E |
163
+ | `unit_flow_rate`, `pedestrian_space` | v_p = v15 / (15 W_E); A_p = 60 S_p / v_p |
164
+ | `corner_circulation`, `crosswalk_circulation` | time-space circulation area per pedestrian |
165
+ | `pedestrian_link_score(...)` | NCHRP 616 / HCM 2010 pedestrian link score, factors and LOS |
166
+ | `bicycle_link_score(...)` | NCHRP 616 / HCM 2010 bicycle link score, factors and LOS |
167
+ | `pedestrian_comfort`, `bicycle_facility` | screening indicators and flags (`ComfortThresholds`) |
168
+ | `evaluate_segment`, `evaluate_rows`, `evaluate_csv` | batch evaluation of segment tables |
169
+ | `LosTable`, `DEFAULT_TABLES`, `tables_with_overrides` | inspect and replace thresholds |
170
+
171
+ All functions take US customary units (ft, mph, veh/h), because that is how the
172
+ models were calibrated. `streetlos.units` converts from SI.
173
+
174
+ ---
175
+
176
+ ## Method and sources
177
+
178
+ ### Walkway LOS
179
+ Unit flow `v_p = v_15 / (15 W_E)` (p/min/ft) and space `A_p = 60 S_p / v_p`
180
+ (ft²/p), where `S_p` defaults to 4.4 ft/s (3.3 ft/s where more than 20 % of
181
+ pedestrians are elderly). Breakpoints:
182
+
183
+ | LOS | space, ft²/p | flow, p/min/ft | platoon space | platoon flow |
184
+ |---|---|---|---|---|
185
+ | A | > 60 | ≤ 5 | > 530 | ≤ 0.5 |
186
+ | B | > 40 | ≤ 7 | > 90 | ≤ 3 |
187
+ | C | > 24 | ≤ 10 | > 40 | ≤ 6 |
188
+ | D | > 15 | ≤ 15 | > 23 | ≤ 11 |
189
+ | E | > 8 | ≤ 23 | > 11 | ≤ 18 |
190
+ | F | ≤ 8 | > 23 | ≤ 11 | > 18 |
191
+
192
+ Sources: Rouphail et al. (1998) FHWA-RD-98-107, Tables 4 and 6 (adopted in HCM
193
+ 2000); NYC Department of City Planning (2006), *Pedestrian Level of Service
194
+ Study, Phase I*, Tables 2.1-2.2. The original platoon research is Pushkarev &
195
+ Zupan (1975), *Urban Space for Pedestrians*.
196
+
197
+ ### Effective width
198
+ Building-side shy distance (3 ft window display, 2 ft building facade, 1.5 ft
199
+ fence or low wall), 1.5 ft curb shy distance where there is no buffer, and the
200
+ effective width of obstructions in the walking path (HCM 6th edition values as
201
+ reported by McTrans). The default street-furniture widths are **not verified**
202
+ (see Limitations); measure them or pass numbers.
203
+
204
+ ### Corners and crosswalks (time-space)
205
+ Fruin's time-space concept as used by the HCM: available time-space
206
+ (area × cycle) minus the time-space held by waiting pedestrians, divided by the
207
+ pedestrian occupancy time. The corner area loses `(1 − π/4) R² ≈ 0.215 R²` to
208
+ the curb return; waiting time per cycle for uniform arrivals is `N r² / (2C)`;
209
+ circulation time is the HCM constant of 4 s per pedestrian, or Fruin, Ketcham
210
+ and Hecht's `0.12 (W_a + W_b) + 1.4` s (`fruin_circulation_time`). See
211
+ FHWA-RD-98-107 Section 4.
212
+
213
+ ### Pedestrian segment (link) LOS score
214
+ `I_p = 6.0468 + F_w + F_v + F_s`, with
215
+ `F_w = −1.2276 ln(W_v + 0.5 W_1 + 50 p_pk + W_buf f_b + W_aA f_sw)`,
216
+ `F_v = 0.0091 v_m / (4 N_th)` and `F_s = 4 (S_R/100)²`, plus the HCM 2010
217
+ width adjustments (`f_b = 5.37` with a continuous barrier, `f_sw = 6.0 − 0.3 W_aA`,
218
+ `W_aA ≤ 10 ft`, volume-adjusted `W_v`, parking-dependent `W_1`). If a pedestrian
219
+ space is known, the reported LOS is the worse of the score LOS and the space LOS.
220
+
221
+ ### Bicycle segment (link) LOS score
222
+ `I_b = 0.760 + F_w + F_v + F_s + F_p`, with `F_w = −0.005 W_e²`,
223
+ `F_v = 0.507 ln(v_ma / (4 N_th))`,
224
+ `F_s = 0.199 [1.1199 ln(S_Ra − 20) + 0.8103] (1 + 0.1038 P_HVa)²` and
225
+ `F_p = 7.066 / P_c²`, plus the adjustments `S_Ra ≥ 21 mph`, `v_ma ≥ 4 N_th`
226
+ and the 50 % heavy-vehicle cap at low volumes.
227
+
228
+ Score letters (both models): A ≤ 2.00, B ≤ 2.75, C ≤ 3.50, D ≤ 4.25, E ≤ 5.00, F > 5.00.
229
+
230
+ Sources: Dowling et al. (2008), *Multimodal Level of Service Analysis for Urban
231
+ Streets*, NCHRP Report 616 (note its published erratum for the pedestrian
232
+ segment equation); HCM 2010 Chapter 17, checked against the open restatement in
233
+ Lewis Center for Regional Policy Studies, UCLA (2014), *HCM Bicycle and
234
+ Pedestrian Level of Service: The Ultimate White Paper*. The models descend from
235
+ Landis et al. (1997, TRR 1578) and Landis et al. (2001, TRR 1773).
236
+
237
+ ### Comfort indicators
238
+ Clear width is checked against the 4.0 ft (1.2 m) minimum and 5.0 ft passing
239
+ width of the US Access Board's Public Right-of-Way Accessibility Guidelines
240
+ (36 CFR Part 1190, R302.3-R302.4). The other flags (speed above 30 mph without a
241
+ buffer, more than 600 veh/h per lane, bike lane narrower than 5 ft, mixed
242
+ traffic above 25 mph, unbuffered bike lane next to parking) are **screening
243
+ heuristics** with defaults you set through `ComfortThresholds`.
244
+
245
+ ### Related package
246
+ For **Bicycle Level of Traffic Stress** (LTS 1-4, Mekuria, Furth & Nixon 2012)
247
+ use [`bikelts`](https://pypi.org/project/bikelts/). `streetlos` gives the
248
+ perception-based LOS scores and walking measures; `bikelts` gives the stress
249
+ classification and low-stress connectivity.
250
+
251
+ ---
252
+
253
+ ## Limitations
254
+
255
+ - **Screening, not a full HCM analysis.** Intersection LOS, mid-segment
256
+ crossing difficulty, pedestrian delay and facility (multi-segment) aggregation
257
+ are not implemented.
258
+ - The segment models were calibrated on US urban streets, in US units. Results
259
+ elsewhere (for example in Türkiye) indicate relative quality; they are not
260
+ calibrated perceptions.
261
+ - The HCM 2010 bicycle width rule counts the bike lane and shoulder twice when
262
+ their combined width is at least 4 ft (as restated by the Lewis Center paper).
263
+ It is implemented as published. Wide, low-volume cross sections can give
264
+ negative scores, which map to LOS A.
265
+ - Walking speed is taken as constant; the speed-flow reduction of newer HCM
266
+ editions is not applied. Pass `walk_speed_ft_s` if you have a measured speed.
267
+ - **Not verified from an open source:** the street-furniture effective widths
268
+ in `walkway.OBSTRUCTION_WIDTH_FT` (midpoints recalled from the HCM 2000
269
+ fixed-object table), and the use of walkway space breakpoints for corner and
270
+ crosswalk circulation area (`CORNER_CROSSWALK_SPACE`, flagged `verified=False`).
271
+ - Comfort thresholds other than the PROWAG widths are heuristics.
272
+
273
+ ---
274
+
275
+ ## Development
276
+
277
+ ```bash
278
+ pip install -e ".[dev]"
279
+ python -m pytest
280
+ python -m ruff check . && python -m ruff format --check src tests
281
+ python -m mypy src
282
+ ```
283
+
284
+ ## Academic citation
285
+
286
+ ```bibtex
287
+ @software{eminoglu_streetlos,
288
+ author = {Eminoğlu, Yusuf},
289
+ title = {streetlos},
290
+ year = {2026},
291
+ version = {0.1.0},
292
+ url = {https://gitlab.com/geophilo1/streetlos_sdk}
293
+ }
294
+ ```
295
+
296
+ ## License
297
+
298
+ MIT © 2026 Yusuf Eminoğlu. Contact: geospacephilo@gmail.com
@@ -0,0 +1,263 @@
1
+ # streetlos
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/streetlos.svg?color=3b82f6)](https://pypi.org/project/streetlos/)
4
+ [![Python version support](https://img.shields.io/pypi/pyversions/streetlos.svg?color=10b981)](https://pypi.org/project/streetlos/)
5
+ [![pipeline](https://gitlab.com/geophilo1/streetlos_sdk/badges/main/pipeline.svg)](https://gitlab.com/geophilo1/streetlos_sdk/-/pipelines)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitlab.com/geophilo1/streetlos_sdk/-/blob/main/LICENSE)
7
+
8
+ **Multimodal street level-of-service screening for walking and cycling.**
9
+
10
+ `streetlos` scores street segments for pedestrians and cyclists from a plain CSV
11
+ of street attributes. It is written for planners and researchers who need a
12
+ transparent, reproducible screening (which streets look poor, and why) rather
13
+ than a black box. Every threshold table is cited and can be overridden.
14
+
15
+ - **Walkway LOS** by space per pedestrian and unit flow rate, with the
16
+ average-flow and the **platoon-adjusted** criteria.
17
+ - **Effective sidewalk width** after shy distances and street furniture.
18
+ - **Corner and crosswalk circulation area** with the time-space method.
19
+ - **Pedestrian and bicycle segment LOS scores** from NCHRP Report 616
20
+ (Dowling et al. 2008), in the form adopted by HCM 2010.
21
+ - **Comfort indicators**: clear width against the PROWAG minimum, buffer,
22
+ traffic speed and volume per lane, bike lane width and door-zone exposure.
23
+ - **CLI**: CSV of segments in, LOS table out. US (ft, mph) or SI (m, km/h) units.
24
+
25
+ No runtime dependencies: the standard library is enough.
26
+
27
+ ```bash
28
+ pip install streetlos
29
+ ```
30
+
31
+ Requires Python 3.9 or newer.
32
+
33
+ > **About the HCM.** The *Highway Capacity Manual* is a copyrighted publication
34
+ > of the Transportation Research Board. `streetlos` does not reproduce its text.
35
+ > It implements published equations and numeric thresholds, cites the openly
36
+ > accessible documents they were checked against, and lets you replace every
37
+ > table (for example with the values of the HCM edition your agency uses).
38
+
39
+ ---
40
+
41
+ ## Quickstart
42
+
43
+ ```python
44
+ import streetlos as sl
45
+
46
+ # Walkway: 8.5 ft effective width, 600 pedestrians in the peak 15 minutes
47
+ w = sl.walkway_los(8.5, 600)
48
+ print(w.unit_flow_p_min_ft, w.space_ft2_p, w.los) # 4.71 56.1 'B'
49
+ print(sl.walkway_los(8.5, 600, platoon=True).los) # 'C'
50
+
51
+ # Effective width: 10 ft sidewalk, building facade, no buffer, a light pole
52
+ sl.effective_walkway_width(10, building_edge="building", obstructions=["light_pole"]) # 3.5
53
+
54
+ # Pedestrian segment LOS score for one side of the street
55
+ p = sl.pedestrian_link_score(
56
+ outside_lane_ft=12, bike_lane_ft=5, shoulder_ft=8, parking_occupancy=0.5,
57
+ buffer_ft=4, sidewalk_ft=6, volume_vph=800, through_lanes=2, running_speed_mph=30,
58
+ )
59
+ print(round(p.score, 3), p.los) # 1.997 'A'
60
+
61
+ # Bicycle segment LOS score for one direction
62
+ b = sl.bicycle_link_score(
63
+ outside_lane_ft=12, bike_lane_ft=5, volume_vph=800, through_lanes=2,
64
+ running_speed_mph=35, heavy_vehicle_pct=2, pavement_rating=4,
65
+ )
66
+ print(round(b.score, 3), b.los) # 2.232 'B'
67
+
68
+ # Corner circulation area (time-space)
69
+ c = sl.corner_circulation(10, 12, 15, cycle_s=90, circulating_peds_per_cycle=120,
70
+ waiting=[(20, 60), (25, 55)])
71
+ print(round(c.space_ft2_p, 2), c.los) # 4.9 'F'
72
+ ```
73
+
74
+ ### Command line
75
+
76
+ ```bash
77
+ streetlos segments.csv -o segments_los.csv # US units (ft, mph)
78
+ streetlos segments.csv --units si # metres, km/h -> segments_los.csv
79
+ streetlos segments.csv --platoon # platoon-adjusted walkway criteria
80
+ streetlos segments.csv --tables my_tables.json # override breakpoints
81
+ streetlos --list-tables # print tables and sources
82
+ ```
83
+
84
+ One row per segment side (pedestrian) or direction (bicycle). Recognised columns
85
+ (all optional; a model runs only when its inputs are present, and `notes` says
86
+ what was skipped):
87
+
88
+ | column | meaning | unit (us / si) |
89
+ |---|---|---|
90
+ | `segment_id` | identifier, copied through | |
91
+ | `outside_lane` | outside through lane width | ft / m |
92
+ | `bike_lane` | bicycle lane width | ft / m |
93
+ | `shoulder` | paved shoulder or parking lane width | ft / m |
94
+ | `curb` | curb present (yes/no, default yes) | |
95
+ | `parking_occupancy` | share of on-street parking occupied, 0-1 | |
96
+ | `parking_striped` | parking spaces striped (yes/no) | |
97
+ | `buffer` | buffer between sidewalk and road | ft / m |
98
+ | `barrier` | continuous barrier at least 3 ft high in the buffer | |
99
+ | `sidewalk_width` | sidewalk width, excluding the buffer | ft / m |
100
+ | `building_edge` | `none`, `building`, `window_display`, `fence`, `low_wall` | |
101
+ | `obstructions` | `;`-separated names or widths in the walking path | ft / m |
102
+ | `volume_vph` | motor vehicle flow in this direction | veh/h |
103
+ | `through_lanes` | through lanes in this direction | |
104
+ | `speed` | motor vehicle running speed | mph / km/h |
105
+ | `heavy_vehicle_pct` | heavy vehicles | % |
106
+ | `pavement_rating` | pavement condition, 0.5-5 (default 4) | |
107
+ | `divided` | divided street (yes/no) | |
108
+ | `ped_volume_15min` / `ped_volume_hour` + `phf` | two-way pedestrian volume | p |
109
+ | `walk_speed` | walking speed (default 4.4 ft/s) | ft/s / m/s |
110
+ | `facility` | `none`, `shared`, `bike_lane`, `buffered_lane`, `separated`, `path` | |
111
+ | `bike_buffer` | buffer beside the bike lane | ft / m |
112
+
113
+ Output columns: effective width, unit flow, space per pedestrian, walkway LOS
114
+ (space, flow, overall), pedestrian score and LOS, bicycle score and LOS,
115
+ `ped_flags`, `bike_flags`, `notes`. See `examples/segments.csv`.
116
+
117
+ Override file format (`--tables`): `{"walkway_flow": [5, 7, 10, 15, 23]}`, i.e.
118
+ five A-E breakpoints per table name (`streetlos --list-tables` shows the names).
119
+
120
+ ---
121
+
122
+ ## API overview
123
+
124
+ | function | purpose |
125
+ |---|---|
126
+ | `walkway_los(width, peds_15min, platoon=False)` | walkway LOS by space and flow; worse governs |
127
+ | `effective_walkway_width(total, building_edge, has_buffer, obstructions)` | effective width W_E |
128
+ | `unit_flow_rate`, `pedestrian_space` | v_p = v15 / (15 W_E); A_p = 60 S_p / v_p |
129
+ | `corner_circulation`, `crosswalk_circulation` | time-space circulation area per pedestrian |
130
+ | `pedestrian_link_score(...)` | NCHRP 616 / HCM 2010 pedestrian link score, factors and LOS |
131
+ | `bicycle_link_score(...)` | NCHRP 616 / HCM 2010 bicycle link score, factors and LOS |
132
+ | `pedestrian_comfort`, `bicycle_facility` | screening indicators and flags (`ComfortThresholds`) |
133
+ | `evaluate_segment`, `evaluate_rows`, `evaluate_csv` | batch evaluation of segment tables |
134
+ | `LosTable`, `DEFAULT_TABLES`, `tables_with_overrides` | inspect and replace thresholds |
135
+
136
+ All functions take US customary units (ft, mph, veh/h), because that is how the
137
+ models were calibrated. `streetlos.units` converts from SI.
138
+
139
+ ---
140
+
141
+ ## Method and sources
142
+
143
+ ### Walkway LOS
144
+ Unit flow `v_p = v_15 / (15 W_E)` (p/min/ft) and space `A_p = 60 S_p / v_p`
145
+ (ft²/p), where `S_p` defaults to 4.4 ft/s (3.3 ft/s where more than 20 % of
146
+ pedestrians are elderly). Breakpoints:
147
+
148
+ | LOS | space, ft²/p | flow, p/min/ft | platoon space | platoon flow |
149
+ |---|---|---|---|---|
150
+ | A | > 60 | ≤ 5 | > 530 | ≤ 0.5 |
151
+ | B | > 40 | ≤ 7 | > 90 | ≤ 3 |
152
+ | C | > 24 | ≤ 10 | > 40 | ≤ 6 |
153
+ | D | > 15 | ≤ 15 | > 23 | ≤ 11 |
154
+ | E | > 8 | ≤ 23 | > 11 | ≤ 18 |
155
+ | F | ≤ 8 | > 23 | ≤ 11 | > 18 |
156
+
157
+ Sources: Rouphail et al. (1998) FHWA-RD-98-107, Tables 4 and 6 (adopted in HCM
158
+ 2000); NYC Department of City Planning (2006), *Pedestrian Level of Service
159
+ Study, Phase I*, Tables 2.1-2.2. The original platoon research is Pushkarev &
160
+ Zupan (1975), *Urban Space for Pedestrians*.
161
+
162
+ ### Effective width
163
+ Building-side shy distance (3 ft window display, 2 ft building facade, 1.5 ft
164
+ fence or low wall), 1.5 ft curb shy distance where there is no buffer, and the
165
+ effective width of obstructions in the walking path (HCM 6th edition values as
166
+ reported by McTrans). The default street-furniture widths are **not verified**
167
+ (see Limitations); measure them or pass numbers.
168
+
169
+ ### Corners and crosswalks (time-space)
170
+ Fruin's time-space concept as used by the HCM: available time-space
171
+ (area × cycle) minus the time-space held by waiting pedestrians, divided by the
172
+ pedestrian occupancy time. The corner area loses `(1 − π/4) R² ≈ 0.215 R²` to
173
+ the curb return; waiting time per cycle for uniform arrivals is `N r² / (2C)`;
174
+ circulation time is the HCM constant of 4 s per pedestrian, or Fruin, Ketcham
175
+ and Hecht's `0.12 (W_a + W_b) + 1.4` s (`fruin_circulation_time`). See
176
+ FHWA-RD-98-107 Section 4.
177
+
178
+ ### Pedestrian segment (link) LOS score
179
+ `I_p = 6.0468 + F_w + F_v + F_s`, with
180
+ `F_w = −1.2276 ln(W_v + 0.5 W_1 + 50 p_pk + W_buf f_b + W_aA f_sw)`,
181
+ `F_v = 0.0091 v_m / (4 N_th)` and `F_s = 4 (S_R/100)²`, plus the HCM 2010
182
+ width adjustments (`f_b = 5.37` with a continuous barrier, `f_sw = 6.0 − 0.3 W_aA`,
183
+ `W_aA ≤ 10 ft`, volume-adjusted `W_v`, parking-dependent `W_1`). If a pedestrian
184
+ space is known, the reported LOS is the worse of the score LOS and the space LOS.
185
+
186
+ ### Bicycle segment (link) LOS score
187
+ `I_b = 0.760 + F_w + F_v + F_s + F_p`, with `F_w = −0.005 W_e²`,
188
+ `F_v = 0.507 ln(v_ma / (4 N_th))`,
189
+ `F_s = 0.199 [1.1199 ln(S_Ra − 20) + 0.8103] (1 + 0.1038 P_HVa)²` and
190
+ `F_p = 7.066 / P_c²`, plus the adjustments `S_Ra ≥ 21 mph`, `v_ma ≥ 4 N_th`
191
+ and the 50 % heavy-vehicle cap at low volumes.
192
+
193
+ Score letters (both models): A ≤ 2.00, B ≤ 2.75, C ≤ 3.50, D ≤ 4.25, E ≤ 5.00, F > 5.00.
194
+
195
+ Sources: Dowling et al. (2008), *Multimodal Level of Service Analysis for Urban
196
+ Streets*, NCHRP Report 616 (note its published erratum for the pedestrian
197
+ segment equation); HCM 2010 Chapter 17, checked against the open restatement in
198
+ Lewis Center for Regional Policy Studies, UCLA (2014), *HCM Bicycle and
199
+ Pedestrian Level of Service: The Ultimate White Paper*. The models descend from
200
+ Landis et al. (1997, TRR 1578) and Landis et al. (2001, TRR 1773).
201
+
202
+ ### Comfort indicators
203
+ Clear width is checked against the 4.0 ft (1.2 m) minimum and 5.0 ft passing
204
+ width of the US Access Board's Public Right-of-Way Accessibility Guidelines
205
+ (36 CFR Part 1190, R302.3-R302.4). The other flags (speed above 30 mph without a
206
+ buffer, more than 600 veh/h per lane, bike lane narrower than 5 ft, mixed
207
+ traffic above 25 mph, unbuffered bike lane next to parking) are **screening
208
+ heuristics** with defaults you set through `ComfortThresholds`.
209
+
210
+ ### Related package
211
+ For **Bicycle Level of Traffic Stress** (LTS 1-4, Mekuria, Furth & Nixon 2012)
212
+ use [`bikelts`](https://pypi.org/project/bikelts/). `streetlos` gives the
213
+ perception-based LOS scores and walking measures; `bikelts` gives the stress
214
+ classification and low-stress connectivity.
215
+
216
+ ---
217
+
218
+ ## Limitations
219
+
220
+ - **Screening, not a full HCM analysis.** Intersection LOS, mid-segment
221
+ crossing difficulty, pedestrian delay and facility (multi-segment) aggregation
222
+ are not implemented.
223
+ - The segment models were calibrated on US urban streets, in US units. Results
224
+ elsewhere (for example in Türkiye) indicate relative quality; they are not
225
+ calibrated perceptions.
226
+ - The HCM 2010 bicycle width rule counts the bike lane and shoulder twice when
227
+ their combined width is at least 4 ft (as restated by the Lewis Center paper).
228
+ It is implemented as published. Wide, low-volume cross sections can give
229
+ negative scores, which map to LOS A.
230
+ - Walking speed is taken as constant; the speed-flow reduction of newer HCM
231
+ editions is not applied. Pass `walk_speed_ft_s` if you have a measured speed.
232
+ - **Not verified from an open source:** the street-furniture effective widths
233
+ in `walkway.OBSTRUCTION_WIDTH_FT` (midpoints recalled from the HCM 2000
234
+ fixed-object table), and the use of walkway space breakpoints for corner and
235
+ crosswalk circulation area (`CORNER_CROSSWALK_SPACE`, flagged `verified=False`).
236
+ - Comfort thresholds other than the PROWAG widths are heuristics.
237
+
238
+ ---
239
+
240
+ ## Development
241
+
242
+ ```bash
243
+ pip install -e ".[dev]"
244
+ python -m pytest
245
+ python -m ruff check . && python -m ruff format --check src tests
246
+ python -m mypy src
247
+ ```
248
+
249
+ ## Academic citation
250
+
251
+ ```bibtex
252
+ @software{eminoglu_streetlos,
253
+ author = {Eminoğlu, Yusuf},
254
+ title = {streetlos},
255
+ year = {2026},
256
+ version = {0.1.0},
257
+ url = {https://gitlab.com/geophilo1/streetlos_sdk}
258
+ }
259
+ ```
260
+
261
+ ## License
262
+
263
+ MIT © 2026 Yusuf Eminoğlu. Contact: geospacephilo@gmail.com