fio-l2-cairo-mixedgeom-split
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