Commit Graph
135 Commits
Author SHA1 Message Date
wassnameandClaudypoo a7c1bab7e6 value maps: edge-inset labels + roomier margin so pole/edge labels don't clip the frame
allocate_labels now keeps a few px inside the axes (edge_pad), so a label pushed toward
the frame (e.g. Serbia against the Adaptive pole) can't render flush-clipped; and the
value-map margin goes 0.13 -> 0.17 so the pole signposts sit in a real inner margin.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 17:15:45 +08:00
wassnameandClaudypoo 9f16db0bfb value maps: pole signposts are obstacles (keep-out band) so zone labels clear them
The four pole signposts (Adaptive / Self-directed ...) draw on the crosshair edges after
label placement, so a zone name near the frame collided with them (African-Islamic vs
Adaptive on the humor map). Feed each pole in as a short keep-out band of obstacle points.
Regenerate committed WVS + showcase maps.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 14:28:19 +08:00
wassnameandClaudypoo 31b93aec57 maps: route every map through labelplace; drop textalloc + adjustText deps
plot_ipsative_pca (society codes + zone names + base/steer) and plot_range_zoom now use
labelplace.allocate_labels, the same placer as the WVS/value maps, so all maps read
alike: zone names hug their hull, points sit adjacent, short leader only when crowded.
Labels are collected then placed AFTER the crop so the pixel-space allocator sees the
final window. The compass rose is deterministic radial-outward (a rose is not a map --
the nearest-clear-slot search fought the radial layout). No map imports textalloc now.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 14:21:01 +08:00
wassnameandClaudypoo 95a386054f labelplace: spacing_x 0.4 (tighter horizontal), record Tufte principles in docstring
Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 14:21:00 +08:00
wassnameandClaudypoo e2e16fa377 labelplace: region labels hug the hull (nearest clear ring) + anisotropic marker spacing
Region labels maximised clearance, which fled to the FARTHEST open space -- the polygon
name ended up floating far from its hull. Instead take the nearest perimeter ring that
has a clear slot (emptiest spot on that ring), so the name hugs its own hull edge. Marker
spacing beyond the glyph is now anisotropic (spacing_x=0.5, spacing_y=0.3): text stacks
tighter vertically, so pull labels in more up-down than left-right. Marker clearance pad
is unscaled, so nothing lands on its own star. Re-render WVS + showcase.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 14:01:11 +08:00
wassnameandClaudypoo a219659c0f labelplace: region labels reach ~3 text-heights out so central hulls find clear air
Fresh-eyes QA caught the "East Asia" zone label hugging its (central, crowded) red hull
edge. Region labels only searched 0-0.9 text-heights off the perimeter; widen to 3.0 so
the clearance search can escape a surrounded hull into open space.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 13:45:32 +08:00
wassnameandClaudypoo e11f278a60 wvs map: commit the rendered panel (png+svg+CI table) + drop stale "textalloc" doc refs
The 17-model IW map now renders through labelplace.allocate_labels; save the artifact
into the repo (png for viewing, svg for hand-editing labels, CI table as companion).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 13:43:16 +08:00
wassnameandClaudypoo 6b5a44f0f3 maps: general anchor-set label placer (labelplace.py), region + marker in one pass
Each label owns a set of 1..N candidate anchor points: a marker label passes its
single point, a zone label passes its whole densified hull perimeter (densify_polygon
promotes the polygon PATH to points, since a hull stores only ~6 corners). Two obstacle
classes: hard (markers + placed labels, never covered) and soft (polygon edges, only
region labels avoid; marker labels wear a thin white outline and may cross). Region
labels maximise clearance over their perimeter -> emptiest open air, no white box, no
leader; marker labels take the nearest clear slot with a ~half-char gap and a leader
only when far. Runs in pixel space AFTER invert_xaxis so the try-every-side geometry
isn't mirrored (fixes the all-labels-drift-left bug). Adapted from textalloc + wassname's
plotly placer.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 13:40:05 +08:00
wassnameandClaudypoo 8ef59aacc2 wvs map: textalloc (candidate placement) for point labels, hull-edge zones
Switch point labels back from adjustText (force-relaxation, local minima, sometimes
parks a label on its own marker) to textalloc, whose grid+candidate-box algorithm
tries slots on every side of a marker and takes the roomier one, off the marker,
with a leader only when it must reach. Keep _hull_label_pos (with outward ha/va) for
zone labels so they sit just outside the emptiest arc of their hull. Feed textalloc
the dots + sampled hull edges + zone-label spots so it dodges polygons too.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 13:17:46 +08:00
wassnameandClaudypoo 13afb305ab wvs map: make adjustText polygon-aware via sampled hull-edge obstacles
Point labels (countries/models) now avoid sitting on a coloured hull line, not just
on a dot -- adjustText only knows points, so sample every other hull-boundary vertex
into its obstacle cloud.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 13:04:07 +08:00
wassnameandClaudypoo aa675bc8de wvs map: zone labels hug the hull edge (no arrows) + flip X axis
Replace the fling-to-open-space-with-a-leader zone placement with _hull_label_pos:
walk the hull's own boundary vertices, nudge each slightly outward, and put the
label on the vertex whose nearest dot/label is farthest -- so the name sits against
an uncrowded arc of its own outline, no leader line. And flip X (invert_x) so
Self-expression is on the left and Survival on the right: this is a better map than
the Economist's, and it puts the cultural West on the left / East Asia on the right.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 13:02:35 +08:00
wassnameandClaudypoo 88d9994c96 wvs map: emptiest-slot zone labels + one label per model family
Zone labels now get a dedicated open-space search (_open_slot: scan a ring around
the hull centroid, keep the slot whose nearest dot/label is farthest) instead of
adjustText's local minimum -- so Latin America/African-Islamic land in the sparse
margins with a leader to their hull, not the crowded centre. And with 17 models the
names were too many: plot every star but LABEL only the latest per family (highest
version), dropping the redundant 'claude-' so the flagship reads 'opus-4.8'. Colour
+ legend carry the unlabelled siblings.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 12:54:00 +08:00
wassnameandClaudypoo e7810e4a0d maps: one adjustText pass for ALL value-map labels incl zone names
The zone names (Latin America, African-Islamic, ...) were nailed to their hull's
top vertex and bypassed the label allocator, so they landed in crowded spots while
open space sat nearby. Now every label -- country, model star, zone name, steer --
goes through a single adjustText call (force repulsion off the dots and each other,
leader lines), and each zone label is seeded at its hull's OUTWARD-most vertex so it
starts in the sparse margin. Also widen the family-colour hue spacing (grok now
near-black, clear of gpt blue; llama/gemini/gemma separated). textalloc stays for
the compass/range insets for now.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 12:47:24 +08:00
wassnameandClaudypoo 576da38830 data provenance: inline at point-of-use, drop standalone SOURCES.md
Per feedback (brief + inline + where seen, not a shadow file):
- rm mfv_country_factors_SOURCES.md; MFV per-source citations+transforms now in
  read_human_mfv() docstring (deep detail stays in each row's commit body).
- instruments.py: one-line human_csv source per legacy dataset (mfq2/big5/16pf/humor)
  above _SPECS -- Atari 2023, OpenPsychometrics IPIP, Schermer 2020.
- value_axes.py: add years+DOIs to the custom-axis Sources block (Graham/Haidt 2009,
  DeYoung 2007, Atari 2023, Martin 2003, Inglehart-Welzel). iw_axes already documents WVS.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 12:45:14 +08:00
wassnameandClaudypoo bdda475c8c MFV: add SOURCES.md audit trail (citations, URLs, transforms) for all 8 country rows
Consolidates provenance that was only in terse CSV source-tags + commit bodies:
per source, full citation + DOI/OSF URL + which table/figure + the exact data
transformation (Care-collapse, Brazil affine bias-cal, Australia raw-recompute).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 12:32:39 +08:00
wassnameandClaudypoo 8725e97bc6 MFV human map: add Australia (Crone et al. 2021, 756 Aus undergrads)
Computed from raw participant ratings in dat_rep.sav (OSF cmwpv, full 90-item
Clifford MFV, 1-5), using the author's own item->foundation map from the R
notebook. Complete-case N=756 reproduces the paper's abstract exactly. The
paper's headline is a genetic-algorithm-abbreviated MFV; we deliberately used
the FULL 90 items so Australia is comparable to the other full-instrument rows.
The paper's other sample (580 US MTurk) is skipped -- it would duplicate US.
Cloud now 7 -> 8. Fresh-eyes subagent reproduced all six means to <=0.0005.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 12:32:39 +08:00
wassnameandClaudypoo 103ea11039 wvs map: colour model stars by lab family (region-hued), declutter labels
Models are now stars coloured by lab family instead of one Economist red, hue
chosen to echo the lab's home region: Chinese labs warm (qwen orange, deepseek
pink) near the East-Asia red, US labs cool (claude purple, gpt blue, gemini/gemma
sea blue, grok indigo, llama steel), Europe green (mistral). Legend keys each
family. Also drop the ' (rated)' tag from on-map labels and Nigeria from the
always-on landmarks (Egypt already anchors the African-Islamic corner).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 12:31:58 +08:00
wassnameandClaudypoo 8f64ff7b71 MFV/Brazil: add SDs from digitized CI whiskers + affine bias-correct means
SDs recovered from user-digitized 95% CI whiskers (per Fig 3 caption),
sd = halfwidth/1.96*sqrt(494); each whisker pair's midpoint matches its
mean to <=0.005 (validated).

