Skip to content

Commit

Permalink
Merge pull request #5 from olincollege/SV-12-query-crosswalk-geojson
Browse files Browse the repository at this point in the history
SV-12-query-crosswalk-geojson
  • Loading branch information
cory0417 authored Nov 7, 2024
2 parents 711cd75 + 234541f commit 2617a48
Show file tree
Hide file tree
Showing 31 changed files with 596 additions and 56 deletions.
7 changes: 7 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import os
import sys

sys.path.insert(0, os.path.abspath("../../tests"))
sys.path.insert(0, os.path.abspath("../../src"))
sys.path.insert(0, os.path.abspath("../../"))

# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
Expand Down
17 changes: 17 additions & 0 deletions docs/source/explanations/datasets.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Dataset Choices
===============

Since creating a synthesized dataset based on multiple datasets is a critical part of the data processing pipeline, we have to make some choices regarding the datasets that we use. This document serves to explain the significant yet non-obvious logic and choices regarding different types of datasets.


Crosswalk Dataset
*****************

The crosswalk dataset should contain polygons that represent the boundaries of the crosswalks. The dataset ideally should accurately reflect the real world, but there is an implicit understanding that the dataset may not be perfect since most cities do not have a comprehensive dataset of crosswalks. The dataset should be in a format that can be easily read by the software, such as GeoJSON. In the testing module, you'll find the tests for fetching the crosswalk dataset and mapping it for the city of Boston. We've chosen Boston for its relative ease of access to various datasets and physical proximity to the team at Olin College of Engineering.

UMass Amherst has been developing a dataset of all crosswalks in Massachusetts using computer vision model (YOLOv8) and aerial imagery. The dataset is not perfect, but it is a good starting point for our project, and has the potential to be applicable for states that also do not have a thorough catalog of their crosswalk assets. The dataset can be viewed at the `following link <https://www.arcgis.com/apps/mapviewer/index.html?url=https://gis.massdot.state.ma.us/arcgis/rest/services/Assets/Crosswalk_Poly/FeatureServer/0&source=sd>`_.

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 `following link <https://www.arcgis.com/apps/mapviewer/index.html?url=https://gis.massdot.state.ma.us/arcgis/rest/services/Roads/VMT/FeatureServer/10&source=sd>`_.
6 changes: 4 additions & 2 deletions docs/source/explanations/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ Explanations


.. toctree::
:maxdepth: 2
:caption: Contents:
:maxdepth: 1
:caption: Contents:

datasets
22 changes: 22 additions & 0 deletions docs/source/generate_test_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os

# Paths configuration
test_dir = "../../tests"
output_dir = "./tests"

if not os.path.exists(output_dir):
os.makedirs(output_dir)

# Iterate over tests files in the tests directory
for filename in os.listdir(test_dir):
if filename.startswith("test_") and filename.endswith(".py"):
module_name = filename.replace(".py", "")

# Create an .rst file for each test module
with open(os.path.join(output_dir, f"{module_name}.rst"), "w") as rst_file:
rst_file.write(f"{module_name}\n")
rst_file.write("=" * len(module_name) + "\n\n")
rst_file.write(f".. automodule:: {module_name}\n")
rst_file.write(" :members:\n")
rst_file.write(" :undoc-members:\n")
rst_file.write(" :show-inheritance:\n")
4 changes: 2 additions & 2 deletions docs/source/guides/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ How-to Guides


.. toctree::
:maxdepth: 2
:caption: Contents:
:maxdepth: 2
:caption: Contents:
13 changes: 7 additions & 6 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ Night Light documentation


.. toctree::
:maxdepth: 2
:caption: Contents:
:maxdepth: 1
:caption: Contents:

tutorials/index
guides/index
references/index
explanations/index
tutorials/index
guides/index
references/index
explanations/index
tests/index
6 changes: 4 additions & 2 deletions docs/source/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ References


.. toctree::
:maxdepth: 2
:caption: Contents:
:maxdepth: 2
:caption: Contents:

utils/index
13 changes: 13 additions & 0 deletions docs/source/references/utils/functions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Utility functions
=================

.. automodule:: night_light.utils.mapping
:members:
:undoc-members:
:show-inheritance:


.. automodule:: night_light.utils.query_geojson
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/references/utils/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Utils Module
============

.. toctree::
:maxdepth: 1

functions
14 changes: 14 additions & 0 deletions docs/source/tests/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Test Modules
============

This section contains the tests for the project.

