Skip to content

Commit

Permalink
Merge pull request #13 from olincollege/SV-22-traffic-volume
Browse files Browse the repository at this point in the history
Sv 22 traffic volume
  • Loading branch information
crane919 authored Nov 20, 2024
2 parents c661c0e + 2e323de commit 1ed431d
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 15 deletions.
4 changes: 3 additions & 1 deletion docs/source/explanations/datasets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Traffic Dataset

Since our project is focused on pedestrian safety at nighttime on crosswalks, we need a dataset that contains information about the volume of traffic. MassDOT provides a convenient dataset that includes average annual daily traffic (AADT) counts for most roads in Massachusetts. The counts will be used to inform the risk of a pedestrian being hit by a car at a given crosswalk. The dataset can be viewed at the `MassDOT Traffic Dataset <https://www.arcgis.com/apps/mapviewer/index.html?url=https://gis.massdot.state.ma.us/arcgis/rest/services/Roads/VMT/FeatureServer/10&source=sd>`_.

To estimate the danger of a road, we also need a dataset with information about speed limits per road. MassDOT provides a database (updated yearly) with speed limits for most roads in Massachusetts. This can be viewed and downloaded at `this link <https://geodot-massdot.hub.arcgis.com/search?groupIds=362562c527bb404884dd1608b4bfdb62>`

Population Density Dataset
--------------------------

Expand Down Expand Up @@ -62,4 +64,4 @@ We have chosen to use the pedestrian accidents dataset from the Vision Zero init

Vision Zero Network Community Map (February 2024)

Vision Zero initiatives are a nationwide effort to eliminate traffic fatalities and severe injuries. Growing number of cities have contributed to this effort and collected data, which will help this project be applicable outside of Boston as well.
Vision Zero initiatives are a nationwide effort to eliminate traffic fatalities and severe injuries. Growing number of cities have contributed to this effort and collected data, which will help this project be applicable outside of Boston as well.
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,3 @@ line-length = 88
[build-system]
requires = ["setuptools>=70.0.0"]
build-backend = "setuptools.build_meta"

3 changes: 2 additions & 1 deletion src/night_light/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
LAYER_HIGHLIGHT_STYLE_DICT,
open_html_file,
)
from .query_geojson import fetch_geojson_data, save_geojson
from .query_geojson import fetch_geojson_data, save_geojson, save_geodatabase_to_geojson

__all__ = [
create_folium_map,
Expand All @@ -15,4 +15,5 @@
open_html_file,
fetch_geojson_data,
save_geojson,
save_geodatabase_to_geojson,
]
26 changes: 23 additions & 3 deletions src/night_light/utils/query_geojson.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ def fetch_geojson_data(url: str, params: dict) -> gpd.GeoDataFrame:
response = requests.get(url, params=params)
response.raise_for_status()
try:
gdf = gpd.GeoDataFrame.from_features(
response.json()["features"], crs="EPSG:4326"
)
gdf = gpd.GeoDataFrame.from_features(response.json()["features"], crs="EPSG:4326")
return gdf
except KeyError:
raise ValueError("Invalid GeoJSON data")
Expand All @@ -45,3 +43,25 @@ def save_geojson(gdf: gpd.GeoDataFrame, filename: str):
None
"""
gdf.to_file(filename, driver="GeoJSON")


def save_geodatabase_to_geojson(
path_gdf: str, filename: str, params: dict = {}
) -> gpd.GeoDataFrame:
"""
Given the path to a GeoDataFrame, filter it and save it as a GeoJSON file
Args:
path_gdf (str): The file path to the GeoDataFrame location
filename (str): The file path where the GeoJSON will be saved
params (dict): Dictionary representing parameters to filter geodataframe by
Returns:
gdf: A GeoDataFrame containing the geometries and properties from
the fetched GeoJSON data
"""
gdf = gpd.read_file(filename=path_gdf)
for key, value in params.items():
gdf_filtered = gdf[gdf[key] == value]
gdf_filtered.to_file(filename, driver="GeoJSON")
return gdf_filtered
26 changes: 17 additions & 9 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from night_light.utils import query_geojson
from night_light.road_characteristics import traffic_speed_data

import pytest
import asyncio
import aiohttp
import geopandas as gpd

MA_CROSSWALK_URL = "https://gis.massdot.state.ma.us/arcgis/rest/services/Assets/Crosswalk_Poly/FeatureServer/0/query"
MA_TRAFFIC_URL = "https://gis.massdot.state.ma.us/arcgis/rest/services/Roads/VMT/FeatureServer/10/query"
MA_TRAFFIC_URL = (
"https://gis.massdot.state.ma.us/arcgis/rest/services/Roads/VMT/FeatureServer/10/query"
)
MA_MUNICIPALITIES_URL = "https://arcgisserver.digital.mass.gov/arcgisserver/rest/services/AGOL/Towns_survey_polym/FeatureServer/0/query"
BOSTON_STREETLIGHTS_URL = "https://services.evari.io/evari/rest/services/Boston/Boston_Read_Only/MapServer/0/query"

Expand All @@ -20,9 +23,7 @@
MA_MUNICIPALITIES = query_geojson.fetch_geojson_data(
url=MA_MUNICIPALITIES_URL, params=MUNICIPALITIES_MA_PARAMS
)
BOSTON_TOWN_ID = MA_MUNICIPALITIES[MA_MUNICIPALITIES["TOWN"] == "BOSTON"][
"TOWN_ID"
].values[0]
BOSTON_TOWN_ID = MA_MUNICIPALITIES[MA_MUNICIPALITIES["TOWN"] == "BOSTON"]["TOWN_ID"].values[0]

CROSSWALK_BOSTON_PARAMS = {
"where": "TOWN='BOSTON'",
Expand All @@ -46,18 +47,25 @@
}
BOSTON_CENTER_COORD = [42.3601, -71.0589]

ROAD_INVENTORY_DATA = "src/night_light/road_characteristics/RoadInventory2023.gdb"


@pytest.fixture
def boston_crosswalk():
return query_geojson.fetch_geojson_data(
url=MA_CROSSWALK_URL, params=CROSSWALK_BOSTON_PARAMS
)
return query_geojson.fetch_geojson_data(url=MA_CROSSWALK_URL, params=CROSSWALK_BOSTON_PARAMS)


@pytest.fixture
def boston_traffic():
return query_geojson.fetch_geojson_data(
url=MA_TRAFFIC_URL, params=TRAFFIC_BOSTON_PARAMS
return query_geojson.fetch_geojson_data(url=MA_TRAFFIC_URL, params=TRAFFIC_BOSTON_PARAMS)


@pytest.fixture
def boston_traffic_speed():
return query_geojson.save_geodatabase_to_geojson(
path_gdf=ROAD_INVENTORY_DATA,
filename="tests/test_road_speeds.geojson",
params={"City": BOSTON_TOWN_ID},
)


Expand Down
18 changes: 18 additions & 0 deletions tests/test_traffic_speed_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import pytest
import os
from night_light.utils import query_geojson


def test_save_boston_traffic_speed_geojson(boston_traffic_speed):
"""
Test saving Boston traffic speed data to a geojson
"""
geojson_name = "tests/test_road_speeds.geojson"
saved_gdf = query_geojson.gpd.read_file(geojson_name)

assert boston_traffic_speed.crs == saved_gdf.crs
assert list(boston_traffic_speed.columns) == list(saved_gdf.columns)
assert boston_traffic_speed.shape == saved_gdf.shape

os.remove(geojson_name)
assert not os.path.exists(geojson_name)

0 comments on commit 1ed431d

Please sign in to comment.