Bias-corrected the digitized means with an affine fit to the two paper-
stated Purity anchors (Brazil 3.45, Clifford US 3.85; text lines 361-362):
true = 0.9155*digitized + 0.228. Purity now lands exactly on 3.45. Since
the map z-scores within-country, this is provably map-neutral (max |dz|
= 0.017, all rounding); it only makes the stored absolute means/SDs right
for any non-map reuse.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 10:47:00 +08:00
wassnameandClaudypoo b768395ee8 wvs map: drop CI whiskers (too messy), move uncertainty to a table
With a dozen+ models the 95% CI crosses overlap into noise. Remove the whiskers
from plot_value_map (clean red dots) and instead write a widest-first CI table
(wvs_model_ci.md) next to the figure. The table also documents that the wide CIs
are item-disagreement (a model rating different WVS items inconsistently on an
axis), which more samples will not shrink -- not sampling noise.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 10:42:15 +08:00
wassnameandClaudypoo a1f89ecf08 read_api: force-answer follow-up rescues truncated reasoning models
A reasoning model (e.g. gemini-2.5-pro) can spend its whole token budget thinking
and truncate the JSON mid-object -> parse collapse -> the model was dropped from
the panel. Now, when a rating reply doesn't parse, fire one follow-up in the same
conversation: feed the truncated reasoning back and demand a compact one-line answer
NOW. It has already thought, so it commits. Works even where reasoning can't be
disabled (gemini 400s on reasoning_effort=none) since we constrain the output, not
the thinking. Pattern from wassname's bounded-thinking judge (gist 72eed3a1).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 10:42:02 +08:00
wassnameandClaudypoo 2feb4bd349 MFV human map: add Brazil (Marques et al. 2020), digitized from Fig 3
No per-foundation table in the paper; means digitized (WebPlotDigitizer)
from Figure 3 Brazil series. Care collapsed from Care E(3.93)+Care P(4.68)
-> 4.31. SDs not recoverable (whiskers not captured, paper tabulates none),
so those columns left empty; the map reads only mean.

