Screening NSW for data-centre land with a solar co-location check
A published agent run. Every NSW parcel screened for data-centre land on zoning, lot size, distance to 330 kV transmission and a substation, a sealed arterial, residents within two kilometres, a town of 5,000 to 50,000 within thirty, slope and flood planning, with the thirty-year solar resource read at each lot.
Zenancy
This is one run, on 3 September 2026, published as it came out of the app. Five of its nineteen calls failed, two of them the agent's own publishing checks rejecting its report, and one figure in the final report disagrees with the table beside it. It is published unedited, and the disagreement is named below.
The prompt
The prompt, as typed
›
Screen NSW for data-centre land: rural- or industrial-zoned lots of 20 ha or more, within 5 km of a 330 kV or higher transmission line and 15 km of a transmission substation, within 3 km of a sealed arterial or highway, with fewer than 200 residents within 2 km but within 30 km of a town of 5,000 to 50,000 people. Exclude flood planning land and slope over 5 degrees, flag bushfire-prone land, and add the 30-year mean daily solar exposure so the same site could carry a co-located solar farm. Rank by area and map the top 25 with the transmission lines and substations.
Datasetsparcel_profiletransmission
19 tool calls39s analysis2 datasets
The prompt has nine tests and one flag. Zoning, lot size, slope and flood planning are parcel attributes. Distance to a 330 kV line, to a transmission substation and to a sealed arterial are proximity measures. Residents within two kilometres is a population sum. The town test needs the nearest town in a population band, not the nearest town. Solar exposure is a climate normal. None of these is a join the agent had to build. Each is a column on the parcel table, and the run is one filter over that table.
That is the point of the run. An earlier screen of this shape, published on this site, spent six failed calls and five minutes rebuilding a transmission distance and a neighbour count that the library already held. After that run the columns were named in the library and the packs, and this run reads them.
What the agent did
Loaded expertiseLoaded expertise: data-centre land screening.
Describe`parcel_profile` — 3,354,329 rows across 1 file(s). Columns: parcel_id BYTE_ARRAY, lot BYTE_ARRAY, plan_label BYTE_ARRAY, lat DOUBLE, lng DOUBLE, h3_r9 BYTE_ARRAY, area_m2 DOUBLE, area_source BYTE_ARR1.8s
Ran a cell in the sandboxexited 1: LINE 17: ), both AS (failed · 36s
Ran a cell in the sandbox┌───────┐1.8s
Rendered a tableTOOL ERROR: column "H3 R9" shows the reader the plumbing ("H3" → areas) — alias it in the SQL (`count(*) AS "Land areas"`). Re-run the query with the column aliased and render the result — a documentfailed
Rendered a mapRendered `data_2` as a points map titled "NSW data-centre land screen — top 25 lots by area" (25 features). Before placing it in a document: "NSW data-centre land screen — top 25 lots by area" measure
Rendered a mapRendered `data_3` as a cells map titled "Transmission context for the top 25 screened lots" (43 features).
Ran a cell in the sandboxexited 1: SyntaxError: unterminated string literal (detected at line 3)failed
Ran a cell in the sandbox┌─────────────────────────────┬─────────┬────────────────┬───┬───────────────────┬──────────────────┬──────────────────┐
Rendered a tableRendered `data_4` as a table (25 rows) titled "NSW data-centre land screen — top 25 lots by area". Note — a document may reject this table as it stands (an id first column or a plumbing header always;
Ran a cell in the sandbox┌───────┬─────────────┬────────────┐
Rendered a tableRendered `data_5` as a table (12 rows) titled "NSW data-centre land screen — 12 largest qualifying lots".
Wrote the documentTOOL ERROR: this document is not publishable yet — 4 things to fix:failed
Rendered a tableRendered `data_1` as a table (8 rows) titled "NSW data-centre land screen funnel".
Wrote the documentTOOL ERROR: this document is not publishable yet — 4 things to fix:failed
Rendered a mapRendered `data_2` as a points map titled "Top 25 qualifying NSW parcels by area" (25 features).
Rendered a mapRendered `data_3` as a cells map titled "High-voltage transmission and substations near the top 25 parcels" (43 features).
Wrote the documentRendered a report titled "NSW data-centre land screen" embedding 4 blocks: data_1 (table), data_5 (table), data_2 (map), data_3 (map). Their standalone copies from this turn have been removed — this r
5 calls failed and the agent recovered within the same run. Failures are shown because they happened.
Nineteen calls, five failed. The first query failed on a SQL syntax error in a common table expression. The first table render was rejected by the publishing check for showing a column called H3 R9. A Python cell failed on an unterminated string. The report was then rejected twice by its own checks, each time with four things to fix, before the third version passed. The analysis itself took under forty seconds of tool time; the run took just under three minutes end to end.
Result
NSW data-centre land screen
The NSW screen leaves 3,999 qualifying lots from 3,354,329 parcel records after the rural or industrial, size, grid, road, population, town, slope and flood-planning tests. The 25 largest range from 605.8 ha to 2,128.5 ha; bushfire-prone land is flagged on 3,562, while 3,071 remain unassessed by the flood-planning map.
Key findings
The final shortlist contains 3,999 lots, compared with 282,366 lots meeting only the rural or industrial, 20 ha and non-strata conditions.
The grid funnel leaves 27,686 lots near a 330 kV or higher line and 18,424 after the 15 km substation test, compared with 282,366 before infrastructure filters.
The 25 largest screened lots range from 605.8 ha to 2,128.5 ha, while the 12-row shortlist ranges from 734.9 ha to 2,128.5 ha.
Bushfire-prone land affects 3,562 of 3,999 final lots, whereas 3,071 are unassessed by the flood-planning map rather than confirmed outside it.
The full screen retains 3,999 lots against 3,354,329 source parcels
The cumulative funnel begins with 3,354,329 NSW parcel records and retains 282,366 rural or industrial non-strata lots of at least 20 ha. The grid test reduces that group to 27,686 lots within 5 km of a 330 kV or higher line and 18,424 also within 15 km of a transmission substation. The road and settlement tests reduce it further to 5,589 lots before the slope and flood-planning conditions leave 3,999. These are parcel counts, not hectares, and the final pool is 1.2 per cent of the source records.
NSW data-centre land screen funnel
Screen stage
Lots remaining
Median area of final lots (ha)
Minimum solar exposure (kWh/m²/day)
Maximum solar exposure (kWh/m²/day)
Bushfire-prone lots
Flood-planning unassessed lots
NSW parcels in source
3,354,329
—
—
—
—
—
Rural or industrial, >=20 ha, non-strata
282,366
—
—
—
—
—
Also within 5 km of 330 kV+ line
27,686
—
—
—
—
—
Also within 15 km of transmission substation
18,424
—
—
—
—
—
Also within 3 km of sealed arterial/highway
9,225
—
—
—
—
—
Also under 200 residents in 2 km screen
7,919
—
—
—
—
—
Also within 30 km of 5,000-50,000 town
5,589
—
—
—
—
—
Final screened lots
3,999
41.6
4.24
5.19
3,562
3,071
Cumulative NSW parcel-screen stages and final solar, bushfire and flood-assessment counts · NSW parcel profile · current catalogue vintage, solar normal 1991–2020
The largest presented lots are 734.9 to 2,128.5 hectares
The 12-row shortlist is ordered by parcel area, with the largest lot at 2,128.5 ha and the smallest presented lot at 734.9 ha. The 12 presented lots therefore sit entirely above the requested 20 ha threshold, while the table retains the nearest high-voltage line and substation distances, road distance, sparse-population result, qualifying town, slope and solar exposure. Area is a ranking measure, not a combined suitability score.
NSW data-centre land screen — 12 largest qualifying lots
Suburb
Local government area
Zone
Zone name
Area (ha)
Nearest 330 kV+ line (km)
Nearest transmission substation (km)
Nearest sealed arterial/highway (km)
Residents in 2 km screen
Nearest qualifying town
Town distance (km)
Solar exposure (kWh/m²/day)
Bushfire-prone
Flood-planning status
Lot/DP
Mallee
Wentworth
RU1
Primary Production
2,128.5
0.99
3.44
2.96
0.1
Mildura - Buronga (Mildura Part)
10.98
5.16
true
assessed: outside mapped flood planning land
2//DP1182353
Wallerawang
Lithgow
RU3
Forestry
1,467.5
1.37
6
1.33
3.8
Lithgow
6.95
4.61
true
unassessed by this flood planning layer
7071//DP1201227
Coombell
Richmond Valley
RU3
Forestry
1,278.8
4.1
6.03
1.31
0.5
Casino
18.73
4.94
true
unassessed by this flood planning layer
42//DP1210739
Kremnos
Clarence Valley
RU2
Rural Landscape
1,255.4
0.38
14.16
2.74
24.3
Woolgoolga
22.73
4.89
true
assessed: outside mapped flood planning land
742//DP621467
Penrose
Wingecarribee
RU3
Forestry
1,231.3
3.98
14.66
1.75
0.6
Moss Vale
16.21
4.45
true
assessed: outside mapped flood planning land
7031//DP1202090
Ellangowan (NSW)
Richmond Valley
RU3
Forestry
1,171.2
1.74
5.12
0.76
9.2
Casino
19.44
4.94
true
unassessed by this flood planning layer
13//DP1209388
Bungendore
Queanbeyan-Palerang
RU1
Primary Production
1,075.2
4.97
2.03
1.66
126.5
Canberra - Queanbeyan (Queanbeyan Part)
16.82
4.71
true
unassessed by this flood planning layer
3//DP876579
Ravensworth (NSW)
Singleton
RU1
Primary Production
845.6
2.5
10.18
0.66
0.4
Singleton
13.44
4.8
true
unassessed by this flood planning layer
10//DP1204457
Lemington
Singleton
RU1
Primary Production
821.8
0.38
8.1
2.32
2.5
Muswellbrook
18.62
4.86
true
unassessed by this flood planning layer
1//DP1112847
Lanitza
Clarence Valley
RU2
Rural Landscape
794.1
4.6
13.41
1.74
33.7
Grafton
15.36
4.93
true
assessed: outside mapped flood planning land
165//DP789434
Swan Vale
Inverell
RU1
Primary Production
746.7
0.38
6.78
1.99
3.9
Inverell
26.18
5.18
true
unassessed by this flood planning layer
1//DP1188925
Bungendore
Queanbeyan-Palerang
RU1
Primary Production
734.9
3.31
3.7
1.67
18.7
Canberra - Queanbeyan (Queanbeyan Part)
27.52
4.68
true
unassessed by this flood planning layer
2//DP1039100
The 12 largest qualifying NSW lots by area, with grid, road, population, town, slope, bushfire, flood-planning and solar-screen attributes · NSW parcel and infrastructure data · current catalogue vintage, solar normal 1991–2020
The top 25 span 605.8 to 2,128.5 hectares and retain material constraint flags
The 25-lot map covers the 605.8–2,128.5 ha range. The accompanying grid-context map identifies 330 kV or higher transmission-line areas intersecting the shortlist and substation areas within 15 km. Bushfire-prone land affects 3,562 of the 3,999 final lots, compared with 437 not flagged; flood-planning status is less complete because 3,071 are unassessed rather than cleared. These figures support proximity screening, not connection capacity or flood safety. Solar exposure across the final pool ranges from 4.45 to 5.19 kWh/m²/day.
Top 25 qualifying NSW parcels by area
The 25 largest qualifying parcels, ranked by land area · NSW parcel screen · current catalogue vintageHigh-voltage transmission and substations near the top 25 parcels
Mapped 330 kV or higher transmission-line areas intersecting the shortlist and substations within 15 km · NSW transmission data · current catalogue vintage1 more figure the agent rendered on the way, which its report did not place
NSW data-centre land screen — top 25 lots by area
Lot/parcel ID
Lot
Plan
Suburb
Local government area
Zone
Zone name
Area (ha)
Nearest 330 kV+ line (km)
Nearest line voltage (kV)
Nearest transmission substation (km)
Nearest sealed arterial/highway (km)
Nearest sealed arterial/highway
Residents in 2 km screen
Population screen method
Nearest 5,000–50,000 town (km)
Nearest qualifying town
Remoteness class
Slope (degrees)
Elevation (m AHD)
Solar exposure (kWh/m²/day)
Bushfire-prone
Flood-planning status
Mapped land use
2
DP1182353
Mallee
Wentworth
RU1
Primary Production
2,128.5
0.99
330
3.44
2.96
Arumpo Road
0.1
sampled
10.98
Mildura - Buronga (Mildura Part)
remote
0.62
59.04
5.16
true
assessed: outside mapped flood planning land
Cropping
7071
DP1201227
Wallerawang
Lithgow
RU3
Forestry
1,467.5
1.37
330
6
1.33
Great Western Highway
3.8
exact
6.95
Lithgow
inner_regional
4.4
960.87
4.61
true
unassessed by this flood planning layer
Production native forests
42
DP1210739
Coombell
Richmond Valley
RU3
Forestry
1,278.8
4.1
66
6.03
1.31
Summerland Way
0.5
exact
18.73
Casino
outer_regional
3.23
81.06
4.94
true
unassessed by this flood planning layer
Production native forests
742
DP621467
Kremnos
Clarence Valley
RU2
Rural Landscape
1,255.4
0.38
330
14.16
2.74
Orara Way
24.3
exact
22.73
Woolgoolga
inner_regional
3.98
213.01
4.89
true
assessed: outside mapped flood planning land
Other minimal use
7031
DP1202090
Penrose
Wingecarribee
RU3
Forestry
1,231.3
3.98
330
14.66
1.75
Hume Highway
0.6
exact
16.21
Moss Vale
inner_regional
4.13
673.61
4.45
true
assessed: outside mapped flood planning land
Plantation forests
13
DP1209388
Ellangowan (NSW)
Richmond Valley
RU3
Forestry
1,171.2
1.74
66
5.12
0.76
Summerland Way
9.2
exact
19.44
Casino
inner_regional
3.21
69.64
4.94
true
unassessed by this flood planning layer
Production native forests
3
DP876579
Bungendore
Queanbeyan-Palerang
RU1
Primary Production
1,075.2
4.97
66
2.03
1.66
Molonglo Street
126.5
exact
16.82
Canberra - Queanbeyan (Queanbeyan Part)
inner_regional
0.57
695.6
4.71
true
unassessed by this flood planning layer
Grazing modified pastures
10
DP1204457
Ravensworth (NSW)
Singleton
RU1
Primary Production
845.6
2.5
132
10.18
0.66
New England Highway
0.4
exact
13.44
Singleton
inner_regional
4.66
110.53
4.8
true
unassessed by this flood planning layer
Mining
1
DP1112847
Lemington
Singleton
RU1
Primary Production
821.8
0.38
330
8.1
2.32
Jerrys Plains Road
2.5
exact
18.62
Muswellbrook
inner_regional
4.69
123.94
4.86
true
unassessed by this flood planning layer
Grazing native vegetation
165
DP789434
Lanitza
Clarence Valley
RU2
Rural Landscape
794.1
4.6
132
13.41
1.74
Orara Way
33.7
exact
15.36
Grafton
inner_regional
2.51
47.43
4.93
true
assessed: outside mapped flood planning land
Grazing native vegetation
1
DP1188925
Swan Vale
Inverell
RU1
Primary Production
746.7
0.38
330
6.78
1.99
Gwydir Highway
3.9
exact
26.18
Inverell
outer_regional
3
753.61
5.18
true
unassessed by this flood planning layer
Cropping
2
DP1039100
Bungendore
Queanbeyan-Palerang
RU1
Primary Production
734.9
3.31
66
3.7
1.67
Tarago Road
18.7
exact
27.52
Canberra - Queanbeyan (Queanbeyan Part)
inner_regional
2.69
730.86
4.68
true
unassessed by this flood planning layer
Grazing native vegetation
2
DP1167699
Lake George
Queanbeyan-Palerang
RU1
Primary Production
728.5
0.38
330
6.02
1.75
Tarago Road
8.2
exact
23.7
Canberra - Queanbeyan (Queanbeyan Part)
inner_regional
0.75
682.59
4.71
true
unassessed by this flood planning layer
Grazing modified pastures
3
DP109536
Uralla (NSW)
Uralla
RU1
Primary Production
721.7
3.63
330
5.55
1.74
New England Highway
16.3
exact
12.16
Armidale
inner_regional
0.96
1,052.2
5.05
false
unassessed by this flood planning layer
Cropping
39
DP830586
Clifden
Clarence Valley
RU2
Rural Landscape
713.8
1.14
330
8.61
2.49
Summerland Way
34.2
exact
12.32
Grafton
outer_regional
4.53
76.37
4.93
true
assessed: outside mapped flood planning land
Other minimal use
12
DP1155686
Tirrannaville
Goulburn Mulwaree
RU1
Primary Production
708.4
0
330
6.4
1.01
Braidwood Road
18.5
exact
4.67
Goulburn
inner_regional
0.52
638.27
4.66
true
unassessed by this flood planning layer
Grazing modified pastures
1
DP1246686
Good Hope
Yass Valley
RU1
Primary Production
672.9
1.98
330
4.51
1.01
Wee Jasper Road
24.6
sampled
5.03
Yass
inner_regional
2.83
551.84
4.84
true
assessed: outside mapped flood planning land
Grazing modified pastures
6
DP569308
Breadalbane (NSW)
Upper Lachlan
RU1
Primary Production
663.6
4.64
132
8.43
1.32
Cullerin Road
10.9
exact
17.01
Goulburn
inner_regional
2.06
699.93
4.73
true
unassessed by this flood planning layer
Grazing modified pastures
1
DP748197
Uralla (NSW)
Uralla
RU1
Primary Production
657
3.48
330
6.29
0.66
New England Highway
25.8
exact
11.2
Armidale
inner_regional
1.24
1,042.48
5.05
false
unassessed by this flood planning layer
Grazing modified pastures
1
DP564941
Rocky River (Uralla - NSW)
Uralla
RU2
Rural Landscape
645.7
4.61
330
9.84
2.11
Thunderbolts Way
22.6
sampled
21.11
Armidale
inner_regional
3.01
983.61
5.06
false
unassessed by this flood planning layer
Grazing modified pastures
10
DP1016481
Eglinton (NSW)
Bathurst
RU1
Primary Production
638.5
0.38
330
9.05
2.63
Sofala Road
30.2
exact
4.62
Bathurst
inner_regional
1.91
713.69
4.89
true
assessed: outside mapped flood planning land
Grazing modified pastures
1
DP977426
Laffing Waters
Bathurst
RU1
Primary Production
625.9
0.38
132
7.6
1.91
Sofala Road
42.4
exact
4.38
Bathurst
inner_regional
2.3
688.02
4.87
true
assessed: outside mapped flood planning land
Grazing modified pastures
2
DP1122828
Breadalbane (NSW)
Upper Lachlan
RU1
Primary Production
624
2.89
132
6.14
1.01
Cullerin Road
17.4
exact
18.9
Goulburn
inner_regional
1.43
698.58
4.73
true
unassessed by this flood planning layer
Grazing modified pastures
3
DP1114623
Camberwell (NSW)
Singleton
RU1
Primary Production
615.5
2.02
132
6.17
1.32
New England Highway
4.7
sampled
9.67
Singleton
inner_regional
1.67
72.48
4.8
true
unassessed by this flood planning layer
Grazing modified pastures
34
DP1210649
Gillenbah
Narrandera
RU3
Forestry
605.8
2.37
330
13.06
0.76
Newell Highway
1.9
sampled
28.89
Leeton
outer_regional
0.26
144.84
5.04
true
unassessed by this flood planning layer
Production native forests
What the figures say
The funnel is the useful table. Of 3,354,329 NSW parcel records, 282,366 are rural or industrial lots of twenty hectares or more. The 330 kV test cuts that to 27,686 and the substation test to 18,424. The sealed arterial test halves it again to 9,225. The population, town, slope and flood tests bring it to 3,999 lots across 44 council areas, with a median area of 41.6 hectares.
The largest lot on the list is 2,128.5 hectares of cropping land at Mallee in Wentworth Shire, under a kilometre from a 330 kV line, 3.4 kilometres from a substation, three kilometres from the sealed Arumpo Road, with a rounded 0.1 residents within two kilometres and Mildura eleven kilometres away. The next eleven are between 735 and 1,468 hectares, at Wallerawang, Coombell, Kremnos, Penrose, Ellangowan, Bungendore, Ravensworth, Lemington, Lanitza and Swan Vale.
The local screen, run against the same parcel table before the prompt was sent, returns the same 3,999 lots, the same 3,562 bushfire-prone, the same 3,071 unassessed for flood planning, and the same top lot.
One figure is wrong. The report's third section says solar exposure across the final pool ranges from 4.45 to 5.19 kWh/m²/day. The funnel table it sits beside says 4.24 to 5.19, and the local screen agrees with the table. The report stays as the agent wrote it.
Code
bashthis cell failed
python3 - <<'EOF'
import zn
con=zn.lake_con()
PP=zn.read('parcel_profile')
# ranked survivors and funnel summary
screen_sql = f"""
WITH screened AS (
SELECT parcel_id, lot, plan_label, suburb, lga_name, zone_code, zone_name,
round(area_m2 / 10000.0, 1) AS area_ha, lat, lng, h3_r9,
tx_330kv_nearest_km, tx_nearest_kv, substation_nearest_km,
road_arterial_nearest_km, road_arterial_nearest_name,
persons_2km, persons_2km_fill,
town_5k_50k_nearest_km, town_5k_50k_nearest_name,
remoteness, slope_deg, elevation_m, ghi_kwh_m2_day,
bushfire_prone,
CASE WHEN flood_planning IS FALSE THEN 'assessed: outside mapped flood planning land'
ELSE 'unassessed by this flood planning layer' END AS flood_status,
alum_label
FROM {PP}
WHERE zone_group IN ('Rural','Industrial')
AND area_m2 >= 200000
AND lot <> ''
AND tx_330kv_nearest_km <= 5
AND substation_nearest_km <= 15
AND road_arterial_nearest_km <= 3
AND persons_2km < 200
AND town_5k_50k_nearest_km <= 30
AND slope_deg <= 5
AND flood_planning IS NOT TRUE
)
SELECT * FROM screened ORDER BY area_ha DESC, parcel_id LIMIT 25
"""
con.execute(f"COPY ({screen_sql}) TO '/workspace/out/datacentre_top25.csv' (HEADER)")
summary_sql=f"""
WITH c AS (
SELECT zone_group IN ('Rural','Industrial') AND area_m2 >= 200000 AND lot <> '' AS c1,
tx_330kv_nearest_km <= 5 AS c2,
substation_nearest_km <= 15 AS c3,
road_arterial_nearest_km <= 3 AS c4,
persons_2km < 200 AS c5,
town_5k_50k_nearest_km <= 30 AS c6,
slope_deg <= 5 AND flood_planning IS NOT TRUE AS c7,
flood_planning, bushfire_prone, area_m2, ghi_kwh_m2_day
FROM {PP}
), k AS (SELECT *, c1 AND c2 AND c3 AND c4 AND c5 AND c6 AND c7 AS kept FROM c)
SELECT 'NSW parcels in source' AS stage, count(*) AS parcels, NULL::DOUBLE AS median_area_ha, NULL::DOUBLE AS solar_min, NULL::DOUBLE AS solar_max, NULL::BIGINT AS bushfire_flagged, NULL::BIGINT AS flood_unassessed FROM k
UNION ALL SELECT 'Rural or industrial, >=20 ha, non-strata', count(*) FILTER(c1), NULL, NULL, NULL, NULL, NULL FROM k
UNION ALL SELECT 'Also within 5 km of 330 kV+ line', count(*) FILTER(c1 AND c2), NULL, NULL, NULL, NULL, NULL FROM k
UNION ALL SELECT 'Also within 15 km of transmission substation', count(*) FILTER(c1 AND c2 AND c3), NULL, NULL, NULL, NULL, NULL FROM k
UNION ALL SELECT 'Also within 3 km of sealed arterial/highway', count(*) FILTER(c1 AND c2 AND c3 AND c4), NULL, NULL, NULL, NULL, NULL FROM k
UNION ALL SELECT 'Also under 200 residents in 2 km screen', count(*) FILTER(c1 AND c2 AND c3 AND c4 AND c5), NULL, NULL, NULL, NULL, NULL FROM k
UNION ALL SELECT 'Also within 30 km of 5,000-50,000 town', count(*) FILTER(c1 AND c2 AND c3 AND c4 AND c5 AND c6), NULL, NULL, NULL, NULL, NULL FROM k
UNION ALL SELECT 'Final screened lots', count(*) FILTER(kept), median(area_m2) FILTER(kept)/10000.0, min(ghi_kwh_m2_day) FILTER(kept), max(ghi_kwh_m2_day) FILTER(kept), count(*) FILTER(kept AND bushfire_prone), count(*) FILTER(kept AND flood_planning IS NULL) FROM k
"""
con.execute(f"COPY ({summary_sql}) TO '/workspace/out/datacentre_funnel.csv' (HEADER)")
# grid context: 330kV+ line cells overlapping top25 extent, plus substations within 15 km of any top25 lot
base_lines=zn.read('transmission',file='lines_h3r9')
base_lines_dim=zn.read('transmission',file='lines')
base_sub=zn.read('transmission',file='substations')
grid_sql=f"""
WITH top AS (SELECT h3_r9 FROM read_csv_auto('/workspace/out/datacentre_top25.csv')),
line_cells AS (
SELECT l.h3_r9, max(l.voltage_kv) AS voltage_kv,
'transmission line' AS feature, string_agg(DISTINCT coalesce(d.name,'unnamed line'), '; ') AS label
FROM {base_lines} l LEFT JOIN {base_lines_dim} d USING(line_id)
JOIN top t USING(h3_r9)
WHERE l.voltage_kv >= 330
GROUP BY l.h3_r9
), sub AS (
SELECT s.h3_r9, max(coalesce(s.voltage_kv,0)) AS voltage_kv,
'substation' AS feature, string_agg(DISTINCT s.name, '; ') AS label
FROM {base_sub} s
JOIN (SELECT DISTINCT lat, lng FROM read_csv_auto('/workspace/out/datacentre_top25.csv')) p
ON h3_great_circle_distance(s.lat,s.lng,p.lat,p.lng,'km') <= 15
GROUP BY s.h3_r9
), both AS (
SELECT * FROM line_cells UNION ALL SELECT * FROM sub
)
SELECT h3_r9, max(voltage_kv) AS voltage_kv, string_agg(DISTINCT feature, ' + ') AS feature, string_agg(DISTINCT label, '; ') AS label
FROM both GROUP BY h3_r9
"""
con.execute(f"COPY ({grid_sql}) TO '/workspace/out/datacentre_grid_context.csv' (HEADER)")
print(con.sql("SELECT * FROM '/workspace/out/datacentre_top25.csv' LIMIT 2"))
print(con.sql("SELECT * FROM '/workspace/out/datacentre_funnel.csv' ORDER BY parcels DESC LIMIT 1"))
print(con.sql("SELECT * FROM '/workspace/out/datacentre_grid_context.csv' LIMIT 2"))
EOF
bashcell 2 of 5
python3 - <<'EOF'
import zn
con=zn.lake_con()
lines=zn.read('transmission',file='lines_h3r9')
dim=zn.read('transmission',file='lines')
sub=zn.read('transmission',file='substations')
sql=f"""
WITH top_sites AS (SELECT h3_r9 FROM read_csv_auto('/workspace/out/datacentre_top25.csv')),
line_cells AS (
SELECT l.h3_r9, max(l.voltage_kv) AS voltage_kv,
'transmission line' AS feature,
string_agg(DISTINCT coalesce(d.name,'unnamed line'), '; ') AS label
FROM {lines} l LEFT JOIN {dim} d USING(line_id)
JOIN top_sites t USING(h3_r9)
WHERE l.voltage_kv >= 330
GROUP BY l.h3_r9
), substation_cells AS (
SELECT s.h3_r9, max(coalesce(s.voltage_kv,0)) AS voltage_kv,
'substation' AS feature,
string_agg(DISTINCT s.name, '; ') AS label
FROM {sub} s
JOIN (SELECT DISTINCT lat, lng FROM read_csv_auto('/workspace/out/datacentre_top25.csv')) p
ON h3_great_circle_distance(s.lat,s.lng,p.lat,p.lng,'km') <= 15
GROUP BY s.h3_r9
), combined_features AS (
SELECT * FROM line_cells
UNION ALL
SELECT * FROM substation_cells
)
SELECT h3_r9, max(voltage_kv) AS voltage_kv,
string_agg(DISTINCT feature, ' + ') AS feature,
string_agg(DISTINCT label, '; ') AS label
FROM combined_features
GROUP BY h3_r9
"""
con.execute(f"COPY ({sql}) TO '/workspace/out/datacentre_grid_context.csv' (HEADER)")
print(con.sql("SELECT count(*) AS cells FROM '/workspace/out/datacentre_grid_context.csv'"))
EOF
bashthis cell failed
python3 - <<'EOF'
import duckdb
con=duckdb.connect()
con.execute("COPY (SELECT * EXCLUDE (h3_r9, lat, lng) FROM read_csv_auto('/workspace/out/datacentre_top25.csv')) TO '/workspace/out/datacentre_top25_reader.csv' (HEADER)
")
print(con.sql("SELECT * FROM read_csv_auto('/workspace/out/datacentre_funnel.csv')"))
print(con.sql("SELECT count(*) AS n, min(area_ha) AS min_ha, max(area_ha) AS max_ha, min(ghi_kwh_m2_day) AS min_ghi, max(ghi_kwh_m2_day) AS max_ghi, sum(CASE WHEN bushfire_prone THEN 1 ELSE 0 END) AS bushfire FROM read_csv_auto('/workspace/out/datacentre_top25.csv')"))
print(con.sql("SELECT parcel_id, suburb, lga_name, area_ha, zone_code, ghi_kwh_m2_day, bushfire_prone FROM read_csv_auto('/workspace/out/datacentre_top25.csv') LIMIT 5"))
EOF
bashcell 4 of 5
python3 - <<'EOF'
import duckdb
con=duckdb.connect()
q="""COPY (SELECT * EXCLUDE (h3_r9, lat, lng) FROM read_csv_auto('/workspace/out/datacentre_top25.csv')) TO '/workspace/out/datacentre_top25_reader.csv' (HEADER)"""
con.execute(q)
print(con.sql("SELECT * FROM read_csv_auto('/workspace/out/datacentre_funnel.csv')"))
print(con.sql("SELECT count(*) AS n, min(area_ha) AS min_ha, max(area_ha) AS max_ha, min(ghi_kwh_m2_day) AS min_ghi, max(ghi_kwh_m2_day) AS max_ghi, sum(CASE WHEN bushfire_prone THEN 1 ELSE 0 END) AS bushfire FROM read_csv_auto('/workspace/out/datacentre_top25.csv')"))
EOF
bashcell 5 of 5
python3 - <<'EOF'
import duckdb
con=duckdb.connect()
q="""COPY (SELECT suburb, lga_name, zone_code, zone_name, area_ha, tx_330kv_nearest_km, substation_nearest_km, road_arterial_nearest_km, persons_2km, town_5k_50k_nearest_name, town_5k_50k_nearest_km, ghi_kwh_m2_day, bushfire_prone, flood_status, parcel_id AS "Lot/DP" FROM read_csv_auto('/workspace/out/datacentre_top25.csv') ORDER BY area_ha DESC, parcel_id LIMIT 12) TO '/workspace/out/datacentre_top12_reader.csv' (HEADER)"""
con.execute(q)
print(con.sql("SELECT count(*) AS rows, min(area_ha) AS smallest_ha, max(area_ha) AS largest_ha FROM read_csv_auto('/workspace/out/datacentre_top12_reader.csv')"))
EOF
The screen is one query. The map cells are the second query: it unions the H3 cells that carry a 330 kV or higher line with the cells that hold a substation, within the area the top 25 lots cover, and labels each cell by what it holds. Lots are drawn as points at the parcel centroid because a map block carries one form at a time.
Limits of this run
Zoned for a data centre is not a phrase this run uses. Data centres are permitted with consent in the NSW employment and industrial zones. Every lot on this shortlist is rural. On rural land a data centre is a planning proposal or a State Significant Development question, and above 15 megawatts of power consumption it is the latter regardless of zone. The screen finds land with the physical attributes; it does not find land that is approved.
Proximity is not capacity. A lot a kilometre from a 330 kV line has no claim on that line. Hosting capacity, connection cost, the connection queue and the new ministerial grid-connection controls for facilities over five megawatts are not in any open dataset. The same applies to water: no open source maps the reticulated supply or recycled-water availability the NSW Data Centre Guidelines expect.
Fibre is absent. No open dataset carries long-haul fibre routes. The library's broadband layer records private fibre estates and NBN technology at the cell, which is not backhaul.
Residents within two kilometres is a census-night sum over a lattice. The population layer places each rural mesh block's people on a coarse grid, so a rounded 0.1 residents means the disk touched a sampled cell, not that a tenth of a person lives there. The table carries a fill-quality column for exactly this reason.
Flood planning is unassessed for most of the shortlist. Only some councils publish the flood planning layer. 3,071 of the 3,999 lots sit in councils that do not, and the report reports them as unassessed rather than clear.
Solar exposure is a resource, not a yield. The 1991 to 2020 mean daily global horizontal irradiance says how much sun reaches the ground. Tilt, tracking, module temperature, losses and curtailment are not in it. It ranks sites; it does not size a farm.
Bushfire-prone land is a flag. 3,562 of the 3,999 lots carry it. Excluding on it would have removed almost the entire shortlist, which is why the prompt asked for a flag.
Run it on your own criteria
The thresholds are the prompt's: twenty hectares, five kilometres, fifteen kilometres, three kilometres, two hundred residents, thirty kilometres, five degrees. Each is a number in the question. The same screen runs with different numbers, a different zone list, a different voltage, or a polygon of your own. To run it, request access. Related pages: renewable energy siting and renewable energy developers.