.. toctree::
:maxdepth: 1

test_adt_query
test_crosswalk_query
test_crosswalk_mapping
test_adt_mapping
test_mapping

7 changes: 7 additions & 0 deletions docs/source/tests/test_adt_mapping.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Test Average Annual Daily Traffic Mapping
=========================================

.. automodule:: test_adt_mapping
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/tests/test_adt_query.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Test Average Annual Daily Traffic Query
=======================================

.. automodule:: test_adt_query
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/tests/test_crosswalk_mapping.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Test Crosswalk Mapping
======================

.. automodule:: test_crosswalk_mapping
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/tests/test_crosswalk_query.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Test Crosswalk Query
====================

.. automodule:: test_crosswalk_query
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/tests/test_mapping.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Test Complete Map Generation
============================

.. automodule:: test_mapping
:members:
:undoc-members:
:show-inheritance:
4 changes: 2 additions & 2 deletions docs/source/tutorials/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ Tutorials


.. toctree::
:maxdepth: 2
:caption: Contents:
:maxdepth: 2
:caption: Contents:
17 changes: 16 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
[project]
name = "night-light"
requires-python = ">=3.12"
version = "0.0.1"
readme = "README.md"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
]
dynamic = ["dependencies"]

[tool.setuptools.dynamic]
dependencies = { file = ["requirements.txt"] }

[tool.black]
line-length = 88
line-length = 88

[build-system]
requires = ["setuptools>=70.0.0"]
build-backend = "setuptools.build_meta"

1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ ultralytics~=8.3.9
requests~=2.32.3
geopandas~=1.0.1
folium~=0.18.0
pytest~=8.3.3
sphinx~=8.1.3
1 change: 1 addition & 0 deletions src/night_light/crosswalks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

21 changes: 0 additions & 21 deletions src/night_light/crosswalks/create_map.py

This file was deleted.

20 changes: 0 additions & 20 deletions src/night_light/crosswalks/query_geojson.py

This file was deleted.

18 changes: 18 additions & 0 deletions src/night_light/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from .mapping import (
create_folium_map,
Tooltip,
LAYER_STYLE_DICT,
LAYER_HIGHLIGHT_STYLE_DICT,
open_html_file,
)
from .query_geojson import fetch_geojson_data, save_geojson

__all__ = [
create_folium_map,
Tooltip,
LAYER_STYLE_DICT,
LAYER_HIGHLIGHT_STYLE_DICT,
open_html_file,
fetch_geojson_data,
save_geojson,
]
77 changes: 77 additions & 0 deletions src/night_light/utils/mapping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import os

import folium
from functools import partial

Tooltip = partial(
folium.GeoJsonTooltip,
localize=True,
sticky=True,
labels=True,
style="""
background-color: #F0EFEF;
border: 2px solid black;
border-radius: 3px;
box-shadow: 3px;
""",
)

LAYER_STYLE_DICT = {
"fillColor": "cyan",
"color": "black",
"weight": 1,
"fillOpacity": 0.5,
}

LAYER_HIGHLIGHT_STYLE_DICT = {
"fillColor": "red",
"color": "red",
"weight": 3,
"fillOpacity": 0.5,
}


def create_folium_map(
layers: list[folium.GeoJson],
center: list,
zoom_start: int,
map_filename: str,
):
"""
Create a Folium map from a GeoDataFrame and save it to an HTML file.
This function generates a Folium map centered at a specified location and zoom
level, overlays the geometries from the provided GeoDataFrame, and saves the map as
an HTML file.
Args:
layers (list[folium.GeoJson]): GeoJson layers containing geometries to be added
to the map.
center (list): A list containing the latitude and longitude for the map center
[latitude, longitude].
zoom_start (int): The initial zoom level for the map.
map_filename (str): The file path where the HTML map will be saved.
Returns:
None
"""
m = folium.Map(location=center, zoom_start=zoom_start)
for layer in layers:
layer.add_to(m)
folium.LayerControl().add_to(m)
m.save(map_filename)


def open_html_file(file_path: str | os.PathLike[str]):
file_path = os.path.abspath(file_path)

if os.name == "posix":
os.system(
f"open '{file_path}'"
if "Darwin" in os.uname().sysname
else f"xdg-open '{file_path}'"
)
elif os.name == "nt":
os.system(f"start {file_path}")
else:
print("Unsupported operating system")
Loading

0 comments on commit 2617a48

Please sign in to comment.