Full sync - all projects, memory, configs
This commit is contained in:
145
tools/ava-converter.py
Executable file
145
tools/ava-converter.py
Executable file
@ -0,0 +1,145 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
AVA GeoJSON to KML Converter
|
||||
|
||||
Downloads American Viticultural Area (AVA) boundary data from the UC Davis
|
||||
Library AVA repository and converts all GeoJSON files to KML format using
|
||||
ogr2ogr (GDAL).
|
||||
|
||||
Source: https://github.com/UCDavisLibrary/ava
|
||||
License: CC0 1.0 Universal (Public Domain)
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import glob
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
DEFAULT_OUTPUT = "/home/wdjones/.openclaw/workspace/projects/ava-kmls"
|
||||
DEFAULT_REPO = "https://github.com/UCDavisLibrary/ava.git"
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def check_ogr2ogr():
|
||||
"""Check that ogr2ogr is available."""
|
||||
if shutil.which("ogr2ogr") is None:
|
||||
log.error("ogr2ogr not found. Install GDAL:")
|
||||
log.error(" Ubuntu/Debian: sudo apt-get install gdal-bin")
|
||||
log.error(" macOS: brew install gdal")
|
||||
log.error(" Conda: conda install -c conda-forge gdal")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def clone_repo(repo_url, dest):
|
||||
"""Clone the AVA repo to a temporary directory."""
|
||||
log.info(f"Cloning {repo_url} ...")
|
||||
subprocess.run(["git", "clone", "--depth", "1", repo_url, dest],
|
||||
check=True, capture_output=True, text=True)
|
||||
log.info("Clone complete.")
|
||||
|
||||
|
||||
def convert_geojson_to_kml(src, dst):
|
||||
"""Convert a single GeoJSON file to KML via ogr2ogr. Returns True on success."""
|
||||
result = subprocess.run(
|
||||
["ogr2ogr", "-f", "KML", dst, src],
|
||||
capture_output=True, text=True
|
||||
)
|
||||
if result.returncode != 0:
|
||||
log.error(f" FAILED: {result.stderr.strip()}")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def generate_readme(output_dir, ava_names, errors, repo_url):
|
||||
"""Generate a README.md summarizing the conversion."""
|
||||
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
lines = [
|
||||
"# AVA Boundary Data — KML & GeoJSON",
|
||||
"",
|
||||
"American Viticultural Area (AVA) boundaries converted from GeoJSON to KML.",
|
||||
"",
|
||||
"## Source",
|
||||
f"- Repository: {repo_url}",
|
||||
"- Maintainer: UC Davis Library",
|
||||
"- License: **CC0 1.0 Universal** (Public Domain)",
|
||||
"",
|
||||
f"## Generated: {now}",
|
||||
"",
|
||||
f"**{len(ava_names)} AVAs converted** ({len(errors)} errors)",
|
||||
"",
|
||||
"## Files",
|
||||
"- `output/kml/` — KML files (one per AVA)",
|
||||
"- `output/geojson/` — Original GeoJSON source files",
|
||||
"",
|
||||
"## AVA List",
|
||||
"",
|
||||
]
|
||||
for name in sorted(ava_names):
|
||||
lines.append(f"- {name}")
|
||||
|
||||
if errors:
|
||||
lines += ["", "## Conversion Errors", ""]
|
||||
for e in sorted(errors):
|
||||
lines.append(f"- {e}")
|
||||
|
||||
readme_path = os.path.join(output_dir, "README.md")
|
||||
with open(readme_path, "w") as f:
|
||||
f.write("\n".join(lines) + "\n")
|
||||
log.info(f"README written to {readme_path}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Convert UC Davis AVA GeoJSON to KML")
|
||||
parser.add_argument("--output", default=DEFAULT_OUTPUT, help="Output directory")
|
||||
parser.add_argument("--repo-url", default=DEFAULT_REPO, help="Source git repo URL")
|
||||
args = parser.parse_args()
|
||||
|
||||
check_ogr2ogr()
|
||||
|
||||
output_dir = os.path.abspath(args.output)
|
||||
kml_dir = os.path.join(output_dir, "output", "kml")
|
||||
geojson_dir = os.path.join(output_dir, "output", "geojson")
|
||||
os.makedirs(kml_dir, exist_ok=True)
|
||||
os.makedirs(geojson_dir, exist_ok=True)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
repo_dir = os.path.join(tmpdir, "ava")
|
||||
clone_repo(args.repo_url, repo_dir)
|
||||
|
||||
avas_dir = os.path.join(repo_dir, "avas")
|
||||
if not os.path.isdir(avas_dir):
|
||||
log.error(f"No 'avas/' directory found in repo at {avas_dir}")
|
||||
sys.exit(1)
|
||||
|
||||
geojson_files = sorted(glob.glob(os.path.join(avas_dir, "*.geojson")))
|
||||
log.info(f"Found {len(geojson_files)} GeoJSON files")
|
||||
|
||||
converted = []
|
||||
errors = []
|
||||
|
||||
for gj in geojson_files:
|
||||
basename = os.path.splitext(os.path.basename(gj))[0]
|
||||
kml_out = os.path.join(kml_dir, f"{basename}.kml")
|
||||
gj_out = os.path.join(geojson_dir, os.path.basename(gj))
|
||||
|
||||
log.info(f"Converting: {basename}")
|
||||
shutil.copy2(gj, gj_out)
|
||||
|
||||
if convert_geojson_to_kml(gj, kml_out):
|
||||
converted.append(basename)
|
||||
else:
|
||||
errors.append(basename)
|
||||
|
||||
log.info(f"Done: {len(converted)} converted, {len(errors)} errors")
|
||||
generate_readme(output_dir, converted, errors, args.repo_url)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user