chore: initialize insar management system v2

This commit is contained in:
2026-04-14 13:16:01 +08:00
commit ecc72ec9cd
361 changed files with 2142522 additions and 0 deletions
@@ -0,0 +1,201 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
import os
import shelve
import shutil
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional
def choose_path(scene: Dict[str, Any], primary_key: str, fallback_key: str) -> str:
primary = scene.get(primary_key)
fallback = scene.get(fallback_key)
for candidate in (primary, fallback):
if candidate and Path(candidate).exists():
return str(Path(candidate))
raise FileNotFoundError(
f"Neither {primary_key} nor {fallback_key} exists for scene {scene.get('date') or scene.get('imaging_date')}"
)
def load_manifest(path: Path) -> Dict[str, Any]:
return json.loads(path.read_text(encoding="utf-8"))
def remove_existing_shelve(stem: Path) -> None:
for suffix in ("", ".db", ".dat", ".dir", ".bak"):
candidate = Path(str(stem) + suffix)
if candidate.exists():
if candidate.is_dir():
shutil.rmtree(candidate)
else:
candidate.unlink()
def shelve_stem_exists(stem: Path) -> bool:
for suffix in ("", ".db", ".dat", ".dir", ".bak"):
if Path(str(stem) + suffix).exists():
return True
return False
@dataclass
class SceneResult:
date: str
output_dir: str
slc_path: str
data_shelve: str
status: str
bytes_written: Optional[int]
started_at_utc: str
ended_at_utc: str
def materialize_one_scene(
scene: Dict[str, Any],
force: bool,
) -> SceneResult:
import isce
from isceobj.Sensor import createSensor
date = str(scene["date"])
output_dir = Path(scene["target_dir_wsl"])
output_dir.mkdir(parents=True, exist_ok=True)
slc_path = Path(scene["expected_slc_wsl"])
slc_xml_path = Path(scene["expected_slc_xml_wsl"])
data_shelve = Path(scene["expected_data_shelve_wsl"])
tiff_path = choose_path(scene, "source_tiff_wsl", "source_tiff_windows")
orbit_xml = choose_path(scene, "orbit_xml_wsl", "orbit_xml_windows")
if force:
for path in (slc_path, slc_xml_path, Path(str(slc_path) + ".vrt")):
if path.exists():
path.unlink()
remove_existing_shelve(data_shelve)
if slc_path.exists() and slc_xml_path.exists() and shelve_stem_exists(data_shelve):
now = datetime.utcnow().replace(microsecond=0).isoformat() + "Z"
return SceneResult(
date=date,
output_dir=str(output_dir),
slc_path=str(slc_path),
data_shelve=str(data_shelve),
status="skipped_existing",
bytes_written=slc_path.stat().st_size,
started_at_utc=now,
ended_at_utc=now,
)
started_at = datetime.utcnow().replace(microsecond=0).isoformat() + "Z"
sensor = createSensor("LUTAN1")
sensor.configure()
sensor.tiff = tiff_path
sensor.orbitFile = orbit_xml
sensor.output = str(slc_path)
sensor.extractImage()
sensor.extractDoppler()
sensor.frame.getImage().renderHdr()
remove_existing_shelve(data_shelve)
with shelve.open(str(data_shelve)) as db:
db["frame"] = sensor.frame
ended_at = datetime.utcnow().replace(microsecond=0).isoformat() + "Z"
report = {
"date": date,
"source_tiff": tiff_path,
"orbit_xml": orbit_xml,
"output_slc": str(slc_path),
"output_slc_xml": str(slc_xml_path),
"data_shelve": str(data_shelve),
"frame_lines": sensor.frame.getNumberOfLines(),
"frame_samples": sensor.frame.getNumberOfSamples(),
"started_at_utc": started_at,
"ended_at_utc": ended_at,
}
(output_dir / "materialization_report.json").write_text(
json.dumps(report, indent=2, ensure_ascii=False),
encoding="utf-8",
)
return SceneResult(
date=date,
output_dir=str(output_dir),
slc_path=str(slc_path),
data_shelve=str(data_shelve),
status="materialized",
bytes_written=slc_path.stat().st_size if slc_path.exists() else None,
started_at_utc=started_at,
ended_at_utc=ended_at,
)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Materialize LT-1 stack acquisitions into stripmapStack-ready SLC/date directories."
)
parser.add_argument(
"--stack-manifest",
required=True,
help="Path to stack_input_manifest.json generated by build_lt1_stack_prep.py",
)
parser.add_argument(
"--dates",
nargs="+",
default=None,
help="Optional subset of acquisition dates to materialize, for example 20250510 20250705",
)
parser.add_argument(
"--force",
action="store_true",
help="Overwrite existing .slc/.xml/data outputs for the selected dates.",
)
return parser.parse_args()
def main() -> int:
args = parse_args()
manifest_path = Path(args.stack_manifest)
if not manifest_path.exists():
raise FileNotFoundError(f"Stack manifest not found: {manifest_path}")
manifest = load_manifest(manifest_path)
scenes = list(manifest.get("scenes", []))
if not scenes:
raise ValueError(f"No scenes found in stack manifest: {manifest_path}")
selected_dates = set(args.dates or [])
if selected_dates:
scenes = [scene for scene in scenes if str(scene["date"]) in selected_dates]
if not scenes:
raise ValueError(f"No matching dates found in manifest for selection: {sorted(selected_dates)}")
results: List[SceneResult] = []
for scene in scenes:
print(f"Materializing {scene['date']} -> {scene['target_dir_wsl']}")
result = materialize_one_scene(scene, force=args.force)
results.append(result)
print(f" status={result.status} slc={result.slc_path}")
report = {
"generated_at_utc": datetime.utcnow().replace(microsecond=0).isoformat() + "Z",
"stack_manifest": str(manifest_path),
"results": [result.__dict__ for result in results],
}
report_path = manifest_path.parent / "materialization_summary.json"
report_path.write_text(json.dumps(report, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"Summary: {report_path}")
return 0
if __name__ == "__main__":
raise SystemExit(main())