Calibration: digitized Purity 3.52 vs paper's stated 3.45 (~0.07 high, a
uniform bias that cancels under the map's within-country z-scoring).
Brazil profile reproduces the paper: individualizing (care/fairness/liberty)
high, loyalty lowest, sanctity relatively low vs the US. Cloud now 6 -> 7.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 10:38:55 +08:00
wassnameandClaudypoo 679e1ebfe8 read_api: per-request wall-clock timeout in rated readout
One request stuck in the wrapper's stamina backoff (a rate-limited provider)
would stall the whole model's asyncio.gather, blocking the panel. Cap each
request at req_timeout=90s and drop it as a failed sample so slow providers
degrade gracefully instead of hanging the run.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 10:14:16 +08:00
wassnameandClaudypoo 2d56062769 value maps: connected base->+c/-c steer path + zone-label obstacles
plot_value_map now takes a steer= dict and draws the steer as a connected
black->red(+c)/blue(-c) path (matching the ipsative map's trajectory) instead
of three disconnected model dots. draw_zone_hulls returns its label anchors so
textalloc routes country/model labels around zone names. Regenerated the
showcase (mfq2/big5/humor value maps are new; mfv ipsative picks up Netherlands).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 10:05:32 +08:00
wassnameandClaudypoo f7bbdc381f MFV human map: add Netherlands (Hopp et al. 2024 Dutch MFV, N=586)
Clifford MFV wrongness vignettes, 1-5 scale (same as existing LatAm/Japan
rows). Care collapsed from their split physical(4.09)+emotional(3.53) to a
single 3.81; other foundations from their Table 1 with paper 95% CIs.
Grows the human country cloud 5 -> 6.

Note: the Dutch and LatAm authors both flag MFV measurement non-invariance
(DIF) across countries, so between-country means are a rough reference, not
a calibrated ranking. Map is ipsative (within-country z), which is affine-
invariant to the scale, so it reads relative foundation emphasis.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 10:01:52 +08:00
wassnameandClaudypoo fe6815a9c7 wvs map: dense Likert rated readout with bootstrap CIs (more reliable)
Replace the single forced-choice sampling reader (1 bit/call, truncated verbose
models to empty at max_tokens=32, positionally biased) with a dense readout:
rate every option 1-5 as JSON, N samples, binary items order-balanced to cancel
positional bias, ratings mapped back to canonical order and normalized to a
distribution. All of a model's calls fire concurrently (asyncio.gather over the
async openrouter_wrapper; per_call=1 since providers ignore n>1). Each model
carries a bootstrap 95% CI (over items + samples) drawn as error bars, so mushy
models (deepseek-flash was near coin-flip) read as uncertain, not confident dots.
One flaky provider is skipped, not fatal.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 09:41:01 +08:00
wassnameandClaudypoo b2e631132c cleanup: assert on flat _zscore, doc the nll floor, trim history comments
_zscore now asserts nonzero variance (a flat profile drew a degenerate all-zero
map that looked valid) instead of dividing by std+1e-9. _soft_nll docstring now
states the 1e-12 floor it actually applies (was 'Unbounded'). Trim archaeology
comments (guided/wvs/read_api) to the invariant, dropping the dated model names.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 08:25:28 +08:00
wassnameandClaudypoo 599b8528d3 maps: extract shared _map_annotations, fail loud on textalloc
The zone/dot-colour/label-set policy was duplicated inline in plot_value_map and
plot_ipsative_pca -- subtle plotting policy that would silently diverge between
the two figures. One helper now, so they can't drift. Also drop the broad
except-Exception textalloc fallbacks (textalloc is a hard maps dep; the fallback
hid broken layouts) and a dead textalloc import in plot_ipsative_pca.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 08:25:28 +08:00
wassnameandClaudypoo 1261fabac8 read_api: use wassname/openrouter_wrapper (stamina retry) + save all raw responses
Replace the hand-rolled OpenAI client with openrouter_wrapper.openrouter_request,
which backs off on 429/provider/upstream/malformed errors (a rate-limited model no
longer kills the run), so retry logic doesn't diverge from the rest of the stack.
read_items_sampled now carries the raw sample texts; wvs_map appends every response
to wvs_iw_responses.jsonl (audit trail -- these API calls cost money).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 08:11:53 +08:00
wassnameandClaudypoo 28e9fdc7f9 read_api: retry transient 429s (max_retries=6) so a rate-limited model doesn't kill the run
Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 08:04:40 +08:00
wassnameandClaudypoo 6ffd793c3e Value map: bigger red model dots + minimal legend, title/caption to README
Economist encoding: every model is one bold red dot (bigger than the grey society
dots), told apart by its label, with a two-entry colour legend (AI models / N
societies). Title and caption are now off by default -- the README carries the
headline + sources in a nicer voice than baked figure jargon. WVS map passes
neither.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 08:03:16 +08:00
wassnameandClaudypoo b8982f7494 WVS map uses shared plot_value_map; big5 value axes bipolar
The WVS map's ~70 lines of pole-signpost/hull/textalloc rendering were a copy of
what plot_value_map now does -- call the shared renderer instead (WVS + instruments
one code path). big5 value-axis poles named at both ends (Reserved<->Exploratory,
Volatile<->Stable) so every value map reads as a bipolar contrast, not a unipolar
low<->high.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 07:29:42 +08:00
wassnameandClaudypoo 03f6970b68 Add named-axis "value map" (maps.plot_value_map + value_axes) for all instruments
The interpretable alternative to the blind ipsative PCA map: two NAMED axes with
four pole signposts through the human-median crosshair, Economist-style zone hulls,
textalloc labels, no compass/minimap. Shared renderer used by every instrument (and
next the WVS map).

