geo-l3-antarctica-stations-geodesic
Map (reference ← swipe → agent)
0:00
I need to put together the cross-station logistics-overlap maps for the Antarctic Treaty consultative meeting next month. Each Antarctic research station has a notional 200 km operational radius. Please pull stations from Overture south of -60 latitude, along with the Antarctic landmass and water features.
For the first output I need the land-clipped station zones grouped into coalitions wherever they overlap. Each coalition gets an integer `coalition` id, and that column has to take more than one distinct value across the dataset. Every feature needs `station_id` and `station_name` as well. For the second output I need the over-water portion of each station's zone, attributed with the water features it intersects. Each row in that file must carry `station_id`, `station_name`, `water_id`, `water_name`, `water_subtype`, and a `water_source` column whose values are the literal Overture theme names `base.water` or `base.bathymetry`.
Please write both as GeoParquet in an appropriate projected coordinate system for Antarctica, with MultiPolygon geometry: `station_spheres.geoparquet` for the land-clipped coalition polygons, and `station_water_overlap.geoparquet` for the per-station over-water intersections with the water attribution described above.
0:00
System info
{
"adapter": "openrouter",
"model": "deepseek/deepseek-v4-flash",
"base_url": "https://openrouter.ai/api/v1"
}
0:04
Let me break down this task: 1. Get Antarctic research stations from Overture south of -60° latitude 2. Get Antarctic landmass and water features from Overture 3. Create 200 km operational radius buffers around each station 4. Clip station buffers to land (for first output) 5. Group land-clipped buffers into coalitions where they overlap 6. Create over-water portions of station buffers (for second output) 7. Intersect over-water portions with water features, attributing with water details Outputs: - `station_spheres.geoparquet` - land-clipped coalition polygons with coalition id, station_id, station_name - `station_water_overlap.geoparquet` - per-station over-water intersections with water attribution Let me start by exploring what's available.
0:04
0:04
Bash
ls /work/
(no output)
0:04
Bash
python -c "import overturemaps; help(overturemaps)" 2>&1 | head -50
Help on package overturemaps:
NAME
overturemaps
PACKAGE CONTENTS
__main__
changelog
cli
core
models
releases
state
writers
FILE
/usr/local/lib/python3.14/site-packages/overturemaps/__init__.py
0:08
Let me understand the Overture library better and look at available themes.
0:08
Bash
python -c "
python -c "
import overturemaps
print(dir(overturemaps))
print('---')
print(overturemaps.__version__ if hasattr(overturemaps, '__version__') else 'no version')
"
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'core', 'geodataframe', 'get_all_overture_types', 'models', 'record_batch_reader'] --- no version
0:09
Bash
python -c "
python -c "
from overturemaps.core import available_themes, available_types
themes = available_themes()
print('Themes:', themes)
for t in themes:
types = available_types(t)
print(f' {t}: {list(types.keys())[:10]}')
"
Traceback (most recent call last):
File "<string>", line 2, in <module>
from overturemaps.core import available_themes, available_types
ImportError: cannot import name 'available_themes' from 'overturemaps.core' (/usr/local/lib/python3.14/site-packages/overturemaps/core.py)
0:13
Let me look at the overturemaps API more carefully.
0:13
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import inspect
print(inspect.signature(record_batch_reader))
print('---')
print(inspect.getsource(record_batch_reader))
" 2>&1 | head -60
(overture_type, bbox=None, release=None, connect_timeout=None, request_timeout=None, stac=False) -> pyarrow.lib.RecordBatchReader | None
---
def record_batch_reader(
overture_type,
bbox=None,
release=None,
connect_timeout=None,
request_timeout=None,
stac=False,
) -> Optional[pa.RecordBatchReader]:
"""Return a pyarrow RecordBatchReader for the desired bounding box and s3 path, or None on error."""
result = _prepare_query(
overture_type, bbox, release, connect_timeout, request_timeout, stac
)
if result is None:
return None
dataset, filter_expr = result
return _record_batch_reader_from_dataset(dataset, filter_expr=filter_expr)
0:14
Bash
python -c "
python -c "
import overturemaps.core as c
print([x for x in dir(c) if not x.startswith('_')])
"
['ALL_RELEASES', 'BBox', 'GeoDataFrame', 'HAS_GEOPANDAS', 'List', 'Optional', 'STAC_CATALOG_URL', 'Tuple', 'count_rows', 'ds', 'fs', 'geoarrow_schema_adapter', 'geodataframe', 'get_all_overture_types', 'get_available_releases', 'get_latest_release', 'io', 'json', 'pa', 'pc', 'pq', 'query_gers_registry', 'record_batch_reader', 'record_batch_reader_from_gers', 'sys', 'type_theme_map', 'urlopen']
0:18
Let me explore the Overture types available to understand how to get buildings/places/divisions (for stations), water, etc.
0:18
Bash
python -c "
python -c "
from overturemaps.core import get_all_overture_types
types = get_all_overture_types()
for t in sorted(types):
print(t)
"
address bathymetry building building_part connector division division_area division_boundary infrastructure land land_cover land_use place segment water
0:23
Great! So the Overture themes available include: - `place` - for research stations (places) - `land` - for Antarctic landmass - `water` - for water features - `bathymetry` - for bathymetry Let me understand the data schema for each of these types.
0:23
Bash
python -c "
python -c "
import pyarrow as pa
from overturemaps.core import record_batch_reader
# Check place schema
r = record_batch_reader('place')
if r:
print('Place schema:')
print(r.schema)
else:
print('place failed')
"
Place schema:
id: string
geometry: binary
-- field metadata --
ARROW:extension:name: 'geoarrow.wkb'
categories: struct<primary: string, alternate: list<element: string>>
child 0, primary: string
child 1, alternate: list<element: string>
child 0, element: string
confidence: double
websites: list<element: string>
child 0, element: string
emails: list<element: string>
child 0, element: string
socials: list<element: string>
child 0, element: string
phones: list<element: string>
child 0, element: string
brand: struct<wikidata: string, names: struct<primary: string, common: map<string, string ('common')>, rule (... 192 chars omitted)
child 0, wikidata: string
child 1, names: struct<primary: string, common: map<string, string ('common')>, rules: list<element: struct<variant: (... 159 chars omitted)
child 0, primary: string
child 1, common: map<string, string ('common')>
child 0, common: struct<key: string not null, value: string> not null
child 0, key: string not null
child 1, value: string
child 2, rules: list<element: struct<variant: string, language: string, perspectives: struct<mode: string, countries (... 87 chars omitted)
child 0, element: struct<variant: string, language: string, perspectives: struct<mode: string, countries: list<element (... 72 chars omitted)
child 0, variant: string
child 1, language: string
child 2, perspectives: struct<mode: string, countries: list<element: string>>
child 0, mode: string
child 1, countries: list<element: string>
child 0, element: string
child 3, value: string
child 4, between: list<element: double>
child 0, element: double
child 5, side: string
addresses: list<element: struct<freeform: string, locality: string, postcode: string, region: string, country: (... 8 chars omitted)
child 0, element: struct<freeform: string, locality: string, postcode: string, region: string, country: string>
child 0, freeform: string
child 1, locality: string
child 2, postcode: string
child 3, region: string
child 4, country: string
names: struct<primary: string, common: map<string, string ('common')>, rules: list<element: struct<variant: (... 159 chars omitted)
child 0, primary: string
child 1, common: map<string, string ('common')>
child 0, common: struct<key: string not null, value: string> not null
child 0, key: string not null
child 1, value: string
child 2, rules: list<element: struct<variant: string, language: string, perspectives: struct<mode: string, countries (... 87 chars omitted)
child 0, element: struct<variant: string, language: string, perspectives: struct<mode: string, countries: list<element (... 72 chars omitted)
child 0, variant: string
child 1, language: string
child 2, perspectives: struct<mode: string, countries: list<element: string>>
child 0, mode: string
child 1, countries: list<element: string>
child 0, element: string
child 3, value: string
child 4, between: list<element: double>
child 0, element: double
child 5, side: string
sources: list<element: struct<property: string, dataset: string, license: string, record_id: string, update_t (... 65 chars omitted)
child 0, element: struct<property: string, dataset: string, license: string, record_id: string, update_time: string, c (... 50 chars omitted)
child 0, property: string
child 1, dataset: string
child 2, license: string
child 3, record_id: string
child 4, update_time: string
child 5, confidence: double
child 6, between: list<element: double>
child 0, element: double
operating_status: string
basic_category: string
taxonomy: struct<primary: string, hierarchy: list<element: string>, alternates: list<element: string>>
child 0, primary: string
child 1, hierarchy: list<element: string>
child 0, element: string
child 2, alternates: list<element: string>
child 0, element: string
version: int32
bbox: struct<xmin: double, xmax: double, ymin: double, ymax: double>
child 0, xmin: double
child 1, xmax: double
child 2, ymin: double
child 3, ymax: double
-- schema metadata --
geo: '{"version": "1.1.0", "primary_column": "geometry", "columns": {"geo' + 275
1:24
Let me understand the data available: 1. `place` - research stations with categories 2. `land` - Antarctic landmass 3. `water` - water features 4. `bathymetry` - bathymetry Let me look at the land and water schemas too, and understand how to filter by geography. First, let me check how to use bbox filtering and what land/water data look like.
1:24
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
for t in ['land', 'water', 'bathymetry']:
r = record_batch_reader(t)
if r:
print(f'{t} schema:')
print(r.schema)
print('---')
"
<exit_code>-1</exit_code> <error>Command timed out after 120000ms</error>
3:28
The command timed out, likely because it's fetching data globally. Let me try with a bbox filter and also restart the approach - I need to be smarter about this. Let me work with a bbox for Antarctica. Actually, the global queries are too large. Let me use a bounding box for Antarctica and filter by geometry later.
3:28
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader, get_all_overture_types
# Just get the schema without downloading much data
for t in ['place', 'water', 'land', 'bathymetry']:
try:
r = record_batch_reader(t, bbox=(-180, -90, 180, -60))
if r:
print(f'{t} schema columns:')
for field in r.schema:
print(f' {field.name}: {field.type}')
print()
except Exception as e:
print(f'{t}: {e}')
" 2>&1
place schema columns:
id: string
geometry: binary
categories: struct<primary: string, alternate: list<element: string>>
confidence: double
websites: list<element: string>
emails: list<element: string>
socials: list<element: string>
phones: list<element: string>
brand: struct<wikidata: string, names: struct<primary: string, common: map<string, string ('common')>, rules: list<element: struct<variant: string, language: string, perspectives: struct<mode: string, countries: list<element: string>>, value: string, between: list<element: double>, side: string>>>>
addresses: list<element: struct<freeform: string, locality: string, postcode: string, region: string, country: string>>
names: struct<primary: string, common: map<string, string ('common')>, rules: list<element: struct<variant: string, language: string, perspectives: struct<mode: string, countries: list<element: string>>, value: string, between: list<element: double>, side: string>>>
sources: list<element: struct<property: string, dataset: string, license: string, record_id: string, update_time: string, confidence: double, between: list<element: double>>>
operating_status: string
basic_category: string
taxonomy: struct<primary: string, hierarchy: list<element: string>, alternates: list<element: string>>
version: int32
bbox: struct<xmin: double, xmax: double, ymin: double, ymax: double>
water schema columns:
id: string
names: struct<primary: string, common: map<string, string ('common')>, rules: list<element: struct<variant: string, language: string, perspectives: struct<mode: string, countries: list<element: string>>, value: string, between: list<element: double>, side: string>>>
subtype: string
class: string
sources: list<element: struct<property: string, dataset: string, license: string, record_id: string, update_time: string, confidence: double, between: list<element: double>>>
source_tags: map<string, string ('source_tags')>
level: int32
wikidata: string
is_intermittent: bool
is_salt: bool
geometry: binary
version: int32
bbox: struct<xmin: double, xmax: double, ymin: double, ymax: double>
land schema columns:
id: string
names: struct<primary: string, common: map<string, string ('common')>, rules: list<element: struct<variant: string, language: string, perspectives: struct<mode: string, countries: list<element: string>>, value: string, between: list<element: double>, side: string>>>
subtype: string
class: string
sources: list<element: struct<property: string, dataset: string, license: string, record_id: string, update_time: string, confidence: double, between: list<element: double>>>
source_tags: map<string, string ('source_tags')>
level: int32
wikidata: string
surface: string
elevation: int32
geometry: binary
version: int32
bbox: struct<xmin: double, xmax: double, ymin: double, ymax: double>
bathymetry schema columns:
id: string
depth: int32
cartography: struct<prominence: int32, min_zoom: int32, max_zoom: int32, sort_key: int32>
geometry: binary
sources: list<element: struct<property: string, dataset: string, license: string, record_id: string, update_time: string, confidence: double, between: list<element: double>>>
version: int32
bbox: struct<xmin: double, xmax: double, ymin: double, ymax: double>
4:42
Let me design the approach: 1. **Get Antarctic research stations** from `place` theme with categories related to research stations, south of -60 latitude. 2. **Get land** from `land` theme for Antarctica (south of -60). 3. **Get water features** from `water` theme (south of -60). 4. **Get bathymetry** from `bathymetry` theme (south of -60). For each station: - Create a 200km buffer - Clip to land → coalition polygons - Clip to water → intersect with water features Let me start by exploring what categories are available in the place data for stations.
4:42
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import pyarrow as pa
import pyarrow.compute as pc
# Get a sample of places south of -60 to see what categories exist
r = record_batch_reader('place', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_next_batch()
print(f'Got {len(tbl)} rows')
# Check categories
cats = tbl.column('categories')
print(type(cats))
print(cats[0])
else:
print('Failed')
" 2>&1
Got 21 rows
<class 'pyarrow.lib.StructArray'>
[('primary', 'retail'), ('alternate', None)]
4:55
There are only 21 places south of -60 in Overture - that's not many. Let me look at the categories more carefully to find research stations.
4:55
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import pyarrow as pa
import pyarrow.compute as pc
# Get all places south of -60 to see what's there
r = record_batch_reader('place', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_all()
print(f'Total: {len(tbl)} rows')
for i in range(len(tbl)):
row = tbl.slice(i, 1)
names = row.column('names')[0]
cats = row.column('categories')[0]
idv = row.column('id')[0].as_py()
primary = cats['primary'].as_py()
name = names['primary'].as_py() if names else None
print(f'{idv}: name={name}, category={primary}')
else:
print('Failed')
" 2>&1
Total: 246 rows ff93e6a3-b7fc-4691-980a-c36820a301c4: name=Poeanuanua, category=retail e4cd796b-b4c6-47e1-927b-79edfc50c48c: name=Muebles Marispal Algeciras, category=furniture_store 52dd18ca-aaae-4f06-aa53-06349b302c66: name=Lamoon Cafe & Restaurant - สระบุรี, category=cafe b01d6401-437f-4be8-bb25-21055d6881fa: name=Cap College Mariveles Bataan, category=college_university d61f38d3-a73b-44d6-ae69-1120a1518aaf: name=מעדני מניה Maadaney Mania, category=delicatessen 855105af-cb9a-4c55-a72e-c5ae356f1c5e: name=Te Fare Informatique, category=hardware_store 237cf98b-d9b0-4756-82ee-528c55f41e29: name=Samira's Hair Fashion +599 98693311, category=beauty_salon 43c099d7-9d1b-41a3-8e43-320e2eacf6fa: name=CAMBO Cleaner, category=None d6149cd5-5a22-43e1-ae86-e7577501d0db: name=Iriga City Public Library, category=public_and_government_association 06cbc176-ade9-45fa-bf4d-1e1047961cd3: name=Dinastia Nortena, category=None 37b38556-e96f-4489-8369-198afd14715f: name=Ser Esencia Restaurant, category=restaurant a8fae705-fa37-4416-9500-53834b942c97: name=مدينة رشيد Rosetta city, category=None e926755f-2666-4c23-b411-a44ec025a072: name=Blessed Souls Photography & Film, category=professional_services 2a57ff3e-de19-4d8c-9a80-894baa013331: name=黎齊妙中醫診所, category=hospital cae3dffc-923f-486f-a9dd-b3978352cd3a: name=dieukhaclienvu.com - phù điêu,điêu khắc đá nhân tạo composite,cảnh quan đẹp, category=arts_and_crafts 6c026c49-4a4f-44a9-b18b-2e858b4176bd: name=R-AGE Nation Apparel, category=womens_clothing_store d586b57b-b36c-41c8-8c6b-0121de8150d0: name=Basketball Forever, category=mass_media f4ed31ee-3bc1-49e9-8a28-3005e0e22ac1: name=Marc Silber, category=professional_services f105891e-42e1-4c5f-90c2-c2932966b6e9: name=Tama Manège Import, category=park 4acb8ee7-5b68-48c7-b77c-a1849ac3280b: name=Irantha Fonseka, category=None 34c0cba6-9f9d-4eeb-bb37-63e4fd235441: name=Ozhousestudio, category=topic_concert_venue 830e25c9-3ec0-488e-921c-11670b9d5c98: name=Jamela Payne, category=panamanian_restaurant b9f600a7-98dd-4d9b-b1a2-70d1d79ed9b2: name=In Aeternum Historia, category=print_media a09c28e0-2005-42d5-b55e-4b2dda79609a: name=Destiny Monique, category=arts_and_entertainment aec03ab5-bce4-484f-a042-9f6b49c3ea93: name=Frente al Mar, category=eat_and_drink 7ae461e2-5c10-4eab-b2aa-b253d5c9cba6: name=SaiJai ใส่ใจ เครื่องปรุงและอาหารสุขภาพ, category=restaurant eb5e3c92-2c72-48a2-832d-9bf7e6ae3192: name=Tay Noel’s Kalan-an, category=fast_food_restaurant d4d2c7e1-1e50-4362-90ae-bf74cd3646e8: name=גלית קאשי עיצוב תכשיטים, category=jewelry_store 028cd213-5f11-4b3e-bd5f-7ed9e22e3e88: name=GypsyMaal, category=fashion_accessories_store 83847f48-3480-47a9-878f-132b275c2880: name=Prasad Art Gallery, category=art_gallery de2b1fec-574c-4461-8bd6-6a2c2b2e3c63: name=Tahlia Marie, category=None 0f605256-4adc-4d04-bdab-44b6e8ca17e1: name=Barbaro Negocios Inmobiliarios, category=real_estate ff41a340-bd7c-49c8-9eb8-be5903a3653a: name=VALKUR Perú, category=lawyer 09e9bea6-d40f-41c2-a88f-561cba558ad3: name=Experience Rarotonga, category=tours 2a30eed0-ca25-4aa6-9147-cece509f4f09: name=Caprichos Accesorios, category=fashion_accessories_store d8a1c3a5-fadc-448d-a543-22067b69d36e: name=Emmy J, category=None f0847dff-07cd-422a-81c9-f20a40b26106: name=Asra Derm Official, category=None 1c2353f9-bc96-4304-8b30-35e0b4ffc40e: name=Mobilio Suksawat โมบิลิโอ้ สาขาสุขสวัสดิ์, category=shopping c2eb4ea6-634e-4cf6-9f53-fe826b4dcb61: name=ال سلوع لتجاره السيراميك والادوات الصحيه, category=real_estate 2a100ade-be10-41c0-b6c2-a49e921a24e7: name=Port Lockroy, Antarctic Peninsula, category=landmark_and_historical_building f73848f3-abaa-432b-b3ed-8092a6b39b9e: name=Palmer Station, Antarctica, category=home_developer f4491389-9904-4c46-ad66-18c0e736e547: name=BellaVista Voronet, category=holiday_rental_home ea957818-ac33-4951-9f52-8845ee4419b3: name=Sachet Imprimé, category=None eb858253-acd6-4231-9ce9-e0e4c799d7a0: name=Brown Station, category=landmark_and_historical_building ba9d8ef6-32f3-4098-a010-b5b485e4e75f: name=González Videla Antarctic Base, category=airport 90087bb3-b8ba-4507-886b-104fe36bc40c: name=Cuverville Island, category=landmark_and_historical_building 49b9a6e2-2e53-4040-8cea-39b554a52b66: name=Madison Beer, category=beer_bar ca45ce1c-ca5e-4cd8-8f98-5975f5706828: name=Dj daya, category=music_production a593665a-c1c6-4acd-b0c0-d25735d6dd4c: name=Matrioska Laços, category=childrens_clothing_store 9d364bf8-eaaf-4f79-ad45-195f74f49a93: name=Antarctica, Antarctic Circle, category=landmark_and_historical_building 3bf8e968-6050-4ee6-8a60-f046db54cc02: name=Esperanto Island, Antarctica, category=landmark_and_historical_building ddfff404-5576-4082-8528-ef0d79f2dbb0: name=Yankee Harbor, category=landmark_and_historical_building 6240b821-30cb-4fe4-a08a-6fddb4fe2978: name=Bellingshausen Russian Antarctic Station, category=educational_research_institute e4b318d7-4b12-4b00-806c-e21f1ca962ac: name=Bahia Fildes (Antartica), category=structure_and_geography eebb9028-32bd-4b7c-a8c2-7a620a35a072: name=Crystal Power, category=jewelry_store b5dbce59-268a-4e42-9bb2-211da08f53e5: name=Bestiario Moderno, category=print_media 18414d58-4e4c-480f-bfab-ee3e224c5b5e: name=Base Marambio, Antartida Argentina, category=central_government_office 015df87e-1265-4d80-844b-97a4c1af44a5: name=Marambio Base, category=airport 4775fc70-d68b-48b4-af40-377af7e9a457: name=Chapel of the Blessed Virgin of Lujan, Antarctica, category=church_cathedral 11037d14-337b-4a53-a23b-85566484f016: name=Base Antártica Marambio, category=public_and_government_association b1662153-d852-4a90-b8a7-5d5e113439bb: name=Base Esperanza, Antartida Argentina, category=airport 8536af5a-82ba-46ed-bd6c-069082cbfc5d: name=Esperanza Base, Antarctica, category=landmark_and_historical_building a13cf580-a927-4f97-a2d6-7f12f7ac954b: name=Backwoods Bouquet, category=None 93371fbe-1368-4cba-96be-b7c04397a8d4: name=Shop Thời Trang Nam - Nữ Thanh Bình, category=fashion 6097b50e-58bc-4b7d-aec4-0161d86e0c26: name=Lucas Fontoura, category=arts_and_entertainment ff744642-189b-47c5-8b59-02176f30b03f: name=Descobrincar - Musicalização infantil, category=school 7cbecc8f-af4f-459e-a503-da31f4e15db1: name=Hurricane On Saturn, category=None 0c99398b-501d-41dd-8dd0-5bc68dd2beec: name=Paradise Eventi, category=event_planning 3cb2a3a2-6b4c-4c0c-9b3c-fe52b1f5ef49: name=Psikolog ve Aile Danışmanı Esra Erciyas, category=None 578ca710-182a-4fa4-94d7-acafa067c6a0: name=Proexc Engenharia, category=engineering_services ec210e56-697b-4e50-8e88-f73a9ab3becf: name=Villa's Caldos, category=fast_food_restaurant be7f69c3-12f2-49d0-8b88-be2abefdc457: name=Gabbi Garcia, category=None a090a904-2767-409a-adf6-92bd9ed0b843: name=Bendita CR, category=None 850678ce-ad91-4646-acc9-645885dbae45: name=Behr Productions, category=music_production b56ce88f-0fb8-42d2-8dd4-9b19447bf9b6: name=Max land MX Raceway Park, category=race_track a7ef9c17-90f8-436b-ac3b-2a6c1f4ec6d5: name=DRK Kreisverband Gelnhausen-Schlüchtern e.V., category=community_services_non_profits 8314e13e-dfe1-4d29-aa98-7f4dfff59e2b: name=Muhammad Hasri Videography, category=professional_services 846206ab-ab1d-4e02-ad32-54acf08bcf73: name=JJ Niceley, category=None 626a584b-87d5-4dc2-a893-a5baa337590f: name=Jankari Kendra जानकारी केन्द्र, category=mass_media c5c5a237-039d-48ee-858d-ed070520875f: name=Reggae Village House of Jerk, category=caterer e266b928-982b-4279-8d49-342930116b3b: name=Công Ty TNHH Nam Hưng Thái Nguyên, category=b2b_textiles f8357f19-e91b-409e-8328-0a3ce09f9250: name=美妍美容教育中心-Beauty in, category=beauty_and_spa 67dc407b-ab3c-4a98-9c4b-021635ec8000: name=Foul Point, category=landmark_and_historical_building 2cd19d2b-bafa-4bef-9841-e89d7e9ffe92: name=Malou Madi, category=None 1f4cbf9e-f030-4e05-b3d0-7645989883b9: name=Institut für Emotionspädagogik, category=educational_services 4bf6997e-7821-40d4-ac35-9c7aa62380cd: name=Animations enfants Tahiti, Le PitiMotu, category=arts_and_entertainment 827514b2-1b65-4edb-abe5-3e54390b67c7: name=Dregg Ackies, category=record_label 0b2d13d5-befe-4a1f-af71-deb7ec35537d: name=Sunsoli, category=None c6dfca54-43db-4011-96e6-5edf7c897bf7: name=Flocreazionipereventi, category=wedding_planning e3fdc1df-ec12-481c-acab-020dccb21d53: name=Martin Kráľ - Skladateľ, category=None cd40e85b-48bf-4a95-b777-2310ce51de03: name=Babul Yaman Store, category=shopping a049cb22-9538-4fe0-b0db-b8211dcde371: name=SMDC Property Investment, category=real_estate_agent 8d5d6b50-56ec-411b-b6c3-9f01c5f85fec: name=WM Case - Profesjonalne skrzynie transportowe, category=None c455a0c7-92a1-4dfa-b4fb-e529e19bf03b: name=Dwill Burguer, category=burger_restaurant 5f194203-4c23-4c00-911b-13f14c6035a1: name=Sund med Mia, category=professional_services 09a01e2c-128a-435c-8330-05134d7a6cb1: name=Deli Repostería, category=desserts 644fd3f9-14f5-475e-bb40-06a9a631b76d: name=Buli Makhubo, category=None 37186c0b-2c16-495d-aac4-f8884e45e352: name=Стиль и мода. Израиль, category=image_consultant e98978c0-2318-4cbe-a1f5-b5ee7c08a287: name=Bedlam Studios, category=graphic_designer c4d32583-0c39-402f-b67b-4b6d3ff66bbc: name=رضا الحديثي - صفحتي الرسمية, category=fitness_trainer e8ada447-c200-445d-b6fb-9b2e272cb0d3: name=Friis Boliger, category=real_estate fa437eeb-d4ac-41ff-884b-5ff86bec8c84: name=রঙ-Israt's Art, category=arts_and_crafts 26e9c69b-1c79-473e-bd85-7291e6c9a8d6: name=DirtySnatcha, category=None 03d664ce-c46e-40c4-ac7a-9748b7fa6f57: name=Calbero, category=None 7977131d-ad69-4f47-a2d0-bb29f8c98906: name=Jobswagon, category=None 6d6ac2ae-2e8a-49f5-abb2-7f631521eb63: name=هاوار, category=education e3417e97-f283-4ecc-a32b-ae164e69903f: name=Antarctica/Troll, category=landmark_and_historical_building fe4a1bd1-1875-422d-85e0-311802f9bcb2: name=Ventamark, category=electronics 1b314288-8b0b-473f-b449-bee33f727f96: name=De Todo, category=electronics afa11645-f1f6-4dbf-9c14-75cf67300532: name=Inglés Personal, category=language_school f813783f-faa6-427f-bb27-bda6ff276a7d: name=João Gomes, category=None 143bfe4e-e494-4e7b-a912-b969a23279d9: name=RA CARS PH, category=car_dealer f0b0d468-b504-4461-bdec-61bcc74bb60b: name=אריאל שרם - צילום, category=professional_services 90b1c6f6-5e99-466e-a342-b6a9a6c0146e: name=Eden's Essential Elements, category=flowers_and_gifts_shop 324d76ee-74f4-42b6-ba46-21444ce2783e: name=Laviva Cosmetics, category=beauty_and_spa e4574119-d881-4681-9afc-219482f6c6c9: name=Elblesk e-mobility, category=automotive f57896bc-008a-48d0-a073-b47eecadae81: name=ليو - Leo, category=social_media_company 4004650a-a32e-4431-9838-3a4265f24b99: name=Otago Potters Group, category=None 30804109-2513-487f-bcd2-1f747515516a: name=Johanna Oedin, category=None da025271-a268-4b31-8993-b3c358bf44b0: name=Alchemist Craftworks, category=metal_fabricator 2fa973bc-63f4-413a-891a-4e224f5b046d: name=Panaderia Doña Tere, category=bakery faad9628-792c-4834-979d-e541a29b9da8: name=廸康醫療中心 Madison Medical Centre, category=acupuncture 6573068f-744b-4a97-ab54-e671178c2365: name=A Tale of Four Mages, category=print_media c132ba4b-db4c-41fd-89b5-347450ef4a65: name=JP Ranch Grass Valley, category=farm ea2f0e50-4251-43f3-89ab-ad1f141f2069: name=Wolf’s Fang Runway, category=None 0df43561-08b3-4e0d-8668-e6d59ae4e11c: name=Fishing 411 TV, category=active_life 94711a0f-334f-4d8a-8f29-81ddbacf2c40: name=Pro Massage & Pro PT, category=None 34ffb80a-2ec5-411c-981b-14d04d3c0c5e: name=St. Isidore Catholic Learning Centre, category=None 6a62900c-ce96-41b5-98de-949d46e5e1fe: name=Cajurine., category=tattoo_and_piercing 8e4c5cd6-402c-44fe-bf75-e0fb4b70391a: name=Higi + Higienização e Impermeabilização de Estofados, category=home_cleaning 33d2cad5-5329-4a8e-8258-48c34338043d: name=Organica Mart, category=food_delivery_service b521d3e2-aa7b-437b-a6a0-bd00d079012c: name=ซัมไทม์ วิว รีสอร์ท, category=hostel 5a95abd1-f5ad-4fa2-a410-092e92160347: name=چارەسەر لە سروشتەوە, category=beauty_and_spa 7a2ef32d-41b7-4fd1-b05a-136b89e6afae: name=Pro Punjab Tv, category=media_news_company 2f0009a4-41f0-4b6d-8b79-9f8329bca235: name=elevatedxconscience, category=None e69c8fa0-b370-431b-9877-9f138003c9b3: name=B.olivia - ps, category=beauty_and_spa 239f485e-336d-4bd7-abb1-a6084783b953: name=Twory i Stwory, category=None b3327bca-f823-4092-8f57-ff4909fc43d6: name=Geraint Jones 4x4, category=automotive_dealer dc072c6e-6745-46d5-a91d-111f47962ec4: name=2 Nice, category=shoe_store 120d0f93-bd72-4fc6-8908-5341a23c816d: name=Stress Relief Massage, category=None 61401ba7-85fa-4e7f-8469-95264ffbbf37: name=Amrinder Bobby, category=None c5755c5c-49bd-4f95-a278-c0036ad3d378: name=Make Noise Pro Audio LTD, category=audio_visual_equipment_store 2166b3fc-617c-4fa8-8f52-825470debd21: name=Morjane Ténéré, category=None cdb4c8c8-9073-435b-8ef3-b91afd117006: name=Southern Ocean, category=landmark_and_historical_building 45e21b66-c772-42d6-81d6-87042c06d118: name=ليلى kids, category=childrens_clothing_store 9edd01f2-2e51-4c81-b1c2-b05ffcd1b00b: name=鉢伏山荘冬期営業, category=lodge db034fd2-6a0b-4eeb-b8df-bb8c6729a4c9: name=البروج للمواد الكهربائية, category=shopping_center 50d11940-d8ac-4b59-9de4-0a0fa17ae0fe: name=Beauty & Care, category=beauty_and_spa 60c01170-1149-4946-95f3-9f5ac9000e94: name=Béjaïa béni ksila vacances, category=None 6f2ca4c1-e58e-4479-b25f-1a9909f66248: name=In Love Furniture - ศูนย์รวมเฟอร์นิเจอร์ชุดห้องนอน และ เฟอร์นิเจอร์สำนักงาน, category=furniture_store 8665150b-23b3-4db4-a036-6e092eb83eef: name=Woodstock Dentistry, category=dentist b2c33d2b-e914-4ff5-aefc-d21b94134b66: name=Paubril’s Beauty, category=beauty_salon 81279d7e-ebc0-451f-acab-d16abb26dfb8: name=This Esme, category=None 1221efca-01ab-4a63-b7cf-b7e57aa4d7de: name=Alex Sá, category=None a54c1fc9-e821-41fc-9676-2217c0cb08b9: name=MOFT, category=fashion_accessories_store aa5ed046-938d-4250-ab80-763dec0a7973: name=I-narin Beauty : เครื่องนวดหน้า สไตล์เกาหลี, category=beauty_and_spa ed8b1616-8305-419a-9c31-7103f33e561b: name=Abracadabra Technologie, category=telecommunications_company d8f0007b-7bd4-49c1-a313-f6edceb1ae0c: name=Cafés Ellouze, category=coffee_shop f2e30c5a-d360-4768-a665-bb4b5e315b92: name=หมามะเร็ง Dogs Cancer, category=community_services_non_profits e99e67d0-44df-42cc-a037-ac56083ab35c: name=Catiline Kindergarten - Whampoa カティライン幼稚園・インターナショナルプレスクール, category=education e8239c37-81ea-4157-bdbe-4886a5d8acc5: name=厚興瑜記 WegoMall, category=restaurant e7042319-227a-4aa2-a1de-418bafdf50a8: name=Americano Cafe' Happy Moment with Coffee and Drink, category=cafe d8a7c84f-87d0-4dbc-8ef7-c005f4815f74: name=Japfa Experience, category=restaurant 5142358e-838a-466f-9ef1-341e2583a0e7: name=Celest Jewelry, category=None 8e8bb400-aef6-4570-a362-c6dc671c8def: name=My湯 - 茘枝角, category=desserts 4e6c21fc-d140-42bd-b03f-fff591b8b1a4: name=Bobby Layal, category=computer_museum 749ef775-0275-444e-afcf-3eeea68632cd: name=Janeth E. Sarona, category=professional_services 93b19196-0fd7-4030-8e31-7bcc6828b12f: name=PD.Kannel, category=None 5bcb716a-3179-4db9-83ff-f23ee47f5708: name=แพวันวาน จังหวัดกาญจนบุรี, category=hotel 8e90e81e-f21e-42f8-a49d-91e007402806: name=Dalbe Réunion, category=None d1f40180-a2a5-46ff-aea5-e421ad771c4b: name=สมุทรสงครามรีวิว, category=None c8d8dd6a-66d4-4f69-ab1b-0d07a2db2c1f: name=مركز آفنيو الطبي, category=hospital c375f9a7-de0b-4c35-a6b2-e0749c6c1fbc: name=ครูเปิ้ล สอนคอมฯ : ปวช. สกร.เมืองนครราชสีมา, category=shopping 1d715c37-7e51-4377-b4c1-f99b08682650: name=Cat & Calmell, category=None e4d040bc-4aeb-47eb-b1c3-2e192284399e: name=Mette MÆRsk, category=professional_services 04a0ba90-1b7f-4a57-9ec8-91fde8e4ba63: name=อึ้งกุ่ยเฮง มอเตอร์ไซค์ ฮอนด้า ยามาฮ่า รถมือสอง ร้อยเอ็ด, category=motorcycle_dealer f6fbba53-4e47-43ba-aa3a-11669c106c27: name=World Auto Glass Inc., category=None 788c50a6-a275-4f65-a4e8-51ff804e2c76: name=Noskill Sensi, category=video_game_store 6ef9d71e-0a81-4353-88c5-0fe3a6298c8a: name=Ingrid Christensen Coast, category=landmark_and_historical_building bfbe1e51-dafc-4aed-b84c-b93cafa9fec7: name=Tutti Bambino, category=toy_store 863c4e6c-5fe1-45d6-a5fd-8a6f0b006e51: name=Ellis Fjord, category=landmark_and_historical_building ecfca81b-f2f7-42c3-a81c-5a7a6c840795: name=Lake Jabs, category=landmark_and_historical_building a088edca-c206-4689-a20e-c6da1adcf298: name=Langnes Fjord, category=landmark_and_historical_building 1f68ade1-0f5a-4f35-908d-e06d98fa5c8a: name=Krok Lake, category=lake 81cfb3fa-b152-4763-ab34-047f7e238b3f: name=Lied Bluff, category=landmark_and_historical_building 064348b3-0c46-412e-89ef-99b5d89a9629: name=Heidemann Bay, category=landmark_and_historical_building 830bdae6-0e87-49f5-8d9f-d09eb55f2ae1: name=Filla Island, category=landmark_and_historical_building aa330079-2239-4210-abce-3f0189a302c9: name=Lake Zvezda, category=landmark_and_historical_building 1d7407a1-6de8-4ada-b682-77b0581f9b5a: name=Dr. Cláudio Gurgel Magalhães - Clínica Belle Esthetique, category=doctor fa828383-ccae-4bc6-8280-dedc9bec84de: name=Ynnez Group, category=non_governmental_association 375a785a-cbe8-483f-9892-411d65e6a048: name=芸臻命理諮詢, category=psychic e4a5838b-2744-4bbb-b631-7d6329f03e87: name=Miya Élégance, category=womens_clothing_store 9611bace-e1ea-41f6-948d-d148653c9189: name=แม่อี่ ผักดองตำหรับยูนนาน, category=None 657610cc-fcce-4cf0-b464-6156bb51b2ab: name=NPS Institutions - Bidar, category=school 4f7ecec0-deee-478f-8695-c5834263ca8d: name=Sozialkontakt, category=None cdb16257-a06c-42d3-a607-2595832bcb1d: name=albertopiernas, category=None 95f38586-af0c-4833-90d6-8691b4cac1af: name=Sekolah Islam Terpadu Green Bhakti Insani, category=middle_school 76a651dd-ec31-40b9-ab8a-9db09f41ad5d: name=Motel Mozaique Concerts, category=hotel 1f8440b3-8f1f-4b26-9f9b-a66f1124bedf: name=CT Trampoline Fitness 沙田 石門 彈床班 Jump Fitness 健身 親子彈床班, category=gym 48a4811a-3075-4054-b63f-3178e564f9e7: name=Casa de Adoración Yahweh, category=religious_organization 9ada4a7f-d61c-4ea0-80a0-fb8e77427b36: name=Sydney Amigurumi Corner 手勾公仔, category=arts_and_crafts bd2419af-7105-4f9d-b663-aa9a409fb43f: name=Shanaya Hotel Borobudur, category=hotel 316d32e2-dd75-40a0-82ca-07edb2866724: name=The Cumberland River Project, category=river 63b91770-28a5-4a5c-bea8-0e5842150734: name=Lake Vostok, category=landmark_and_historical_building af82bf4b-f128-4169-a1c5-17003b6079b3: name=ร้านแน็ตโมบายโฟน, category=None bfd01a42-92a7-43f9-a7d3-0cc7fb3157b4: name=Vostok İstasyonu, category=landmark_and_historical_building d7827f14-512a-4e6e-b797-9d66a117f488: name=Tiệm ảnh Phúc- Lạng Sơn, category=professional_services 360518d5-1db3-4636-a7a1-c365891ae149: name=مدرسة أحمد نمر حمدان الأساسية للبنين, category=school 20ed15c3-ed4a-459d-9ba0-07aad85c2749: name=ইলমুল কুরআন মাদ্রাসা লিল্লাহ বোর্ডিং ও ইয়াতিম খানা, category=None d2de84a6-d20f-463e-8a77-7affecc053fc: name=سنتر بغداد, category=shopping f64a2822-9dfa-4267-b634-1912aeeca8b4: name=住商不動產樹林后站加盟店, category=professional_services bc8d2cd3-b5ce-46c9-81f5-6c52d700166b: name=塩彩 ~shiosai~, category=shopping 1c18608c-90c2-4657-b19e-7326bb9e41b6: name=Kurd Sport HD, category=sports_club_and_league 445f1366-e41d-4ceb-ad94-c556ca440987: name=Sofiya Designs Gh, category=None 0fa972cb-d0a0-4322-8dbe-bad88268f96b: name=水草館, category=museum 639c6258-52e6-4b6b-8cef-c840a33ecefc: name=Compartilhagem, category=arts_and_crafts b62b8f0a-8a79-49c4-9ae2-462cdb5a345c: name=Kimstore, category=retail 7857e963-4baa-4107-83f5-49c554d73305: name=Masjid Terapung Tanjung Bungah, Pulau Pinang, category=mosque fb8eb545-4390-45bf-b407-340592033b54: name=Angel Rising, category=None ecf6de82-41c3-4de0-b65a-094affdfd2d1: name=Lailo Farm Sanctuary, category=community_services_non_profits d345d139-6ba1-4085-a0c8-3de8043ca6d4: name=Dr Henri Bauer, category=None 36a428fd-122e-4c13-8060-8d8d36162018: name=Academia Nacional de Sommeliers y Gastrónomos, category=school 65458250-4795-48f1-b740-41fe80b96871: name=ทำประกันกับอาอิซะห์, category=beauty_and_spa 04d8258a-e765-4a4d-96c0-20cd3b11a9c3: name=Base antarctique Dumont-d'Urville, category=landmark_and_historical_building fc899431-4ab7-4890-9900-78c44dc030ce: name=شركة الأركان لقطع غيار وزيوت السيارات\nAlarkan Auto Parts & Oils, category=shopping ba6072a7-e330-4288-9e7f-b345f2e18d7b: name=Seaoil Dangcagan, category=gas_station e2e091af-6137-403e-bbd4-6b67f7c55102: name=The Seasoning Outlet, category=shopping 4c24258b-5017-4b9b-b97c-fb85810468cf: name=MAX Reprise, category=automotive_repair 26f0564a-e108-46da-b7aa-a4f3aca0daa2: name=Antarctic Plateau, category=landmark_and_historical_building 83fcb72b-6a48-45ed-b8ba-86133e5c0a81: name=Warning Five จำหน่ายสายนาฬิกาหนังแท้ สายนาฬิกา smartwatch, category=None e53f80a9-1a41-4215-84b6-6b71e2e2cbbd: name=海港青年商會 JCI Harbour, category=community_services_non_profits 696feff0-bd87-4a7b-b778-479dced0681a: name=মুক্তি হারবাল চিকিৎসালয়-Mukti Herbal Chikitsalay, category=family_practice ce4a2fc8-49de-48b1-babe-ad78bf4328ac: name=Herrlich Beauty By Cloriss, category=beauty_salon fcdd73f9-5cb8-4812-be88-099727bf3936: name=Mario-Zucchelli-Station, category=None 693626b4-7ef6-41ee-bc0a-ae604b3351d2: name=Psicóloga Serly C. de Souza, category=psychotherapist bb48b222-57c4-4c85-8743-752df4bba2ca: name=Polární stanice McMurdo, category=landmark_and_historical_building d5882de0-07ff-46b9-a3c0-bbfb0cc9552c: name=Base McMurdo, category=landmark_and_historical_building d74e5a73-042c-4694-9e16-fa9622f203b3: name=Base antarctique McMurdo, category=landmark_and_historical_building fd4c334a-7431-4d8c-888b-3f8c7adda8d1: name=Gallagher Pub, category=bar b3790f8f-7451-4a53-abff-62ab3af51607: name=Southern Exposure, category=bar 9e4a3d08-61ff-4b24-b19f-ff6701d7f012: name=ZiroZiro, category=religious_organization 82b40435-6b61-4d8e-9caa-7ff1d248b8a1: name=McMurdo General Hospital, category=hospital 2390d849-b20b-4b63-9be3-0209ee70518b: name=Coffee House, category=coffee_shop 64a5e802-0687-4df3-8389-5a4f84e649a0: name=Chapel of the Snows, category=church_cathedral e0e03e63-936d-427e-92bc-815a9a44b6a5: name=Pegasus Field, category=airport 512534a4-cc70-416d-89f0-9144564048d3: name=悦聖翡翠, category=fashion
5:28
The Overture places feature a lot of noisy data. Let me think about how to find actual Antarctic research stations. The approach should be: 1. Look at places with categories like "educational_research_institute", "landmark_and_historical_building", "airport", etc. that have "station", "base", "antarctic" in their names south of -60. 2. Better approach: Use the Overture `place` data and filter for research stations/antarctic bases. Let me also look at the geometry to see where the actual stations are located. Actually, a much better approach would be to use known Antarctic research stations lists. But the instruction says "pull stations from Overture" - so let me use Overture places. Let me write the main script now. The approach: 1. Download all Overture places south of -60, filter for research stations/antarctic bases 2. Download land polygon data for Antarctica 3. Download water and bathymetry data 4. Create 200km buffers around stations 5. Clip buffers to land -> coalitions 6. Clip buffers to water -> water overlaps Let me first understand what data I get from the place query. I noticed most of those results have coordinates that are NOT in Antarctica - they're all over the world. The bbox parameter for record_batch_reader seems to not be filtering properly? Let me check. Actually wait - bbox in overturemaps uses (xmin, ymin, xmax, ymax). Let me check if the geometry column has actual coordinates.
5:28
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import pyarrow as pa
import pyarrow.compute as pc
# Get geometries for a few rows to check coordinates
r = record_batch_reader('place', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_all()
print(f'Total: {len(tbl)}')
# Look at bbox column for first 10
bboxes = tbl.column('bbox')
for i in range(min(10, len(tbl))):
bb = bboxes[i]
print(f'{i}: xmin={bb[\"xmin\"]}, ymin={bb[\"ymin\"]}, xmax={bb[\"xmax\"]}, ymax={bb[\"ymax\"]}')
" 2>&1
Total: 246 0: xmin=-172.8719482421875, ymin=-64.6113510131836, xmax=-172.87191772460938, ymax=-64.61134338378906 1: xmin=-156.796875, ymin=-78.34941101074219, xmax=-156.796875, ymax=-78.34940338134766 2: xmin=-156.20516967773438, ymin=-77.52698516845703, xmax=-156.2051544189453, ymax=-77.5269775390625 3: xmin=-143.4375, ymin=-82.49482727050781, xmax=-143.4375, ymax=-82.49481201171875 4: xmin=-144.84375, ymin=-80.76062774658203, xmax=-144.84375, ymax=-80.76061248779297 5: xmin=-146.87623596191406, ymin=-65.75599670410156, xmax=-146.876220703125, ymax=-65.75598907470703 6: xmin=-136.40625, ymin=-74.77584838867188, xmax=-136.40625, ymax=-74.77584075927734 7: xmin=-137.6954345703125, ymin=-75.42521667480469, xmax=-137.69540405273438, ymax=-75.42520904541016 8: xmin=-136.546875, ymin=-81.08232116699219, xmax=-136.54685974121094, ymax=-81.08231353759766 9: xmin=-137.8125, ymin=-81.92318725585938, xmax=-137.8125, ymax=-81.92317962646484
6:23
Lots of the places aren't actually Antarctic stations. The Overture places data contains many POIs that aren't stations. I need to find actual research stations. Let me filter by things with station names. I see some promising ones: - "Port Lockroy, Antarctic Peninsula" - "Palmer Station, Antarctica" - "Brown Station" - "González Videla Antarctic Base" - "Bellingshausen Russian Antarctic Station" - "Base Marambio, Antartida Argentina" - "Esperanza Base, Antarctica" - "Vostok İstasyonu" (Vostok Station) - "Base antarctique Dumont-d'Urville" - "Mario-Zucchelli-Station" - "Polární stanice McMurdo" (McMurdo Station) - "Antarctica/Troll" But this won't be comprehensive. The Overture `place` theme may not have all research stations. Let me think about this differently. The task asks me to pull stations from Overture south of -60. In Overture, a "station" might be tagged differently. Actually, looking more carefully at the data, the `categories.primary` field has things like `educational_research_institute`, `airport` (for stations with runways), `landmark_and_historical_building` etc. Let me look more carefully at which records could be Antarctic stations. Let me search more systematically for station-related entries.
6:23
6:23
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import pyarrow as pa
import pyarrow.compute as pc
import json
r = record_batch_reader('place', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_all()
# Print those with station/base/antarctic in name
names = tbl.column('names')
ids = tbl.column('id')
cats = tbl.column('categories')
for i in range(len(tbl)):
n = names[i]
if n:
name = n['primary'].as_py()
if name and any(k in (name.lower() or '') for k in ['station', 'base', 'antarctic', 'antarct', 'vostok', 'mcmurdo', 'dumont', 'marambio', 'esperanza', 'bellingshausen', 'palmer', 'brown', 'troll', 'zucchelli', 'halley', 'rothschild']):
cat = cats[i]
primary = cat['primary'].as_py() if cat else None
cid = ids[i].as_py()
# Get geometry
print(f'{cid}: \"{name}\" -> cat={primary}')
" 2>&1
2a100ade-be10-41c0-b6c2-a49e921a24e7: "Port Lockroy, Antarctic Peninsula" -> cat=landmark_and_historical_building f73848f3-abaa-432b-b3ed-8092a6b39b9e: "Palmer Station, Antarctica" -> cat=home_developer eb858253-acd6-4231-9ce9-e0e4c799d7a0: "Brown Station" -> cat=landmark_and_historical_building ba9d8ef6-32f3-4098-a010-b5b485e4e75f: "González Videla Antarctic Base" -> cat=airport 9d364bf8-eaaf-4f79-ad45-195f74f49a93: "Antarctica, Antarctic Circle" -> cat=landmark_and_historical_building 3bf8e968-6050-4ee6-8a60-f046db54cc02: "Esperanto Island, Antarctica" -> cat=landmark_and_historical_building 6240b821-30cb-4fe4-a08a-6fddb4fe2978: "Bellingshausen Russian Antarctic Station" -> cat=educational_research_institute 18414d58-4e4c-480f-bfab-ee3e224c5b5e: "Base Marambio, Antartida Argentina" -> cat=central_government_office 015df87e-1265-4d80-844b-97a4c1af44a5: "Marambio Base" -> cat=airport 4775fc70-d68b-48b4-af40-377af7e9a457: "Chapel of the Blessed Virgin of Lujan, Antarctica" -> cat=church_cathedral 11037d14-337b-4a53-a23b-85566484f016: "Base Antártica Marambio" -> cat=public_and_government_association b1662153-d852-4a90-b8a7-5d5e113439bb: "Base Esperanza, Antartida Argentina" -> cat=airport 8536af5a-82ba-46ed-bd6c-069082cbfc5d: "Esperanza Base, Antarctica" -> cat=landmark_and_historical_building e3417e97-f283-4ecc-a32b-ae164e69903f: "Antarctica/Troll" -> cat=landmark_and_historical_building 63b91770-28a5-4a5c-bea8-0e5842150734: "Lake Vostok" -> cat=landmark_and_historical_building bfd01a42-92a7-43f9-a7d3-0cc7fb3157b4: "Vostok İstasyonu" -> cat=landmark_and_historical_building 04d8258a-e765-4a4d-96c0-20cd3b11a9c3: "Base antarctique Dumont-d'Urville" -> cat=landmark_and_historical_building 26f0564a-e108-46da-b7aa-a4f3aca0daa2: "Antarctic Plateau" -> cat=landmark_and_historical_building fcdd73f9-5cb8-4812-be88-099727bf3936: "Mario-Zucchelli-Station" -> cat=None bb48b222-57c4-4c85-8743-752df4bba2ca: "Polární stanice McMurdo" -> cat=landmark_and_historical_building d5882de0-07ff-46b9-a3c0-bbfb0cc9552c: "Base McMurdo" -> cat=landmark_and_historical_building d74e5a73-042c-4694-9e16-fa9622f203b3: "Base antarctique McMurdo" -> cat=landmark_and_historical_building 82b40435-6b61-4d8e-9caa-7ff1d248b8a1: "McMurdo General Hospital" -> cat=hospital
6:59
There are many place records in Antarctica. I need to identify research stations specifically. Let me also check if there's a better way - using Overture infrastructure (infrastructure theme) or division_area for settlements, or look at place categories more closely. Actually, let me think about the approach more carefully: 1. First, I need to find Antarctic research stations. The `place` data has a mix of things. I should look for stations specifically. Let me filter by category or name pattern. 2. The best approach might be to: - Download all `place` records south of -60 - Filter those that are research stations (by name patterns like "Station", "Base", etc.) - Download `land` data to clip the 200km buffers - Download `water` and `bathymetry` for the water intersection analysis - Use an Antarctic projected CRS (e.g., EPSG:3031 - Antarctic Polar Stereographic) - Create 200km buffers, clip to land, create coalitions - Create over-water portions with water attribution Let me also check the infrastructure and division_area types for stations. Actually, let me check if there's a taxonomy field that indicates "research_station" or similar.
6:59
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import pyarrow as pa
import pyarrow.compute as pc
r = record_batch_reader('place', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_all()
taxonomies = tbl.column('taxonomy')
for i in range(len(tbl)):
tax = taxonomies[i]
if tax:
primary = tax['primary'].as_py()
name = tbl.column('names')[i]
n = name['primary'].as_py() if name else None
if n and any(k in (n.lower() or '') for k in ['station', 'base', 'antarct', 'vostok', 'mcmurdo', 'dumont', 'marambio', 'esperanza', 'bellingshausen', 'palmer', 'brown', 'troll', 'zucchelli']):
print(f'{n}: taxonomy={primary}, hierarchy={tax[\"hierarchy\"].as_py()}')
" 2>&1
Port Lockroy, Antarctic Peninsula: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Palmer Station, Antarctica: taxonomy=home_developer, hierarchy=['services_and_business', 'real_estate_service', 'builder', 'home_developer'] Brown Station: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] González Videla Antarctic Base: taxonomy=airport, hierarchy=['travel_and_transportation', 'air_transport_facility_or_service', 'airport'] Antarctica, Antarctic Circle: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Esperanto Island, Antarctica: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Bellingshausen Russian Antarctic Station: taxonomy=educational_research_institute, hierarchy=['education', 'research_institute', 'educational_research_institute'] Base Marambio, Antartida Argentina: taxonomy=government_office, hierarchy=['community_and_government', 'government_office'] Marambio Base: taxonomy=airport, hierarchy=['travel_and_transportation', 'air_transport_facility_or_service', 'airport'] Chapel of the Blessed Virgin of Lujan, Antarctica: taxonomy=christian_place_of_worship, hierarchy=['cultural_and_historic', 'religious_organization', 'place_of_worship', 'christian_place_of_worship'] Base Antártica Marambio: taxonomy=government_office, hierarchy=['community_and_government', 'government_office'] Base Esperanza, Antartida Argentina: taxonomy=airport, hierarchy=['travel_and_transportation', 'air_transport_facility_or_service', 'airport'] Esperanza Base, Antarctica: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Antarctica/Troll: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Lake Vostok: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Vostok İstasyonu: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Base antarctique Dumont-d'Urville: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Antarctic Plateau: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Mario-Zucchelli-Station: taxonomy=None, hierarchy=None Polární stanice McMurdo: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Base McMurdo: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] Base antarctique McMurdo: taxonomy=historic_site, hierarchy=['cultural_and_historic', 'historic_site'] McMurdo General Hospital: taxonomy=hospital, hierarchy=['health_care', 'hospital']
7:40
I can see the place data isn't well tagged for stations. Let me look at what Overture has for `divisions` or see if there's a better way to get Antarctic research stations. Maybe I should also check OSM data or use overturemaps CLI to list available types more thoroughly. Actually, looking at the place data, I see a bunch of stations but they're poorly categorized. Let me think about how to approach this. The user wants: 1. Antarctic research stations south of -60 latitude 2. Their 200 km operational radius zones clipped to land (Antarctic landmass) 3. Grouping into coalitions based on overlap 4. Over-water portions attributed with water features Let me look for a comprehensive list. The Overture `place` type has stations like: - Palmer Station - Brown Station - González Videla Antarctic Base - Bellingshausen Russian Antarctic Station - Base Marambio / Marambio Base - Base Esperanza / Esperanza Base - Troll Station (Antarctica/Troll) - Vostok Station (Vostok İstasyonu) - Dumont-d'Urville Base - Mario Zucchelli Station - McMurdo Station (multiple entries) There are multiple entries for the same stations (Marambio, Esperanza, McMurdo all have duplicates). Let me check the geometries to deduplicate. Actually, let me take a step back and use a more comprehensive approach. Let me lean on the Overture places and also consider using DuckDB or OSM data. But first let me check if the Overture `division` theme has Antarctica info.
7:40
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import pyarrow as pa
import pyarrow.compute as pc
r = record_batch_reader('division', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_all()
print(f'Total divisions: {len(tbl)}')
for field in tbl.schema:
print(f' {field.name}: {field.type}')
" 2>&1
Total divisions: 49
id: string
geometry: binary
country: string
sources: list<element: struct<property: string, dataset: string, license: string, record_id: string, update_time: string, confidence: double, between: list<element: double>>>
subtype: string
admin_level: int32
class: string
names: struct<primary: string, common: map<string, string ('common')>, rules: list<element: struct<variant: string, language: string, perspectives: struct<mode: string, countries: list<element: string>>, value: string, between: list<element: double>, side: string>>>
wikidata: string
perspectives: struct<mode: string, countries: list<element: string>>
local_type: map<string, string ('local_type')>
region: string
hierarchies: list<element: list<element: struct<division_id: string, subtype: string, name: string>>>
parent_division_id: string
norms: struct<driving_side: string>
population: int32
capital_division_ids: list<element: string>
capital_of_divisions: list<element: struct<division_id: string, subtype: string>>
cartography: struct<prominence: int32, min_zoom: int32, max_zoom: int32, sort_key: int32>
version: int32
bbox: struct<xmin: double, xmax: double, ymin: double, ymax: double>
7:54
7:54
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import pyarrow as pa
r = record_batch_reader('division', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_all()
names = tbl.column('names')
subtypes = tbl.column('subtype')
for i in range(len(tbl)):
n = names[i]
name = n['primary'].as_py() if n else 'None'
sub = subtypes[i].as_py()
print(f'{i}: {name} ({sub})')
" 2>&1
0: Amundsen–Scott South Pole (locality) 1: Rothera Research Station (locality) 2: Base Antártica San Martín (locality) 3: Vernadsky Research Base (locality) 4: Palmer Station (locality) 5: 남극세종과학기지 (locality) 6: Base Artigas (locality) 7: Беллинсгаузен (locality) 8: Base Profesor Julio Escudero (neighborhood) 9: Base Presidente Eduardo Frei Montalva (neighborhood) 10: Villa Las Estrellas (locality) 11: 长城站 (locality) 12: Base Naval Antartica Arturo Prat (locality) 13: Base Carlini (locality) 14: Arctowski (locality) 15: Estação Antártica Comandante Ferraz (locality) 16: Base Bernardo O’Higgins (locality) 17: Deutsche Antarktis-Empfangsstation O'Higgins (locality) 18: Fortín Sargento Cabral (locality) 19: Base Esperanza (neighborhood) 20: Base Marambio (locality) 21: Base Antártica Orcadas (locality) 22: Base Antártica Belgrano II (locality) 23: Halley VI Research Station (locality) 24: Nordenskiöld Base (neighborhood) 25: Neumayer-Station III (locality) 26: Antarctica (country) 27: Troll (locality) 28: Новолазаревская (locality) 29: Maitri Station (locality) 30: 昭和基地 (locality) 31: Mawson Station (locality) 32: Bharati Research Station (locality) 33: 中山站 (locality) 34: Прогресс (locality) 35: 昆仑站 (locality) 36: Davis Station (locality) 37: Мирный (locality) 38: Stacja im. A.B. Dobrowolskiego (locality) 39: Восток (locality) 40: Casey Station (locality) 41: Concordia Station (locality) 42: Camp d'été (neighborhood) 43: Base Dumont d'Urville (locality) 44: 秦岭站 (locality) 45: 남극장보고과학기지 (locality) 46: Stazione Mario Zucchelli (locality) 47: McMurdo Station (locality) 48: Scott Base (locality)
8:09
Now I can see that the `division` theme has the Antarctic research stations as localities with much better data. Let me also get the geometry for these divisions and extract the stations south of -60 to work with. Let me also check what geometries these divisions have - they might be point geometries.
8:09
8:09
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader, geodataframe
import pyarrow as pa
r = record_batch_reader('division', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_all()
print(f'Total: {len(tbl)}')
print(f'Columns: {tbl.column_names}')
# Check the geometry column binary type and try converting
print(f'Geometry type: {tbl.schema.field(\"geometry\").type}')
# Try to get a geopandas dataframe
gdf = geodataframe(tbl)
print(gdf.head())
print(f'Geometry types: {gdf.geom_type.unique()}')
print(f'CRS: {gdf.crs}')
" 2>&1
Total: 49
Columns: ['id', 'geometry', 'country', 'sources', 'subtype', 'admin_level', 'class', 'names', 'wikidata', 'perspectives', 'local_type', 'region', 'hierarchies', 'parent_division_id', 'norms', 'population', 'capital_division_ids', 'capital_of_divisions', 'cartography', 'version', 'bbox']
Geometry type: binary
Traceback (most recent call last):
File "<string>", line 13, in <module>
gdf = geodataframe(tbl)
File "/usr/local/lib/python3.14/site-packages/overturemaps/core.py", line 342, in geodataframe
reader = record_batch_reader(
overture_type,
...<4 lines>...
stac=stac,
)
File "/usr/local/lib/python3.14/site-packages/overturemaps/core.py", line 307, in record_batch_reader
result = _prepare_query(
overture_type, bbox, release, connect_timeout, request_timeout, stac
)
File "/usr/local/lib/python3.14/site-packages/overturemaps/core.py", line 244, in _prepare_query
path = _dataset_path(overture_type, release)
File "/usr/local/lib/python3.14/site-packages/overturemaps/core.py", line 409, in _dataset_path
theme = type_theme_map[overture_type]
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
TypeError: cannot use 'pyarrow.lib.Table' as a dict key (unhashable type: 'pyarrow.lib.Table')
8:25
The `geodataframe()` function expects a different call signature. Let me use pyogrio or shapely directly to convert the WKB geometries.
8:25
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import geopandas as gpd
from shapely import wkb
import pyarrow as pa
r = record_batch_reader('division', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_all()
print(f'Rows: {len(tbl)}')
# Convert WKB geometry column
geoms = []
for i in range(len(tbl)):
geom_bytes = tbl.column('geometry')[i].as_py()
geom = wkb.loads(geom_bytes)
geoms.append(geom)
names_col = tbl.column('names')
ids_col = tbl.column('id')
names = []
ids = []
for i in range(len(tbl)):
n = names_col[i]
name = n['primary'].as_py() if n else None
names.append(name)
ids.append(ids_col[i].as_py())
gdf = gpd.GeoDataFrame({'station_id': ids, 'station_name': names, 'geometry': geoms}, crs='EPSG:4326')
print(gdf)
print(f'Geometry types: {gdf.geom_type.unique()}')
" 2>&1
Rows: 49
station_id ... geometry
0 23e81262-d6ed-45a3-a1a0-4bc6a2a887d8 ... POINT (-139.2728 -89.998)
1 ed7d4df0-fb65-49a7-a46e-4d3595ab8f9e ... POINT (-68.12217 -67.56924)
2 2921924c-7938-4ef0-9cd2-cd6ac0947c6c ... POINT (-67.10132 -68.13006)
3 90c7bf02-04af-423b-8f54-8ffb4bfa6c45 ... POINT (-64.25769 -65.24551)
4 f6b7b583-191a-449b-95dc-7bd90ecddef7 ... POINT (-64.05311 -64.77429)
5 d76b5d42-78a1-49aa-a015-be14688c29d9 ... POINT (-58.78731 -62.22305)
6 4463ec21-3f98-4603-8174-c2c2ea68bd71 ... POINT (-58.90385 -62.1844)
7 c38eadd2-432f-443b-a45d-0dd6f970b03a ... POINT (-58.95992 -62.1982)
8 06cc197e-bade-42aa-9dfc-39a687d41a78 ... POINT (-58.96152 -62.2014)
9 e89b5561-840e-4ebc-99ca-3d748a78a60a ... POINT (-58.96317 -62.19985)
10 3a6a5d5a-3040-49a1-a0aa-a1c408a60146 ... POINT (-58.96537 -62.20043)
11 1ae1d16b-e347-4085-89be-feb8f5151c50 ... POINT (-58.96118 -62.21775)
12 3554e829-89ff-4681-942f-e361e9a93acf ... POINT (-59.66434 -62.47889)
13 7ed44c37-1664-42da-9e1a-fbc1774a7367 ... POINT (-58.66701 -62.23793)
14 5cd11342-bb88-4ffb-a8cb-d12bc90635c6 ... POINT (-58.47194 -62.15901)
15 8f17d23a-553a-4641-a5d1-e67ca1c7bacc ... POINT (-58.39083 -62.08424)
16 9d034b39-095a-45bf-8463-9b89102bf6a2 ... POINT (-57.89986 -63.32083)
17 de5df6e3-3b22-468c-ba43-4d243d721c9f ... POINT (-57.90117 -63.32089)
18 59fb7587-704a-4a4c-8a80-4de39fc865eb ... POINT (-56.99717 -63.39834)
19 96ed2dba-5a05-4d96-bdbf-a162ee11b655 ... POINT (-56.99637 -63.39806)
20 0bd9aea9-7334-4ae1-afe0-3954079e80f8 ... POINT (-56.62769 -64.24062)
21 e2a72a14-ea5e-47c7-8f7c-303b9fd47f73 ... POINT (-44.73769 -60.73807)
22 256f7a41-8ba5-42e3-9544-73621992f5c6 ... POINT (-34.62745 -77.87361)
23 5a06bf03-22f9-46a0-a805-dfd7d56c54eb ... POINT (-26.19771 -75.6125)
24 13f83c85-ac47-43aa-a11f-248c14eb5d7e ... POINT (-13.4077 -73.04279)
25 76fc8784-4217-4eb7-951e-77a7fc986ec3 ... POINT (-8.27417 -70.67444)
26 2ba5ad8b-6784-4088-87bb-50c14f2cbdc0 ... POINT (0.31493 -79.40631)
27 01e06782-a4dc-4d9e-a850-242c94f1dbc2 ... POINT (2.53443 -72.01198)
28 864311b8-c1ba-4818-8b15-402122495a65 ... POINT (11.82453 -70.7766)
29 30a92d5d-700e-4501-8ad8-d7b373d07e90 ... POINT (11.73276 -70.76741)
30 47f64194-6f2c-4cd5-bf8a-0fd5ac49d24b ... POINT (39.58203 -69.00424)
31 d4a35fd4-5e6c-4c00-9c36-8249179b5641 ... POINT (62.87375 -67.6029)
32 c8b9875f-3051-4b51-bc75-e5fd03507bcd ... POINT (76.19533 -69.40683)
33 0471ebb0-e185-48f0-8146-ce23d4a5a931 ... POINT (76.37175 -69.37361)
34 ad792a75-c72e-4204-8fda-a14235a2791d ... POINT (76.38864 -69.38006)
35 66fc254c-4bd6-4f3d-8f95-c5c0aaafa206 ... POINT (77.11737 -80.41738)
36 61fa8848-c708-48c8-8842-817124296b41 ... POINT (77.96837 -68.57691)
37 3a151f12-0ce5-4a2f-b17e-d5740a5b5a21 ... POINT (93.00928 -66.55305)
38 656c3136-8b2a-4ef6-870e-e98b961e8638 ... POINT (100.74975 -66.27459)
39 19aeddf3-edd8-456d-8171-4c902e794824 ... POINT (106.83829 -78.46435)
40 e02d07a5-de40-4997-8062-2adecb7640d8 ... POINT (110.52408 -66.28209)
41 42d554ba-4456-42f8-b7df-3faa71e6daf6 ... POINT (123.33333 -75.10001)
42 ca812f6a-ae44-4d83-8c80-1d55d4b1d2f1 ... POINT (123.34713 -75.10122)
43 81f11e7c-fc8f-4e71-8dec-40c625e64689 ... POINT (140.0011 -66.66328)
44 a2b3c483-20d5-4044-a098-3a9eeb5e1a2b ... POINT (163.71527 -74.93434)
45 81ab83f2-39a1-4289-8674-2c6111c3280d ... POINT (164.22882 -74.62409)
46 65e16630-0264-40b3-b21f-2df6716d5c7e ... POINT (164.11311 -74.69439)
47 a1a1291c-4171-4768-8b8e-4df289c7ed30 ... POINT (166.66833 -77.84833)
48 2069a892-5e6c-4b45-9659-53f0967cc370 ... POINT (166.76834 -77.84945)
[49 rows x 3 columns]
Geometry types: <ArrowStringArray>
['Point']
Length: 1, dtype: str
8:40
Now I have all 49 stations as points. I need to: 1. Create 200km buffer around each station 2. Get land data from Overture (land) for Antarctica south of -60 3. Get water data from Overture (water) and bathymetry data 4. Clip station spheres to land for the first output 5. Compute over-water portions and intersect with water features for the second output Let me plan the approach: 1. Download land polygons south of -60 2. Download water polygons south of -60 3. Download bathymetry polygons south of -60 4. Create station buffer spheres (200km radius) - need to use an Antarctic projection 5. Clip spheres to land -> grouped into coalitions where they overlap 6. Over-water portion intersected with water features For projection, the standard Antarctic projection is EPSG:3031 (Antarctic Polar Stereographic) or EPSG:3976 (NSIDC Sea Ice Polar Stereographic South). Let's use EPSG:3031 (WGS 84 / Antarctic Polar Stereographic). Let me also check the land and water data to see how much data we're dealing with.
8:40
8:40
Bash
python -c "
python -c "
from overturemaps.core import record_batch_reader
import pyarrow as pa
# Check land data volume
r = record_batch_reader('land', bbox=(-180, -90, 180, -60))
if r:
tbl = r.read_all()
print(f'Land features: {len(tbl)}')
subtypes = tbl.column('subtype')
for s in subtypes.unique():
print(f' subtype: {s.as_py()}')
else:
print('land failed')
r2 = record_batch_reader('water', bbox=(-180, -90, 180, -60))
if r2:
tbl2 = r2.read_all()
print(f'Water features: {len(tbl2)}')
subtypes = tbl2.column('subtype')
for s in subtypes.unique():
print(f' subtype: {s.as_py()}')
else:
print('water failed')
r3 = record_batch_reader('bathymetry', bbox=(-180, -90, 180, -60))
if r3:
tbl3 = r3.read_all()
print(f'Bathymetry features: {len(tbl3)}')
else:
print('bathymetry failed')
" 2>&1
Land features: 93369 subtype: land subtype: rock subtype: physical subtype: glacier subtype: crater subtype: sand subtype: reef subtype: wetland subtype: shrub subtype: grass Water features: 13500 subtype: lake subtype: physical subtype: stream subtype: ocean subtype: human_made subtype: canal subtype: water subtype: pond subtype: river subtype: reservoir Bathymetry features: 3096
11:34
Let me plan the approach: 1. **Stations**: Use `division` theme, filter to only the locality/neighborhood entries (these are the research stations). There are 49 total, the first row is Amundsen-Scott South Pole (locality) which is a station too, and Antarctica (country) at index 26 should be excluded. 2. **200 km radius**: Create buffer circles around each station point. - Need an appropriate projected CRS for Antarctica. The best choice is EPSG:3031 (Antarctic Polar Stereographic) which is suitable for the entire continent south of -60. 3. **Land**: From the `land` theme. We need to clip the station buffers by land, keeping only the portion that overlaps with land. 4. **Water**: From `water` and `bathymetry` themes. 5. **Coalition grouping**: Group the land-clipped station zones into coalitions where they overlap. Use `unary_union` + overlay approach. Let me write the comprehensive script now. The plan: - Download stations from division theme (south of -60) - Download land polygons from land theme (south of -60) - Download water polygons from water theme (south of -60) - Download bathymetry from bathymetry theme (south of -60) - Project to EPSG:3031 (Antarctic Polar Stereographic) - Create 200km buffers around each station - Clip buffers by land polygons → station spheres (land-clipped) - From this, dissolve overlapping ones into coalitions - Also create the water overlap: intersect each station's buffer with water features, attributing with water info Let me think about the coalition part more carefully. The requirement says: "the land-clipped station zones grouped into coalitions wherever they overlap. Each coalition gets an integer coalition id" So the process is: 1. Create 200km buffers around each station 2. Clip each buffer by land (keep only the part overlapping land) 3. Where these land-clipped buffers overlap/touch, they form a coalition 4. Assign a coalition id to each feature Each feature also needs `station_id` and `station_name`. For the water overlap: - Take each station's 200km buffer (full circle, not land-clipped) - Intersect with water features - Keep the intersection parts (over water) - Attribute with station_id, station_name, water_id, water_name, water_subtype, water_source Let me write this step by step.
11:34
11:34
Write
/work/solve.py
content · 352 lines · py
"""
Cross-station logistics-overlap maps for Antarctic Treaty consultative meeting.
Produces two GeoParquet files:
1. station_spheres.geoparquet — land-clipped station zones grouped into coalitions
2. station_water_overlap.geoparquet — per-station over-water intersections with water attribution
"""
import sys
import time
import traceback
import pyarrow as pa
import pyarrow.compute as pc
import geopandas as gpd
import pandas as pd
from shapely import wkb, wkt
from shapely.geometry import box, Point, MultiPolygon
from shapely.ops import unary_union
from overturemaps.core import record_batch_reader
# ---------------------------------------------------------------------------
# 1. Helper: retry wrapper for Overture downloads
# ---------------------------------------------------------------------------
def fetch_overture(overture_type, bbox=(-180, -90, 180, -60), max_retries=3):
"""Download an Overture theme within a bounding box, return a GeoDataFrame."""
for attempt in range(1, max_retries + 1):
try:
reader = record_batch_reader(overture_type, bbox=bbox, request_timeout=120)
if reader is None:
raise RuntimeError(f"record_batch_reader returned None for {overture_type}")
table = reader.read_all()
print(f" {overture_type}: {len(table)} features")
if len(table) == 0:
return gpd.GeoDataFrame({"geometry": []}, crs="EPSG:4326")
# Convert WKB geometry column to shapely objects
geoms = []
for i in range(len(table)):
gb = table.column("geometry")[i].as_py()
if gb is not None:
geoms.append(wkb.loads(gb))
else:
geoms.append(None)
# Build a dict of column arrays
data = {}
for field_name in table.schema.names:
if field_name == "geometry":
continue
col = table.column(field_name)
data[field_name] = [col[i].as_py() for i in range(len(table))]
gdf = gpd.GeoDataFrame(data, geometry=geoms, crs="EPSG:4326")
return gdf
except Exception as exc:
print(f" Attempt {attempt} failed: {exc}")
if attempt < max_retries:
time.sleep(2 * attempt)
else:
raise
# ---------------------------------------------------------------------------
# 2. Fetch data
# ---------------------------------------------------------------------------
print("=== Fetching data ===")
print("Fetching divisions (research stations) ...")
divisions = fetch_overture("division", bbox=(-180, -90, 180, -60))
print("Fetching land...")
land_raw = fetch_overture("land", bbox=(-180, -90, 180, -60))
print("Fetching water...")
water_raw = fetch_overture("water", bbox=(-180, -90, 180, -60))
print("Fetching bathymetry...")
bathy_raw = fetch_overture("bathymetry", bbox=(-180, -90, 180, -60))
# ---------------------------------------------------------------------------
# 3. Filter stations — keep only locality/neighborhood (research stations)
# ---------------------------------------------------------------------------
print("\n=== Processing stations ===")
print(f"Total divisions: {len(divisions)}")
# The 'subtype' column tells us what kind of place it is
# Keep locality and neighborhood subtypes (exclude 'country')
stations = divisions[divisions["subtype"].isin(["locality", "neighborhood"])].copy()
print(f"Station candidates: {len(stations)}")
# Extract station name from names.primary
def extract_name(names_val):
if names_val and isinstance(names_val, dict) and "primary" in names_val:
return names_val["primary"]
return None
stations["station_name"] = stations["names"].apply(extract_name)
stations["station_id"] = stations["id"].astype(str)
# Drop Antarctica country entry by checking station_name
stations = stations[stations["station_name"].notna()].copy()
# Filter out Antarctica itself (the country entry)
stations = stations[~stations["station_name"].str.lower().isin(["antarctica"])].copy()
# Also filter points that are actually south of -60 (some may be questionable)
stations = stations[stations.geometry.y <= -60].copy()
print(f"Final station count: {len(stations)}")
for idx, row in stations.iterrows():
print(f" {row['station_name']} @ ({row.geometry.x:.4f}, {row.geometry.y:.4f})")
# ---------------------------------------------------------------------------
# 4. Project to EPSG:3031 (Antarctic Polar Stereographic)
# ---------------------------------------------------------------------------
print("\n=== Projecting to EPSG:3031 ===")
stations = stations.to_crs("EPSG:3031")
print(f"Stations CRS: {stations.crs}")
# ---------------------------------------------------------------------------
# 5. Create 200 km buffers
# ---------------------------------------------------------------------------
print("\n=== Creating 200 km buffers ===")
BUFFER_DIST = 200_000 # meters = 200 km
stations["buffer"] = stations.geometry.buffer(BUFFER_DIST)
print("Buffers created.")
# ---------------------------------------------------------------------------
# 6. Process land — dissolve into a single land mask
# ---------------------------------------------------------------------------
print("\n=== Processing land ===")
# Keep only the geometry, dissolve
if len(land_raw) > 0:
land_gdf = land_raw.to_crs("EPSG:3031")
# Dissolve all land polygons into a single multipolygon
land_union = unary_union(land_gdf.geometry.values)
print(f"Land union type: {land_union.geom_type if land_union else 'None'}")
else:
land_union = None
print("WARNING: No land features found!")
# ---------------------------------------------------------------------------
# 7. Clip station buffers by land → station spheres
# ---------------------------------------------------------------------------
print("\n=== Clipping station buffers to land ===")
clipped_polys = []
for idx, row in stations.iterrows():
buf = row["buffer"]
if land_union is not None and not land_union.is_empty:
clipped = buf.intersection(land_union)
else:
clipped = buf # no land data, keep full buffer
if clipped.is_empty:
continue
# Ensure MultiPolygon
if clipped.geom_type == "Polygon":
clipped = MultiPolygon([clipped])
elif clipped.geom_type != "MultiPolygon":
# Skip weird geometry types
continue
clipped_polys.append({
"station_id": row["station_id"],
"station_name": row["station_name"],
"geometry": clipped
})
spheres_gdf = gpd.GeoDataFrame(clipped_polys, crs="EPSG:3031")
print(f"Land-clipped spheres: {len(spheres_gdf)}")
# ---------------------------------------------------------------------------
# 8. Group into coalitions where they overlap
# ---------------------------------------------------------------------------
print("\n=== Grouping into coalitions ===")
# Spatial join to find overlapping pairs
if len(spheres_gdf) > 0:
# Self-join to find overlaps
sj = gpd.sjoin(spheres_gdf, spheres_gdf, how="inner", predicate="intersects")
# Build a graph of overlapping indices
import collections
graph = collections.defaultdict(set)
for _, row in sj.iterrows():
i = row.index_left
j = row.index_right
if i != j:
graph[i].add(j)
graph[j].add(i)
# Find connected components (coalitions)
visited = set()
coalitions = []
for node in graph:
if node in visited:
continue
stack = [node]
comp = set()
while stack:
v = stack.pop()
if v in visited:
continue
visited.add(v)
comp.add(v)
for nb in graph[v]:
if nb not in visited:
stack.append(nb)
coalitions.append(comp)
# Also include isolated stations (no overlaps)
all_indices = set(spheres_gdf.index)
isolated = all_indices - visited
for idx in isolated:
coalitions.append({idx})
# Assign coalition IDs
spheres_gdf["coalition"] = -1
for cid, members in enumerate(coalitions):
for idx in members:
spheres_gdf.at[idx, "coalition"] = cid
# Check: more than one distinct coalition value
distinct = spheres_gdf["coalition"].nunique()
print(f"Coalitions formed: {len(coalitions)}, distinct coalition ids: {distinct}")
if distinct < 2:
print("WARNING: fewer than 2 distinct coalition IDs — forcing a second group")
if len(spheres_gdf) > 1:
# Split the first coalition arbitrarily to get 2+ groups
# Group by station proximity or just assign sequential
pass # The logic above should handle this naturally
else:
spheres_gdf["coalition"] = -1
print("Coalition counts:")
print(spheres_gdf["coalition"].value_counts().sort_index())
# Sort by coalition id for readability
spheres_gdf = spheres_gdf.sort_values("coalition").reset_index(drop=True)
# ---------------------------------------------------------------------------
# 9. Write station_spheres.geoparquet
# ---------------------------------------------------------------------------
print("\n=== Writing station_spheres.geoparquet ===")
keep_cols = ["station_id", "station_name", "coalition", "geometry"]
spheres_out = spheres_gdf[keep_cols].copy()
spheres_out.to_parquet("/work/station_spheres.geoparquet", index=False)
print(f"Written {len(spheres_out)} features.")
# ---------------------------------------------------------------------------
# 10. Water overlap — per-station over-water portion
# ---------------------------------------------------------------------------
print("\n=== Computing water overlaps ===")
# Prepare water features
def prep_water(gdf, source_name):
"""Extract key columns and project."""
if len(gdf) == 0:
return gpd.GeoDataFrame({"geometry": []}, crs="EPSG:4326")
gdf = gdf.to_crs("EPSG:3031")
def extract_name(names_val):
if names_val and isinstance(names_val, dict):
return names_val.get("primary", None)
return None
records = []
for idx, row in gdf.iterrows():
records.append({
"water_id": str(row.get("id", "")),
"water_name": extract_name(row.get("names")),
"water_subtype": row.get("subtype", ""),
"water_source": source_name,
"geometry": row.geometry
})
result = gpd.GeoDataFrame(records, crs="EPSG:3031")
return result
water_prepped = prep_water(water_raw, "base.water")
bathy_prepped = prep_water(bathy_raw, "base.bathymetry")
# Combine
all_water = gpd.GeoDataFrame(
pd.concat([water_prepped, bathy_prepped], ignore_index=True),
crs="EPSG:3031"
)
print(f"Combined water features: {len(all_water)}")
# For each station's buffer, intersect with water features
water_overlap_rows = []
for idx, row in stations.iterrows():
buf = row["buffer"]
station_id = row["station_id"]
station_name = row["station_name"]
# Find water features that intersect this buffer
if len(all_water) > 0:
# Spatial subset
water_sub = all_water[all_water.intersects(buf)].copy()
if len(water_sub) == 0:
continue
for w_idx, w_row in water_sub.iterrows():
inter = buf.intersection(w_row.geometry)
if inter.is_empty:
continue
if inter.geom_type == "Polygon":
inter = MultiPolygon([inter])
elif inter.geom_type != "MultiPolygon":
continue
water_overlap_rows.append({
"station_id": station_id,
"station_name": station_name,
"water_id": w_row["water_id"],
"water_name": w_row["water_name"],
"water_subtype": w_row["water_subtype"],
"water_source": w_row["water_source"],
"geometry": inter
})
water_overlap_gdf = gpd.GeoDataFrame(water_overlap_rows, crs="EPSG:3031")
print(f"Water overlap features: {len(water_overlap_gdf)}")
# ---------------------------------------------------------------------------
# 11. Write station_water_overlap.geoparquet
# ---------------------------------------------------------------------------
print("\n=== Writing station_water_overlap.geoparquet ===")
wo_cols = ["station_id", "station_name", "water_id", "water_name",
"water_subtype", "water_source", "geometry"]
water_out = water_overlap_gdf[wo_cols].copy()
water_out.to_parquet("/work/station_water_overlap.geoparquet", index=False)
print(f"Written {len(water_out)} features.")
# ---------------------------------------------------------------------------
# 12. Sanity checks
# ---------------------------------------------------------------------------
print("\n=== Final sanity checks ===")
# Read back and verify
s1 = gpd.read_parquet("/work/station_spheres.geoparquet")
print(f"station_spheres.geoparquet: {len(s1)} features, CRS={s1.crs}")
print(f" Columns: {list(s1.columns)}")
print(f" Coalition distinct values: {s1['coalition'].nunique()}")
print(f" Geometry types: {s1.geom_type.unique()}")
s2 = gpd.read_parquet("/work/station_water_overlap.geoparquet")
print(f"station_water_overlap.geoparquet: {len(s2)} features, CRS={s2.crs}")
print(f" Columns: {list(s2.columns)}")
print(f" water_source values: {s2['water_source'].unique()}")
print("\nDone!")
Wrote /work/solve.py (13592 chars).
11:39
11:39
Bash
cd /work && python solve.py 2>&1
=== Fetching data ===
Fetching divisions (research stations) ...
division: 49 features
Fetching land...
land: 93369 features
Fetching water...
water: 13500 features
Fetching bathymetry...
bathymetry: 3096 features
=== Processing stations ===
Total divisions: 49
Station candidates: 48
Final station count: 48
Amundsen–Scott South Pole @ (-139.2728, -89.9980)
Rothera Research Station @ (-68.1222, -67.5692)
Base Antártica San Martín @ (-67.1013, -68.1301)
Vernadsky Research Base @ (-64.2577, -65.2455)
Palmer Station @ (-64.0531, -64.7743)
남극세종과학기지 @ (-58.7873, -62.2230)
Base Artigas @ (-58.9039, -62.1844)
Беллинсгаузен @ (-58.9599, -62.1982)
Base Profesor Julio Escudero @ (-58.9615, -62.2014)
Base Presidente Eduardo Frei Montalva @ (-58.9632, -62.1998)
Villa Las Estrellas @ (-58.9654, -62.2004)
长城站 @ (-58.9612, -62.2177)
Base Naval Antartica Arturo Prat @ (-59.6643, -62.4789)
Base Carlini @ (-58.6670, -62.2379)
Arctowski @ (-58.4719, -62.1590)
Estação Antártica Comandante Ferraz @ (-58.3908, -62.0842)
Base Bernardo O’Higgins @ (-57.8999, -63.3208)
Deutsche Antarktis-Empfangsstation O'Higgins @ (-57.9012, -63.3209)
Fortín Sargento Cabral @ (-56.9972, -63.3983)
Base Esperanza @ (-56.9964, -63.3981)
Base Marambio @ (-56.6277, -64.2406)
Base Antártica Orcadas @ (-44.7377, -60.7381)
Base Antártica Belgrano II @ (-34.6275, -77.8736)
Halley VI Research Station @ (-26.1977, -75.6125)
Nordenskiöld Base @ (-13.4077, -73.0428)
Neumayer-Station III @ (-8.2742, -70.6744)
Troll @ (2.5344, -72.0120)
Новолазаревская @ (11.8245, -70.7766)
Maitri Station @ (11.7328, -70.7674)
昭和基地 @ (39.5820, -69.0042)
Mawson Station @ (62.8738, -67.6029)
Bharati Research Station @ (76.1953, -69.4068)
中山站 @ (76.3717, -69.3736)
Прогресс @ (76.3886, -69.3801)
昆仑站 @ (77.1174, -80.4174)
Davis Station @ (77.9684, -68.5769)
Мирный @ (93.0093, -66.5530)
Stacja im. A.B. Dobrowolskiego @ (100.7497, -66.2746)
Восток @ (106.8383, -78.4643)
Casey Station @ (110.5241, -66.2821)
Concordia Station @ (123.3333, -75.1000)
Camp d'été @ (123.3471, -75.1012)
Base Dumont d'Urville @ (140.0011, -66.6633)
秦岭站 @ (163.7153, -74.9343)
남극장보고과학기지 @ (164.2288, -74.6241)
Stazione Mario Zucchelli @ (164.1131, -74.6944)
McMurdo Station @ (166.6683, -77.8483)
Scott Base @ (166.7683, -77.8495)
=== Projecting to EPSG:3031 ===
Stations CRS: EPSG:3031
=== Creating 200 km buffers ===
Buffers created.
=== Processing land ===
Land union type: GeometryCollection
=== Clipping station buffers to land ===
Land-clipped spheres: 16
=== Grouping into coalitions ===
Traceback (most recent call last):
File "/work/solve.py", line 187, in <module>
i = row.index_left
^^^^^^^^^^^^^^
File "/usr/local/lib/python3.14/site-packages/pandas/core/generic.py", line 6206, in __getattr__
return object.__getattribute__(self, name)
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
AttributeError: 'Series' object has no attribute 'index_left'. Did you mean: 'index_right'?
17:12
The issue is that the `sjoin` result has a named index. Let me check the column names. The sjoin returns columns `index_left` and `index_right` as the index names, or as actual columns. Let me fix this.
17:12
Read
/work/solve.py
175 # 8. Group into coalitions where they overlap
176 # ---------------------------------------------------------------------------
177 print("\n=== Grouping into coalitions ===")
178
179 # Spatial join to find overlapping pairs
180 if len(spheres_gdf) > 0:
181 # Self-join to find overlaps
182 sj = gpd.sjoin(spheres_gdf, spheres_gdf, how="inner", predicate="intersects")
183 # Build a graph of overlapping indices
184 import collections
185 graph = collections.defaultdict(set)
186 for _, row in sj.iterrows():
187 i = row.index_left
188 j = row.index_right
189 if i != j:
190 graph[i].add(j)
191 graph[j].add(i)
192
193 # Find connected components (coalitions)
194 visited = set()
195 coalitions = []
196 for node in graph:
197 if node in visited:
198 continue
199 stack = [node]
<system-reminder>Showed lines 175-199 of 352. Re-call Read with offset=200 to continue, or raise limit.</system-reminder>
17:17
The issue is that sjoin returns a DataFrame with `index_left` and `index_right` when using `sjoin()` with the modern geopandas. Let me check what the actual index names are. The error says 'Series' object has no attribute 'index_left'. It's possible that the index columns are stored differently. Let me check the column names returned by sjoin.
17:17
Bash
cd /work && python -c "
cd /work && python -c "
import geopandas as gpd
# Quick test
s1 = gpd.read_parquet('station_spheres.geoparquet') if False else None
# Test sjoin column names
from shapely.geometry import Point
import pandas as pd
gdf1 = gpd.GeoDataFrame({'a': [1,2]}, geometry=[Point(0,0), Point(1,1)], crs='EPSG:3031')
gdf2 = gpd.GeoDataFrame({'b': [3,4]}, geometry=[Point(0.1,0.1), Point(2,2)], crs='EPSG:3031')
sj = gpd.sjoin(gdf1, gdf2, how='inner', predicate='intersects')
print('Columns:', list(sj.columns))
print(sj)
"
Columns: ['a', 'geometry', 'index_right', 'b'] Empty GeoDataFrame Columns: [a, geometry, index_right, b] Index: []
17:25
The sjoin result has `index_left` (the index of the left gdf) and `index_right` columns. Let me fix the code.
17:25
Edit
/work/solve.py
Edited /work/solve.py.
17:31
Wait, `row.name` won't work because `iterrows()` gives (index, series) and the series name is the index. Let me think about this.
When you call `gpd.sjoin(gdf, gdf, ...)`, the result has the index from the left dataframe, and a column `index_right` from the right dataframe. So when iterating:
```python
for idx, row in sj.iterrows():
i = idx # left index
j = row["index_right"] # right index
```
That's the fix.
17:31
Edit
/work/solve.py
Edited /work/solve.py.
17:36
The land union returned a GeometryCollection, not a nice Polygon/MultiPolygon. That's because the land data has many geometry types. Let me also fix that and re-run.
17:36
17:36
Read
/work/solve.py
105 stations = stations[~stations["station_name"].str.lower().isin(["antarctica"])].copy()
106
107 # Also filter points that are actually south of -60 (some may be questionable)
108 stations = stations[stations.geometry.y <= -60].copy()
109
110 print(f"Final station count: {len(stations)}")
111 for idx, row in stations.iterrows():
112 print(f" {row['station_name']} @ ({row.geometry.x:.4f}, {row.geometry.y:.4f})")
113
114 # ---------------------------------------------------------------------------
115 # 4. Project to EPSG:3031 (Antarctic Polar Stereographic)
116 # ---------------------------------------------------------------------------
117 print("\n=== Projecting to EPSG:3031 ===")
118 stations = stations.to_crs("EPSG:3031")
119 print(f"Stations CRS: {stations.crs}")
120
121 # ---------------------------------------------------------------------------
122 # 5. Create 200 km buffers
123 # ---------------------------------------------------------------------------
124 print("\n=== Creating 200 km buffers ===")
125 BUFFER_DIST = 200_000 # meters = 200 km
126 stations["buffer"] = stations.geometry.buffer(BUFFER_DIST)
127 print("Buffers created.")
128
129 # ---------------------------------------------------------------------------
130 # 6. Process land — dissolve into a single land mask
131 # ---------------------------------------------------------------------------
132 print("\n=== Processing land ===")
133 # Keep only the geometry, dissolve
134 if len(land_raw) > 0:
135 land_gdf = land_raw.to_crs("EPSG:3031")
136 # Dissolve all land polygons into a single multipolygon
137 land_union = unary_union(land_gdf.geometry.values)
138 print(f"Land union type: {land_union.geom_type if land_union else 'None'}")
139 else:
140 land_union = None
141 print("WARNING: No land features found!")
142
143 # ---------------------------------------------------------------------------
144 # 7. Clip station buffers by land → station spheres
145 # ---------------------------------------------------------------------------
146 print("\n=== Clipping station buffers to land ===")
147 clipped_polys = []
148 for idx, row in stations.iterrows():
149 buf = row["buffer"]
150 if land_union is not None and not land_union.is_empty:
151 clipped = buf.intersection(land_union)
152 else:
153 clipped = buf # no land data, keep full buffer
154
<system-reminder>Showed lines 105-154 of 352. Re-call Read with offset=155 to continue, or raise limit.</system-reminder>
17:43
When the land union is a GeometryCollection, I need to extract only the Polygon/MultiPolygon parts to use it as a clipping mask. Let me fix the land processing to handle this.
17:43
Edit
/work/solve.py
Edited /work/solve.py.
17:49
Now let me also think about a key issue. The Antarctic land mass is basically the entire continent. When we clip station buffers to land, we're getting the portion of each 200km buffer that lies on land. But since Antarctica is a big land mass, most buffers will simply be clipped to the land area that overlaps them. But we also need to consider that the buffers around the coast extend out over water - we want the land-clipped portion to be just the part on land. Wait, actually the land features from Overture include things like glaciers, rock, etc. The Antarctic continent as a land mass should be covered. Let me think about this more carefully. The land union should be the Antarctic continent. Buffers from coastal stations extend over water. The intersection of buffer with land gives the on-land portion. For the water overlap (output 2), we want the portion of the buffer that's over water features. So it's buffer ∩ (water ∪ bathymetry). Let me also think about the GeometryCollection issue - the land union may include point/line geometries from the Overture land layer. We need to handle that. Let me also consider that the water features include both "ocean" subtype water and other water types. And bathymetry is separate. Let me re-run the script.
17:49
Bash
cd /work && python solve.py 2>&1
=== Fetching data ===
Fetching divisions (research stations) ...
division: 49 features
Fetching land...
land: 93369 features
Fetching water...
water: 13500 features
Fetching bathymetry...
bathymetry: 3096 features
=== Processing stations ===
Total divisions: 49
Station candidates: 48
Final station count: 48
Amundsen–Scott South Pole @ (-139.2728, -89.9980)
Rothera Research Station @ (-68.1222, -67.5692)
Base Antártica San Martín @ (-67.1013, -68.1301)
Vernadsky Research Base @ (-64.2577, -65.2455)
Palmer Station @ (-64.0531, -64.7743)
남극세종과학기지 @ (-58.7873, -62.2230)
Base Artigas @ (-58.9039, -62.1844)
Беллинсгаузен @ (-58.9599, -62.1982)
Base Profesor Julio Escudero @ (-58.9615, -62.2014)
Base Presidente Eduardo Frei Montalva @ (-58.9632, -62.1998)
Villa Las Estrellas @ (-58.9654, -62.2004)
长城站 @ (-58.9612, -62.2177)
Base Naval Antartica Arturo Prat @ (-59.6643, -62.4789)
Base Carlini @ (-58.6670, -62.2379)
Arctowski @ (-58.4719, -62.1590)
Estação Antártica Comandante Ferraz @ (-58.3908, -62.0842)
Base Bernardo O’Higgins @ (-57.8999, -63.3208)
Deutsche Antarktis-Empfangsstation O'Higgins @ (-57.9012, -63.3209)
Fortín Sargento Cabral @ (-56.9972, -63.3983)
Base Esperanza @ (-56.9964, -63.3981)
Base Marambio @ (-56.6277, -64.2406)
Base Antártica Orcadas @ (-44.7377, -60.7381)
Base Antártica Belgrano II @ (-34.6275, -77.8736)
Halley VI Research Station @ (-26.1977, -75.6125)
Nordenskiöld Base @ (-13.4077, -73.0428)
Neumayer-Station III @ (-8.2742, -70.6744)
Troll @ (2.5344, -72.0120)
Новолазаревская @ (11.8245, -70.7766)
Maitri Station @ (11.7328, -70.7674)
昭和基地 @ (39.5820, -69.0042)
Mawson Station @ (62.8738, -67.6029)
Bharati Research Station @ (76.1953, -69.4068)
中山站 @ (76.3717, -69.3736)
Прогресс @ (76.3886, -69.3801)
昆仑站 @ (77.1174, -80.4174)
Davis Station @ (77.9684, -68.5769)
Мирный @ (93.0093, -66.5530)
Stacja im. A.B. Dobrowolskiego @ (100.7497, -66.2746)
Восток @ (106.8383, -78.4643)
Casey Station @ (110.5241, -66.2821)
Concordia Station @ (123.3333, -75.1000)
Camp d'été @ (123.3471, -75.1012)
Base Dumont d'Urville @ (140.0011, -66.6633)
秦岭站 @ (163.7153, -74.9343)
남극장보고과학기지 @ (164.2288, -74.6241)
Stazione Mario Zucchelli @ (164.1131, -74.6944)
McMurdo Station @ (166.6683, -77.8483)
Scott Base @ (166.7683, -77.8495)
=== Projecting to EPSG:3031 ===
Stations CRS: EPSG:3031
=== Creating 200 km buffers ===
Buffers created.
=== Processing land ===
Land union type: MultiPolygon
=== Clipping station buffers to land ===
Land-clipped spheres: 48
=== Grouping into coalitions ===
Coalitions formed: 16, distinct coalition ids: 16
Coalition counts:
coalition
0 20
1 2
2 2
3 3
4 4
5 2
6 2
7 5
8 1
9 1
10 1
11 1
12 1
13 1
14 1
15 1
Name: count, dtype: int64
=== Writing station_spheres.geoparquet ===
Written 48 features.
=== Computing water overlaps ===
Combined water features: 16596
Water overlap features: 14212
=== Writing station_water_overlap.geoparquet ===
Written 14212 features.
=== Final sanity checks ===
station_spheres.geoparquet: 48 features, CRS={"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "ProjectedCRS", "name": "WGS 84 / Antarctic Polar Stereographic", "base_crs": {"name": "WGS 84", "datum_ensemble": {"name": "World Geodetic System 1984 ensemble", "members": [{"name": "World Geodetic System 1984 (Transit)"}, {"name": "World Geodetic System 1984 (G730)"}, {"name": "World Geodetic System 1984 (G873)"}, {"name": "World Geodetic System 1984 (G1150)"}, {"name": "World Geodetic System 1984 (G1674)"}, {"name": "World Geodetic System 1984 (G1762)"}, {"name": "World Geodetic System 1984 (G2139)"}, {"name": "World Geodetic System 1984 (G2296)"}], "ellipsoid": {"name": "WGS 84", "semi_major_axis": 6378137, "inverse_flattening": 298.257223563}, "accuracy": "2.0", "id": {"authority": "EPSG", "code": 6326}}, "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": 4326}}, "conversion": {"name": "Antarctic Polar Stereographic", "method": {"name": "Polar Stereographic (variant B)", "id": {"authority": "EPSG", "code": 9829}}, "parameters": [{"name": "Latitude of standard parallel", "value": -71, "unit": "degree", "id": {"authority": "EPSG", "code": 8832}}, {"name": "Longitude of origin", "value": 0, "unit": "degree", "id": {"authority": "EPSG", "code": 8833}}, {"name": "False easting", "value": 0, "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": "north", "meridian": {"longitude": 90}, "unit": "metre"}, {"name": "Northing", "abbreviation": "N", "direction": "north", "meridian": {"longitude": 0}, "unit": "metre"}]}, "scope": "Antarctic Digital Database and small scale topographic mapping.", "area": "Antarctica.", "bbox": {"south_latitude": -90, "west_longitude": -180, "north_latitude": -60, "east_longitude": 180}, "id": {"authority": "EPSG", "code": 3031}}
Columns: ['station_id', 'station_name', 'coalition', 'geometry']
Coalition distinct values: 16
Geometry types: <ArrowStringArray>
['MultiPolygon']
Length: 1, dtype: str
station_water_overlap.geoparquet: 14212 features, CRS={"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "ProjectedCRS", "name": "WGS 84 / Antarctic Polar Stereographic", "base_crs": {"name": "WGS 84", "datum_ensemble": {"name": "World Geodetic System 1984 ensemble", "members": [{"name": "World Geodetic System 1984 (Transit)"}, {"name": "World Geodetic System 1984 (G730)"}, {"name": "World Geodetic System 1984 (G873)"}, {"name": "World Geodetic System 1984 (G1150)"}, {"name": "World Geodetic System 1984 (G1674)"}, {"name": "World Geodetic System 1984 (G1762)"}, {"name": "World Geodetic System 1984 (G2139)"}, {"name": "World Geodetic System 1984 (G2296)"}], "ellipsoid": {"name": "WGS 84", "semi_major_axis": 6378137, "inverse_flattening": 298.257223563}, "accuracy": "2.0", "id": {"authority": "EPSG", "code": 6326}}, "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": 4326}}, "conversion": {"name": "Antarctic Polar Stereographic", "method": {"name": "Polar Stereographic (variant B)", "id": {"authority": "EPSG", "code": 9829}}, "parameters": [{"name": "Latitude of standard parallel", "value": -71, "unit": "degree", "id": {"authority": "EPSG", "code": 8832}}, {"name": "Longitude of origin", "value": 0, "unit": "degree", "id": {"authority": "EPSG", "code": 8833}}, {"name": "False easting", "value": 0, "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": "north", "meridian": {"longitude": 90}, "unit": "metre"}, {"name": "Northing", "abbreviation": "N", "direction": "north", "meridian": {"longitude": 0}, "unit": "metre"}]}, "scope": "Antarctic Digital Database and small scale topographic mapping.", "area": "Antarctica.", "bbox": {"south_latitude": -90, "west_longitude": -180, "north_latitude": -60, "east_longitude": 180}, "id": {"authority": "EPSG", "code": 3031}}
Columns: ['station_id', 'station_name', 'water_id', 'water_name', 'water_subtype', 'water_source', 'geometry']
water_source values: <ArrowStringArray>
['base.bathymetry', 'base.water']
Length: 2, dtype: str
Done!
20:54
The outputs look good! Let me verify the output files exist and do some more sanity checks: 1. `station_spheres.geoparquet` - 48 features, CRS EPSG:3031, columns: station_id, station_name, coalition, geometry (MultiPolygon). 16 distinct coalition IDs - more than 1, ✓ 2. `station_water_overlap.geoparquet` - 14212 features, CRS EPSG:3031, columns: station_id, station_name, water_id, water_name, water_subtype, water_source, geometry (MultiPolygon). water_source has both 'base.bathymetry' and 'base.water' ✓ Let me verify the files exist and do a quick spot check on the data.
20:54
20:54
Bash
ls -lh /work/station_spheres.geoparquet /work/station_water_overlap.geoparquet
-rw-r--r-- 1 agent agent 31M Jun 18 01:45 /work/station_spheres.geoparquet -rw-r--r-- 1 agent agent 48M Jun 18 01:45 /work/station_water_overlap.geoparquet
21:01
Let me verify the outputs more carefully: 1. `station_spheres.geoparquet` - has `station_id`, `station_name`, `coalition`, geometry with MultiPolygon type - coalition has 16 distinct values (>1 ✓) - CRS is EPSG:3031 ✓ - 48 features ✓ 2. `station_water_overlap.geoparquet` - has `station_id`, `station_name`, `water_id`, `water_name`, `water_subtype`, `water_source`, geometry with MultiPolygon type - water_source values are `base.water` and `base.bathymetry` ✓ - CRS is EPSG:3031 ✓ Let me do a quick spot check on a few stations to make sure the data looks right.
21:01
21:01
Bash
cd /work && python -c "
cd /work && python -c "
import geopandas as gpd
s1 = gpd.read_parquet('station_spheres.geoparquet')
print('=== station_spheres sample ===')
print(s1.head(10).to_string())
print()
s2 = gpd.read_parquet('station_water_overlap.geoparquet')
print('=== station_water_overlap sample ===')
print(s2.head(10).to_string())
print()
# Check specific station
for stn in ['McMurdo Station', 'Palmer Station', 'Base Esperanza']:
sub = s2[s2['station_name'] == stn]
print(f'{stn}: {len(sub)} water overlap features')
if len(sub) > 0:
print(f' water_source values: {sub[\"water_source\"].unique()}')
print(f' water_subtype values: {sub[\"water_subtype\"].unique()}')
"
=== station_spheres sample ===
station_id station_name coalition
[... truncated ...]6129.243, -94421.13 176219.574, -76678.469 184611.227, -58198.718 191223.388, -39159.847 195992.377, -19745.21 198872.266, -141.782 199835.321, 19461.646 198872.266, 38876.282 195992.377, 57915.153 191223.388, 76394.904 184611.227, 94137.565 176219.574, 110972.264 166129.243, 126736.874 154437.412, 141279.574 141256.677, 154460.308 126713.978, 166152.14 110949.368, 176242.471 94114.668, 184634.124 76372.007, 191246.285 57892.256, 196015.274 38853.385, 198895.163 19438.749, 199858.218 -164.679, 198895.163 -19768.107)))
2 23e81262-d6ed-45a3-a1a0-4bc6a2a887d8 Amundsen–Scott South Pole d1548a3a-2bc5-502a-bd2d-dd985969e9dd NaN base.bathymetry MULTIPOLYGON (((198895.163 -19768.107, 196015.274 -39182.743, 191246.285 -58221.614, 184634.124 -76701.365, 176242.471 -94444.026, 166152.14 -111278.726, 154460.308 -127043.336, 141279.574 -141586.035, 126736.874 -154766.77, 110972.264 -166458.601, 94137.565 -176548.932, 85482.349 -180642.544, 93589.026 -140112.009, 84187.457 -56269.591, 50594.837 -4989.799, 15194.438 8119.344, 161.518 389.831, -161.755 390.597, -15073.829 8058.316, -50189.075 -4940.835, -83515.863 -55799.373, -92853.525 -138957.74, -84393.081 -181291.846, -94421.13 -176548.932, -111255.829 -166458.601, -127020.439 -154766.77, -141563.139 -141586.035, -154743.873 -127043.336, -166435.705 -111278.726, -176526.035 -94444.026, -184917.689 -76701.365, -191529.85 -58221.614, -196298.838 -39182.743, -199178.728 -19768.107, -200141.782 -164.679, -199178.728 19438.749, -196298.838 38853.385, -191529.85 57892.256, -184917.689 76372.007, -176526.035 94114.668, -166435.705 110949.368, -154743.873 126713.978, -141563.139 141256.677, -127020.439 154437.412, -111255.829 166129.243, -94421.13 176219.574, -76678.469 184611.227, -58198.718 191223.388, -39159.847 195992.377, -19745.21 198872.266, -141.782 199835.321, 19461.646 198872.266, 38876.282 195992.377, 57915.153 191223.388, 76394.904 184611.227, 94137.565 176219.574, 110972.264 166129.243, 126736.874 154437.412, 141279.574 141256.677, 154460.308 126713.978, 166152.14 110949.368, 176242.471 94114.668, 184634.124 76372.007, 191246.285 57892.256, 196015.274 38853.385, 198895.163 19438.749, 199858.218 -164.679, 198895.163 -19768.107)))
3 23e81262-d6ed-45a3-a1a0-4bc6a2a887d8 Amundsen–Scott South Pole c10a3ab1-cda7-595c-8769-99cef4f67429 NaN base.bathymetry MULTIPOLYGON (((198895.163 -19768.107, 196015.274 -39182.743, 191246.285 -58221.614, 184634.124 -76701.365, 176242.471 -94444.026, 166152.14 -111278.726, 154460.308 -127043.336, 141279.574 -141586.035, 126736.874 -154766.77, 110972.264 -166458.601, 94993.134 -176036.123, 100197.556 -150005.63, 90121.747 -60235.978, 54146.32 -5340.056, 16243.595 8679.975, 161.518 389.831, -161.755 390.597, -15665.605 8374.674, -52192.509 -5138.062, -86863.796 -58036.224, -96582.367 -144538.05, -89744.557 -178760.786, -94421.13 -176548.932, -111255.829 -166458.601, -127020.439 -154766.77, -141563.139 -141586.035, -154743.873 -127043.336, -166435.705 -111278.726, -176526.035 -94444.026, -184917.689 -76701.365, -191529.85 -58221.614, -196298.838 -39182.743, -199178.728 -19768.107, -200141.782 -164.679, -199178.728 19438.749, -196298.838 38853.385, -191529.85 57892.256, -184917.689 76372.007, -176526.035 94114.668, -166435.705 110949.368, -154743.873 126713.978, -141563.139 141256.677, -127020.439 154437.412, -111255.829 166129.243, -94421.13 176219.574, -76678.469 184611.227, -58198.718 191223.388, -39159.847 195992.377, -19745.21 198872.266, -141.782 199835.321, 19461.646 198872.266, 38876.282 195992.377, 57915.153 191223.388, 76394.904 184611.227, 94137.565 176219.574, 110972.264 166129.243, 126736.874 154437.412, 141279.574 141256.677, 154460.308 126713.978, 166152.14 110949.368, 176242.471 94114.668, 184634.124 76372.007, 191246.285 57892.256, 196015.274 38853.385, 198895.163 19438.749, 199858.218 -164.679, 198895.163 -19768.107)))
4 23e81262-d6ed-45a3-a1a0-4bc6a2a887d8 Amundsen–Scott South Pole 002c89a3-1f5e-56ee-a399-a4bb9cf6d081 NaN base.bathymetry MULTIPOLYGON (((198895.163 -19768.107, 196015.274 -39182.743, 191246.285 -58221.614, 184634.124 -76701.365, 176242.471 -94444.026, 166152.14 -111278.726, 164875.268 -113000.388, 164533.007 -109971.25, 98675.533 -9731.621, 29397.007 15708.68, 161 388.582, -161.352 389.625, -26854.737 14356.265, -90075.187 -8867.413, -150173.071 -100335.027, -153364.789 -128564.921, -154743.873 -127043.336, -166435.705 -111278.726, -176526.035 -94444.026, -184917.689 -76701.365, -191529.85 -58221.614, -196298.838 -39182.743, -199178.728 -19768.107, -200141.782 -164.679, -199178.728 19438.749, -196298.838 38853.385, -191529.85 57892.256, -184917.689 76372.007, -176526.035 94114.668, -166435.705 110949.368, -154743.873 126713.978, -141563.139 141256.677, -127020.439 154437.412, -111255.829 166129.243, -94421.13 176219.574, -76678.469 184611.227, -58198.718 191223.388, -39159.847 195992.377, -19745.21 198872.266, -141.782 199835.321, 19461.646 198872.266, 38876.282 195992.377, 57915.153 191223.388, 76394.904 184611.227, 94137.565 176219.574, 110972.264 166129.243, 126736.874 154437.412, 141279.574 141256.677, 154460.308 126713.978, 166152.14 110949.368, 176242.471 94114.668, 184634.124 76372.007, 191246.285 57892.256, 196015.274 38853.385, 198895.163 19438.749, 199858.218 -164.679, 198895.163 -19768.107)))
5 23e81262-d6ed-45a3-a1a0-4bc6a2a887d8 Amundsen–Scott South Pole d8eecaa0-c85c-59c2-94c3-e31c00a8fdd7 NaN base.bathymetry MULTIPOLYGON (((198895.163 -19768.107, 196015.274 -39182.743, 191246.285 -58221.614, 184634.124 -76701.365, 184398.52 -77199.509, 142896.754 -14092.891, 42462.93 22690.604, 162.893 393.149, -162.824 393.178, -29574.079 15810.006, -99275.187 -9773.087, -165546.714 -110606.581, -165730.393 -112229.729, -166435.705 -111278.726, -176526.035 -94444.026, -184917.689 -76701.365, -191529.85 -58221.614, -196298.838 -39182.743, -199178.728 -19768.107, -200141.782 -164.679, -199178.728 19438.749, -196298.838 38853.385, -191529.85 57892.256, -184917.689 76372.007, -176526.035 94114.668, -166435.705 110949.368, -154743.873 126713.978, -141563.139 141256.677, -127020.439 154437.412, -111255.829 166129.243, -94421.13 176219.574, -76678.469 184611.227, -58198.718 191223.388, -39159.847 195992.377, -19745.21 198872.266, -141.782 199835.321, 19461.646 198872.266, 38876.282 195992.377, 57915.153 191223.388, 76394.904 184611.227, 94137.565 176219.574, 110972.264 166129.243, 126736.874 154437.412, 141279.574 141256.677, 154460.308 126713.978, 166152.14 110949.368, 176242.471 94114.668, 184634.124 76372.007, 191246.285 57892.256, 196015.274 38853.385, 198895.163 19438.749, 199858.218 -164.679, 198895.163 -19768.107)))
6 23e81262-d6ed-45a3-a1a0-4bc6a2a887d8 Amundsen–Scott South Pole c5dba2bc-a386-5655-afec-6fab1456dcb1 NaN base.bathymetry MULTIPOLYGON (((198895.163 -19768.107, 196015.274 -39182.743, 191246.285 -58221.614, 184634.124 -76701.365, 176242.471 -94444.026, 166152.14 -111278.726, 165973.196 -111520.003, 165901.539 -110885.874, 99493.9 -9812.297, 29638.181 15837.566, 160.668 387.78, -161.094 389.001, -29396.393 15715.003, -98681.306 -9714.645, -164556.83 -109945.229, -164936.481 -113300.195, -166435.705 -111278.726, -176526.035 -94444.026, -184917.689 -76701.365, -191529.85 -58221.614, -196298.838 -39182.743, -199178.728 -19768.107, -200141.782 -164.679, -199178.728 19438.749, -196298.838 38853.385, -191529.85 57892.256, -184917.689 76372.007, -176526.035 94114.668, -166435.705 110949.368, -154743.873 126713.978, -141563.139 141256.677, -127020.439 154437.412, -111255.829 166129.243, -94421.13 176219.574, -76678.469 184611.227, -58198.718 191223.388, -39159.847 195992.377, -19745.21 198872.266, -141.782 199835.321, 19461.646 198872.266, 38876.282 195992.377, 57915.153 191223.388, 76394.904 184611.227, 94137.565 176219.574, 110972.264 166129.243, 126736.874 154437.412, 141279.574 141256.677, 154460.308 126713.978, 166152.14 110949.368, 176242.471 94114.668, 184634.124 76372.007, 191246.285 57892.256, 196015.274 38853.385, 198895.163 19438.749, 199858.218 -164.679, 198895.163 -19768.107)))
7 23e81262-d6ed-45a3-a1a0-4bc6a2a887d8 Amundsen–Scott South Pole 2ca98fcf-27c9-5086-ac07-1729ffe0546e NaN base.bathymetry MULTIPOLYGON (((198895.163 -19768.107, 196015.274 -39182.743, 191246.285 -58221.614, 184634.124 -76701.365, 176242.471 -94444.026, 166152.14 -111278.726, 154460.308 -127043.336, 151054.4 -130801.177, 147411.434 -98527.271, 88429.216 -8721.033, 26369.432 14090.878, 160.553 387.503, -161.005 388.786, -26060.62 13931.727, -87388.19 -8602.914, -145682.924 -97335.062, -149673.189 -132637.974, -154743.873 -127043.336, -166435.705 -111278.726, -176526.035 -94444.026, -184917.689 -76701.365, -191529.85 -58221.614, -196298.838 -39182.743, -199178.728 -19768.107, -200141.782 -164.679, -199178.728 19438.749, -196298.838 38853.385, -191529.85 57892.256, -184917.689 76372.007, -176526.035 94114.668, -166435.705 110949.368, -154743.873 126713.978, -141563.139 141256.677, -127020.439 154437.412, -111255.829 166129.243, -94421.13 176219.574, -76678.469 184611.227, -58198.718 191223.388, -39159.847 195992.377, -19745.21 198872.266, -141.782 199835.321, 19461.646 198872.266, 38876.282 195992.377, 57915.153 191223.388, 76394.904 184611.227, 94137.565 176219.574, 110972.264 166129.243, 126736.874 154437.412, 141279.574 141256.677, 154460.308 126713.978, 166152.14 110949.368, 176242.471 94114.668, 184634.124 76372.007, 191246.285 57892.256, 196015.274 38853.385, 198895.163 19438.749, 199858.218 -164.679, 198895.163 -19768.107)))
8 23e81262-d6ed-45a3-a1a0-4bc6a2a887d8 Amundsen–Scott South Pole d97068b2-8f46-5a0e-9a93-803579a73525 NaN base.bathymetry MULTIPOLYGON (((198895.163 -19768.107, 196015.274 -39182.743, 191246.285 -58221.614, 184634.124 -76701.365, 176242.471 -94444.026, 166152.14 -111278.726, 154460.308 -127043.336, 149051.635 -133010.887, 144976.189 -96899.623, 86971.943 -8577.32, 25938.946 13860.841, 160.553 387.503, -161.005 388.786, -18165.913 9711.302, -60660.554 -5971.714, -101016.027 -67491.773, -112088.119 -165841.333, -127020.439 -154766.77, -141563.139 -141586.035, -154743.873 -127043.336, -166435.705 -111278.726, -176526.035 -94444.026, -184917.689 -76701.365, -191529.85 -58221.614, -196298.838 -39182.743, -199178.728 -19768.107, -200141.782 -164.679, -199178.728 19438.749, -196298.838 38853.385, -191529.85 57892.256, -184917.689 76372.007, -176526.035 94114.668, -166435.705 110949.368, -154743.873 126713.978, -141563.139 141256.677, -127020.439 154437.412, -111255.829 166129.243, -94421.13 176219.574, -76678.469 184611.227, -58198.718 191223.388, -39159.847 195992.377, -19745.21 198872.266, -141.782 199835.321, 19461.646 198872.266, 38876.282 195992.377, 57915.153 191223.388, 76394.904 184611.227, 94137.565 176219.574, 110972.264 166129.243, 126736.874 154437.412, 141279.574 141256.677, 154460.308 126713.978, 166152.14 110949.368, 176242.471 94114.668, 184634.124 76372.007, 191246.285 57892.256, 196015.274 38853.385, 198895.163 19438.749, 199858.218 -164.679, 198895.163 -19768.107)))
9 23e81262-d6ed-45a3-a1a0-4bc6a2a887d8 Amundsen–Scott South Pole 5637be2d-a08a-59c9-8239-d900a3bc3212 NaN base.bathymetry MULTIPOLYGON (((198895.163 -19768.107, 196015.274 -39182.743, 191246.285 -58221.614, 189284.097 -63705.563, 157602.609 -15543.301, 46804.384 25010.479, 161.074 388.758, -160.485 387.532, -30966.523 16554.439, -104003.045 -10238.386, -168337.665 -108105.497, -176526.035 -94444.026, -184917.689 -76701.365, -191529.85 -58221.614, -196298.838 -39182.743, -199178.728 -19768.107, -200141.782 -164.679, -199178.728 19438.749, -196298.838 38853.385, -191529.85 57892.256, -184917.689 76372.007, -176526.035 94114.668, -166435.705 110949.368, -154743.873 126713.978, -141563.139 141256.677, -127020.439 154437.412, -111255.829 166129.243, -94421.13 176219.574, -76678.469 184611.227, -58198.718 191223.388, -39159.847 195992.377, -19745.21 198872.266, -141.782 199835.321, 19461.646 198872.266, 38876.282 195992.377, 57915.153 191223.388, 76394.904 184611.227, 94137.565 176219.574, 110972.264 166129.243, 126736.874 154437.412, 141279.574 141256.677, 154460.308 126713.978, 166152.14 110949.368, 176242.471 94114.668, 184634.124 76372.007, 191246.285 57892.256, 196015.274 38853.385, 198895.163 19438.749, 199858.218 -164.679, 198895.163 -19768.107)))
McMurdo Station: 817 water overlap features
water_source values: <ArrowStringArray>
['base.water', 'base.bathymetry']
Length: 2, dtype: str
water_subtype values: <ArrowStringArray>
['physical', 'lake', 'pond', 'ocean', 'water', '']
Length: 6, dtype: str
Palmer Station: 166 water overlap features
water_source values: <ArrowStringArray>
['base.water', 'base.bathymetry']
Length: 2, dtype: str
water_subtype values: <ArrowStringArray>
['ocean', 'human_made', 'physical', '']
Length: 4, dtype: str
Base Esperanza: 596 water overlap features
water_source values: <ArrowStringArray>
['base.water', 'base.bathymetry']
Length: 2, dtype: str
water_subtype values: <ArrowStringArray>
['physical', 'ocean', 'lake', 'water', 'pond', 'stream', '']
Length: 7, dtype: str
21:15
The output looks good! Let me verify a few things: 1. `station_spheres.geoparquet` - Has station_id, station_name, coalition (and coalition has more than one distinct value - 16 distinct values). Geometry is MultiPolygon. CRS is EPSG:3031. ✓ 2. `station_water_overlap.geoparquet` - Has station_id, station_name, water_id, water_name, water_subtype, water_source. water_source values are 'base.bathymetry' and 'base.water'. Geometry is MultiPolygon. CRS is EPSG:3031. ✓ Let me also check if the station_name column appears correctly for each station in the spheres file, and that all stations have at least some land clipping. Wait, looking at the output, the spheres file has "coalition" values that are integers. Let me also verify the station_water_overlap file has the water_name column populated properly (some are NaN, which is fine - not all water features have names). Let me verify both files are in proper MultiPolygon geometry format.
21:15
21:15
Bash
cd /work && python -c "
cd /work && python -c "
import geopandas as gpd
# Check station_spheres
s1 = gpd.read_parquet('station_spheres.geoparquet')
print('=== station_spheres.geoparquet ===')
print(f'Rows: {len(s1)}')
print(f'CRS: {s1.crs}')
print(f'Columns: {list(s1.columns)}')
print(f'Geometry types: {s1.geom_type.unique()}')
print(f'Coalition distinct: {s1[\"coalition\"].nunique()}')
print(f'Coalition values: {sorted(s1[\"coalition\"].unique())}')
print(f'Null station_id: {s1[\"station_id\"].isna().sum()}')
print(f'Null station_name: {s1[\"station_name\"].isna().sum()}')
print()
# Check station_water_overlap
s2 = gpd.read_parquet('station_water_overlap.geoparquet')
print('=== station_water_overlap.geoparquet ===')
print(f'Rows: {len(s2)}')
print(f'CRS: {s2.crs}')
print(f'Columns: {list(s2.columns)}')
print(f'Geometry types: {s2.geom_type.unique()}')
print(f'water_source values: {list(s2[\"water_source\"].unique())}')
print(f'Null station_id: {s2[\"station_id\"].isna().sum()}')
print(f'Null station_name: {s2[\"station_name\"].isna().sum()}')
print(f'Null water_id: {s2[\"water_id\"].isna().sum()}')
print(f'Null water_subtype: {s2[\"water_subtype\"].isna().sum()}')
print(f'Null water_name: {s2[\"water_name\"].isna().sum()}')
print(f'Sample water_name values (non-null): {list(s2[s2[\"water_name\"].notna()][\"water_name\"].head(10))}')
# Check that all stations from spheres appear in water overlap
stations_in_spheres = set(s1['station_id'].unique())
stations_in_water = set(s2['station_id'].unique())
missing = stations_in_spheres - stations_in_water
print(f'\nStations in spheres but NOT in water overlap: {len(missing)}')
if missing:
print(f' {missing}')
"
=== station_spheres.geoparquet ===
Rows: 48
CRS: {"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "ProjectedCRS", "name": "WGS 84 / Antarctic Polar Stereographic", "base_crs": {"name": "WGS 84", "datum_ensemble": {"name": "World Geodetic System 1984 ensemble", "members": [{"name": "World Geodetic System 1984 (Transit)"}, {"name": "World Geodetic System 1984 (G730)"}, {"name": "World Geodetic System 1984 (G873)"}, {"name": "World Geodetic System 1984 (G1150)"}, {"name": "World Geodetic System 1984 (G1674)"}, {"name": "World Geodetic System 1984 (G1762)"}, {"name": "World Geodetic System 1984 (G2139)"}, {"name": "World Geodetic System 1984 (G2296)"}], "ellipsoid": {"name": "WGS 84", "semi_major_axis": 6378137, "inverse_flattening": 298.257223563}, "accuracy": "2.0", "id": {"authority": "EPSG", "code": 6326}}, "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": 4326}}, "conversion": {"name": "Antarctic Polar Stereographic", "method": {"name": "Polar Stereographic (variant B)", "id": {"authority": "EPSG", "code": 9829}}, "parameters": [{"name": "Latitude of standard parallel", "value": -71, "unit": "degree", "id": {"authority": "EPSG", "code": 8832}}, {"name": "Longitude of origin", "value": 0, "unit": "degree", "id": {"authority": "EPSG", "code": 8833}}, {"name": "False easting", "value": 0, "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": "north", "meridian": {"longitude": 90}, "unit": "metre"}, {"name": "Northing", "abbreviation": "N", "direction": "north", "meridian": {"longitude": 0}, "unit": "metre"}]}, "scope": "Antarctic Digital Database and small scale topographic mapping.", "area": "Antarctica.", "bbox": {"south_latitude": -90, "west_longitude": -180, "north_latitude": -60, "east_longitude": 180}, "id": {"authority": "EPSG", "code": 3031}}
Columns: ['station_id', 'station_name', 'coalition', 'geometry']
Geometry types: <ArrowStringArray>
['MultiPolygon']
Length: 1, dtype: str
Coalition distinct: 16
Coalition values: [np.int64(0), np.int64(1), np.int64(2), np.int64(3), np.int64(4), np.int64(5), np.int64(6), np.int64(7), np.int64(8), np.int64(9), np.int64(10), np.int64(11), np.int64(12), np.int64(13), np.int64(14), np.int64(15)]
Null station_id: 0
Null station_name: 0
=== station_water_overlap.geoparquet ===
Rows: 14212
CRS: {"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "ProjectedCRS", "name": "WGS 84 / Antarctic Polar Stereographic", "base_crs": {"name": "WGS 84", "datum_ensemble": {"name": "World Geodetic System 1984 ensemble", "members": [{"name": "World Geodetic System 1984 (Transit)"}, {"name": "World Geodetic System 1984 (G730)"}, {"name": "World Geodetic System 1984 (G873)"}, {"name": "World Geodetic System 1984 (G1150)"}, {"name": "World Geodetic System 1984 (G1674)"}, {"name": "World Geodetic System 1984 (G1762)"}, {"name": "World Geodetic System 1984 (G2139)"}, {"name": "World Geodetic System 1984 (G2296)"}], "ellipsoid": {"name": "WGS 84", "semi_major_axis": 6378137, "inverse_flattening": 298.257223563}, "accuracy": "2.0", "id": {"authority": "EPSG", "code": 6326}}, "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": 4326}}, "conversion": {"name": "Antarctic Polar Stereographic", "method": {"name": "Polar Stereographic (variant B)", "id": {"authority": "EPSG", "code": 9829}}, "parameters": [{"name": "Latitude of standard parallel", "value": -71, "unit": "degree", "id": {"authority": "EPSG", "code": 8832}}, {"name": "Longitude of origin", "value": 0, "unit": "degree", "id": {"authority": "EPSG", "code": 8833}}, {"name": "False easting", "value": 0, "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": "north", "meridian": {"longitude": 90}, "unit": "metre"}, {"name": "Northing", "abbreviation": "N", "direction": "north", "meridian": {"longitude": 0}, "unit": "metre"}]}, "scope": "Antarctic Digital Database and small scale topographic mapping.", "area": "Antarctica.", "bbox": {"south_latitude": -90, "west_longitude": -180, "north_latitude": -60, "east_longitude": 180}, "id": {"authority": "EPSG", "code": 3031}}
Columns: ['station_id', 'station_name', 'water_id', 'water_name', 'water_subtype', 'water_source', 'geometry']
Geometry types: <ArrowStringArray>
['MultiPolygon']
Length: 1, dtype: str
water_source values: ['base.bathymetry', 'base.water']
Null station_id: 0
Null station_name: 0
Null water_id: 0
Null water_subtype: 0
Null water_name: 10499
Sample water_name values (non-null): ['Bellingshausen Sea', 'Bellingshausen Sea', 'Hot Tub', 'Port-Charcot', 'Flanders Bay', 'Oscar Pinochet Strait', 'Gerritsz Bay', 'Neko Harbour', 'Buls Bay', 'Canal Almirante Merino']
Stations in spheres but NOT in water overlap: 0
21:22
Everything looks good! Let me verify the outputs match all requirements: **station_spheres.geoparquet:** - ✅ Land-clipped station zones (clipped to Antarctic landmass) - ✅ Grouped into coalitions wherever they overlap (16 coalitions, coalition column has 16 distinct values) - ✅ Each feature has `station_id` and `station_name` - ✅ `coalition` integer id, more than one distinct value (16 distinct) - ✅ MultiPolygon geometry - ✅ EPSG:3031 projected CRS (Antarctic Polar Stereographic) **station_water_overlap.geoparquet:** - ✅ Over-water portion of each station's zone - ✅ Attributed with water features it intersects - ✅ Each row has `station_id`, `station_name`, `water_id`, `water_name`, `water_subtype`, `water_source` - ✅ `water_source` values are `base.water` or `base.bathymetry` - ✅ MultiPolygon geometry - ✅ EPSG:3031 projected CRS Let me verify the file listing.
21:22
21:22
Bash
ls -lh /work/station_spheres.geoparquet /work/station_water_overlap.geoparquet
-rw-r--r-- 1 agent agent 31M Jun 18 01:45 /work/station_spheres.geoparquet -rw-r--r-- 1 agent agent 48M Jun 18 01:45 /work/station_water_overlap.geoparquet
21:33
Everything looks good. Let me summarize what was done.
21:33