spa-l2-lagos-hotspot-overlaps

Status: done
Score: 79
Duration: 3:17
Cost: 2.22¢
Model: google/gemma-4-26b-a4b-it

Map (reference ← swipe → agent)

0:00
Hot-spot map for the Lagos housing brief. `lagos_landuse` carries land-use polygons with a population density attribute; `lagos_hex_grid` is a hex grid. I need the top 10 % of hex cells ranked by area-weighted mean population density across overlapping land-use polygons. Tiny polygons under 100 m² are noise and should be excluded. I need two output files that share exactly the same set of `hex_id` values, one row per cell. `hotspots.geoparquet` is a GeoParquet (Polygon or MultiPolygon geometry) in Nigeria's national grid with columns `hex_id`, `rank`, `area_weighted_density`, and `geometry`. `hotspot_ranking.parquet` is a plain Parquet with no geometry, carrying `hex_id`, `rank`, `area_weighted_density`, `n_overlap_polygons` (integer), and `n_slivers_filtered` (integer). In both files `rank` must be a unique integer starting at 1 where ascending rank corresponds to descending `area_weighted_density`.
0:00
System info
{
  "adapter": "openrouter",
  "model": "google/gemma-4-26b-a4b-it",
  "base_url": "https://openrouter.ai/api/v1"
}
0:02
Bash ls -F
lagos_hex_grid.geojson
lagos_landuse.geojson
0:05
Write /work/inspect_data.py
content · 20 lines · py
import geopandas as gpd

# Check the first few rows and CRS of both files
try:
    landuse = gpd.read_file('lagos_landuse.geojson')
    print("Landuse columns:", landuse.columns)
    print("Landuse CRS:", landuse.crs)
    print("Landuse first 5 rows:\n", landuse.head())
    print("Landuse area check:", landuse.geometry.area.describe())
except Exception as e:
    print(f"Error reading landuse: {e}")

try:
    hex_grid = gpd.read_file('lagos_hex_grid.geojson')
    print("\nHex grid columns:", hex_grid.columns)
    print("Hex grid CRS:", hex_grid.crs)
    print("Hex grid first 5 rows:\n", hex_grid.head())
except Exception as e:
    print(f"Error reading hex_grid: {e}")
Wrote /work/inspect_data.py (675 chars).
0:06
Bash python /work/inspect_data.py
Landuse columns: Index(['id', 'class', 'pop_density', 'geometry'], dtype='str')
Landuse CRS: EPSG:4326
Landuse first 5 rows:
                                      id  ...                                           geometry
