Repository navigation
Conversation
v2's absolute and relative constituency hex maps drew each constituency at the x and y its result gives, on the untiled square grid. Those positions are the Open Innovations layout's [q, r], but the untiled grid shifts the even rows where the layout's odd-r rows need the odd ones shifted, so v2's arrangement differed from v3's in every other row. Both now place their areas with placeOnUKHexLayout, which holds the rule v3's local-area map had inline: each area whose ONS code the layout has takes the layout's position, on the tiled grid. An area the layout cannot place (no code, as in an older saved result, or a code the layout lacks) keeps its result's position, and the map then draws the untiled grid those positions were made for. v3's map now calls the same function, with no change in what it draws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v2's absolute and relative local-authority hex maps drew each authority at the x and y its result gives, on the untiled square grid. The Public API's positions differ from the layout for 56 of the 361 authorities, and put Cumberland, Westmorland and Furness, North Yorkshire, Somerset and Bournemouth, Christchurch and Poole, created in 2019 and 2023, all at (0, 0), so v2 drew them on top of one another. Both maps now place their areas with placeOnUKHexLayout, as v3's local-area map and v2's constituency maps do: each authority whose ONS code the layout has takes the layout's position, on the tiled grid. An area the layout cannot place keeps its result's position, on the untiled grid. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The README said only v3's "Local areas" tab draws from the layout files. v2's constituency and local-authority tabs now do as well, through placeOnUKHexLayout. The test fixture that compares v2's and v3's hex maps also takes UKAreaLevel from its adapter instead of repeating the type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the tiled grid a hexagon's radius is 0.55 of the scale, but the map fitted only the hexagons' centres inside a margin of twice hexSize. A map of few areas has a large scale, so its top and bottom hexagons ran past the frame and were clipped, in the map and in its download. v2's hex map of three Welsh constituencies, now tiled, reached y = -15.6 in its 380-unit frame. v3's map of a nation had the same problem. The tiled map's bounds now take in each hexagon's edges, its radius up and down and √3/2 of it sideways, so the scale leaves room for them. HexMapConfig's hexSize comment now says what it sets on each grid. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The README said the hex maps no longer depend on the x and y the Public API sends. An area without a code in the layout still falls back to them, so it now says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PavelMakarchuk
left a comment
There was a problem hiding this comment.
Thanks @anth-volk. I checked this against current main (06f6441): it merges cleanly, CI is green, and in a local checkout 47 test files (518 tests) and tsc --noEmit pass. It fixes two real v2 defects: constituency rows half a hex out of place, and the five local authorities the API puts at (0,0), which drew as one hex.
1. A partly placed map mixes two coordinate systems (ukHexLayout.ts, placeOnUKHexLayout)
When some codes are missing from the layout, the placed points take layout positions and the rest keep API positions, and all of them are drawn on the untiled grid. The two grids differ (by a row for constituencies, entirely for local authorities), so the hexes overlap or scatter. This came from my code in #1430, which v3 already has, and the unit test asserts it. It is reachable: the layout has no pre-2023 local-authority codes (E07000026, E07000187, E07000163 are absent), so a saved result with old codes would draw this map. Before this PR, v2 drew such a result from API positions only, which was at least consistent.
Suggested fix: make it all-or-nothing. If any point is missing from the layout, return the points unchanged with tiled: false, and change the test to expect that.
2. Timing
This changes the four v2 report pages under pages/report-output/{constituency,local-authority}/. It is a bug fix, so that is fine, but UK users are on v2 and the Budget is on 28 October. I would merge it after the Budget unless the v2 map fix is needed live tomorrow.
Nits
- A tiled map still adds
padding = hexSize * 2on top of the new hexagon reach, so the margin is doubled. Harmless. placeOnUKHexLayout([])returnstiled: true. Every caller returns early on empty input, so it has no effect.- The description says the API positions "equal the layout's [q, r]", but
ukHexPositionadds 1 to the row.
Merge after the fix in point 1.
When the layout had no position for some of a result's areas, placeOnUKHexLayout moved the others to their layout positions and left those at the x and y their results gave, all on the untiled grid. The two sets of positions are different grids (a row apart for constituencies, entirely different for local authorities), so the map's hexagons overlapped or scattered. A saved result from before April 2023 reaches this: the layout follows the April 2023 boundaries and has no code for a district abolished then, such as Allerdale (E07000026), Craven (E07000163) or Mendip (E07000187). Placement is now all or none. If the layout lacks any point's code, every point keeps its result's position, on the untiled grid; only when it has every code do the points take its positions, tiled. v2's and v3's hex maps both use it. The README and v3's comment say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1433 now places a hex map's areas from the layout all or none: if the layout lacks any area's code, every area keeps its result's position on the untiled grid. This branch replaces that fallback, so the conflicts keep its behaviour: placeOnUKHexLayout leaves out an area the layout cannot place, the map always tiles, and the note counts the areas left out. From #1433 it keeps the README's and the function comment's example of a district abolished in April 2023, the check that the layout has no pre-2023 local authority code, and the pre-2023 fixtures, without x and y as this branch's typed fixtures are. The pre-2023 tests now expect this branch's behaviour: Allerdale is left out while Darlington takes its layout position, and on v2's and v3's maps the three pre-2023 districts are left off and counted in the note ("3 of 5 local authorities are not on the hex map ..."). #1433's comparison with the same result without codes, and its uncoded fixture, are dropped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Superseded by #1448, which carries all of this PR's commits, cherry-picked with |
#1448 (1A · 2) holds #1433's six commits, cherry-picked unchanged, and #1447's work adapted to main: the hex maps draw the areas a disclosure-controlled breakdown withheld, hatched, as "Not reported", but only on the tiled grid, because areas still carry x and y there. This branch now builds on it. The conflicts keep this branch's behaviour and #1448's withheld areas: - The app reads no x or y: placeOnUKHexLayout takes the adapters' UKAreaChoroplethDataPoint, leaves out an area the layout cannot place, and returns only the placed points. #1448's Welsh fixture points lose their positions, and its fixture with every API position at the origin is dropped. - HexagonalMap draws only the tiled grid. #1448's missingAreas are positioned as the valued areas are, by a positionOnGrid with no coordinate scale or row-spacing argument, and count in the bounds. The duplicate "tiled frame" tests and the missing-area tests' tiled config are dropped. - No note says which areas are left off. - The withheld areas are kept. Under this branch every map tiles, so the callers' "only when tiled" checks are gone: v3's UKLocalAreaMaps and the four v2 charts ask withheldUKHexAreas for a breakdown level's withheld areas whenever the level is disclosure-controlled. withheldUKHexAreas still lists none when any of the result's areas has no code or a code outside the region's layout. That check is about matching the result to the layout, not about the grid: a layout area the result lacks may be covered by one of its unmatched areas, such as the districts a 2023 unitary authority replaced, so calling it withheld could be wrong. A map that leaves out unplaceable areas therefore draws no withheld areas, and the function's comment says why. #1448's v3 test for a breakdown area without a code now expects that: Gower left off, the other constituencies tiled, and no withheld areas. The README keeps both sides' text, and the tests take #1448's "not reported" wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #1432
What changed
v2's constituency and local-authority hex maps now place each area from the app's own layout files, as v3's do. Before, they used the
xandyin the result.placeOnUKHexLayout(level, points)incomponents/visualization/choropleth/ukHexLayout.ts. It replaces the rule v3'sUKLocalAreaMapshad inline. When the layout has every point's ONS code, each point takesukHexPosition's position and the map tiles (config.tiled). Otherwise no point moves; see below.UKLocalAreaMapsand the four v2 charts all call it, so v2 and v3 put every area in the same hex. The four charts areAbsoluteChangeByConstituency,RelativeChangeByConstituency,AbsoluteChangeByLocalAuthorityandRelativeChangeByLocalAuthority. They are the only places v2 draws these hex maps:ConstituencySubPageandLocalAuthoritySubPagerender them, both on the report's tabs and in the UK sections ofMigrationSubPage.An area missing from the layout
Placement is all or none. If the layout has no position for even one of a result's areas, every area in that result keeps the position its result gives it, and the map draws the untiled square grid those positions were made for. That covers two kinds of area:
by_constituencyshape;E07000026), Craven (E07000163) or Mendip (E07000187). The layouts follow the April 2023 boundaries.v3's inline rule, from #1430, placed whichever areas it could and left the rest at their result positions, all on the untiled grid. Those are two different grids, a row apart for constituencies and wholly different for local authorities, so such a map overlapped or scattered its hexagons. Results from the list shape and from local-area breakdowns carry current codes, and the layouts hold all 650 constituencies and 361 local authorities, so the fallback applies only to older saved results.
The follow-up PR removes this fallback and the rest of the app's handling of
xandy.What it fixes
[q, r]. v2 shifted the wrong row parity and spaced rows a full column apart, so every other row sat half a hex out of place.(0, 0).Hexagons kept inside the frame
Tiling v2's maps exposed a sizing fault in
HexagonalMap, which v3's map of a nation already had. On the tiled grid, a hexagon's radius is 0.55 of the scale, but the map fitted only the hexagons' centres inside a margin of twicehexSize. A map of few areas, such as one nation's constituencies, therefore drew its top and bottom hexagons past the frame. They were clipped on screen and in the download.The tiled map's bounds now include each hexagon's edges, so the scale leaves room for them.
HexMapConfig'shexSizecomment now says what it sets on each grid.Tests
The work was done red-green: each commit's tests were written first and seen failing before the code.
placeOnUKHexLayout(ukHexLayout.test.ts):Each of the four v2 charts:
UKLocalAreaMapsfor the same result. The test renders both maps, then compares hexagon centres, normalised for the maps' different sizes;A pre-2023 local-authority code:
AbsoluteChangeByLocalAuthorityand v3'sUKLocalAreaMapsdraw a saved result with pre-2023 codes exactly as they draw the same result without codes: the same arrangement, on the untiled grid.The local-authority charts also check that the five authorities the Public API stacks at
(0, 0)now get five separate hexes. The fixture uses the Public API's real positions.HexagonalMapchecks that a tiled map of three areas and a UK-shaped tiled map keep every hexagon inside the frame.AbsoluteChangeByConstituencychecks the same for three Welsh constituencies. Before the fix, the top hexagon reached y = −66.5 and y = −15.6 respectively.Before the change, v2's arrangement of three Welsh constituencies had the second at
(0.164, 0.986)relative to the first, where v3's has it at(0.189, 0.982). Its five local authorities had only three distinct centres.Review
UKAreaLeveltype.hexSize's comment and the README went too far. Both are corrected: the README now says an area without a layout position still uses its result'sxandy.To check by hand
On a UK report with constituency results (for example a saved one, or one whose local-area breakdown has run):
🤖 Generated with Claude Code