Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ versions of pandas (>= 2.2), GeoPandas (>= 1.0), scikit-learn and statsmodels.

### Added
- `crime_mapping.get_city_shape("Natal, RN, Brazil")` — thin wrapper around
`osmnx.geocode_to_gdf` returning the raw city shape.
`osmnx.geocode_to_gdf` returning the raw city shape; `osmnx` is now a core
dependency (the `osm` extra is kept, empty, for compatibility).
- `examples/natal.ipynb`: an executed end-to-end walkthrough on Natal with
synthetic data, also rendered in the documentation.
- `PredictionPipeline.evaluate` accepts a list of scorings and returns a
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Thanks for your interest in Predspot! Issues and pull requests are welcome.
git clone https://github.com/adaj/predspot.git
cd predspot
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,osm,contour]"
pip install -e ".[dev,contour,examples]"
```

## Checks
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,14 @@ Install from PyPI (Python 3.10 or newer):

```bash
pip install predspot # core
pip install "predspot[osm]" # + study areas from OpenStreetMap (osmnx)
pip install "predspot[contour]" # + GeoJSON contour export (geojsoncontour)
pip install "predspot[examples]" # + jupyter, to run the example notebooks
```

Not on PyPI yet? Install straight from GitHub:

```bash
pip install "git+https://github.com/adaj/predspot.git"
```

Basic usage example:
Expand Down Expand Up @@ -81,7 +87,7 @@ mapping = QuadratCount(tfreq='W', grid=create_gridhexagonal(study_area_gdf, reso
### Study area from OpenStreetMap and synthetic data

You do not need real data to try Predspot. Fetch a city boundary from
OpenStreetMap (`pip install "predspot[osm]"`) and generate synthetic events
OpenStreetMap and generate synthetic events
with spatial hotspots and realistic temporal patterns (trend, annual cycle,
day-of-week and hour-of-day profiles):

Expand Down Expand Up @@ -276,7 +282,7 @@ From source, for development:
```bash
git clone https://github.com/adaj/predspot.git
cd predspot
pip install -e ".[dev,osm,contour]"
pip install -e ".[dev,contour,examples]"
ruff check src tests # lint
pytest # ~10 s
```
Expand Down
9 changes: 5 additions & 4 deletions docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ Optional extras add features that need heavier dependencies:

| Extra | Installs | Enables |
|-------|----------|---------|
| `osm` | [osmnx](https://osmnx.readthedocs.io) | [`load_study_area`][predspot.crime_mapping.load_study_area] — study areas from OpenStreetMap |
| `contour` | [geojsoncontour](https://github.com/bartromgens/geojsoncontour) | [`contour_geojson`][predspot.utilities.contour_geojson] — GeoJSON contour export |
| `examples` | jupyter, nbconvert, ipykernel | Running the example notebooks |
| `dev` | pytest, ruff, build, twine | Running the test suite and building the package |

```bash
pip install "predspot[osm,contour]"
pip install "predspot[contour,examples]"
```

The core dependencies — pandas, GeoPandas, Shapely, NumPy, SciPy, scikit-learn,
statsmodels and Matplotlib — are installed automatically.
statsmodels, Matplotlib and [osmnx](https://osmnx.readthedocs.io) (study areas
from OpenStreetMap) — are installed automatically.

!!! tip "conda users"
GeoPandas and its GEOS/PROJ stack install fine from PyPI wheels nowadays,
Expand All @@ -31,7 +32,7 @@ statsmodels and Matplotlib — are installed automatically.
```bash
git clone https://github.com/adaj/predspot.git
cd predspot
pip install -e ".[dev,osm,contour]"
pip install -e ".[dev,contour,examples]"
pytest
```

Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ synthetic data so you can run it as is. Every step is explained in depth in the

Predspot needs the boundary of the region you are studying as a GeoDataFrame
with a CRS. The easiest way is to fetch it from OpenStreetMap
(`pip install "predspot[osm]"`):
(osmnx is installed with Predspot):

```python
from predspot import load_study_area
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ removed, but grid cells are only created where they intersect it.
place with [osmnx](https://osmnx.readthedocs.io) (Nominatim) and returns
its administrative boundary. Be specific — add the state and country —
so that the first match is the boundary you want; `which_result` lets you
pick another match. Requires `pip install "predspot[osm]"`.
pick another match. osmnx is installed with Predspot.

=== "From a file"

Expand Down
2 changes: 1 addition & 1 deletion examples/build_natal_notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def code(text):
6. forecast the next months and check how well the true hotspots are recovered.

Every intermediate object is displayed so you can see exactly what flows
between the steps. Requirements: `pip install "predspot[osm]" matplotlib`.
between the steps. Requirements: `pip install predspot jupyter` (or `pip install "predspot[examples]"`).
""")

code("""
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,17 @@ dependencies = [
"scikit-learn>=1.3",
"statsmodels>=0.14",
"matplotlib>=3.7",
"osmnx>=2.0",
]

[project.optional-dependencies]
contour = ["geojsoncontour>=0.4"]
osm = [] # kept for compatibility: osmnx is now a core dependency
examples = [
"jupyter>=1.0",
"nbconvert>=7",
"ipykernel>=6",
]
docs = [
"mkdocs>=1.6,<2",
"mkdocs-material>=9.5,<10",
Expand Down
9 changes: 4 additions & 5 deletions src/predspot/crime_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ def load_study_area(place, crs=WGS84, which_result=None):
"""
Fetch the boundary polygon of a place from OpenStreetMap.

Uses `osmnx <https://osmnx.readthedocs.io>`_ (optional dependency:
``pip install predspot[osm]``) to geocode ``place`` with Nominatim and
Uses `osmnx <https://osmnx.readthedocs.io>`_ to geocode ``place`` with Nominatim and
return its administrative boundary, ready to be used as the
``study_area`` of [`Dataset`][predspot.Dataset] or as the ``bbox`` of the
``create_grid*`` functions.
Expand All @@ -122,7 +121,7 @@ def load_study_area(place, crs=WGS84, which_result=None):
import osmnx as ox
except ImportError as exc:
raise ImportError(
"load_study_area requires the optional dependency `osmnx`: pip install predspot[osm]"
"load_study_area requires `osmnx` (installed with predspot): pip install osmnx"
) from exc
logger.debug("Geocoding study area %r with osmnx", place)
gdf = ox.geocode_to_gdf(place, which_result=which_result)
Expand All @@ -145,7 +144,7 @@ def get_city_shape(place_query):
A thin wrapper around ``osmnx.geocode_to_gdf`` that returns the raw
Nominatim result. Prefer [`load_study_area`][predspot.crime_mapping.load_study_area]
when you want the result validated (polygon geometry, tidy columns).
Requires the optional ``osmnx`` dependency (``pip install predspot[osm]``).
Uses ``osmnx``, installed with Predspot.

Args:
place_query (str): Name of the place, in a format Nominatim accepts,
Expand All @@ -163,7 +162,7 @@ def get_city_shape(place_query):
import osmnx as ox
except ImportError as exc:
raise ImportError(
"get_city_shape requires the optional dependency `osmnx`: pip install predspot[osm]"
"get_city_shape requires `osmnx` (installed with predspot): pip install osmnx"
) from exc
return ox.geocode_to_gdf(place_query)

Expand Down
4 changes: 2 additions & 2 deletions tests/test_load_study_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def test_load_study_area_rejects_points(monkeypatch):

def test_load_study_area_without_osmnx(monkeypatch):
monkeypatch.setitem(sys.modules, "osmnx", None)
with pytest.raises(ImportError, match="predspot\\[osm\\]"):
with pytest.raises(ImportError, match="pip install osmnx"):
load_study_area("Natal, Brazil")


Expand All @@ -82,5 +82,5 @@ def test_get_city_shape_returns_raw_geocode(monkeypatch):

def test_get_city_shape_without_osmnx(monkeypatch):
monkeypatch.setitem(sys.modules, "osmnx", None)
with pytest.raises(ImportError, match="predspot\\[osm\\]"):
with pytest.raises(ImportError, match="pip install osmnx"):
get_city_shape("Natal, RN, Brazil")
Loading