diff --git a/fbfmaproom/data-conversion-scripts/madagascar/shapes-2025-10/conda-packages.txt b/fbfmaproom/data-conversion-scripts/madagascar/shapes-2025-10/conda-packages.txt new file mode 100644 index 00000000..47e343e3 --- /dev/null +++ b/fbfmaproom/data-conversion-scripts/madagascar/shapes-2025-10/conda-packages.txt @@ -0,0 +1,142 @@ +# This file may be used to create an environment using: +# $ conda create --name --file +# platform: linux-64 +# created-by: conda 24.9.2 +@EXPLICIT +https://repo.anaconda.com/pkgs/main/linux-64/_libgcc_mutex-0.1-main.conda +https://repo.anaconda.com/pkgs/main/linux-64/blas-1.0-mkl.conda +https://repo.anaconda.com/pkgs/main/linux-64/ca-certificates-2025.11.4-h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/intel-openmp-2025.0.0-h06a4308_1171.conda +https://repo.anaconda.com/pkgs/main/linux-64/ld_impl_linux-64-2.44-h153f514_2.conda +https://repo.anaconda.com/pkgs/main/linux-64/libgomp-15.2.0-h4751f2c_7.conda +https://repo.anaconda.com/pkgs/main/linux-64/python_abi-3.13-1_cp313.conda +https://repo.anaconda.com/pkgs/main/noarch/tzdata-2025b-h04d1e81_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/_openmp_mutex-5.1-1_gnu.conda +https://repo.anaconda.com/pkgs/main/linux-64/libgcc-15.2.0-h69a1729_7.conda +https://repo.anaconda.com/pkgs/main/linux-64/libgcc-ng-15.2.0-h166f726_7.conda +https://repo.anaconda.com/pkgs/main/linux-64/libgfortran5-15.2.0-hc633d37_7.conda +https://repo.anaconda.com/pkgs/main/linux-64/libstdcxx-15.2.0-h39759b7_7.conda +https://repo.anaconda.com/pkgs/main/linux-64/bzip2-1.0.8-h5eee18b_6.conda +https://repo.anaconda.com/pkgs/main/linux-64/dav1d-1.2.1-h5eee18b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/fribidi-1.0.10-h7b6447c_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/giflib-5.2.2-h5eee18b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/jansson-2.14-h5eee18b_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/jpeg-9e-h5eee18b_3.conda +https://repo.anaconda.com/pkgs/main/linux-64/json-c-0.16-h5eee18b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libdeflate-1.22-h5eee18b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libev-4.33-h7f8727e_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/libgfortran-15.2.0-h166f726_7.conda +https://repo.anaconda.com/pkgs/main/linux-64/libiconv-1.16-h5eee18b_3.conda +https://repo.anaconda.com/pkgs/main/linux-64/libmpdec-4.0.0-h5eee18b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libopenjpeg-2.5.4-hee96239_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/libstdcxx-ng-15.2.0-hc03a8fd_7.conda +https://repo.anaconda.com/pkgs/main/linux-64/libunistring-1.3-hb25bd0a_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libuuid-1.41.5-h5eee18b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libwebp-base-1.3.2-h5eee18b_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/libzlib-1.3.1-hb25bd0a_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/ncurses-6.5-h7934f7d_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/openssl-3.0.18-hd6dcaed_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/pthread-stubs-0.3-h0ce48e5_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/uriparser-0.9.8-h451ca9b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/xorg-libxau-1.0.12-h9b100fa_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/xorg-libxdmcp-1.1.5-h9b100fa_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/xorg-xorgproto-2024.1-h5eee18b_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/xz-5.6.4-h5eee18b_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/aom-3.6.0-h6a678d5_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/c-ares-1.34.5-hef5626c_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/expat-2.7.3-h3385a95_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/geos-3.10.6-h6a678d5_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/graphite2-1.3.14-h295c915_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/icu-73.1-h6a678d5_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/lerc-4.0.0-h6a678d5_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libffi-3.4.4-h6a678d5_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/libgfortran-ng-15.2.0-h166f726_7.conda +https://repo.anaconda.com/pkgs/main/linux-64/libxcb-1.17.0-h9b100fa_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/lz4-c-1.9.4-h6a678d5_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/pixman-0.46.4-h7934f7d_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/readline-8.3-hc2a1206_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/tbb-2022.0.0-hdb19cb5_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/zlib-1.3.1-hb25bd0a_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libavif-1.1.1-h5eee18b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libkml-1.3.0-h096b73e_7.conda +https://repo.anaconda.com/pkgs/main/linux-64/libpng-1.6.50-h2ed474d_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libssh2-1.11.1-h251f7ec_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libxml2-2.13.9-h2c43086_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/pcre2-10.42-hebb0a14_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/sqlite-3.51.0-h2a70700_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/tbb-devel-2022.0.0-hdb19cb5_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/xerces-c-3.2.4-h6a678d5_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/xorg-libx11-1.8.12-h9b100fa_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/zstd-1.5.7-h11fc155_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/blosc-1.21.6-hf7d4471_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/freetype-2.13.3-h4a9f257_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/gettext-0.21.0-hedfda30_2.conda +https://repo.anaconda.com/pkgs/main/linux-64/libarchive-3.7.7-hfab0078_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libglib-2.84.2-h37c7471_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libnghttp2-1.67.1-h697f920_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libtiff-4.7.0-hde9077f_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/minizip-4.0.3-hf59b114_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/mkl-2025.0.0-hacee8c2_941.conda +https://repo.anaconda.com/pkgs/main/linux-64/tk-8.6.15-h54e0aa7_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/xorg-libxext-1.3.6-h9b100fa_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/xorg-libxrender-0.9.12-h9b100fa_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/fontconfig-2.15.0-h2c49b7f_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/freexl-2.0.0-hf309648_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/lcms2-2.16-h92b89f2_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/libidn2-2.3.8-hf80d704_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/python-3.13.9-h7e8bc2b_100_cp313.conda +https://repo.anaconda.com/pkgs/main/linux-64/cairo-1.18.4-h44eff21_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/certifi-2025.10.5-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/charset-normalizer-3.4.4-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/noarch/cycler-0.11.0-pyhd3eb1b0_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/fonttools-4.60.1-py313hee96239_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/idna-3.11-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/joblib-1.5.2-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/kiwisolver-1.4.8-py313h6a678d5_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/libcurl-8.16.0-heebcbe5_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/markupsafe-3.0.2-py313h5eee18b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/mkl-service-2.5.2-py313hacdc0fc_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/networkx-3.5-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/packaging-25.0-py313h06a4308_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/pycparser-2.23-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/pyparsing-3.2.0-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/pysocks-1.7.1-py313h06a4308_1.conda +https://repo.anaconda.com/pkgs/main/noarch/python-tzdata-2025.2-pyhd3eb1b0_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/pytz-2025.2-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/setuptools-80.9.0-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/six-1.17.0-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/threadpoolctl-3.5.0-py313h7040dfc_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/wheel-0.45.1-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/xyzservices-2025.4.0-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/cffi-2.0.0-py313h4eded50_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/harfbuzz-10.2.0-hdfddeaa_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/jinja2-3.1.6-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/numpy-base-2.3.4-py313h95072fd_1.conda +https://repo.anaconda.com/pkgs/main/noarch/pip-25.2-pyhc872135_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/proj-9.3.1-h4591001_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/python-dateutil-2.9.0post0-py313h06a4308_2.conda +https://repo.anaconda.com/pkgs/main/linux-64/branca-0.8.1-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/brotlicffi-1.0.9.2-py313hbdd6827_2.conda +https://repo.anaconda.com/pkgs/main/linux-64/geotiff-1.7.0-ha59944b_4.conda +https://repo.anaconda.com/pkgs/main/linux-64/libspatialite-5.1.0-h798b768_2.conda +https://repo.anaconda.com/pkgs/main/linux-64/pillow-12.0.0-py313h3b88751_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/pyproj-3.6.1-py313h75c29da_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/libgdal-core-3.11.0-h177e9c5_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/urllib3-2.5.0-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/requests-2.32.5-py313h06a4308_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/bottleneck-1.4.2-py313haa0f9ac_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/contourpy-1.3.1-py313hdb19cb5_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/folium-0.20.0-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/matplotlib-base-3.10.6-py313h4948728_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/mkl_fft-2.1.1-py313h57662e1_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/mkl_random-1.3.0-py313h23c847b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/numpy-2.3.4-py313h720eef7_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/numexpr-2.14.1-py313h41d4191_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/pyogrio-0.10.0-py313h16bd0e6_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/scipy-1.16.3-py313h33bc11c_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/shapely-2.1.1-py313h05a33e2_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/pandas-2.3.3-py313h23c847b_1.conda +https://repo.anaconda.com/pkgs/main/linux-64/scikit-learn-1.7.2-py313h23c847b_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/geopandas-base-1.1.1-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/mapclassify-2.10.0-py313h06a4308_0.conda +https://repo.anaconda.com/pkgs/main/linux-64/geopandas-1.1.1-py313h06a4308_0.conda diff --git a/fbfmaproom/data-conversion-scripts/madagascar/shapes-2025-10/create_admin_levels.py b/fbfmaproom/data-conversion-scripts/madagascar/shapes-2025-10/create_admin_levels.py new file mode 100644 index 00000000..0da485ba --- /dev/null +++ b/fbfmaproom/data-conversion-scripts/madagascar/shapes-2025-10/create_admin_levels.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +""" +Create Admin 0, Admin 1, and Admin 2 Shapefiles from Admin 2 Input + +This script processes Madagascar administrative boundary data to create +four separate shapefiles for different administrative levels: +- Admin 0: National boundaries (country level) +- Admin 1: Regional boundaries (province/region level) +- Admin 2: District boundaries (district level) +- ALL: Combined shapefile with all admin levels + +The script: +1. Dissolves (merges) lower-level boundaries to create higher-level boundaries +2. Reprojects from projected coordinate system (EPSG:3395 - meters) to + geographic coordinate system (EPSG:4326 - degrees) for web mapping compatibility +3. Maintains hierarchical field structure (e.g., Admin 1 includes Admin 0 fields) +4. Creates an ALL levels shapefile with admLevel field for filtering + +Requirements: + - geopandas + - pandas + - zipfile (standard library) + - tempfile (standard library) + - pathlib (standard library) + +Usage: + python create_admin_levels.py + +Input: + SHP_ADM2_UPDATE.zip - Original admin 2 shapefile in projected CRS (EPSG:3395) + +Output: + SHP_MERGED.zip - New zip file containing all three admin level shapefiles + in geographic coordinate system (EPSG:4326) for Python maproom integration +""" + +import geopandas as gpd +import pandas as pd +import zipfile +import tempfile +import os +import shutil +from pathlib import Path +import shapely + +def main(): + """ + Main function to process shapefiles and create admin levels. + + Process: + 1. Extract the original admin 2 shapefile from the input zip + 2. Read the shapefile using GeoPandas + 3. Reproject from EPSG:3395 (projected, meters) to EPSG:4326 (geographic, degrees) + 4. Create admin 0 by dissolving all polygons into one national boundary + 5. Create admin 1 by dissolving polygons grouped by region code (includes Admin 0 fields) + 6. Create admin 2 by filtering columns from the original data (includes Admin 0 + Admin 1 fields) + 7. Create ALL levels shapefile by combining all admin levels with admLevel field + 8. Save all four shapefiles with consistent naming + 9. Package everything into a new zip file with geographic coordinates + """ + # Input and output paths + input_zip = "SHP_ADM2_UPDATE.zip" + output_zip = "SHP_MERGED.zip" + + # Create temporary directory for processing + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + print("Extracting shapefile from zip...") + # Extract the shapefile from zip + with zipfile.ZipFile(input_zip, 'r') as zip_ref: + zip_ref.extractall(temp_path) + + # Read the admin 2 shapefile + shapefile_path = temp_path / "SHP_ADM2_UPDATE" / "mdg_bnd_adm2_dis_pam.shp" + print(f"Reading shapefile: {shapefile_path}") + gdf = gpd.read_file(shapefile_path) + + print(f"Original shapefile has {len(gdf)} features") + print(f"Columns: {list(gdf.columns)}") + print(f"Original CRS: {gdf.crs}") + + # Reproject from projected coordinate system to geographic coordinate system + # Input: EPSG:3395 (WGS 84 / World Mercator - projected, units in meters) + # Output: EPSG:4326 (WGS 84 - geographic, units in degrees) + # This conversion is required for Python maproom applications which expect + # geographic coordinates in degrees (lat/lon) rather than projected meters + print(f"\nReprojecting from {gdf.crs} to EPSG:4326 (WGS 84 - geographic)...") + gdf = gdf.to_crs('EPSG:4326') + print(f"Reprojected CRS: {gdf.crs}") + print("Coordinates are now in degrees (longitude, latitude)") + + # Create admin 0 (National) - dissolve by ADM0_PCODE + # This merges all 120 district polygons into 1 national boundary + print("\nCreating Admin 0 (National) shapefile...") + adm0 = merge(gdf, 'ADM0_PCODE') + # Reset index to make ADM0_PCODE a column again, then select fields + adm0 = adm0.reset_index() + adm0 = adm0[['ADM0_PCODE', 'ADM0_EN', 'geometry']] + print(f"Admin 0 has {len(adm0)} feature(s)") + + # Create admin 1 (Regional) - dissolve by ADM1_PCODE + # This merges district polygons that share the same region code + # Include hierarchical fields (Admin 0 + Admin 1 fields) + print("\nCreating Admin 1 (Regional) shapefile...") + adm1 = merge(gdf, 'ADM1_PCODE') + # Reset index to make ADM1_PCODE a column again, then select fields + adm1 = adm1.reset_index() + adm1 = adm1[['ADM0_PCODE', 'ADM0_EN', 'ADM1_PCODE', 'ADM1_EN', 'ADM1_TYPE', 'geometry']] + print(f"Admin 1 has {len(adm1)} feature(s)") + + # Create admin 2 (District) - keep original geometries but filter columns + # This preserves all 120 district boundaries + # Include hierarchical fields (Admin 0 + Admin 1 + Admin 2 fields) + print("\nCreating Admin 2 (District) shapefile...") + adm2 = gdf[['ADM0_PCODE', 'ADM0_EN', 'ADM1_PCODE', 'ADM1_EN', 'ADM1_TYPE', 'ADM2_PCODE', 'ADM2_EN', 'ADM2_TYPE', 'geometry']].copy() + print(f"Admin 2 has {len(adm2)} feature(s)") + + # Save shapefiles to temporary directory + print("\nSaving shapefiles...") + adm0_path = temp_path / "mdg_adm0.shp" + adm1_path = temp_path / "mdg_adm1.shp" + adm2_path = temp_path / "mdg_adm2.shp" + + adm0.to_file(adm0_path) + adm1.to_file(adm1_path) + adm2.to_file(adm2_path) + + print(f"Saved Admin 0: {adm0_path}") + print(f"Saved Admin 1: {adm1_path}") + print(f"Saved Admin 2: {adm2_path}") + + # Create new zip file with all three shapefiles + print(f"\nCreating new zip file: {output_zip}") + with zipfile.ZipFile(output_zip, 'w', zipfile.ZIP_DEFLATED) as zip_ref: + # Add all shapefile components for each admin level + for admin_level in ['mdg_adm0', 'mdg_adm1', 'mdg_adm2']: + for ext in ['.shp', '.shx', '.dbf', '.prj', '.cpg', '.sbn', '.sbx', '.shp.xml']: + file_path = temp_path / f"{admin_level}{ext}" + if file_path.exists(): + zip_ref.write(file_path, file_path.name) + print(f" Added: {file_path.name}") + + print(f"\nSuccessfully created {output_zip} with all admin levels!") + print("\nLayer names:") + print("- Admin 0 (National): mdg_adm0") + print("- Admin 1 (Regional): mdg_adm1") + print("- Admin 2 (District): mdg_adm2") + print(f"\nAll shapefiles are in EPSG:4326 (WGS 84 - geographic coordinate system)") + print("Coordinates are in degrees (longitude, latitude) for web mapping compatibility") + + +def merge(gdf, by): + merged_df = gdf.dissolve(by=by) + merged_df['geometry'] = [ + remove_holes(geom) for geom in merged_df['geometry'] + ] + return merged_df + + +def remove_holes(geom): + if isinstance(geom, shapely.Polygon): + result = shapely.Polygon(geom.exterior) + elif isinstance(geom, shapely.MultiPolygon): + result = shapely.MultiPolygon([ + shapely.Polygon(poly.exterior) for poly in geom.geoms + ]) + else: + raise Exception(f"Bad argument type for remove_holes: {type(geom)}") + return result + + +if __name__ == "__main__": + main() diff --git a/fbfmaproom/fbfmaproom-sample.yaml b/fbfmaproom/fbfmaproom-sample.yaml index 7b998b18..05bd3444 100644 --- a/fbfmaproom/fbfmaproom-sample.yaml +++ b/fbfmaproom/fbfmaproom-sample.yaml @@ -137,25 +137,24 @@ countries: zoom: 7 rotation: 0 marker: [45.5, -24] - clip: no shapes: - name: National - sql: select adm0_code as key, adm0_name as label, ST_AsBinary(ST_Union(the_geom)) as the_geom - from iridb.g2015_2014_1 g where adm0_name = 'Madagascar' - and adm1_name in ('Androy', 'Anosy', 'Atsimo Andrefana', 'Atsimo Atsinanana') - group by 1, 2 + file: madagascar/shapes/2025-10/SHP_MERGED.zip + layer: mdg_adm0 + key_field: ADM0_PCODE + label_field: ADM0_EN - name: Regional - sql: select (adm0_code, adm1_code) as key, adm1_name as label, - ST_AsBinary(the_geom) as the_geom from iridb.g2015_2014_1 - where adm0_name = 'Madagascar' - and adm1_name in ('Androy', 'Anosy', 'Atsimo Andrefana', 'Atsimo Atsinanana') + file: madagascar/shapes/2025-10/SHP_MERGED.zip + layer: mdg_adm1 + key_field: ADM1_PCODE + label_field: ADM1_EN - name: District - sql: select (adm0_code, adm1_code, adm2_code) as key, adm2_name as label, - ST_AsBinary(the_geom) as the_geom from iridb.g2015_2014_2 - where adm0_name = 'Madagascar' - and adm1_name in ('Androy', 'Anosy', 'Atsimo Andrefana', 'Atsimo Atsinanana') + file: madagascar/shapes/2025-10/SHP_MERGED.zip + layer: mdg_adm2 + key_field: ADM2_PCODE + label_field: ADM2_EN datasets: defaults: @@ -379,25 +378,24 @@ countries: zoom: 7 rotation: 0 marker: [45.5, -24] - clip: no shapes: - name: National - sql: select adm0_code as key, adm0_name as label, ST_AsBinary(ST_Union(the_geom)) as the_geom - from iridb.g2015_2014_1 g where adm0_name = 'Madagascar' - and adm1_name in ('Androy', 'Anosy', 'Atsimo Andrefana', 'Atsimo Atsinanana') - group by 1, 2 + file: madagascar/shapes/2025-10/SHP_MERGED.zip + layer: mdg_adm0 + key_field: ADM0_PCODE + label_field: ADM0_EN - name: Regional - sql: select (adm0_code, adm1_code) as key, adm1_name as label, - ST_AsBinary(the_geom) as the_geom from iridb.g2015_2014_1 - where adm0_name = 'Madagascar' - and adm1_name in ('Androy', 'Anosy', 'Atsimo Andrefana', 'Atsimo Atsinanana') + file: madagascar/shapes/2025-10/SHP_MERGED.zip + layer: mdg_adm1 + key_field: ADM1_PCODE + label_field: ADM1_EN - name: District - sql: select (adm0_code, adm1_code, adm2_code) as key, adm2_name as label, - ST_AsBinary(the_geom) as the_geom from iridb.g2015_2014_2 - where adm0_name = 'Madagascar' - and adm1_name in ('Androy', 'Anosy', 'Atsimo Andrefana', 'Atsimo Atsinanana') + file: madagascar/shapes/2025-10/SHP_MERGED.zip + layer: mdg_adm2 + key_field: ADM2_PCODE + label_field: ADM2_EN datasets: defaults: @@ -574,26 +572,24 @@ countries: zoom: 7 rotation: 0 marker: [45.5, -24] - clip: no shapes: - name: National - sql: select adm0_code as key, adm0_name as label, ST_AsBinary(ST_Union(the_geom)) as the_geom - from iridb.g2015_2014_1 g where adm0_name = 'Madagascar' - and adm1_name in ('Androy', 'Anosy', 'Atsimo Andrefana', 'Atsimo Atsinanana') - group by 1, 2 - + file: madagascar/shapes/2025-10/SHP_MERGED.zip + layer: mdg_adm0 + key_field: ADM0_PCODE + label_field: ADM0_EN - name: Regional - sql: select (adm0_code, adm1_code) as key, adm1_name as label, - ST_AsBinary(the_geom) as the_geom from iridb.g2015_2014_1 - where adm0_name = 'Madagascar' - and adm1_name in ('Androy', 'Anosy', 'Atsimo Andrefana', 'Atsimo Atsinanana') + file: madagascar/shapes/2025-10/SHP_MERGED.zip + layer: mdg_adm1 + key_field: ADM1_PCODE + label_field: ADM1_EN - name: District - sql: select (adm0_code, adm1_code, adm2_code) as key, adm2_name as label, - ST_AsBinary(the_geom) as the_geom from iridb.g2015_2014_2 - where adm0_name = 'Madagascar' - and adm1_name in ('Androy', 'Anosy', 'Atsimo Andrefana', 'Atsimo Atsinanana') + file: madagascar/shapes/2025-10/SHP_MERGED.zip + layer: mdg_adm2 + key_field: ADM2_PCODE + label_field: ADM2_EN datasets: defaults: diff --git a/fbfmaproom/fbfmaproom.py b/fbfmaproom/fbfmaproom.py index c344019b..9ecab295 100644 --- a/fbfmaproom/fbfmaproom.py +++ b/fbfmaproom/fbfmaproom.py @@ -344,9 +344,13 @@ def retrieve_shapes( df = pd.read_sql(query, conn, params={"key": key}) if "the_geom" in fields: df["the_geom"] = df["the_geom"].apply(lambda x: wkb.loads(x.tobytes())) - elif 'file' in sc: - filepath = Path(CONFIG["data_root"]) / sc["file"] - with fiona.open(f"zip://{filepath}", layer=sc["layer"]) as collection: + elif "file" in sc: + if sc["file"].endswith(".zip"): + prefix = "zip://" + else: + prefix = "" + file_arg = f"{prefix}{CONFIG['data_root']}/{sc['file']}" + with fiona.open(file_arg, layer=sc["layer"]) as collection: tuples = [ ( feature['properties'][sc["key_field"]], @@ -1138,7 +1142,7 @@ def table_cb(issue_month_abbrev, freq, mode, geom_key, pathname, severity, predi try: if geom_key is None: - raise NotFoundError("No region found") + raise Exception("No region found") main_df, summary_df, thresholds = generate_tables( country_key,