fio-l2-cairo-mixedgeom-split

Status: done
Score: 1.000
Duration: 0:39
Cost: 0.30¢
Model: google/gemma-4-26b-a4b-it

Map (reference ← swipe → agent)

0:00
Heritage analyst here. I've put together `heritage_sites.geojson` from my own field work, and every site in it is several features sharing a `site_id`. I need to load the data into our desktop tool, which only ingests typed GPKG layers, no mixed-geometry files, and every feature has to be single-part. Can you give me back `heritage.gpkg` with three layers named `points`, `lines`, and `polygons`, keeping the `site_id` on every feature so I don't lose the cross-layer link? Use Egypt's national grid.
0:00
System info
{
  "adapter": "openrouter",
  "model": "google/gemma-4-26b-a4b-it",
  "base_url": "https://openrouter.ai/api/v1"
}
0:01
Bash ls -F
heritage_sites.geojson
0:18
Write /work/solve.py
content · 73 lines · py
import geopandas as gpd

def solve():
    # Load the data
    gdf = gpd.read_file('heritage_sites.geojson')
    
    # Print info for debugging
    print("Initial Data Info:")
    print(gdf.info())
    print("\nGeometry types present:")
    print(gdf.geometry.type.value_counts())
    print("\nCRS:", gdf.crs)
    
    # 1. Convert to single-part geometries
    # explode() is the standard way to turn Multi-part into Single-part
    gdf = gdf.explode(index_parts=False)
    
    # 2. Project to Egypt's National Grid
    # Egypt National Grid is EPSG:22992 (UTM zone 36N) or similar? 
    # Actually, Egypt uses several. Let's check common ones or use a robust one like EPSG:32636 (UTM 36N).
    # However, "Egypt National Grid" often refers to a specific local projection.
    # Let's check if EPSG:22992 is correct or if I should use a standard UTM.
    # Looking up "Egypt National Grid EPSG": EPSG:22992 is often cited.
    # I'll use EPSG:32636 as a safe bet for UTM 36N if I'm unsure, but I'll try to find 22992.
    # Wait, EPSG:22992 is for Egypt (Egypt Grid). Let's try that.
    target_crs = "EPSG:22992"
    gdf = gdf.to_crs(target_crs)
    print(f"\nProjected to {target_crs}")
    
    # 3. Split into layers
    points = gdf[gdf.geometry.type == 'Point']
    lines = gdf[gdf.geometry.type.isin(['LineString', 'MultiLineString'])] # explode handled MultiLineString
    polygons = gdf[gdf.geometry.type.isin(['Polygon', 'MultiPolygon'])] # explode handled MultiPolygon
    
    # Re-filtering after explode to ensure we only have single parts
    # Since we exploded, they should already be single parts.
    # But let's be explicit about types.
    
    # Note: explode() on a MultiLineString gives LineString.
    # Let's refine the split logic.
    
    points = gdf[gdf.geometry.type == 'Point']
    lines = gdf[gdf.geometry.type == 'LineString']
    polygons = gdf[gdf.geometry.type == 'Polygon']
    
    # 4. Save to GPKG
    # Use pyogrio or fiona (geopandas uses them)
    output_file = 'heritage.gpkg'
    
    if not points.empty:
        points.to_file(output_file, layer='points', driver='GPKG')
    else:
        print("Warning: No points found.")
        
    if not lines.empty:
        lines.to_file(output_file, layer='lines', driver='GPKG')
    else:
        print("Warning: No lines found.")
        
    if not polygons.empty:
        polygons.to_file(output_file, layer='polygons', driver='GPKG')
    else:
        print("Warning: No polygons found.")

    print(f"\nSuccessfully saved to {output_file}")
    print("Layers created:")
    print(f"Points: {len(points)}")
    print(f"Lines: {len(lines)}")
    print(f"Polygons: {len(polygons)}")

if __name__ == "__main__":
    solve()
Wrote /work/solve.py (2719 chars).
0:19
Bash python solve.py
Initial Data Info:
<class 'geopandas.geodataframe.GeoDataFrame'>
RangeIndex: 50 entries, 0 to 49
Data columns (total 5 columns):
 #   Column        Non-Null Count  Dtype   
---  ------        --------------  -----   
 0   site_id       50 non-null     str     
 1   feature_kind  50 non-null     str     
 2   name_en       50 non-null     str     
 3   name_ar       50 non-null     str     
 4   geometry      50 non-null     geometry
dtypes: geometry(1), str(4)
memory usage: 5.4 KB
None

Geometry types present:
Point           25
LineString      15
Polygon          5
MultiPolygon     5
Name: count, dtype: int64

CRS: EPSG:4326

Projected to EPSG:22992

Successfully saved to heritage.gpkg
Layers created:
Points: 25
Lines: 15
Polygons: 15
0:26
Bash # Check the layer contents with ogrinfo or similar if available, or just trust t...
# Check the layer contents with ogrinfo or similar if available, or just trust the script output.
# Since I can't run ogrinfo easily without knowing if it's installed, I'll write a small python check.
cat <<EOF > check_gpkg.py
import geopandas as gpd
import fiona

file = 'heritage.gpkg'
layers = fiona.listlayers(file)
print(f"Layers in {file}: {layers}")

for layer in layers:
    gdf = gpd.read_file(file, layer=layer)
    print(f"\nLayer: {layer}")
    print(f"Count: {len(gdf)}")
    print(f"Geometry types: {gdf.geometry.type.unique()}")
    print(f"CRS: {gdf.crs}")
    print(f"First 2 rows:\n{gdf.head(2)}")
EOF
python check_gpkg.py
Layers in heritage.gpkg: ['points', 'lines', 'polygons']

Layer: points
Count: 25
Geometry types: <ArrowStringArray>
['Point']
Length: 1, dtype: str
CRS: EPSG:22992
First 2 rows:
      site_id  ...                       geometry
0  EG-CAI-001  ...  POINT (639589.453 813622.922)
1  EG-CAI-001  ...  POINT (639628.134 813578.667)

[2 rows x 5 columns]

Layer: lines
Count: 15
Geometry types: <ArrowStringArray>
['LineString']
Length: 1, dtype: str
CRS: EPSG:22992
First 2 rows:
      site_id  ...                                           geometry
0  EG-CAI-001  ...  LINESTRING (639493.121 813567.28, 639589.552 8...
1  EG-CAI-001  ...  LINESTRING (639599.445 813467.749, 639589.552 ...

[2 rows x 5 columns]

Layer: polygons
Count: 15
Geometry types: <ArrowStringArray>
['Polygon']
Length: 1, dtype: str
CRS: EPSG:22992
First 2 rows:
      site_id  ...                                           geometry
0  EG-CAI-001  ...  POLYGON ((639531.827 813511.939, 639647.574 81...
1  EG-CAI-002  ...  POLYGON ((639628.084 813600.837, 639743.83 813...

[2 rows x 5 columns]
0:30
Bash ls -F
check_gpkg.py
heritage.gpkg
heritage_sites.geojson
solve.py
0:37