---
id: compute_centers_reachability_pipeline_py_pipelines
name: compute_centers_reachability_pipeline
kind: pipeline
lang: py
domain: pipelines
version: "1.0.0"
purity: impure
signature: "async def compute_centers_reachability_pipeline(origins, centers, isochrone_minutes, base_url, concurrency) -> dict"
description: "Calcula la accesibilidad de centros de servicio: matriz tiempo/distancia clientes→centros e isócronas por centro usando Valhalla."
tags: [pipeline, geo, footprint, valhalla, isochrone, matrix, reachability, pendiente-usar]
uses_functions: ["valhalla_matrix_1_to_n_py_geo", "valhalla_isochrones_async_py_geo"]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
example: |
  import asyncio
  result = asyncio.run(compute_centers_reachability_pipeline(
      origins=[(40.4168, -3.7038), (37.3891, -5.9845)],
      centers=[(41.3851, 2.1734), (43.2627, -2.9253)],
      isochrone_minutes=15,
  ))
  # result["matrix"] tiene 4 entries (2 orígenes × 2 centros)
  # result["isochrones"] tiene 2 GeoJSON dicts
tested: true
tests: ["test_compute_centers_reachability_pipeline"]
test_file_path: "python/functions/pipelines/tests/test_compute_centers_reachability_pipeline.py"
file_path: "python/functions/pipelines/compute_centers_reachability_pipeline.py"
params:
  - {name: origins, desc: "Lista de (lat, lon) de los clientes u orígenes. Coordenadas WGS84."}
  - {name: centers, desc: "Lista de (lat, lon) de los centros de servicio. Coordenadas WGS84."}
  - {name: isochrone_minutes, desc: "Minutos de tiempo de viaje para las isócronas de cada centro. Default 15."}
  - {name: base_url, desc: "URL base del servidor Valhalla. Default http://localhost:8002."}
  - {name: concurrency, desc: "Número máximo de requests async simultáneos para isócronas. Default 6."}
output: "Dict con 'matrix' (list[dict] con i,j,meters,seconds,error por par) e 'isochrones' (list[dict|None] con GeoJSON por centro)."
source_repo: "internal:footprint_aurgi"
source_license: "internal-aurgi"
source_file: "internal:composed"
---

## Ejemplo

```python
import asyncio

result = asyncio.run(compute_centers_reachability_pipeline(
    origins=[(40.4168, -3.7038), (37.3891, -5.9845)],   # Madrid, Sevilla
    centers=[(41.3851, 2.1734), (43.2627, -2.9253)],     # Barcelona, Bilbao
    isochrone_minutes=15,
    base_url="http://localhost:8002",
))

for entry in result["matrix"]:
    print(f"origen[{entry['i']}] → centro[{entry['j']}]: {entry['meters']:.0f}m / {entry['seconds']:.0f}s")

print(f"Isócronas calculadas: {sum(1 for iso in result['isochrones'] if iso is not None)}")
```

## Notas

Función async — requiere `asyncio.run(...)` o `await` dentro de un contexto async.
La matriz se calcula con threads (valhalla_matrix_1_to_n usa ThreadPoolExecutor).
Las isócronas se calculan con httpx async (valhalla_isochrones_async).
Orden de la matrix: [(0,0),(0,1),...,(0,N-1),(1,0),...,(M-1,N-1)] donde M=orígenes, N=centros.