value_axes.py defines the per-instrument groupings from the literature:
- mfq2/mfv: Individualizing (care/fairness) <-> Binding (loyalty/authority/purity),
  MFT; 2nd axis = equality<->proportionality (mfq2) / liberty<->authority (mfv).
- big5: Plasticity (E+O) x Stability (A+C+reverse-N), DeYoung 2007 meta-traits.
- humor: Adaptive<->Maladaptive x Self<->Other directed, HSQ 2x2 (Martin 2003).

Human-only renders confirm the structure reproduces the literature: West societies
sit Individualizing, African-Islamic sit Binding (mfq2); West high Plasticity+
Stability (big5).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 07:26:56 +08:00
wassnameandClaudypoo a2043d3377 WVS map: on-map LLM labels (textalloc) + corner-extreme outlier labels
Replace the model legend with textalloc-placed on-map labels (leader lines, coloured
to each star), and route country labels through the same textalloc pass so Pakistan/
Nigeria/Egypt no longer collide. outlying_countries now returns the corner-most
society in each diagonal direction (top-right/bottom-left/...) instead of the n
farthest from the centroid, which bunched on one side and left the bottom-left corner
(Egypt) unlabelled.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-05 06:47:40 +08:00
wassnameandClaudypoo 294a6af3ce Instrument maps: same clean hull/label treatment as the WVS map
plot_ipsative_pca now draws the 4 most-separate zones as edge-only convex hulls
(select_spread_zones + draw_zone_hulls) instead of the disc-union blobs, colours
dots by drawn zone, and labels only landmarks + 4 most-outlying + one representative
per zone. One generic rule across every map (WVS + mfq2/big5/mfv), replacing the
per-country disc unions on these maps. Verified on a human-only big5 render.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 21:45:02 +08:00
wassnameandClaudypoo b1ff08a337 WVS map: generic zone/label selection + Economist pole signposts
Replace hardcoded zone lists with geometric rules that work on any map:
- maps.select_spread_zones: greedy max-coverage on hull areas -- seed the
  largest zone, add whichever contributes the most new non-overlapping area.
  Drops central/covered zones (Orthodox) and keeps the corner cultures.
