fio-l2-capetown-landuse-dissolve

Status: done
Score: 0.941
Duration: 0:54
Cost: 0.17¢
Model: google/gemma-4-26b-a4b-it

Map (reference ← swipe → agent)

0:00
I'm prepping a transit-corridor study for the Cape Town metro, and I need a class-level summary of `landuse` so the team's spatial-SQL notebooks can join it against the bus-route table. Can you give me one row per landuse class with the geometry unified into a single MultiPolygon, the total area in m², and the count of source parcels that fed in? Please write the result to `landuse_dissolved.geoparquet` with `class`, `area_m2`, and `parcel_count` columns.
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
capetown_landuse.fgb
0:02
Bash python -c "import geopandas as gpd; print(gpd.read_file('capetown_landuse.fgb')....
                                     id  ...                                           geometry
0  f328c054-b040-3a7d-a015-53747d608fef  ...  MULTIPOLYGON (((872000.605 6252622.417, 871205...
1  f1943847-f785-390c-abb0-edc923f97997  ...  MULTIPOLYGON (((253543.223 6283900.241, 254921...
2  c37e40aa-f202-3b15-b68d-89dafeeaa478  ...  MULTIPOLYGON (((255047.308 6280773.284, 255024...
3  b9d39db7-5dcc-379e-bfeb-c994628df5a7  ...  MULTIPOLYGON (((254978.723 6280842.179, 254992...
4  0033302c-c1d6-3624-b71e-0e300db64963  ...  MULTIPOLYGON (((264759.63 6280552.85, 264825.5...

[5 rows x 4 columns]
0:05
Bash python -c "import geopandas as gpd; print(gpd.read_file('capetown_landuse.fgb')....
['id', 'class', 'subtype', 'geometry']
0:21
Write /work/solve.py
content · 57 lines · py
import geopandas as gpd

def main():
    # Load the data
    gdf = gpd.read_file('capetown_landuse.fgb')

    # Ensure we are in a projected CRS to calculate area in m2 correctly
    # If the data is already projected (UTM/Lo), we'll use it.
    # If it's EPSG:4326, we must reproject.
    if gdf.crs.is_geographic:
        print("Reprojecting to UTM Zone 34S (EPSG:32734) for accurate area calculation...")
        gdf = gdf.to_crs(epsg=32734)
    else:
        print(f"Using existing CRS: {gdf.crs}")

    # Group by 'class'
    # We need: 
    # 1. Dissolved geometry (MultiPolygon)
    # 2. Total area (sum of areas)
    # 3. Count of original parcels

    # First, calculate area of each individual parcel in the projected CRS
    gdf['area_m2_parcel'] = gdf.geometry.area

    # Grouping and aggregating
    # dissolved: we'll use unary_union via groupby.apply or dissolve()
    # total area: sum of parcel areas
    # parcel count: count of rows per group

    print("Dissolving landuse classes...")
    # The dissolve() method is highly efficient for this
    dissolved = gdf.dissolve(by='class', aggfunc={
        'area_m2_parcel': 'sum',
        'id': 'count'
    })

    # Rename columns to match requirements
    dissolved = dissolved.rename(columns={
        'area_m2_parcel': 'area_m2',
        'id': 'parcel_count'
    })

    # Reset index so 'class' becomes a column
    dissolved = dissolved.reset_index()

    # Select/Order columns as requested
    # requested: 'class', 'area_m2', 'parcel_count'
    result = dissolved[['class', 'area_m2', 'parcel_count', 'geometry']]

    # Write to GeoParquet
    print(f"Writing result to landuse_dissolved.geoparquet...")
    result.to_parquet('landuse_dissolved.geoparquet')
    print("Done.")

if __name__ == "__main__":
    main()
Wrote /work/solve.py (1793 chars).
0:22
Bash python /work/solve.py
Using existing CRS: EPSG:32734
Dissolving landuse classes...
Writing result to landuse_dissolved.geoparquet...
Done.
0:28
Bash python -c "import geopandas as gpd; df = gpd.read_parquet('landuse_dissolved.geo...
            class  ...                                           geometry
0        airfield  ...  POLYGON ((267829.758 6244743.665, 267820.919 6...
1      allotments  ...  MULTIPOLYGON (((263870.512 6232477.907, 263865...
2  animal_keeping  ...  MULTIPOLYGON (((264114.249 6261265.896, 264220...
3        barracks  ...  MULTIPOLYGON (((262288.681 6215543.331, 262280...
4            base  ...  POLYGON ((272069.73 6245748.538, 272064.541 62...

[5 rows x 4 columns]
['class', 'area_m2', 'parcel_count', 'geometry']
0:31
Bash python -c "import geopandas as gpd; df = gpd.read_parquet('landuse_dissolved.geo...
            class  ...                                           geometry
0        airfield  ...  POLYGON ((267829.758 6244743.665, 267820.919 6...
1      allotments  ...  MULTIPOLYGON (((263870.512 6232477.907, 263865...
2  animal_keeping  ...  MULTIPOLYGON (((264114.249 6261265.896, 264220...
3        barracks  ...  MULTIPOLYGON (((262288.681 6215543.331, 262280...
4            base  ...  POLYGON ((272069.73 6245748.538, 272064.541 62...

[5 rows x 4 columns]
0:39