0  004ca249-d2cf-3617-906e-dea1138e762b  ...  POLYGON ((3.46992 6.44615, 3.46993 6.44566, 3....
1  006a7dc6-2b5e-34fa-84a2-8a679620c9de  ...  POLYGON ((3.42136 6.43091, 3.42118 6.43051, 3....
2  00a334d1-7e8e-3e4c-8565-3501d4ed74df  ...  POLYGON ((3.45824 6.43361, 3.45872 6.43306, 3....
3  00af9ff7-3138-37a7-bbb8-0a2fbe2bb8e2  ...  POLYGON ((3.34834 6.61603, 3.34842 6.61593, 3....
4  00d4b7d6-09b5-3d43-97c5-009fd8c97362  ...  POLYGON ((3.31147 6.48073, 3.31041 6.47971, 3....

[5 rows x 4 columns]
Landuse area check: count    5.542000e+03
mean     7.606990e-06
std      7.631376e-05
min      8.184751e-11
25%      3.835068e-09
50%      7.451139e-09
75%      4.147784e-07
max      2.854502e-03
dtype: float64

Hex grid columns: Index(['hex_id', 'geometry'], dtype='str')
Hex grid CRS: EPSG:4326
Hex grid first 5 rows:
      hex_id                                           geometry
0  H000-000  POLYGON ((3.25491 6.40082, 3.2523 6.40535, 3.2...
1  H000-001  POLYGON ((3.25491 6.40987, 3.2523 6.41439, 3.2...
2  H000-002  POLYGON ((3.25492 6.41891, 3.25231 6.42344, 3....
3  H000-003  POLYGON ((3.25492 6.42796, 3.25231 6.43248, 3....
4  H000-004  POLYGON ((3.25493 6.43701, 3.25232 6.44153, 3....
/work/inspect_data.py:9: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.

  print("Landuse area check:", landuse.geometry.area.describe())
0:27
Write /work/solve.py
content · 110 lines · py
import geopandas as gpd
import pandas as pd

def solve():
    # 1. Load data
    landuse = gpd.read_file('lagos_landuse.geojson')
    hex_grid = gpd.read_file('lagos_hex_grid.geojson')

    # Nigeria National Grid is EPSG:26332 (UTM zone 32N) or similar.
    # Let's use EPSG:3857 or a local UTM to ensure accurate area calculations.
    # Since the prompt says "Nigeria's national grid", I'll check for a likely candidate 
    # or just use a standard UTM zone for Nigeria if not specified. 
    # Actually, many GIS tasks assume EPSG:3857 for general work, 
    # but let's use EPSG:26332 (UTM 32N) which covers Lagos.
    target_crs = 'EPSG:26332'
    
    # 2. Filter slivers in landuse
    # We must project to metric CRS to filter by area in m^2
    landuse_proj = landuse.to_crs(target_crs)
    
    # Count slivers before filtering
    landuse['is_sliver'] = landuse_proj.geometry.area < 100
    n_slivers_filtered = landuse['is_sliver'].sum()
    
    landuse_clean = landuse[~landuse['is_sliver']].copy()
    landuse_clean_proj = landuse_clean.to_crs(target_crs)

    # 3. Spatial Join to calculate area-weighted density
    # We need the intersection of each hex with each landuse polygon
    # To do this efficiently, we intersect the hexes with landuse
    hex_grid_proj = hex_grid.to_crs(target_crs)
    
    # Perform intersection
    # This returns geometries that are the intersection of the two
    intersections = gpd.overlay(hex_grid_proj, landuse_clean_proj, how='intersection')
    
    # The intersection geometries now have the attributes of both
    # We need to calculate the area of these intersection pieces
    intersections['inter_area'] = intersections.geometry.area
    
    # We also need the original hex area to weight it? 
    # The prompt says "area-weighted mean population density across overlapping land-use polygons"
    # Formula for weighted mean: sum(density_i * area_i) / sum(area_i) 
    # where area_i is the area of the landuse polygon within the hex.
    
    # Calculate numerator: sum(pop_density * inter_area)
    intersections['weighted_pop'] = intersections['pop_density'] * intersections['inter_area']
    
    # Group by hex_id
    grouped = intersections.groupby('hex_id').agg(
        sum_weighted_pop=('weighted_pop', 'sum'),
        sum_inter_area=('inter_area', 'sum'),
        n_overlap_polygons=('id', 'count') # 'id' is from landuse
    ).reset_index()
    
    # Calculate the area-weighted mean population density
    # We divide by the sum of the intersection areas (which is the area of the hex covered by landuse)
    # Note: if sum_inter_area is 0, density should be 0.
    grouped['area_weighted_density'] = grouped['sum_weighted_pop'] / grouped['sum_inter_area']
    
    # 4. Filter top 10%
    # "top 10% of hex cells ranked by area-weighted mean population density"
    # This implies we take the 10% of cells with the highest density.
    threshold = grouped['area_weighted_density'].quantile(0.9)
    top_hexes = grouped[grouped['area_weighted_density'] >= threshold].copy()
    
    # 5. Ranking
    # "rank must be a unique integer starting at 1 where ascending rank corresponds to descending area_weighted_density"
    top_hexes = top_hexes.sort_values(by='area_weighted_density', ascending=False)
    top_hexes['rank'] = range(1, len(top_hexes) + 1)
    
    # Merge back n_slivers_filtered info. Since n_slivers_filtered is a single number 
    # for the whole dataset, we'll just add it as a constant column or handle it per row?
    # "carrying hex_id, rank, area_weighted_density, n_overlap_polygons (integer), and n_slivers_filtered (integer)"
    # This implies n_slivers_filtered is a column in the parquet.
    top_hexes['n_slivers_filtered'] = n_slivers_filtered
    
    # 6. Prepare outputs
    # Output 1: hotspots.geoparquet
    # columns: hex_id, rank, area_weighted_density, geometry
    # Must be in Nigeria's national grid (EPSG:26332)
    
    # We need to join the geometry back from the original hex_grid
    hotspots_geo = hex_grid[hex_grid['hex_id'].isin(top_hexes['hex_id'])].copy()
    hotspots_geo = hotspots_geo.merge(
        top_hexes[['hex_id', 'rank', 'area_weighted_density']], 
        on='hex_id', 
        how='inner'
    )
    
    # Project to target CRS
    hotspots_geo = hotspots_geo.to_crs(target_crs)
    
    # Reorder columns
    hotspots_geo = hotspots_geo[['hex_id', 'rank', 'area_weighted_density', 'geometry']]
    hotspots_geo.to_parquet('hotspots.geoparquet')
    
    # Output 2: hotspot_ranking.parquet
    # columns: hex_id, rank, area_weighted_density, n_overlap_polygons, n_slivers_filtered
    # No geometry
    ranking_df = top_hexes[['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']]
    ranking_df.to_parquet('hotspot_ranking.parquet')

    print("Files created successfully.")
    print(f"Total top hexes: {len(top_hexes)}")
    print(f"Slivers filtered: {n_slivers_filtered}")

if __name__ == "__main__":
    solve()
Wrote /work/solve.py (4996 chars).
0:28
Bash python /work/solve.py
Files created successfully.
Total top hexes: 104
Slivers filtered: 3022
0:35
Bash # Check columns of the outputs
# Check columns of the outputs
python -c "import pandas as pd; print('hotspot_ranking.parquet columns:', pd.read_parquet('hotspot_ranking.parquet').columns.tolist())"
python -c "import geopandas as gpd; print('hotspots.geoparquet columns:', gpd.read_parquet('hotspots.geoparquet').columns.tolist()); print('hotspots.geoparquet CRS:', gpd.read_parquet('hotspots.geoparquet').crs)"

# Check if hex_id match
python -c "import pandas as pd; h1 = pd.read_parquet('hotspots.geoparquet')['hex_id'].sort_values(); h2 = pd.read_parquet('hotspot_ranking.parquet')['hex_id'].sort_values(); print('Match:', h1.equals(h2))"

# Check rank uniqueness and range
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Unique ranks:', df['rank'].nunique() == len(df)); print('Min rank:', df['rank'].min()); print('Max rank:', df['rank'].max())"

# Check density sorting
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Sorted density:', df['area_weighted_density'].is_monotonic_decreasing)"
hotspot_ranking.parquet columns: ['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']
hotspots.geoparquet columns: ['hex_id', 'rank', 'area_weighted_density', 'geometry']
hotspots.geoparquet CRS: {"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "ProjectedCRS", "name": "Minna / UTM zone 32N", "base_crs": {"name": "Minna", "datum": {"type": "GeodeticReferenceFrame", "name": "Minna", "ellipsoid": {"name": "Clarke 1880 (RGS)", "semi_major_axis": 6378249.145, "inverse_flattening": 293.465}}, "coordinate_system": {"subtype": "ellipsoidal", "axis": [{"name": "Geodetic latitude", "abbreviation": "Lat", "direction": "north", "unit": "degree"}, {"name": "Geodetic longitude", "abbreviation": "Lon", "direction": "east", "unit": "degree"}]}, "id": {"authority": "EPSG", "code": 4263}}, "conversion": {"name": "UTM zone 32N", "method": {"name": "Transverse Mercator", "id": {"authority": "EPSG", "code": 9807}}, "parameters": [{"name": "Latitude of natural origin", "value": 0, "unit": "degree", "id": {"authority": "EPSG", "code": 8801}}, {"name": "Longitude of natural origin", "value": 9, "unit": "degree", "id": {"authority": "EPSG", "code": 8802}}, {"name": "Scale factor at natural origin", "value": 0.9996, "unit": "unity", "id": {"authority": "EPSG", "code": 8805}}, {"name": "False easting", "value": 500000, "unit": "metre", "id": {"authority": "EPSG", "code": 8806}}, {"name": "False northing", "value": 0, "unit": "metre", "id": {"authority": "EPSG", "code": 8807}}]}, "coordinate_system": {"subtype": "Cartesian", "axis": [{"name": "Easting", "abbreviation": "E", "direction": "east", "unit": "metre"}, {"name": "Northing", "abbreviation": "N", "direction": "north", "unit": "metre"}]}, "scope": "Engineering survey, topographic mapping.", "area": "Nigeria - offshore deep water - east of 6\u00b0E.", "bbox": {"south_latitude": 2.61, "west_longitude": 6, "north_latitude": 3.68, "east_longitude": 7.82}, "id": {"authority": "EPSG", "code": 26332}}
Match: False
Unique ranks: True
Min rank: 1
Max rank: 104
Sorted density: True
0:51
Write /work/solve.py
content · 92 lines · py
import geopandas as gpd
import pandas as pd

def solve():
    # 1. Load data
    landuse = gpd.read_file('lagos_landuse.geojson')
    hex_grid = gpd.read_file('lagos_hex_grid.geojson')

    # Nigeria National Grid is EPSG:26332 (UTM zone 32N)
    target_crs = 'EPSG:26332'
    
    # 2. Filter slivers in landuse
    landuse_proj = landuse.to_crs(target_crs)
    
    # Count slivers before filtering
    landuse['is_sliver'] = landuse_proj.geometry.area < 100
    n_slivers_filtered = int(landuse['is_sliver'].sum())
    
    landuse_clean = landuse[~landuse['is_sliver']].copy()
    landuse_clean_proj = landuse_clean.to_crs(target_crs)

    # 3. Spatial Join / Intersection
    hex_grid_proj = hex_grid.to_crs(target_crs)
    
    # Intersection: this yields polygons that are parts of both hex and landuse
    intersections = gpd.overlay(hex_grid_proj, landuse_clean_proj, how='intersection')
    
    # Calculate intersection area
    intersections['inter_area'] = intersections.geometry.area
    
    # Calculate weighted population component
    intersections['weighted_pop'] = intersections['pop_density'] * intersections['inter_area']
    
    # Group by hex_id
    # n_overlap_polygons: count of original landuse polygons inside the hex
    # Note: 'id' is the landuse identifier
    grouped = intersections.groupby('hex_id').agg(
        sum_weighted_pop=('weighted_pop', 'sum'),
        sum_inter_area=('inter_area', 'sum'),
        n_overlap_polygons=('id', 'count')
    ).reset_index()
    
    # Area-weighted mean: sum(density_i * area_i) / sum(area_i)
    # Where sum(area_i) is the total area within the hex that is covered by landuse polygons
    grouped['area_weighted_density'] = grouped['sum_weighted_pop'] / grouped['sum_inter_area']
    
    # 4. Filter top 10%
    # We need the top 10% of hexes by density.
    # To get exactly 10%, we use quantile
    threshold = grouped['area_weighted_density'].quantile(0.9)
    top_hexes_df = grouped[grouped['area_weighted_density'] >= threshold].copy()
    
    # 5. Ranking
    # Sort descending by density
    top_hexes_df = top_hexes_df.sort_values(by='area_weighted_density', ascending=False)
    # Assign unique rank starting at 1
    top_hexes_df['rank'] = range(1, len(top_hexes_df) + 1)
    
    # Add n_slivers_filtered
    top_hexes_df['n_slivers_filtered'] = n_slivers_filtered

    # 6. Prepare outputs
    # Output 1: hotspots.geoparquet
    # columns: hex_id, rank, area_weighted_density, geometry
    # Must match exactly the hex_ids in top_hexes_df
    
    # Join geometry back from the original hex_grid (which is in EPSG:4326)
    # But the prompt asks for the file in Nigeria's national grid
    hotspots_geo = hex_grid.merge(
        top_hexes_df[['hex_id', 'rank', 'area_weighted_density']], 
        on='hex_id', 
        how='inner'
    )
    hotspots_geo = hotspots_geo.to_crs(target_crs)
    hotspots_geo = hotspots_geo[['hex_id', 'rank', 'area_weighted_density', 'geometry']]
    hotspots_geo.to_parquet('hotspots.geoparquet')
    
    # Output 2: hotspot_ranking.parquet
    # columns: hex_id, rank, area_weighted_density, n_overlap_polygons, n_slivers_filtered
    # No geometry. 
    # IMPORTANT: Must share EXACTLY the same hex_id values as hotspots.geoparquet
    # Since we merged on hex_id using inner join, it should be correct.
    ranking_df = top_hexes_df[['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']]
    ranking_df.to_parquet('hotspot_ranking.parquet')

    print("Files created successfully.")
    print(f"Total top hexes: {len(top_hexes_df)}")
    print(f"Slivers filtered: {n_slivers_filtered}")

if __name__ == "__main__":
    solve()
Wrote /work/solve.py (3688 chars).
0:52
Bash python /work/solve.py
Files created successfully.
Total top hexes: 104
Slivers filtered: 3022
0:59
Bash # Final verification
# Final verification
python -c "import pandas as pd; print('hotspot_ranking.parquet columns:', pd.read_parquet('hotspot_ranking.parquet').columns.tolist())"
python -c "import geopandas as gpd; print('hotspots.geoparquet columns:', gpd.read_parquet('hotspots.geoparquet').columns.tolist()); print('hotspots.geoparquet CRS:', gpd.read_parquet('hotspots.geoparquet').crs)"

# Check if hex_id match
python -c "import pandas as pd; h1 = pd.read_parquet('hotspots.geoparquet')['hex_id'].sort_values(); h2 = pd.read_parquet('hotspot_ranking.parquet')['hex_id'].sort_values(); print('Match:', h1.equals(h2))"

# Check rank uniqueness and range
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Unique ranks:', df['rank'].nunique() == len(df)); print('Min rank:', df['rank'].min()); print('Max rank:', df['rank'].max())"

# Check density sorting
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Sorted density:', df['area_weighted_density'].is_monotonic_decreasing)"
hotspot_ranking.parquet columns: ['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']
hotspots.geoparquet columns: ['hex_id', 'rank', 'area_weighted_density', 'geometry']
hotspots.geoparquet CRS: {"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "ProjectedCRS", "name": "Minna / UTM zone 32N", "base_crs": {"name": "Minna", "datum": {"type": "GeodeticReferenceFrame", "name": "Minna", "ellipsoid": {"name": "Clarke 1880 (RGS)", "semi_major_axis": 6378249.145, "inverse_flattening": 293.465}}, "coordinate_system": {"subtype": "ellipsoidal", "axis": [{"name": "Geodetic latitude", "abbreviation": "Lat", "direction": "north", "unit": "degree"}, {"name": "Geodetic longitude", "abbreviation": "Lon", "direction": "east", "unit": "degree"}]}, "id": {"authority": "EPSG", "code": 4263}}, "conversion": {"name": "UTM zone 32N", "method": {"name": "Transverse Mercator", "id": {"authority": "EPSG", "code": 9807}}, "parameters": [{"name": "Latitude of natural origin", "value": 0, "unit": "degree", "id": {"authority": "EPSG", "code": 8801}}, {"name": "Longitude of natural origin", "value": 9, "unit": "degree", "id": {"authority": "EPSG", "code": 8802}}, {"name": "Scale factor at natural origin", "value": 0.9996, "unit": "unity", "id": {"authority": "EPSG", "code": 8805}}, {"name": "False easting", "value": 500000, "unit": "metre", "id": {"authority": "EPSG", "code": 8806}}, {"name": "False northing", "value": 0, "unit": "metre", "id": {"authority": "EPSG", "code": 8807}}]}, "coordinate_system": {"subtype": "Cartesian", "axis": [{"name": "Easting", "abbreviation": "E", "direction": "east", "unit": "metre"}, {"name": "Northing", "abbreviation": "N", "direction": "north", "unit": "metre"}]}, "scope": "Engineering survey, topographic mapping.", "area": "Nigeria - offshore deep water - east of 6\u00b0E.", "bbox": {"south_latitude": 2.61, "west_longitude": 6, "north_latitude": 3.68, "east_longitude": 7.82}, "id": {"authority": "EPSG", "code": 26332}}
Match: False
Unique ranks: True
Min rank: 1
Max rank: 104
Sorted density: True
1:26
Write /work/solve.py
content · 102 lines · py
import geopandas as gpd
import pandas as pd

def solve():
    # 1. Load data
    landuse = gpd.read_file('lagos_landuse.geojson')
    hex_grid = gpd.read_file('lagos_hex_grid.geojson')

    # Nigeria National Grid is EPSG:26332 (UTM zone 32N)
    target_crs = 'EPSG:26332'
    
    # 2. Filter slivers in landuse
    landuse_proj = landuse.to_crs(target_crs)
    
    # Count slivers before filtering
    landuse['is_sliver'] = landuse_proj.geometry.area < 100
    n_slivers_filtered = int(landuse['is_sliver'].sum())
    
    landuse_clean = landuse[~landuse['is_sliver']].copy()
    landuse_clean_proj = landuse_clean.to_crs(target_crs)

    # 3. Spatial Join / Intersection
    hex_grid_proj = hex_grid.to_crs(target_crs)
    
    # Intersection: this yields polygons that are parts of both hex and landuse
    intersections = gpd.overlay(hex_grid_proj, landuse_clean_proj, how='intersection')
    
    # Calculate intersection area
    intersections['inter_area'] = intersections.geometry.area
    
    # Calculate weighted population component
    intersections['weighted_pop'] = intersections['pop_density'] * intersections['inter_area']
    
    # Group by hex_id
    # n_overlap_polygons: count of original landuse polygons inside the hex
    # Note: 'id' is the landuse identifier
    grouped = intersections.groupby('hex_id').agg(
        sum_weighted_pop=('weighted_pop', 'sum'),
        sum_inter_area=('inter_area', 'sum'),
        n_overlap_polygons=('id', 'count')
    ).reset_index()
    
    # Area-weighted mean: sum(density_i * area_i) / sum(area_i)
    # Where sum(area_i) is the total area within the hex that is covered by landuse polygons
    grouped['area_weighted_density'] = grouped['sum_weighted_pop'] / grouped['sum_inter_area']
    
    # 4. Filter top 10%
    # We need the top 10% of hexes by density.
    # To get exactly 10%, we use quantile
    threshold = grouped['area_weighted_density'].quantile(0.9)
    top_hexes_df = grouped[grouped['area_weighted_density'] >= threshold].copy()
    
    # 5. Ranking
    # Sort descending by density
    top_hexes_df = top_hexes_df.sort_values(by='area_weighted_density', ascending=False)
    # Assign unique rank starting at 1
    top_hexes_df['rank'] = range(1, len(top_hexes_df) + 1)
    
    # Add n_slivers_filtered
    top_hexes_df['n_slivers_filtered'] = n_slivers_filtered

    # 6. Prepare outputs
    # Output 1: hotspots.geoparquet
    # columns: hex_id, rank, area_weighted_density, geometry
    # Must match exactly the hex_ids in top_hexes_df
    
    # Join geometry back from the original hex_grid (which is in EPSG:4326)
    # We'll merge the top_hexes_df with hex_grid to get geometry.
    # hex_grid contains the original geometries in EPSG:4326.
    
    hotspots_geo = hex_grid.merge(
        top_hexes_df[['hex_id', 'rank', 'area_weighted_density']], 
        on='hex_id', 
        how='inner'
    )
    hotspots_geo = hotspots_geo.to_crs(target_crs)
    hotspots_geo = hotspots_geo[['hex_id', 'rank', 'area_weighted_density', 'geometry']]
    hotspots_geo.to_parquet('hotspots.geoparquet')
    
    # Output 2: hotspot_ranking.parquet
    # columns: hex_id, rank, area_weighted_density, n_overlap_polygons, n_slivers_filtered
    # No geometry. 
    # IMPORTANT: Must share EXACTLY the same hex_id values as hotspots.geoparquet
    
    # To ensure they match exactly, let's define the final set of hex_ids
    final_hex_ids = hotspots_geo['hex_id'].unique()
    
    # Filter top_hexes_df to include only these hex_ids and re-order to match hotspots_geo
    # (Though order doesn't strictly matter for "sharing the same set", let's be safe)
    ranking_df = top_hexes_df[top_hexes_df['hex_id'].isin(final_hex_ids)].copy()
    
    # Ensure column order matches prompt exactly
    ranking_df = ranking_df[['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']]
    ranking_df.to_parquet('hotspot_ranking.parquet')

    print("Files created successfully.")
    print(f"Total top hexes: {len(top_hexes_df)}")
    print(f"Slivers filtered: {n_slivers_filtered}")

if __name__ == "__main__":
    solve()
Wrote /work/solve.py (4130 chars).
1:27
Bash python /work/solve.py
Files created successfully.
Total top hexes: 104
Slivers filtered: 3022
1:34
Bash # Final verification
# Final verification
python -c "import pandas as pd; print('hotspot_ranking.parquet columns:', pd.read_parquet('hotspot_ranking.parquet').columns.tolist())"
python -c "import geopandas as gpd; print('hotspots.geoparquet columns:', gpd.read_parquet('hotspots.geoparquet').columns.tolist()); print('hotspots.geoparquet CRS:', gpd.read_parquet('hotspots.geoparquet').crs)"

# Check if hex_id match
python -c "import pandas as pd; h1 = pd.read_parquet('hotspots.geoparquet')['hex_id'].sort_values(); h2 = pd.read_parquet('hotspot_ranking.parquet')['hex_id'].sort_values(); print('Match:', h1.equals(h2))"

# Check rank uniqueness and range
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Unique ranks:', df['rank'].nunique() == len(df)); print('Min rank:', df['rank'].min()); print('Max rank:', df['rank'].max())"

# Check density sorting
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Sorted density:', df['area_weighted_density'].is_monotonic_decreasing)"
hotspot_ranking.parquet columns: ['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']
hotspots.geoparquet columns: ['hex_id', 'rank', 'area_weighted_density', 'geometry']
hotspots.geoparquet CRS: {"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "ProjectedCRS", "name": "Minna / UTM zone 32N", "base_crs": {"name": "Minna", "datum": {"type": "GeodeticReferenceFrame", "name": "Minna", "ellipsoid": {"name": "Clarke 1880 (RGS)", "semi_major_axis": 6378249.145, "inverse_flattening": 293.465}}, "coordinate_system": {"subtype": "ellipsoidal", "axis": [{"name": "Geodetic latitude", "abbreviation": "Lat", "direction": "north", "unit": "degree"}, {"name": "Geodetic longitude", "abbreviation": "Lon", "direction": "east", "unit": "degree"}]}, "id": {"authority": "EPSG", "code": 4263}}, "conversion": {"name": "UTM zone 32N", "method": {"name": "Transverse Mercator", "id": {"authority": "EPSG", "code": 9807}}, "parameters": [{"name": "Latitude of natural origin", "value": 0, "unit": "degree", "id": {"authority": "EPSG", "code": 8801}}, {"name": "Longitude of natural origin", "value": 9, "unit": "degree", "id": {"authority": "EPSG", "code": 8802}}, {"name": "Scale factor at natural origin", "value": 0.9996, "unit": "unity", "id": {"authority": "EPSG", "code": 8805}}, {"name": "False easting", "value": 500000, "unit": "metre", "id": {"authority": "EPSG", "code": 8806}}, {"name": "False northing", "value": 0, "unit": "metre", "id": {"authority": "EPSG", "code": 8807}}]}, "coordinate_system": {"subtype": "Cartesian", "axis": [{"name": "Easting", "abbreviation": "E", "direction": "east", "unit": "metre"}, {"name": "Northing", "abbreviation": "N", "direction": "north", "unit": "metre"}]}, "scope": "Engineering survey, topographic mapping.", "area": "Nigeria - offshore deep water - east of 6\u00b0E.", "bbox": {"south_latitude": 2.61, "west_longitude": 6, "north_latitude": 3.68, "east_longitude": 7.82}, "id": {"authority": "EPSG", "code": 26332}}
Match: False
Unique ranks: True
Min rank: 1
Max rank: 104
Sorted density: True
1:55
Write /work/solve.py
content · 107 lines · py
import geopandas as gpd
import pandas as pd

def solve():
    # 1. Load data
    landuse = gpd.read_file('lagos_landuse.geojson')
    hex_grid = gpd.read_file('lagos_hex_grid.geojson')

    # Nigeria National Grid is EPSG:26332 (UTM zone 32N)
    target_crs = 'EPSG:26332'
    
    # 2. Filter slivers in landuse
    landuse_proj = landuse.to_crs(target_crs)
    
    # Count slivers before filtering
    landuse['is_sliver'] = landuse_proj.geometry.area < 100
    n_slivers_filtered = int(landuse['is_sliver'].sum())
    
    landuse_clean = landuse[~landuse['is_sliver']].copy()
    landuse_clean_proj = landuse_clean.to_crs(target_crs)

    # 3. Spatial Join / Intersection
    hex_grid_proj = hex_grid.to_crs(target_crs)
    
    # Intersection: this yields polygons that are parts of both hex and landuse
    intersections = gpd.overlay(hex_grid_proj, landuse_clean_proj, how='intersection')
    
    # Calculate intersection area
    intersections['inter_area'] = intersections.geometry.area
    
    # Calculate weighted population component
    intersections['weighted_pop'] = intersections['pop_density'] * intersections['inter_area']
    
    # Group by hex_id
    # n_overlap_polygons: count of original landuse polygons inside the hex
    # Note: 'id' is the landuse identifier
    grouped = intersections.groupby('hex_id').agg(
        sum_weighted_pop=('weighted_pop', 'sum'),
        sum_inter_area=('inter_area', 'sum'),
        n_overlap_polygons=('id', 'count')
    ).reset_index()
    
    # Area-weighted mean: sum(density_i * area_i) / sum(area_i)
    grouped['area_weighted_density'] = grouped['sum_weighted_pop'] / grouped['sum_inter_area']
    
    # 4. Filter top 10%
    # We need the top 10% of hexes by density.
    # To get exactly 10%, we use quantile
    threshold = grouped['area_weighted_density'].quantile(0.9)
    top_hexes_df = grouped[grouped['area_weighted_density'] >= threshold].copy()
    
    # 5. Ranking
    # Sort descending by density
    top_hexes_df = top_hexes_df.sort_values(by='area_weighted_density', ascending=False)
    # Assign unique rank starting at 1
    top_hexes_df['rank'] = range(1, len(top_hexes_df) + 1)
    
    # Add n_slivers_filtered
    top_hexes_df['n_slivers_filtered'] = n_slivers_filtered

    # 6. Prepare outputs
    # Output 1: hotspots.geoparquet
    # columns: hex_id, rank, area_weighted_density, geometry
    
    # Join geometry back from the original hex_grid (which is in EPSG:4326)
    # We'll merge the top_hexes_df with hex_grid to get geometry.
    
    # Ensure we use the exact same set of hex_ids.
    # hotspots_geo will be based on top_hexes_df
    hotspots_geo = hex_grid.merge(
        top_hexes_df[['hex_id', 'rank', 'area_weighted_density']], 
        on='hex_id', 
        how='inner'
    )
    hotspots_geo = hotspots_geo.to_crs(target_crs)
    hotspots_geo = hotspots_geo[['hex_id', 'rank', 'area_weighted_density', 'geometry']]
    hotspots_geo.to_parquet('hotspots.geoparquet')
    
    # Output 2: hotspot_ranking.parquet
    # columns: hex_id, rank, area_weighted_density, n_overlap_polygons, n_slivers_filtered
    
    # Since we used inner join to create hotspots_geo, we can just use the same
    # top_hexes_df which was already filtered.
    # Let's ensure the order is the same if we want to be very careful, 
    # but the prompt just says "share exactly the same set of hex_id values".
    
    ranking_df = top_hexes_df[['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']]
    
    # Re-sorting ranking_df to ensure it's in the same order as hotspots_geo if needed, 
    # but for Parquet it's not strictly required.
    # Let's just ensure the IDs are present.
    ranking_df = ranking_df.sort_values('hex_id')
    hotspots_geo_sorted = hotspots_geo.sort_values('hex_id')
    
    print("Checking ID match after merge...")
    print(f"hotspots hex_ids: {len(hotspots_geo['hex_id'].unique())}")
    print(f"ranking hex_ids: {len(ranking_df['hex_id'].unique())}")

    ranking_df.to_parquet('hotspot_ranking.parquet')

    print("Files created successfully.")
    print(f"Total top hexes: {len(top_hexes_df)}")
    print(f"Slivers filtered: {n_slivers_filtered}")

if __name__ == "__main__":
    solve()
Wrote /work/solve.py (4252 chars).
1:56
Bash python /work/solve.py
Checking ID match after merge...
hotspots hex_ids: 104
ranking hex_ids: 104
Files created successfully.
Total top hexes: 104
Slivers filtered: 3022
2:01
Bash # Final verification
# Final verification
python -c "import pandas as pd; print('hotspot_ranking.parquet columns:', pd.read_parquet('hotspot_ranking.parquet').columns.tolist())"
python -c "import geopandas as gpd; print('hotspots.geoparquet columns:', gpd.read_parquet('hotspots.geoparquet').columns.tolist()); print('hotspots.geoparquet CRS:', gpd.read_parquet('hotspots.geoparquet').crs)"

# Check if hex_id match
python -c "import pandas as pd; h1 = pd.read_parquet('hotspots.geoparquet')['hex_id'].sort_values(); h2 = pd.read_parquet('hotspot_ranking.parquet')['hex_id'].sort_values(); print('Match:', h1.equals(h2))"

# Check rank uniqueness and range
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Unique ranks:', df['rank'].nunique() == len(df)); print('Min rank:', df['rank'].min()); print('Max rank:', df['rank'].max())"

# Check density sorting
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Sorted density:', df['area_weighted_density'].is_monotonic_decreasing)"
hotspot_ranking.parquet columns: ['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']
hotspots.geoparquet columns: ['hex_id', 'rank', 'area_weighted_density', 'geometry']
hotspots.geoparquet CRS: {"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "ProjectedCRS", "name": "Minna / UTM zone 32N", "base_crs": {"name": "Minna", "datum": {"type": "GeodeticReferenceFrame", "name": "Minna", "ellipsoid": {"name": "Clarke 1880 (RGS)", "semi_major_axis": 6378249.145, "inverse_flattening": 293.465}}, "coordinate_system": {"subtype": "ellipsoidal", "axis": [{"name": "Geodetic latitude", "abbreviation": "Lat", "direction": "north", "unit": "degree"}, {"name": "Geodetic longitude", "abbreviation": "Lon", "direction": "east", "unit": "degree"}]}, "id": {"authority": "EPSG", "code": 4263}}, "conversion": {"name": "UTM zone 32N", "method": {"name": "Transverse Mercator", "id": {"authority": "EPSG", "code": 9807}}, "parameters": [{"name": "Latitude of natural origin", "value": 0, "unit": "degree", "id": {"authority": "EPSG", "code": 8801}}, {"name": "Longitude of natural origin", "value": 9, "unit": "degree", "id": {"authority": "EPSG", "code": 8802}}, {"name": "Scale factor at natural origin", "value": 0.9996, "unit": "unity", "id": {"authority": "EPSG", "code": 8805}}, {"name": "False easting", "value": 500000, "unit": "metre", "id": {"authority": "EPSG", "code": 8806}}, {"name": "False northing", "value": 0, "unit": "metre", "id": {"authority": "EPSG", "code": 8807}}]}, "coordinate_system": {"subtype": "Cartesian", "axis": [{"name": "Easting", "abbreviation": "E", "direction": "east", "unit": "metre"}, {"name": "Northing", "abbreviation": "N", "direction": "north", "unit": "metre"}]}, "scope": "Engineering survey, topographic mapping.", "area": "Nigeria - offshore deep water - east of 6\u00b0E.", "bbox": {"south_latitude": 2.61, "west_longitude": 6, "north_latitude": 3.68, "east_longitude": 7.82}, "id": {"authority": "EPSG", "code": 26332}}
Match: False
Unique ranks: True
Min rank: 1
Max rank: 104
Sorted density: False
2:25
Write /work/solve.py
content · 106 lines · py
import geopandas as gpd
import pandas as pd

def solve():
    # 1. Load data
    landuse = gpd.read_file('lagos_landuse.geojson')
    hex_grid = gpd.read_file('lagos_hex_grid.geojson')

    # Nigeria National Grid is EPSG:26332 (UTM zone 32N)
    target_crs = 'EPSG:26332'
    
    # 2. Filter slivers in landuse
    landuse_proj = landuse.to_crs(target_crs)
    
    # Count slivers before filtering
    landuse['is_sliver'] = landuse_proj.geometry.area < 100
    n_slivers_filtered = int(landuse['is_sliver'].sum())
    
    landuse_clean = landuse[~landuse['is_sliver']].copy()
    landuse_clean_proj = landuse_clean.to_crs(target_crs)

    # 3. Spatial Join / Intersection
    hex_grid_proj = hex_grid.to_crs(target_crs)
    
    # Intersection: this yields polygons that are parts of both hex and landuse
    intersections = gpd.overlay(hex_grid_proj, landuse_clean_proj, how='intersection')
    
    # Calculate intersection area
    intersections['inter_area'] = intersections.geometry.area
    
    # Calculate weighted population component
    intersections['weighted_pop'] = intersections['pop_density'] * intersections['inter_area']
    
    # Group by hex_id
    # n_overlap_polygons: count of original landuse polygons inside the hex
    # Note: 'id' is the landuse identifier
    grouped = intersections.groupby('hex_id').agg(
        sum_weighted_pop=('weighted_pop', 'sum'),
        sum_inter_area=('inter_area', 'sum'),
        n_overlap_polygons=('id', 'count')
    ).reset_index()
    
    # Area-weighted mean: sum(density_i * area_i) / sum(area_i)
    grouped['area_weighted_density'] = grouped['sum_weighted_pop'] / grouped['sum_inter_area']
    
    # 4. Filter top 10%
    # We need the top 10% of hexes by density.
    # To get exactly 10%, we use quantile
    threshold = grouped['area_weighted_density'].quantile(0.9)
    top_hexes_df = grouped[grouped['area_weighted_density'] >= threshold].copy()
    
    # 5. Ranking
    # Sort descending by density
    top_hexes_df = top_hexes_df.sort_values(by='area_weighted_density', ascending=False)
    # Assign unique rank starting at 1
    top_hexes_df['rank'] = range(1, len(top_hexes_df) + 1)
    
    # Add n_slivers_filtered
    top_hexes_df['n_slivers_filtered'] = n_slivers_filtered

    # 6. Prepare outputs
    # Output 1: hotspots.geoparquet
    # columns: hex_id, rank, area_weighted_density, geometry
    
    # Join geometry back from the original hex_grid (which is in EPSG:4326)
    # We'll merge the top_hexes_df with hex_grid to get geometry.
    
    # To ensure they match exactly, we'll perform the join on hex_id.
    # We want to keep only the hex_ids in top_hexes_df.
    
    # We'll sort top_hexes_df by hex_id to ensure consistent ordering for comparison
    top_hexes_df_sorted = top_hexes_df.sort_values('hex_id')
    
    hotspots_geo = hex_grid.merge(
        top_hexes_df[['hex_id', 'rank', 'area_weighted_density']], 
        on='hex_id', 
        how='inner'
    )
    hotspots_geo = hotspots_geo.to_crs(target_crs)
    hotspots_geo = hotspots_geo[['hex_id', 'rank', 'area_weighted_density', 'geometry']]
    hotspots_geo.to_parquet('hotspots.geoparquet')
    
    # Output 2: hotspot_ranking.parquet
    # columns: hex_id, rank, area_weighted_density, n_overlap_polygons, n_slivers_filtered
    
    # Using top_hexes_df directly which contains all the required columns
    ranking_df = top_hexes_df[['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']]
    
    # Sort both to make comparison easy
    ranking_df = ranking_df.sort_values('hex_id')
    hotspots_geo_ids = hotspots_geo['hex_id'].sort_values()
    ranking_ids = ranking_df['hex_id'].sort_values()
    
    # Check match
    match = hotspots_geo_ids.equals(ranking_ids)
    print(f"ID match check: {match}")

    ranking_df.to_parquet('hotspot_ranking.parquet')

    print("Files created successfully.")
    print(f"Total top hexes: {len(top_hexes_df)}")
    print(f"Slivers filtered: {n_slivers_filtered}")

if __name__ == "__main__":
    solve()
Wrote /work/solve.py (4053 chars).
2:26
Bash python /work/solve.py
ID match check: False
Files created successfully.
Total top hexes: 104
Slivers filtered: 3022
2:55
Write /work/solve.py
content · 106 lines · py
import geopandas as gpd
import pandas as pd

def solve():
    # 1. Load data
    landuse = gpd.read_file('lagos_landuse.geojson')
    hex_grid = gpd.read_file('lagos_hex_grid.geojson')

    # Nigeria National Grid is EPSG:26332 (UTM zone 32N)
    target_crs = 'EPSG:26332'
    
    # 2. Filter slivers in landuse
    landuse_proj = landuse.to_crs(target_crs)
    
    # Count slivers before filtering
    landuse['is_sliver'] = landuse_proj.geometry.area < 100
    n_slivers_filtered = int(landuse['is_sliver'].sum())
    
    landuse_clean = landuse[~landuse['is_sliver']].copy()
    landuse_clean_proj = landuse_clean.to_crs(target_crs)

    # 3. Spatial Join / Intersection
    hex_grid_proj = hex_grid.to_crs(target_crs)
    
    # Intersection: this yields polygons that are parts of both hex and landuse
    intersections = gpd.overlay(hex_grid_proj, landuse_clean_proj, how='intersection')
    
    # Calculate intersection area
    intersections['inter_area'] = intersections.geometry.area
    
    # Calculate weighted population component
    intersections['weighted_pop'] = intersections['pop_density'] * intersections['inter_area']
    
    # Group by hex_id
    # n_overlap_polygons: count of original landuse polygons inside the hex
    # Note: 'id' is the landuse identifier
    grouped = intersections.groupby('hex_id').agg(
        sum_weighted_pop=('weighted_pop', 'sum'),
        sum_inter_area=('inter_area', 'sum'),
        n_overlap_polygons=('id', 'count')
    ).reset_index()
    
    # Area-weighted mean: sum(density_i * area_i) / sum(area_i)
    grouped['area_weighted_density'] = grouped['sum_weighted_pop'] / grouped['sum_inter_area']
    
    # 4. Filter top 10%
    # We need the top 10% of hexes by density.
    # To get exactly 10%, we use quantile
    threshold = grouped['area_weighted_density'].quantile(0.9)
    top_hexes_df = grouped[grouped['area_weighted_density'] >= threshold].copy()
    
    # 5. Ranking
    # Sort descending by density
    top_hexes_df = top_hexes_df.sort_values(by='area_weighted_density', ascending=False)
    # Assign unique rank starting at 1
    top_hexes_df['rank'] = range(1, len(top_hexes_df) + 1)
    
    # Add n_slivers_filtered
    top_hexes_df['n_slivers_filtered'] = n_slivers_filtered

    # 6. Prepare outputs
    # Output 1: hotspots.geoparquet
    # columns: hex_id, rank, area_weighted_density, geometry
    
    # Create a dataframe that will be the source for both outputs to ensure exact match
    # This is our master table for the top hexes
    master_df = top_hexes_df.copy()

    # Create the geo version
    # We'll merge master_df with the original hex_grid to get the geometry in EPSG:4326,
    # then transform to target_crs.
    hotspots_geo = hex_grid.merge(
        master_df[['hex_id', 'rank', 'area_weighted_density']], 
        on='hex_id', 
        how='inner'
    )
    hotspots_geo = hotspots_geo.to_crs(target_crs)
    hotspots_geo = hotspots_geo[['hex_id', 'rank', 'area_weighted_density', 'geometry']]
    hotspots_geo.to_parquet('hotspots.geoparquet')
    
    # Create the ranking version
    # We'll use the same master_df.
    # The prompt specifies: hex_id, rank, area_weighted_density, n_overlap_polygons, n_slivers_filtered
    ranking_df = master_df[['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']]
    
    # Final validation before writing
    # Ensure the hex_ids in both files are the same.
    # Because we used master_df to drive both, and hex_grid merge is an inner join on hex_id,
    # they MUST be identical.
    
    # Convert to sets for comparison to be absolutely sure.
    set_geo = set(hotspots_geo['hex_id'])
    set_rank = set(ranking_df['hex_id'])
    
    if set_geo != set_rank:
        raise ValueError(f"Mismatch! Geo IDs: {set_geo}, Rank IDs: {set_rank}")
    
    ranking_df.to_parquet('hotspot_ranking.parquet')

    print("Files created successfully.")
    print(f"Total top hexes: {len(master_df)}")
    print(f"Slivers filtered: {n_slivers_filtered}")

if __name__ == "__main__":
    solve()
Wrote /work/solve.py (4073 chars).
2:58
Bash python /work/solve.py
Files created successfully.
Total top hexes: 104
Slivers filtered: 3022
3:06
Bash # Final verification
# Final verification
python -c "import pandas as pd; print('hotspot_ranking.parquet columns:', pd.read_parquet('hotspot_ranking.parquet').columns.tolist())"
python -c "import geopandas as gpd; print('hotspots.geoparquet columns:', gpd.read_parquet('hotspots.geoparquet').columns.tolist()); print('hotspots.geoparquet CRS:', gpd.read_parquet('hotspots.geoparquet').crs)"

# Check if hex_id match
python -c "import pandas as pd; h1 = pd.read_parquet('hotspots.geoparquet')['hex_id'].sort_values(); h2 = pd.read_parquet('hotspot_ranking.parquet')['hex_id'].sort_values(); print('Match:', h1.equals(h2))"

# Check rank uniqueness and range
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Unique ranks:', df['rank'].nunique() == len(df)); print('Min rank:', df['rank'].min()); print('Max rank:', df['rank'].max())"

# Check density sorting
python -c "import pandas as pd; df = pd.read_parquet('hotspot_ranking.parquet'); print('Sorted density:', df['area_weighted_density'].is_monotonic_decreasing)"
hotspot_ranking.parquet columns: ['hex_id', 'rank', 'area_weighted_density', 'n_overlap_polygons', 'n_slivers_filtered']
hotspots.geoparquet columns: ['hex_id', 'rank', 'area_weighted_density', 'geometry']
hotspots.geoparquet CRS: {"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "ProjectedCRS", "name": "Minna / UTM zone 32N", "base_crs": {"name": "Minna", "datum": {"type": "GeodeticReferenceFrame", "name": "Minna", "ellipsoid": {"name": "Clarke 1880 (RGS)", "semi_major_axis": 6378249.145, "inverse_flattening": 293.465}}, "coordinate_system": {"subtype": "ellipsoidal", "axis": [{"name": "Geodetic latitude", "abbreviation": "Lat", "direction": "north", "unit": "degree"}, {"name": "Geodetic longitude", "abbreviation": "Lon", "direction": "east", "unit": "degree"}]}, "id": {"authority": "EPSG", "code": 4263}}, "conversion": {"name": "UTM zone 32N", "method": {"name": "Transverse Mercator", "id": {"authority": "EPSG", "code": 9807}}, "parameters": [{"name": "Latitude of natural origin", "value": 0, "unit": "degree", "id": {"authority": "EPSG", "code": 8801}}, {"name": "Longitude of natural origin", "value": 9, "unit": "degree", "id": {"authority": "EPSG", "code": 8802}}, {"name": "Scale factor at natural origin", "value": 0.9996, "unit": "unity", "id": {"authority": "EPSG", "code": 8805}}, {"name": "False easting", "value": 500000, "unit": "metre", "id": {"authority": "EPSG", "code": 8806}}, {"name": "False northing", "value": 0, "unit": "metre", "id": {"authority": "EPSG", "code": 8807}}]}, "coordinate_system": {"subtype": "Cartesian", "axis": [{"name": "Easting", "abbreviation": "E", "direction": "east", "unit": "metre"}, {"name": "Northing", "abbreviation": "N", "direction": "north", "unit": "metre"}]}, "scope": "Engineering survey, topographic mapping.", "area": "Nigeria - offshore deep water - east of 6\u00b0E.", "bbox": {"south_latitude": 2.61, "west_longitude": 6, "north_latitude": 3.68, "east_longitude": 7.82}, "id": {"authority": "EPSG", "code": 26332}}
Match: False
Unique ranks: True
Min rank: 1
Max rank: 104
Sorted density: True
3:15