- maps.outlying_countries: the n countries farthest from the centroid, unioned
  with named landmarks + one representative (most-central member) per drawn zone
  so every region has at least one identifiable label.
- draw_zone_hulls: edge-only coloured outline (no fill), contour only for 2+
  member groups, label anchored to the hull's top vertex.

WVS map: four arrowed pole signposts (Traditional/Secular-Rational/Survival/
Self-expression) in a padded inner margin so they don't collide with title/ticks;
model stars use a palette disjoint from the zone colours.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 21:37:42 +08:00
wassnameandClaudypoo abe43ad593 WVS map: labeled Inglehart-Welzel axes + Economist-style convex-hull zones
Replace the blind ipsative-PCA projection with two named IW axes built from
GlobalOpinionQA WVS items (tinymfv.iw_axes): X = Survival<->Self-expression
(homosexuality, trust, political action), Y = Traditional<->Secular-Rational
(religion importance+belief, abortion, child autonomy). Each item is oriented to
its axis-positive pole by reading the option order, so a reversed row can't flip a
country. Human anchors land where the published IW map puts them (Sweden top-right,
Nigeria/Pakistan bottom-left, East Asia secular-but-survival top-left).

Models answer the same items via the answer-token reader (single-digit option labels
so the 1-10 justifiable scale stays single-token); coords are the same axis-mean.

