Spaces:
Paused
Paused
Download app/services/integrated_analysis.py from SM737/satquery-api: direct link, hf CLI and curl.
- Browser
- Download file 2.95 kB
-
https://huggingface.co/spaces/SM737/satquery-api/resolve/main/app/services/integrated_analysis.py
- Command line
-
hf download hf://spaces/SM737/satquery-api/app/services/integrated_analysis.py
-
curl -L -o integrated_analysis.py https://huggingface.co/spaces/SM737/satquery-api/resolve/main/app/services/integrated_analysis.py
2.95 kB
| """Use the imported surface specialists only for single-image surface tasks.""" | |
| from pathlib import Path | |
| from app.schemas import AnalysisResponse, AnalysisSummary, SummaryMetric | |
| from app.schemas import TaskType | |
| from app.services.planner import plan_query | |
| def uses_surface_pipeline(query: str, pair_type: str, image_count: int, modality: str = "optical") -> bool: | |
| plan = plan_query(query, image_count, pair_type) | |
| surface_tasks = {TaskType.WATER_ANALYSIS, TaskType.LAND_COVER, TaskType.BUILDINGS} | |
| surface_subtasks = {"water_analysis", "land_cover", "built_up_analysis", "building_detection"} | |
| return ( | |
| image_count == 1 | |
| and modality in {"optical", "multispectral"} | |
| and pair_type not in {"bi_temporal", "optical_sar"} | |
| and ( | |
| plan.task in surface_tasks | |
| or (plan.task == TaskType.GROUNDING and plan.target in {"water", "land_cover", "built-up"}) | |
| ) | |
| and set(plan.sub_tasks).issubset(surface_subtasks) | |
| ) | |
| async def analyze( | |
| *, | |
| result_id: str, | |
| query: str, | |
| pair_type: str, | |
| image_paths: list[Path], | |
| output_dir: Path, | |
| ) -> AnalysisResponse: | |
| modality = "unknown" | |
| if len(image_paths) == 1: | |
| from app.services.croma_pipeline import inspect_modality | |
| modality = inspect_modality(image_paths[0]).modality | |
| if not uses_surface_pipeline(query, pair_type, len(image_paths), modality): | |
| # Keep the current project's SAR, change, vegetation, VQA, and other | |
| # analysis routes and models unchanged. | |
| from app.services.orchestrator import analyze as analyze_current | |
| return await analyze_current( | |
| result_id=result_id, | |
| query=query, | |
| pair_type=pair_type, | |
| image_paths=image_paths, | |
| output_dir=output_dir, | |
| ) | |
| from satquery_engine.services.execution import analyze as run_engine | |
| from satquery_engine.services.report import write_manifest | |
| result = await run_engine( | |
| result_id=result_id, | |
| query=query, | |
| pair_type=pair_type, | |
| image_paths=image_paths, | |
| output_dir=output_dir, | |
| ) | |
| payload = result.model_dump(mode="json") | |
| # The current dashboard expects this summary field. Use the canonical answer | |
| # verbatim so that counts, areas, and limitations cannot drift from the report. | |
| verdict = result.verdict | |
| payload["summary"] = AnalysisSummary( | |
| title="ANALYSIS SUMMARY", | |
| headline=verdict.answer, | |
| explanation=verdict.answer, | |
| metrics=[SummaryMetric(label="Status", value=verdict.status.value.replace("_", " ").title())], | |
| is_insufficient=verdict.status.value in { | |
| "insufficient_evidence", "invalid_input", "unsupported_task", "model_unavailable" | |
| }, | |
| ).model_dump(mode="json") | |
| response = AnalysisResponse.model_validate(payload) | |
| write_manifest(output_dir, response.model_dump(mode="json")) | |
| return response | |