Spaces:
Sleeping
Sleeping
Upload 3 files
#2
by ESJL - opened
app.py
CHANGED
|
@@ -1589,22 +1589,27 @@ def _select_best_polygon_row(
|
|
| 1589 |
return rank.iloc[0], float("nan"), alerts
|
| 1590 |
|
| 1591 |
|
| 1592 |
-
def
|
| 1593 |
polygons: PolygonContext,
|
| 1594 |
numbloco: Any,
|
| 1595 |
x: float | None = None,
|
| 1596 |
y: float | None = None,
|
| 1597 |
-
) -> tuple[
|
| 1598 |
if not polygons.has_data or not polygons.numbloco_key_index:
|
| 1599 |
-
return
|
| 1600 |
|
| 1601 |
key = _normalize_numbloco_key(numbloco)
|
| 1602 |
if not key:
|
| 1603 |
-
return
|
| 1604 |
|
| 1605 |
candidate_idx = polygons.numbloco_key_index.get(key)
|
| 1606 |
if not candidate_idx:
|
| 1607 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1608 |
|
| 1609 |
point = None
|
| 1610 |
x_number = _to_float(x)
|
|
@@ -1620,11 +1625,29 @@ def _infer_polygon_context_by_numbloco(
|
|
| 1620 |
matches = polygons.gdf.loc[candidate_idx]
|
| 1621 |
row, polygon_distance, alerts = _select_best_polygon_row(polygons, matches, point)
|
| 1622 |
if row is None:
|
| 1623 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1624 |
|
| 1625 |
if len(candidate_idx) > 1:
|
| 1626 |
alerts.append(f"NUMBLOCO encontrado em {len(candidate_idx)} poligonos; aplicado desempate deterministico.")
|
| 1627 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1628 |
values, sources, _ = _polygon_row_to_context(polygons, row, "poligono_numbloco", polygon_distance)
|
| 1629 |
return values, sources, alerts
|
| 1630 |
|
|
@@ -2492,6 +2515,75 @@ def initialize_app_state(base_dir: Path = BASE_DIR) -> AppState:
|
|
| 2492 |
APP_STATE = initialize_app_state(BASE_DIR)
|
| 2493 |
|
| 2494 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2495 |
def predict(
|
| 2496 |
area: float,
|
| 2497 |
numbloco: str,
|
|
@@ -2845,6 +2937,11 @@ with gr.Blocks(title=APP_TITLE) as demo:
|
|
| 2845 |
],
|
| 2846 |
outputs=[result_markdown, details_json, report_file],
|
| 2847 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2848 |
autofill_button.click(
|
| 2849 |
fn=preencher_por_coordenadas,
|
| 2850 |
inputs=[numbloco_input, lat_input, lon_input],
|
|
|
|
| 1589 |
return rank.iloc[0], float("nan"), alerts
|
| 1590 |
|
| 1591 |
|
| 1592 |
+
def _select_polygon_row_by_numbloco(
|
| 1593 |
polygons: PolygonContext,
|
| 1594 |
numbloco: Any,
|
| 1595 |
x: float | None = None,
|
| 1596 |
y: float | None = None,
|
| 1597 |
+
) -> tuple[pd.Series | None, float, list[str], int]:
|
| 1598 |
if not polygons.has_data or not polygons.numbloco_key_index:
|
| 1599 |
+
return None, float("nan"), [], 0
|
| 1600 |
|
| 1601 |
key = _normalize_numbloco_key(numbloco)
|
| 1602 |
if not key:
|
| 1603 |
+
return None, float("nan"), [], 0
|
| 1604 |
|
| 1605 |
candidate_idx = polygons.numbloco_key_index.get(key)
|
| 1606 |
if not candidate_idx:
|
| 1607 |
+
return (
|
| 1608 |
+
None,
|
| 1609 |
+
float("nan"),
|
| 1610 |
+
[f"NUMBLOCO `{_safe_text(numbloco, '')}` nao encontrado no geoparquet enriquecido; usada busca espacial."],
|
| 1611 |
+
0,
|
| 1612 |
+
)
|
| 1613 |
|
| 1614 |
point = None
|
| 1615 |
x_number = _to_float(x)
|
|
|
|
| 1625 |
matches = polygons.gdf.loc[candidate_idx]
|
| 1626 |
row, polygon_distance, alerts = _select_best_polygon_row(polygons, matches, point)
|
| 1627 |
if row is None:
|
| 1628 |
+
return (
|
| 1629 |
+
None,
|
| 1630 |
+
float("nan"),
|
| 1631 |
+
[f"NUMBLOCO `{_safe_text(numbloco, '')}` sem linha utilizavel no geoparquet; usada busca espacial."],
|
| 1632 |
+
len(candidate_idx),
|
| 1633 |
+
)
|
| 1634 |
|
| 1635 |
if len(candidate_idx) > 1:
|
| 1636 |
alerts.append(f"NUMBLOCO encontrado em {len(candidate_idx)} poligonos; aplicado desempate deterministico.")
|
| 1637 |
|
| 1638 |
+
return row, polygon_distance, alerts, len(candidate_idx)
|
| 1639 |
+
|
| 1640 |
+
|
| 1641 |
+
def _infer_polygon_context_by_numbloco(
|
| 1642 |
+
polygons: PolygonContext,
|
| 1643 |
+
numbloco: Any,
|
| 1644 |
+
x: float | None = None,
|
| 1645 |
+
y: float | None = None,
|
| 1646 |
+
) -> tuple[dict[str, Any], dict[str, str], list[str]]:
|
| 1647 |
+
row, polygon_distance, alerts, _ = _select_polygon_row_by_numbloco(polygons, numbloco, x, y)
|
| 1648 |
+
if row is None:
|
| 1649 |
+
return {}, {}, alerts
|
| 1650 |
+
|
| 1651 |
values, sources, _ = _polygon_row_to_context(polygons, row, "poligono_numbloco", polygon_distance)
|
| 1652 |
return values, sources, alerts
|
| 1653 |
|
|
|
|
| 2515 |
APP_STATE = initialize_app_state(BASE_DIR)
|
| 2516 |
|
| 2517 |
|
| 2518 |
+
def obter_lat_lon_centroide_por_numbloco(
|
| 2519 |
+
numbloco: Any,
|
| 2520 |
+
lat_atual: Any = None,
|
| 2521 |
+
lon_atual: Any = None,
|
| 2522 |
+
) -> tuple[float, float] | None:
|
| 2523 |
+
polygon_x = None
|
| 2524 |
+
polygon_y = None
|
| 2525 |
+
lon_number = _to_float(lon_atual)
|
| 2526 |
+
lat_number = _to_float(lat_atual)
|
| 2527 |
+
if (
|
| 2528 |
+
APP_STATE.polygon_context.to_base_crs is not None
|
| 2529 |
+
and lon_number is not None
|
| 2530 |
+
and lat_number is not None
|
| 2531 |
+
and -180.0 <= lon_number <= 180.0
|
| 2532 |
+
and -90.0 <= lat_number <= 90.0
|
| 2533 |
+
):
|
| 2534 |
+
try:
|
| 2535 |
+
polygon_x, polygon_y = APP_STATE.polygon_context.to_base_crs.transform(lon_number, lat_number)
|
| 2536 |
+
except Exception as exc:
|
| 2537 |
+
LOGGER.warning("Falha ao transformar coordenada atual para desempate por NUMBLOCO: %s", exc)
|
| 2538 |
+
|
| 2539 |
+
row, _, _, _ = _select_polygon_row_by_numbloco(APP_STATE.polygon_context, numbloco, polygon_x, polygon_y)
|
| 2540 |
+
if row is None:
|
| 2541 |
+
return None
|
| 2542 |
+
|
| 2543 |
+
geometry = row.get("geometry")
|
| 2544 |
+
if geometry is None or getattr(geometry, "is_empty", True):
|
| 2545 |
+
return None
|
| 2546 |
+
if hasattr(geometry, "is_valid") and not geometry.is_valid:
|
| 2547 |
+
return None
|
| 2548 |
+
|
| 2549 |
+
source_crs = getattr(APP_STATE.polygon_context.gdf, "crs", None)
|
| 2550 |
+
if source_crs is None:
|
| 2551 |
+
return None
|
| 2552 |
+
|
| 2553 |
+
try:
|
| 2554 |
+
centroid = geometry.centroid
|
| 2555 |
+
if centroid is None or getattr(centroid, "is_empty", True):
|
| 2556 |
+
return None
|
| 2557 |
+
lon_centroid, lat_centroid = Transformer.from_crs(source_crs, "EPSG:4326", always_xy=True).transform(
|
| 2558 |
+
float(centroid.x),
|
| 2559 |
+
float(centroid.y),
|
| 2560 |
+
)
|
| 2561 |
+
except Exception as exc:
|
| 2562 |
+
LOGGER.warning("Falha ao calcular centroide por NUMBLOCO: %s", exc)
|
| 2563 |
+
return None
|
| 2564 |
+
|
| 2565 |
+
lat_result = _to_float(lat_centroid)
|
| 2566 |
+
lon_result = _to_float(lon_centroid)
|
| 2567 |
+
if (
|
| 2568 |
+
lat_result is None
|
| 2569 |
+
or lon_result is None
|
| 2570 |
+
or not np.isfinite(lat_result)
|
| 2571 |
+
or not np.isfinite(lon_result)
|
| 2572 |
+
or not (-90.0 <= lat_result <= 90.0 and -180.0 <= lon_result <= 180.0)
|
| 2573 |
+
):
|
| 2574 |
+
return None
|
| 2575 |
+
return float(lat_result), float(lon_result)
|
| 2576 |
+
|
| 2577 |
+
|
| 2578 |
+
def atualizar_lat_lon_por_numbloco(numbloco: str, lat_atual: Any, lon_atual: Any) -> tuple[Any, Any]:
|
| 2579 |
+
centroide = obter_lat_lon_centroide_por_numbloco(numbloco, lat_atual, lon_atual)
|
| 2580 |
+
if centroide is None:
|
| 2581 |
+
return gr.update(), gr.update()
|
| 2582 |
+
|
| 2583 |
+
lat, lon = centroide
|
| 2584 |
+
return gr.update(value=lat), gr.update(value=lon)
|
| 2585 |
+
|
| 2586 |
+
|
| 2587 |
def predict(
|
| 2588 |
area: float,
|
| 2589 |
numbloco: str,
|
|
|
|
| 2937 |
],
|
| 2938 |
outputs=[result_markdown, details_json, report_file],
|
| 2939 |
)
|
| 2940 |
+
numbloco_input.change(
|
| 2941 |
+
fn=atualizar_lat_lon_por_numbloco,
|
| 2942 |
+
inputs=[numbloco_input, lat_input, lon_input],
|
| 2943 |
+
outputs=[lat_input, lon_input],
|
| 2944 |
+
)
|
| 2945 |
autofill_button.click(
|
| 2946 |
fn=preencher_por_coordenadas,
|
| 2947 |
inputs=[numbloco_input, lat_input, lon_input],
|