FA-70001 / Map projection transforms / Open access
UTM zone and latitude band lookup: svalbard zone split · case 01
Svalbard points near 21 degrees east are assigned to the wrong widened zone.
ROOT CAUSE
The zone 33 range of the Svalbard exception is closed at 21, taking the zone 35 edge.
VERIFIED REPAIR
At the svalbard zone split step restore `elif lon < 21.0:`, leaving the rest of the model unchanged.
Unsuccessful approach: Moving the split to 20 degrees misassigns the whole [20, 21) strip to zone 35.
Case contract
Input [lon, lat]. zone = floor((lon+180)/6)+1, with lon=180 mapped to zone 60. Exceptions: lat in [56, 64) and lon in [3, 12) is zone 32; lat in [72, 84] uses zone 31 for lon in [0, 9), 33 for [9, 21), 35 for [21, 33) and 37 for [33, 42). Band letters "CDEFGHJKLMNPQRSTUVWX" (no I or O) cover 8 degrees each from -80; band X also covers up to 84 inclusive. Outside [-80, 84] the band is None. Return [zone, band].
Why this case matters
Grid references, MGRS labels and CRS selection rely on the zone and band, including the Norway and Svalbard exceptions.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
lon, lat = x
zone = int(math.floor((lon + 180.0) / 6.0)) + 1
if zone > 60:
zone = 60
if 56.0 <= lat < 64.0 and 3.0 <= lon < 12.0:
zone = 32
if 72.0 <= lat <= 84.0 and 0.0 <= lon < 42.0:
if lon < 9.0:
zone = 31
elif lon <= 21.0:
zone = 33
elif lon < 33.0:
zone = 35
else:
zone = 37
letters = 'CDEFGHJKLMNPQRSTUVWX'
if lat < -80.0 or lat > 84.0:
band = None
else:
band = letters[min(int((lat + 80.0) // 8), 19)]
return [zone, band]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [-63.1, 21.44], [20, 'Q']), ('control #1', [-175.96, 80.22], [1, 'X']), ('control #2', [115.33, 82.84], [50, 'X']), ('control #3', [-84.72, -46.68], [16, 'G']), ('control #4', [-159.4, -47.6], [4, 'G']), ('control #5', [-170.34, 33.06], [2, 'S']), ('boundary #21', [20.9, 80.0], [33, 'X']), ('boundary #36', [21.0, 78.0], [35, 'X'])], [('control #3', [-84.72, -46.68], [16, 'G']), ('control #4', [-159.4, -47.6], [4, 'G']), ('control #5', [-170.34, 33.06], [2, 'S']), ('control #6', [-48.09, 53.12], [22, 'U']), ('control #7', [93.32, -22.41], [46, 'K']), ('control #8', [-119.29, -22.68], [11, 'K']), ('boundary #36', [21.0, 78.0], [35, 'X']), ('boundary #37', [20.5, 79.0], [33, 'X'])], [('control #6', [-48.09, 53.12], [22, 'U']), ('control #7', [93.32, -22.41], [46, 'K']), ('control #8', [-119.29, -22.68], [11, 'K']), ('control #9', [-168.15, 26.03], [2, 'R']), ('control #10', [-111.05, -54.91], [12, 'F']), ('control #11', [139.05, -8.2], [54, 'L']), ('boundary #21', [20.9, 80.0], [33, 'X']), ('boundary #36', [21.0, 78.0], [35, 'X'])], [('control #9', [-168.15, 26.03], [2, 'R']), ('control #10', [-111.05, -54.91], [12, 'F']), ('control #11', [139.05, -8.2], [54, 'L']), ('boundary #12', [180.0, 10.0], [60, 'P']), ('boundary #13', [-180.0, -10.0], [1, 'L']), ('regression #14', [5.0, 60.0], [32, 'V']), ('boundary #36', [21.0, 78.0], [35, 'X']), ('boundary #37', [20.5, 79.0], [33, 'X'])], [('boundary #12', [180.0, 10.0], [60, 'P']), ('boundary #13', [-180.0, -10.0], [1, 'L']), ('regression #14', [5.0, 60.0], [32, 'V']), ('boundary #15', [3.0, 56.0], [32, 'V']), ('boundary #16', [2.99, 60.0], [31, 'V']), ('boundary #17', [11.99, 63.99], [32, 'V']), ('boundary #21', [20.9, 80.0], [33, 'X']), ('boundary #36', [21.0, 78.0], [35, 'X'])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| control #0 | [20, 'Q'] | [20, 'Q'] | Passed |
| control #1 | [1, 'X'] | [1, 'X'] | Passed |
| control #2 | [50, 'X'] | [50, 'X'] | Passed |
| control #3 | [16, 'G'] | [16, 'G'] | Passed |
| control #4 | [4, 'G'] | [4, 'G'] | Passed |
| control #5 | [2, 'S'] | [2, 'S'] | Passed |
| boundary #21 | [33, 'X'] | [33, 'X'] | Passed |
| boundary #36 | [33, 'X'] | [35, 'X'] | Failed |
SHA-256 / acff4948841197d036dbfa9faddc2f59e08dbbb5eee5abd8fb35be1b6d977285
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
lon, lat = x
zone = int(math.floor((lon + 180.0) / 6.0)) + 1
if zone > 60:
zone = 60
if 56.0 <= lat < 64.0 and 3.0 <= lon < 12.0:
zone = 32
if 72.0 <= lat <= 84.0 and 0.0 <= lon < 42.0:
if lon < 9.0:
zone = 31
elif lon < 20.0:
zone = 33
elif lon < 33.0:
zone = 35
else:
zone = 37
letters = 'CDEFGHJKLMNPQRSTUVWX'
if lat < -80.0 or lat > 84.0:
band = None
else:
band = letters[min(int((lat + 80.0) // 8), 19)]
return [zone, band]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [-63.1, 21.44], [20, 'Q']), ('control #1', [-175.96, 80.22], [1, 'X']), ('control #2', [115.33, 82.84], [50, 'X']), ('control #3', [-84.72, -46.68], [16, 'G']), ('control #4', [-159.4, -47.6], [4, 'G']), ('control #5', [-170.34, 33.06], [2, 'S']), ('boundary #21', [20.9, 80.0], [33, 'X']), ('boundary #36', [21.0, 78.0], [35, 'X'])], [('control #3', [-84.72, -46.68], [16, 'G']), ('control #4', [-159.4, -47.6], [4, 'G']), ('control #5', [-170.34, 33.06], [2, 'S']), ('control #6', [-48.09, 53.12], [22, 'U']), ('control #7', [93.32, -22.41], [46, 'K']), ('control #8', [-119.29, -22.68], [11, 'K']), ('boundary #36', [21.0, 78.0], [35, 'X']), ('boundary #37', [20.5, 79.0], [33, 'X'])], [('control #6', [-48.09, 53.12], [22, 'U']), ('control #7', [93.32, -22.41], [46, 'K']), ('control #8', [-119.29, -22.68], [11, 'K']), ('control #9', [-168.15, 26.03], [2, 'R']), ('control #10', [-111.05, -54.91], [12, 'F']), ('control #11', [139.05, -8.2], [54, 'L']), ('boundary #21', [20.9, 80.0], [33, 'X']), ('boundary #36', [21.0, 78.0], [35, 'X'])], [('control #9', [-168.15, 26.03], [2, 'R']), ('control #10', [-111.05, -54.91], [12, 'F']), ('control #11', [139.05, -8.2], [54, 'L']), ('boundary #12', [180.0, 10.0], [60, 'P']), ('boundary #13', [-180.0, -10.0], [1, 'L']), ('regression #14', [5.0, 60.0], [32, 'V']), ('boundary #36', [21.0, 78.0], [35, 'X']), ('boundary #37', [20.5, 79.0], [33, 'X'])], [('boundary #12', [180.0, 10.0], [60, 'P']), ('boundary #13', [-180.0, -10.0], [1, 'L']), ('regression #14', [5.0, 60.0], [32, 'V']), ('boundary #15', [3.0, 56.0], [32, 'V']), ('boundary #16', [2.99, 60.0], [31, 'V']), ('boundary #17', [11.99, 63.99], [32, 'V']), ('boundary #21', [20.9, 80.0], [33, 'X']), ('boundary #36', [21.0, 78.0], [35, 'X'])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| control #0 | [20, 'Q'] | [20, 'Q'] | Passed |
| control #1 | [1, 'X'] | [1, 'X'] | Passed |
| control #2 | [50, 'X'] | [50, 'X'] | Passed |
| control #3 | [16, 'G'] | [16, 'G'] | Passed |
| control #4 | [4, 'G'] | [4, 'G'] | Passed |
| control #5 | [2, 'S'] | [2, 'S'] | Passed |
| boundary #21 | [35, 'X'] | [33, 'X'] | Failed |
| boundary #36 | [35, 'X'] | [35, 'X'] | Passed |
SHA-256 / 57170f2b0ec6f06a25dddaf27a8e947d8ef9d5eaed91d9c19763ac1d629e8bda
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
lon, lat = x
zone = int(math.floor((lon + 180.0) / 6.0)) + 1
if zone > 60:
zone = 60
if 56.0 <= lat < 64.0 and 3.0 <= lon < 12.0:
zone = 32
if 72.0 <= lat <= 84.0 and 0.0 <= lon < 42.0:
if lon < 9.0:
zone = 31
elif lon < 21.0:
zone = 33
elif lon < 33.0:
zone = 35
else:
zone = 37
letters = 'CDEFGHJKLMNPQRSTUVWX'
if lat < -80.0 or lat > 84.0:
band = None
else:
band = letters[min(int((lat + 80.0) // 8), 19)]
return [zone, band]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [-63.1, 21.44], [20, 'Q']), ('control #1', [-175.96, 80.22], [1, 'X']), ('control #2', [115.33, 82.84], [50, 'X']), ('control #3', [-84.72, -46.68], [16, 'G']), ('control #4', [-159.4, -47.6], [4, 'G']), ('control #5', [-170.34, 33.06], [2, 'S']), ('boundary #21', [20.9, 80.0], [33, 'X']), ('boundary #36', [21.0, 78.0], [35, 'X'])], [('control #3', [-84.72, -46.68], [16, 'G']), ('control #4', [-159.4, -47.6], [4, 'G']), ('control #5', [-170.34, 33.06], [2, 'S']), ('control #6', [-48.09, 53.12], [22, 'U']), ('control #7', [93.32, -22.41], [46, 'K']), ('control #8', [-119.29, -22.68], [11, 'K']), ('boundary #36', [21.0, 78.0], [35, 'X']), ('boundary #37', [20.5, 79.0], [33, 'X'])], [('control #6', [-48.09, 53.12], [22, 'U']), ('control #7', [93.32, -22.41], [46, 'K']), ('control #8', [-119.29, -22.68], [11, 'K']), ('control #9', [-168.15, 26.03], [2, 'R']), ('control #10', [-111.05, -54.91], [12, 'F']), ('control #11', [139.05, -8.2], [54, 'L']), ('boundary #21', [20.9, 80.0], [33, 'X']), ('boundary #36', [21.0, 78.0], [35, 'X'])], [('control #9', [-168.15, 26.03], [2, 'R']), ('control #10', [-111.05, -54.91], [12, 'F']), ('control #11', [139.05, -8.2], [54, 'L']), ('boundary #12', [180.0, 10.0], [60, 'P']), ('boundary #13', [-180.0, -10.0], [1, 'L']), ('regression #14', [5.0, 60.0], [32, 'V']), ('boundary #36', [21.0, 78.0], [35, 'X']), ('boundary #37', [20.5, 79.0], [33, 'X'])], [('boundary #12', [180.0, 10.0], [60, 'P']), ('boundary #13', [-180.0, -10.0], [1, 'L']), ('regression #14', [5.0, 60.0], [32, 'V']), ('boundary #15', [3.0, 56.0], [32, 'V']), ('boundary #16', [2.99, 60.0], [31, 'V']), ('boundary #17', [11.99, 63.99], [32, 'V']), ('boundary #21', [20.9, 80.0], [33, 'X']), ('boundary #36', [21.0, 78.0], [35, 'X'])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| control #0 | [20, 'Q'] | [20, 'Q'] | Passed |
| control #1 | [1, 'X'] | [1, 'X'] | Passed |
| control #2 | [50, 'X'] | [50, 'X'] | Passed |
| control #3 | [16, 'G'] | [16, 'G'] | Passed |
| control #4 | [4, 'G'] | [4, 'G'] | Passed |
| control #5 | [2, 'S'] | [2, 'S'] | Passed |
| boundary #21 | [33, 'X'] | [33, 'X'] | Passed |
| boundary #36 | [35, 'X'] | [35, 'X'] | Passed |
SHA-256 / 4aab08b8255d029e16c6de722ace498716bf40323696c438a8404875d0ccd626
Verification & scope
Stipulated deterministic toy contract on a bounded input domain; results are rounded as stated and no conformance with any published standard or library is claimed. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:48:16.575501+00:00.
Case digest / 4c4145c6dff38ca54acbe9608278cb2bda7af55b5d2bf75847ef5455fe0c0763