# jp-station-neighborhoods

> Generate ekiseiken (station catchment areas) for Japanese railway stations using Voronoi tessellation.

## Install

```
pip install jp-station-neighborhoods
```

## Public API

```python
from jp_station_neighborhoods import (
    run_station_neighborhoods,
    fetch_stations,
    cluster_stations,
    build_neighborhoods,
    download_boundaries,
    build_map,
    PREFECTURE_BBOX,
)
```

### run_station_neighborhoods(boundaries_gdf, bbox, output_dir=..., prefix="tokyo") -> GeoDataFrame
Full pipeline: fetch stations from OSM -> DBSCAN cluster -> Voronoi tessellate -> save outputs -> build map.
- `boundaries_gdf`: Admin boundary polygons (EPSG:4326)
- `bbox`: (west, south, east, north) in WGS84
- Returns neighborhood polygons with importance_class, station_count, line_count, neighborhood_area_km2

### fetch_stations(bbox, cache_dir) -> GeoDataFrame
Fetch railway stations from OSM Overpass API. Returns points with osm_id, name, name_en, line_count, geometry.

### cluster_stations(stations_gdf) -> GeoDataFrame
DBSCAN clustering (400m eps). Groups nearby stations into blocks. Returns centroids with block_id, station_block_name, importance_class (major_hub/medium/minor).

### build_neighborhoods(blocks_gdf, study_area) -> GeoDataFrame
Voronoi tessellation clipped to buffer circles (1500m major, 1200m others) and study area. Returns non-overlapping polygons.

### download_boundaries(prefecture=None, scope="prefecture", cache_dir=...) -> GeoDataFrame
Download MLIT N03 admin boundaries. scope="prefecture" for municipalities, "country" for all 47 prefectures.

### build_map(neighborhoods_gdf, stations_gdf, output_path) -> None
Interactive Folium HTML map with color-coded neighborhoods and station markers.

### PREFECTURE_BBOX: dict[str, tuple[float, float, float, float]]
Bounding boxes for all 47 prefectures. Keys are lowercase romaji (e.g. "tokyo", "osaka").

## Common Pattern

```python
from jp_station_neighborhoods import download_boundaries, run_station_neighborhoods, PREFECTURE_BBOX

boundaries = download_boundaries(prefecture="osaka")
neighborhoods = run_station_neighborhoods(
    boundaries_gdf=boundaries,
    bbox=PREFECTURE_BBOX["osaka"],
    prefix="osaka",
)
```

## Key Details
- CRS: EPSG:6677 for internal projected operations, EPSG:4326 for all outputs
- Cache: ~/.cache/jp-station-neighborhoods/ (raw JSON, processed parquet, maps)
- Overpass API has rate limits; responses are cached locally after first fetch
- Requires Python >= 3.10