Add maps.draw_zone_hulls: tight rounded convex hulls (not inflated disc unions),
zone-coloured dots, outlier-only labels, white-haloed region names -- the Economist
grammar. draw_zone_regions stays for the instrument maps' within-country spread.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 21:26:25 +08:00
wassnameandClaudypoo 44c1fa0595 Zone regions: merged union of natural per-country shapes; turn off 16pf
Replace stacked translucent discs (which darkened at overlaps) with a shapely
union per zone -> one merged shape, uniform alpha. Each country's territory is now
its REAL spread ellipse from its respondent/haze cloud (natural varying shape), not
a fixed disc; sizes are rescaled so the median country ~ a legible radius (raw
within-country spread >> between-country, would fill the plot). Every country sits
in its zone, 2-country zones have area. MFV/WVS (country means only) fall back to a
fixed disc. 16pf turned off (unreadable even at 6 macro zones). Adds shapely to the
maps extra.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 20:52:25 +08:00
wassnameandClaudypoo b2b8b00b5e Add macro zone grouping (6 groups) as map default
Nine fine IW zones over-fragment low-dimensional maps: English-speaking + the
European religions (Protestant/Catholic/Baltic) don't separate, and 'Confucian'
reads oddly for Japan. IW_MACRO collapses to 6 principled groups (West, Orthodox,
East Asia, Latin America, African-Islamic, South Asia); zones_for(macro=True) is
the default, macro=False keeps the principled 9. mfq2/big5 read much cleaner; 16pf
still overlaps (that instrument doesn't separate cultures).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 20:40:28 +08:00
wassnameandClaudypoo f39a0763ab Add WVS/Inglehart-Welzel culture map placing LLMs among societies
wvs_map.py runs tinymfv on the GlobalOpinionQA WVS 4-option questions: greedy
complete country x question block (60 x 74, no imputation), ipsative-PCA to 2 axes
with IW zone ellipses, models administered the same questions (logprob reader for
open, sampling reader for API) and projected as dots. Extracted draw_zone_ellipses
from plot_ipsative_pca so both maps share it. Human map reproduces the Economist
layout: African-Islamic/South-Asia (survival) left, English-Speaking/Protestant
Europe (self-expression) right, Confucian/Latin America/Orthodox separating.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 20:37:02 +08:00
wassnameandClaudypoo 2af00b374c Extract IW zone taxonomy to tinymfv.zones, extend to WVS 90 countries
Second consumer (the WVS map) needs the same curated zone data, so move it out of
the showcase script into the package rather than duplicate it (avoids drift in
research data). Extended IW_ZONE to cover all 90 WVS countries + SAR/name-variant
aliases. Showcase script now imports zones_for from tinymfv.zones.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 20:26:44 +08:00
wassnameandClaudypoo b2532acd90 Switch zone blobs to country-mean covariance ellipses, fit PCA on means
Per feedback the individual-respondent contours filled the frame (within >>
between variance). Now each IW zone is a ~1.6-sigma covariance ellipse over its
member country-mean dots, with an eigenvalue floor so 1-2 country zones get a
visible blob instead of a dot/line (fixes big5 SG/PK orphans). PCA now fits on the
country means M so the axes are between-country and zones separate. mfq2/big5/mfv
read cleanly; humor still overlaps (real negative result: humor country profiles
don't cluster the IW way).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 20:22:23 +08:00
wassnameandClaudypoo f5efbd24bd Add sampling readout for logprob-less API models (OpenRouter)
read_api.read_items_sampled samples N chat completions at temperature and uses the
empirical answer frequency as the per-item categorical p, emitting the same row
shape the logprob reader does -- so E/profile/entropy flow through the identical
per_item_categorical + reducers and a frontier model without logprobs drops onto
the same map. pmass_allowed becomes the parse rate (sampling coherence gate); C/LO
are omitted by design (log of a frequency has -inf zeros). This is the Economist's
'average of ten responses' method.

UAT (docs/reviews/p3_api_sampling_uat.md): E_mc == E_logprob to <=0.01 (unbiased),
llama-3.1-8b sampled E lands on the same [1,5] scale, parse-rate gate flags
off-format draws.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 19:39:18 +08:00
wassnameandClaudypoo 2c2dd9b9bf Add MFQ-2 per-zone p90 respondent ellipses to ipsative map
respondent_profiles now returns countries alongside profiles; plot_ipsative_pca
gains respondent_zones -> a p90 Gaussian ellipse per IW zone of the projected
Atari respondent cloud (edge-only, no scipy). mfq2 uses these real-respondent
ellipses; the other instruments keep country-mean hulls. Journal notes the
finding: individual profiles overlap across cultures (within >> between variance),
so only the country-mean hull reproduces the Economist's clean zone blobs.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 19:25:52 +08:00
wassnameandClaudypoo 0e7178dfbd Add Inglehart-Welzel zone hulls + outlier labels to ipsative maps
Echoes the Economist WVS 'Godless hippies' chart: shaded convex-hull blobs per
IW cultural zone (inline 2D hull, no scipy dep so the maps extra stays
matplotlib-only) and bold-first labels for named outliers. Caller owns the zone
taxonomy + name/ISO2 normalizer, fails loud on unmapped countries; the corrupt
'(nu' big5 row is explicitly excluded with a warning.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-04 19:16:41 +08:00
wassname 061ce8a4f6 Export MFQ2 sample logprobs for N bootstrap 2026-07-01 06:24:13 +08:00
wassname 6fcdfea30f Support sampled survey reads and MFV c-grid plots 2026-06-30 13:28:20 +08:00
wassname d8941f47ac Rewrite README around profile plots 2026-06-30 12:38:20 +08:00
wassname 5a39b7ba9c Simplify showcase plot encodings 2026-06-29 21:32:05 +08:00
wassnameandClaudypoo 4cc233db3c eval: add a load-bearing SHOULD next to the default-level aux stats
At verbose level 1 (default) the aux-stats line and 64-char free-form had no
interpretation; only verbose>=2 carried SHOULDs. Pair a directional/counterfactual
SHOULD with the always-shown aux stats: pmass_allowed near base + informedness>0 =
in-format signal; pmass_allowed falling / frac_unscorable rising while informedness->0
= the steer broke format and the moral numbers are noise (the steer/breakage confound).

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-06-27 08:32:43 +08:00
wassnameandClaudypoo 3732994193 unscorable reads -> NaN + nanmean, add frac_unscorable coherence signal
pmass under a force-prefilled slot is pinned high (the scaffold primes a
valid token), so a low mean_pmass no longer flags steering breakage. Make
the real signal explicit: unscorable rows (self-close with no answer slot,
or a non-finite forward) now carry pmass=NaN instead of a fabricated 0.0 --
an undefined read is not zero coherence. Means use nanmean (drop them,
matching the dlogit path); frac_unscorable reports the drop rate, and
mean_nll_prefill (scaffold fit) is the sensitive coherence readout. Smoke:
frac_unscorable=0.0, mean_pmass=0.985.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-06-26 21:13:17 +08:00