Primes; Main Python Script Used: POLARITY COMPARISON — neg_mod30 vs pos_mod30 (Compared with each other and with both)

For Part 1, File_00 to File_30, see https://490d.com/the-490d-unified-chronology-knowledge-graph-repository/


!/usr/bin/env python3

“””

POLARITY COMPARISON — neg_mod30 vs pos_mod30

Companion to the generic both_mod30 validation script.

Purpose: Demonstrate that the two rail polarities contribute
asymmetrically to the signal, confirming the structural
correspondence between neg_mod30 and BC (negative) dates.

Rail systems tested per tier:
neg_mod30 : B, -B, -M (3 rails per quad)
pos_mod30 : B, M, -B (3 rails per quad)
both_mod30 : B, M, -B, -M (4 rails per quad — reference baseline)

Targets : Same 63 MT-only unsigned targets as the generic script.
(P2-normalized via decadal admission gate; no minus signs.)

Core claim : TRIO_CORE = [2300, 2520, 3430]
Expanded : ALL_CYCLES = Year + Key23 + Daniel families

Tier naming : Pn denotes tier n of the curated build.
Sizes: P3 = 1; P4 = 4; for k >= 5, |Pk| = 4 + 3*(k-4).

Z-score method: Multi-seed MC (20 seeds x 100,000 samples) plus
analytical (exact mean; variance exact when joint periods <= 1e7,
else covariance is MC-estimated).
“””

import math
import random
import warnings
from functools import reduce
import numpy as np

— Colab / matplotlib setup —

try:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
HAS_MPL = True
plt.rcParams.update({
‘figure.facecolor’: ‘#FAFAF8’,
‘axes.facecolor’: ‘#FAFAF8’,
‘axes.edgecolor’: ‘#333333’,
‘axes.labelcolor’: ‘#222222’,
‘text.color’: ‘#222222’,
‘xtick.color’: ‘#444444’,
‘ytick.color’: ‘#444444’,
‘grid.color’: ‘#DDDDDD’,
‘grid.linestyle’: ‘–‘,
‘grid.alpha’: 0.7,
‘font.family’: ‘serif’,
‘font.size’: 11,
‘axes.titlesize’: 13,
‘axes.titleweight’: ‘bold’,
‘figure.titlesize’: 15,
‘figure.titleweight’:’bold’,
})
except ImportError:
HAS_MPL = False
print(“⚠ matplotlib not found — charts will be skipped.”)

=========================================================

COLOUR PALETTE

=========================================================

C_NEG = ‘#C0392B’ # warm red — neg_mod30
C_POS = ‘#2E86C1’ # cool blue — pos_mod30
C_BOTH = ‘#7D8C8E’ # neutral grey — both_mod30 reference
C_OBS = ‘#1B1B1B’ # near-black — observed marker

=========================================================

TARGETS (MT only: Cum ±Cainan + Regular; P2-normalized

via decadal admission gate; no minus signs)

#

These are the post-gate decade admissions produced from

MT Regular + MT Cumulative (±Cainan) using the P2

naturalization-before-gate protocol. This script does

not regenerate them; if the forwarded bands or the P2

gate are revised, TARGETS must be regenerated and rerun. Targets “160, 440, 530, 600” are optional, but included here because they represent the 70-year exile (606 to 536 BC) and the initial fulfillment of the Danielic prophecies (in 445 and 165 BC).

=========================================================

TARGETS = sorted(set([

   160, 440, 530, 600,               
1400, 1440, 1470, 1520, 1870, 2000, 2060, 2070,
2080, 2160, 2230, 2250, 2260, 2290, 2320, 2350, 2430, 2450,
2550, 2630, 2640, 2780, 3010, 3050, 3120, 3250, 3420, 3490,
3650, 3950, 3960, 3980, 4110, 4390, 4830, 4850, 5290, 5430,
5890, 6380, 6840, 7150, 7610, 8120, 8490, 8580, 8950, 9450,
9910, 10340, 10350, 10800, 10810, 11250, 11260, 11710, 11720, 12160,
12620, 13070, 13530, 14000, 14460

]))
print(f”Targets: {len(TARGETS)} dates”)

=========================================================

CYCLE FAMILIES

=========================================================

── Core claim: the standard trio ──

TRIO_CORE = [2300, 2520, 3430]

── Expanded families (cross-validation) ──

FAMILY_YEAR = [3360, 3540, 3600, 3610, 3640, 3650, 14610, 12900, 12960, 10000]
FAMILY_KEY23 = [2300, 2990, 6900]
FAMILY_DANIEL = [1000, 2520, 2550, 2580, 3430, 6660, 12000]
ALL_CYCLES = FAMILY_YEAR + FAMILY_KEY23 + FAMILY_DANIEL

STEP = 30

=========================================================

PRIME QUADRUPLET TIERS (P3–P18)

#

Pn denotes tier n of the curated build.

Sizes: P3 = 1; P4 = 4; for k ≥ 5, |Pk| = 4 + 3·(k − 4).

=========================================================

PRIME_QUAD_LISTS = {
‘P3’: [101],
‘P4’: [101, 191, 281, 911],
‘P5’: [101, 191, 281, 821, 911, 1091, 1751],
‘P6’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 2561, 2951],
‘P7’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2561, 2951, 4421, 4631],
‘P8’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 4421, 4631, 6491, 7661],
‘P9’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 4421, 4631, 6491, 7661, 9731, 9941],
‘P10’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 6491, 7661, 9731, 9941, 13181, 15371],
‘P11’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9731, 9941, 13181, 15371, 18821, 22601],
‘P12’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13181, 15371, 18821, 22601, 28241, 31811],
‘P13’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 18821, 22601, 28241, 31811, 41231, 43871],
‘P14’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951],
‘P15’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911],
‘P16’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 16061, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911, 88631, 90611],
‘P17’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 16061, 18041, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911, 88631, 90611, 106661, 107531],
‘P18’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 16061, 18041, 18821, 18911, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911, 88631, 90611, 106661, 107531, 125561, 126071],
}

── Tier sanity check: P3 = 1, P4 = 4, then +3 per tier ──

for k in range(3, 19):
pn = f”P{k}”
if pn not in PRIME_QUAD_LISTS:
continue
if k == 3:
expected = 1
elif k == 4:
expected = 4
else:
expected = 4 + 3 * (k – 4)
actual = len(PRIME_QUAD_LISTS[pn])
assert actual == expected, (
f”Tier {pn}: expected {expected} quads, got {actual}”
)
print(f”✓ All {len(PRIME_QUAD_LISTS)} tiers pass size check (P3=1, P4=4, +3/tier)”)

=========================================================

HELPERS

=========================================================

def compute_lcm(nums):
def lcm(a, b):
return abs(a * b) // math.gcd(a, b)
return reduce(lcm, nums, 1)

def build_rails(quads, config=”both_mod30″):
“””Generate rails from quadruplet starts.”””
rails = []
for Q in quads:
B = Q – 11
M = B + 30
if config == “no_mod30”: rails.extend([B, -B])
elif config == “neg_mod30”: rails.extend([B, -B, -M])
elif config == “pos_mod30”: rails.extend([B, M, -B])
elif config == “both_mod30”: rails.extend([B, M, -B, -M])
return rails

def score_observed(rails, targets, cycles):
total = 0
for c in cycles:
for r in rails:
for t in targets:
if (t – r) % c == 0:
total += 1
return total

def compute_K(cycles, step=STEP):
“””LCM of periods — the shift lattice cardinality.”””
periods = [c // math.gcd(c, step) for c in cycles]
return compute_lcm(periods)

=========================================================

MC + ANALYTICAL ENGINES

=========================================================

MC_SAMPLES = 100_000
MC_RUNS = 20

def multi_seed_mc(rails, targets, cycles, n_runs=MC_RUNS,
samples_per_run=MC_SAMPLES):
“””Run multiple independent MC trials → CI on Z.”””
obs = score_observed(rails, targets, cycles)

residue_counts = []
for c in cycles:
    counts = np.zeros(c, dtype=np.int32)
    for r in rails:
        for t in targets:
            counts[(t - r) % c] += 1
    residue_counts.append((c, counts))

K = compute_K(cycles)

z_values = []
all_scores = []
for run in range(n_runs):
    rng = random.Random(run * 12345 + 7)
    scores = np.empty(samples_per_run, dtype=np.int32)
    for i in range(samples_per_run):
        offset = rng.randrange(K)
        shift = offset * STEP
        total = 0
        for c, counts in residue_counts:
            total += counts[shift % c]
        scores[i] = total

    mean = float(np.mean(scores))
    std  = float(np.std(scores, ddof=0))
    if std > 1e-9:
        z = (obs - mean) / std
        z_values.append(z)
    all_scores.append(scores)

return z_values, obs, all_scores

def analytical_stats(rails, targets, cycles, verbose=False):
“””Exact E[S]; Var[S] exact when all joint periods <= 1e7,
else covariance is estimated by sampling.”””
obs = score_observed(rails, targets, cycles)

total_mean = 0.0
total_var_independent = 0.0
cycle_histograms = {}

for c in cycles:
    g = math.gcd(c, STEP)
    period = c // g

    hist = np.zeros(period, dtype=np.int64)
    for r in rails:
        for t in targets:
            diff = (t - r) % c
            if diff % g == 0:
                slot = (diff // g) % period
                hist[slot] += 1

    e_hits  = float(np.mean(hist))
    v_hits  = float(np.var(hist, ddof=0))

    total_mean += e_hits
    total_var_independent += v_hits
    cycle_histograms[c] = (g, period, hist)

total_cov = 0.0
n_cycle_pairs = 0

for i, c1 in enumerate(cycles):
    _g1, p1, h1 = cycle_histograms[c1]
    for c2 in cycles[i + 1:]:
        _g2, p2, h2 = cycle_histograms[c2]
        joint_period = compute_lcm([p1, p2])

        mu1 = float(np.mean(h1))
        mu2 = float(np.mean(h2))

        if joint_period <= 10_000_000:
            offsets = np.arange(joint_period, dtype=np.int64)
            vals1 = h1[offsets % p1].astype(np.float64)
            vals2 = h2[offsets % p2].astype(np.float64)
            e_product = float(np.mean(vals1 * vals2))
        else:
            rng = random.Random(42 + i * 1000 + n_cycle_pairs)
            n_sample = min(500_000, joint_period)
            offsets = np.array([rng.randrange(joint_period)
                                for _ in range(n_sample)], dtype=np.int64)
            vals1 = h1[offsets % p1].astype(np.float64)
            vals2 = h2[offsets % p2].astype(np.float64)
            e_product = float(np.mean(vals1 * vals2))

        cov = e_product - mu1 * mu2
        total_cov += cov
        n_cycle_pairs += 1

total_var = total_var_independent + 2.0 * total_cov
if total_var < 0:
    warnings.warn(f"Negative total_var ({total_var:.6f}) — clamping.")
    total_var = total_var_independent

total_std = math.sqrt(total_var) if total_var > 0 else 1e-12
z_analytical = (obs - total_mean) / total_std

if verbose:
    print(f"    Obs={obs}  E[S]={total_mean:.2f}  "
          f"std={total_std:.2f}  Z={z_analytical:+.4f}")

return z_analytical, obs, total_mean, total_std

=========================================================

EVALUATE ONE CONFIGURATION

=========================================================

def evaluate_config(config_name, quads, targets, cycles):
“””Run MC + analytical for one rail configuration. Returns dict.”””
rails = build_rails(quads, config_name)

# MC
z_values, obs, score_lists = multi_seed_mc(rails, targets, cycles)
z_mean = float(np.mean(z_values))
z_std  = float(np.std(z_values, ddof=1)) if len(z_values) > 1 else 0.0
ci_lo  = z_mean - 1.96 * z_std / math.sqrt(max(len(z_values), 1))
ci_hi  = z_mean + 1.96 * z_std / math.sqrt(max(len(z_values), 1))

# Analytical
z_anal, _, mean_a, std_a = analytical_stats(rails, targets, cycles)

return {
    'config':         config_name,
    'n_rails':        len(rails),
    'obs':            obs,
    'mc_z_mean':      z_mean,
    'mc_z_std':       z_std,
    'mc_ci':          (ci_lo, ci_hi),
    'mc_z_values':    z_values,
    'mc_scores_seed0': score_lists[0] if score_lists else np.array([]),
    'analytical_z':   z_anal,
    'analytical_mean': mean_a,
    'analytical_std':  std_a,
}

=========================================================

CHARTS

=========================================================

def plot_polarity_ladder(all_results):
“””Fig 1: Z-score progression — neg vs pos vs both, TRIO.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
x = np.arange(n)

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 10),
                                constrained_layout=True,
                                sharex=True)
fig.suptitle('Polarity Comparison — neg_mod30 vs pos_mod30 vs both_mod30',
             fontsize=16, fontweight='bold')

# ── Panel A: TRIO ──
for cfg, color, ls, marker in [
    ('neg_mod30',  C_NEG,  '-',  'o'),
    ('pos_mod30',  C_POS,  '-',  's'),
    ('both_mod30', C_BOTH, '--', 'D'),
]:
    z_vals = [all_results[t]['trio'][cfg]['mc_z_mean'] for t in tiers]
    ci_lo  = [all_results[t]['trio'][cfg]['mc_ci'][0] for t in tiers]
    ci_hi  = [all_results[t]['trio'][cfg]['mc_ci'][1] for t in tiers]

    ax1.fill_between(x, ci_lo, ci_hi, color=color, alpha=0.10)
    ax1.plot(x, z_vals, f'{marker}{ls}', color=color, lw=2, ms=6,
             label=f'{cfg}', alpha=0.9)

ax1.axhline(0, color='#999999', lw=0.8)
ax1.set_ylabel('Z-score (MC)')
ax1.set_title('A.  TRIO [2300, 2520, 3430]')
ax1.legend(fontsize=10, framealpha=0.9, edgecolor='#CCCCCC')
ax1.grid(axis='y')

# ── Panel B: ALL ──
for cfg, color, ls, marker in [
    ('neg_mod30',  C_NEG,  '-',  'o'),
    ('pos_mod30',  C_POS,  '-',  's'),
    ('both_mod30', C_BOTH, '--', 'D'),
]:
    z_vals = [all_results[t]['all'][cfg]['mc_z_mean'] for t in tiers]
    ci_lo  = [all_results[t]['all'][cfg]['mc_ci'][0] for t in tiers]
    ci_hi  = [all_results[t]['all'][cfg]['mc_ci'][1] for t in tiers]

    ax2.fill_between(x, ci_lo, ci_hi, color=color, alpha=0.10)
    ax2.plot(x, z_vals, f'{marker}{ls}', color=color, lw=2, ms=6,
             label=f'{cfg}', alpha=0.9)

ax2.axhline(0, color='#999999', lw=0.8)
ax2.set_ylabel('Z-score (MC)')
ax2.set_xlabel('Prime-Quadruplet Tier')
ax2.set_title(f'B.  ALL CYCLES ({len(ALL_CYCLES)} cycles)')
ax2.set_xticks(x)
ax2.set_xticklabels(tiers, fontsize=10)
ax2.legend(fontsize=10, framealpha=0.9, edgecolor='#CCCCCC')
ax2.grid(axis='y')

plt.savefig('polarity_ladder.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → polarity_ladder.png")

def plot_polarity_delta(all_results):
“””Fig 2: Delta Z (neg − pos) across tiers for TRIO and ALL.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
x = np.arange(n)

trio_delta = [all_results[t]['trio']['neg_mod30']['mc_z_mean']
              - all_results[t]['trio']['pos_mod30']['mc_z_mean']
              for t in tiers]
all_delta  = [all_results[t]['all']['neg_mod30']['mc_z_mean']
              - all_results[t]['all']['pos_mod30']['mc_z_mean']
              for t in tiers]

fig, ax = plt.subplots(figsize=(14, 5), constrained_layout=True)

w = 0.35
ax.bar(x - w/2, trio_delta, w, color=C_NEG, alpha=0.7,
       label='TRIO (neg − pos)', edgecolor='white', linewidth=0.5)
ax.bar(x + w/2, all_delta, w, color=C_POS, alpha=0.7,
       label='ALL (neg − pos)', edgecolor='white', linewidth=0.5)

ax.axhline(0, color='#999999', lw=1)
ax.set_xticks(x)
ax.set_xticklabels(tiers, fontsize=10)
ax.set_xlabel('Prime-Quadruplet Tier')
ax.set_ylabel('ΔZ  (neg_mod30 − pos_mod30)')
ax.set_title('Polarity Asymmetry: ΔZ = Z(neg) − Z(pos)')
ax.legend(fontsize=10, framealpha=0.9, edgecolor='#CCCCCC')
ax.grid(axis='y')

plt.savefig('polarity_delta.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → polarity_delta.png")

def plot_polarity_null_comparison(all_results):
“””Fig 3: Side-by-side null distributions for neg vs pos (TRIO),
selected tiers in a 4×4 grid.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
ncols = 4
nrows = math.ceil(n / ncols)

fig, axes = plt.subplots(nrows, ncols, figsize=(5 * ncols, 3.8 * nrows),
                         constrained_layout=True, squeeze=False)
fig.suptitle('Null Distributions — neg_mod30 vs pos_mod30 (TRIO)',
             fontsize=14, fontweight='bold')

for idx, pn in enumerate(tiers):
    r, c_idx = divmod(idx, ncols)
    ax = axes[r][c_idx]

    neg_scores = all_results[pn]['trio']['neg_mod30']['mc_scores_seed0']
    pos_scores = all_results[pn]['trio']['pos_mod30']['mc_scores_seed0']
    neg_obs    = all_results[pn]['trio']['neg_mod30']['obs']
    pos_obs    = all_results[pn]['trio']['pos_mod30']['obs']

    ax.hist(neg_scores, bins=40, density=True, color=C_NEG,
            alpha=0.40, edgecolor='white', linewidth=0.3, label='neg null')
    ax.hist(pos_scores, bins=40, density=True, color=C_POS,
            alpha=0.40, edgecolor='white', linewidth=0.3, label='pos null')

    ax.axvline(neg_obs, color=C_NEG, lw=2, ls='--',
               label=f'neg obs={neg_obs}')
    ax.axvline(pos_obs, color=C_POS, lw=2, ls=':',
               label=f'pos obs={pos_obs}')

    ax.set_xlabel('Score')
    ax.set_ylabel('Density')
    ax.set_title(pn, fontsize=12)
    ax.legend(fontsize=7, framealpha=0.9, edgecolor='#CCCCCC')
    ax.grid(axis='y')

for idx in range(n, nrows * ncols):
    r, c_idx = divmod(idx, ncols)
    axes[r][c_idx].set_visible(False)

plt.savefig('polarity_null_comparison.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → polarity_null_comparison.png")

def plot_observed_breakdown(all_results):
“””Fig 4: Stacked-style bar chart — observed hits per config.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
x = np.arange(n)

fig, ax = plt.subplots(figsize=(14, 5), constrained_layout=True)

w = 0.25
for i, (cfg, color) in enumerate([
    ('neg_mod30', C_NEG), ('pos_mod30', C_POS), ('both_mod30', C_BOTH)
]):
    obs = [all_results[t]['trio'][cfg]['obs'] for t in tiers]
    ax.bar(x + (i - 1) * w, obs, w, color=color, alpha=0.80,
           label=cfg, edgecolor='white', linewidth=0.5)

ax.set_xticks(x)
ax.set_xticklabels(tiers, fontsize=10)
ax.set_xlabel('Prime-Quadruplet Tier')
ax.set_ylabel('Observed Hits (TRIO)')
ax.set_title('Observed Hits by Rail Configuration — TRIO [2300,2520,3430]')
ax.legend(fontsize=10, framealpha=0.9, edgecolor='#CCCCCC')
ax.grid(axis='y')

plt.savefig('polarity_observed.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → polarity_observed.png")

=========================================================

MAIN

=========================================================

def main():
tier_names = [f”P{k}” for k in range(3, 19)]
configs = [‘neg_mod30’, ‘pos_mod30’, ‘both_mod30’]

all_results = {}

# ── Metadata table ──
K_TRIO = compute_K(TRIO_CORE)
K_ALL  = compute_K(ALL_CYCLES)

print("\n" + "=" * 90)
print("  TIER METADATA — POLARITY COMPARISON")
print("=" * 90)
print(f"  {'Tier':<6} {'Quads':>6} "
      f"{'neg rails':>10} {'pos rails':>10} {'both rails':>11} "
      f"{'Targets':>8}")
print("  " + "-" * 78)
for pn in tier_names:
    quads = PRIME_QUAD_LISTS[pn]
    r_neg  = len(build_rails(quads, 'neg_mod30'))
    r_pos  = len(build_rails(quads, 'pos_mod30'))
    r_both = len(build_rails(quads, 'both_mod30'))
    print(f"  {pn:<6} {len(quads):>6} "
          f"{r_neg:>10} {r_pos:>10} {r_both:>11} "
          f"{len(TARGETS):>8}")

# ── Main evaluation loop ──
for pn in tier_names:
    quads = PRIME_QUAD_LISTS[pn]

    print("\n" + "=" * 90)
    print(f"  {pn}  ({len(quads)} quadruplets, {len(TARGETS)} targets)")
    print("=" * 90)

    tier_data = {'trio': {}, 'all': {}}

    for cfg in configs:
        rails = build_rails(quads, cfg)
        print(f"\n  ── {cfg} ({len(rails)} rails) ──")

        # TRIO
        print(f"    TRIO [{', '.join(str(c) for c in TRIO_CORE)}]:")
        trio_result = evaluate_config(cfg, quads, TARGETS, TRIO_CORE)
        print(f"      MC:   Z = {trio_result['mc_z_mean']:+.4f} "
              f"[{trio_result['mc_ci'][0]:+.4f}, "
              f"{trio_result['mc_ci'][1]:+.4f}]  "
              f"obs={trio_result['obs']}")
        print(f"      Anal: Z = {trio_result['analytical_z']:+.4f}  "
              f"E[S]={trio_result['analytical_mean']:.2f}")

        # ALL
        print(f"    ALL ({len(ALL_CYCLES)} cycles):")
        all_result = evaluate_config(cfg, quads, TARGETS, ALL_CYCLES)
        print(f"      MC:   Z = {all_result['mc_z_mean']:+.4f} "
              f"[{all_result['mc_ci'][0]:+.4f}, "
              f"{all_result['mc_ci'][1]:+.4f}]  "
              f"obs={all_result['obs']}")
        print(f"      Anal: Z = {all_result['analytical_z']:+.4f}  "
              f"E[S]={all_result['analytical_mean']:.2f}")

        tier_data['trio'][cfg] = trio_result
        tier_data['all'][cfg]  = all_result

    # ── Summary ──
    print(f"\n  ╔══ SUMMARY {pn} — TRIO ══╗")
    for cfg in configs:
        d = tier_data['trio'][cfg]
        print(f"  ║ {cfg:>12}: Z = {d['mc_z_mean']:+.4f}  "
              f"obs={d['obs']:>4}  ({d['n_rails']} rails)")
    print(f"  ╚{'═' * 32}╝")

    print(f"  ╔══ SUMMARY {pn} — ALL ══╗")
    for cfg in configs:
        d = tier_data['all'][cfg]
        print(f"  ║ {cfg:>12}: Z = {d['mc_z_mean']:+.4f}  "
              f"obs={d['obs']:>4}  ({d['n_rails']} rails)")
    print(f"  ╚{'═' * 31}╝")

    all_results[pn] = tier_data

# ── Grand summary table ──
print("\n" + "=" * 90)
print("  GRAND SUMMARY — TRIO Z-SCORES (MC)")
print("=" * 90)
print(f"  {'Tier':<6} {'neg_mod30':>12} {'pos_mod30':>12} "
      f"{'both_mod30':>12} {'Δ(neg−pos)':>12}")
print("  " + "-" * 56)
for pn in tier_names:
    zn = all_results[pn]['trio']['neg_mod30']['mc_z_mean']
    zp = all_results[pn]['trio']['pos_mod30']['mc_z_mean']
    zb = all_results[pn]['trio']['both_mod30']['mc_z_mean']
    print(f"  {pn:<6} {zn:>+12.4f} {zp:>+12.4f} "
          f"{zb:>+12.4f} {zn - zp:>+12.4f}")

print(f"\n  {'Tier':<6} {'neg_mod30':>12} {'pos_mod30':>12} "
      f"{'both_mod30':>12} {'Δ(neg−pos)':>12}")
print("  " + "-" * 56)
print("  GRAND SUMMARY — ALL CYCLES Z-SCORES (MC)")
print("  " + "-" * 56)
for pn in tier_names:
    zn = all_results[pn]['all']['neg_mod30']['mc_z_mean']
    zp = all_results[pn]['all']['pos_mod30']['mc_z_mean']
    zb = all_results[pn]['all']['both_mod30']['mc_z_mean']
    print(f"  {pn:<6} {zn:>+12.4f} {zp:>+12.4f} "
          f"{zb:>+12.4f} {zn - zp:>+12.4f}")

# ── Charts ──
print("\n" + "=" * 90)
print("  GENERATING CHARTS")
print("=" * 90)
plot_polarity_ladder(all_results)
plot_polarity_delta(all_results)
plot_polarity_null_comparison(all_results)
plot_observed_breakdown(all_results)

if name == “main“:
main()





Script Used For Both Mod-30 (Same as above, though not specialized for neg or pos preference)

!/usr/bin/env python3

“””

MC RELIABILITY VALIDATION — BOTH_MOD30 (Full 4-Rail System)

Generic hypothesis test: prime-quadruplet phase-lock against MT
biblical chronology targets.

Rail system : B, M, -B, -M (both_mod30) for every quadruplet start Q
Targets : MT only — Cumulative ±Cainan + Regular, P2-normalized via
the decadal admission gate (not rounding), plus privileged
anchors 1446 BC (Exodus), 1406 BC (Conquest), 1876 (Entry
nexus), 3127 (Enoch ascension). No minus signs (sign
irrelevant under both_mod30 symmetry). Aaron at 1520
(same decade gate as Moses).
Core claim : TRIO_CORE = [2300, 2520, 3430]
Expanded : ALL_CYCLES = Year + Key23 + Daniel families (cross-validation)

Tier naming : Pn denotes tier n of the curated build; list sizes are
1 (P3), 4 (P4), 7, 10, 13, … (seed + 3 per tier for k ≥ 5).

Three cross-validating Z-score methods:

  1. MULTI-SEED MC — 20 independent trials → confidence interval
  2. ANALYTICAL — Exact mean; variance exact unless joint periods
    exceed 1e7 (then covariance is MC-estimated)
  3. PER-FAMILY EXACT — Each cycle family tested where K permits
    “””

import math
import random
import warnings
from functools import reduce
import numpy as np

— Colab / matplotlib setup —

try:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import matplotlib.ticker as mticker
HAS_MPL = True
plt.rcParams.update({
‘figure.facecolor’: ‘#FAFAF8’,
‘axes.facecolor’: ‘#FAFAF8’,
‘axes.edgecolor’: ‘#333333’,
‘axes.labelcolor’: ‘#222222’,
‘text.color’: ‘#222222’,
‘xtick.color’: ‘#444444’,
‘ytick.color’: ‘#444444’,
‘grid.color’: ‘#DDDDDD’,
‘grid.linestyle’: ‘–‘,
‘grid.alpha’: 0.7,
‘font.family’: ‘serif’,
‘font.size’: 11,
‘axes.titlesize’: 13,
‘axes.titleweight’: ‘bold’,
‘figure.titlesize’: 15,
‘figure.titleweight’:’bold’,
})
except ImportError:
HAS_MPL = False
print(“⚠ matplotlib not found — charts will be skipped.”)

=========================================================

COLOUR PALETTE (muted jewel tones, colourblind-safe)

=========================================================

C_TRIO = ‘#1B6B93’ # deep ocean blue — core claim
C_ALL = ‘#E07A3A’ # warm amber — expanded
C_OBS = ‘#C0392B’ # signal red — observed marker
C_FAMS = {
‘Year Types’: ‘#2E6171’,
‘Key of 23’: ‘#B55A30’,
‘Daniel/7-fold’: ‘#5E3A7E’,
}

Tier gradient: teal → plum across P4–P18

def tier_color(idx, n):
“””Smooth gradient from teal to plum for tier index.”””
t = idx / max(n – 1, 1)
r = int(46 + t * (94 – 46))
g = int(97 + t * (58 – 97))
b = int(113 + t * (126 – 113))
return f’#{r:02x}{g:02x}{b:02x}’

=========================================================

TARGETS (MT only: Cum ±Cainan + Regular; P2-normalized

via decadal admission gate; no minus signs)

#

These are the post-gate decade admissions produced from

MT Regular + MT Cumulative (±Cainan) using the P2

naturalization-before-gate protocol. This script does

not regenerate them; if the forwarded bands or the P2

gate are revised, TARGETS must be regenerated and rerun.

=========================================================

TARGETS = sorted(set([
1400, 1440, 1470, 1520, 1870, 2000, 2060, 2070,
2080, 2160, 2230, 2250, 2260, 2290, 2320, 2350, 2430, 2450,
2550, 2630, 2640, 2780, 3010, 3050, 3120, 3250, 3420, 3490,
3650, 3950, 3960, 3980, 4110, 4390, 4830, 4850, 5290, 5430,
5890, 6380, 6840, 7150, 7610, 8120, 8490, 8580, 8950, 9450,
9910, 10340, 10350, 10800, 10810, 11250, 11260, 11710, 11720, 12160,
12620, 13070, 13530, 14000, 14460
]))
print(f”Targets: {len(TARGETS)} dates”)

=========================================================

CYCLE FAMILIES

=========================================================

── Core claim: the standard trio ──

TRIO_CORE = [2300, 2520, 3430]

── Expanded families (cross-validation) ──

FAMILY_YEAR = [3360, 3540, 3600, 3610, 3640, 3650, 14610, 12900, 12960, 10000]
FAMILY_KEY23 = [2300, 6900, 2990]
FAMILY_DANIEL = [1000, 2520, 2550, 2580, 3430, 6660, 12000]
ALL_CYCLES = FAMILY_YEAR + FAMILY_KEY23 + FAMILY_DANIEL

STEP = 30

=========================================================

PRIME QUADRUPLET TIERS (P3–P18)

#

Pn denotes tier n of the curated build.

Sizes: P3 = 1; P4 = 4; for k ≥ 5, |Pk| = 4 + 3·(k − 4).

=========================================================

PRIME_QUAD_LISTS = {
‘P3’: [101],
‘P4’: [101, 191, 281, 911],
‘P5’: [101, 191, 281, 821, 911, 1091, 1751],
‘P6’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 2561, 2951],
‘P7’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2561, 2951, 4421, 4631],
‘P8’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 4421, 4631, 6491, 7661],
‘P9’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 4421, 4631, 6491, 7661, 9731, 9941],
‘P10’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 6491, 7661, 9731, 9941, 13181, 15371],
‘P11’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9731, 9941, 13181, 15371, 18821, 22601],
‘P12’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13181, 15371, 18821, 22601, 28241, 31811],
‘P13’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 18821, 22601, 28241, 31811, 41231, 43871],
‘P14’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951],
‘P15’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911],
‘P16’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 16061, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911, 88631, 90611],
‘P17’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 16061, 18041, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911, 88631, 90611, 106661, 107531],
‘P18’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 16061, 18041, 18821, 18911, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911, 88631, 90611, 106661, 107531, 125561, 126071],
}

── Tier sanity check: P3 = 1, P4 = 4, then +3 per tier ──

for k in range(3, 19):
pn = f”P{k}”
if pn not in PRIME_QUAD_LISTS:
continue
if k == 3:
expected = 1
elif k == 4:
expected = 4
else:
expected = 4 + 3 * (k – 4)
actual = len(PRIME_QUAD_LISTS[pn])
assert actual == expected, (
f”Tier {pn}: expected {expected} quads, got {actual}”
)
print(f”✓ All {len(PRIME_QUAD_LISTS)} tiers pass size check (P3=1, P4=4, +3/tier)”)

=========================================================

HELPERS

=========================================================

def compute_lcm(nums):
def lcm(a, b):
return abs(a * b) // math.gcd(a, b)
return reduce(lcm, nums, 1)

def build_rails(quads, config=”both_mod30″):
“””Generate rails from quadruplet starts. Only both_mod30 for generic run.”””
rails = []
for Q in quads:
B = Q – 11
M = B + 30
if config == “no_mod30”: rails.extend([B, -B])
elif config == “neg_mod30”: rails.extend([B, -B, -M])
elif config == “pos_mod30”: rails.extend([B, M, -B])
elif config == “both_mod30”: rails.extend([B, M, -B, -M])
return rails

def score_observed(rails, targets, cycles):
total = 0
for c in cycles:
for r in rails:
for t in targets:
if (t – r) % c == 0:
total += 1
return total

def compute_K(cycles, step=STEP):
“””LCM of periods — the shift lattice cardinality.”””
periods = [c // math.gcd(c, step) for c in cycles]
return compute_lcm(periods)

=========================================================

METHOD 1: MULTI-SEED MONTE CARLO

=========================================================

MC_SAMPLES = 100_000
MC_RUNS = 20

def multi_seed_mc(rails, targets, cycles, n_runs=MC_RUNS,
samples_per_run=MC_SAMPLES):
“””Run multiple independent MC trials → CI on Z.”””
obs = score_observed(rails, targets, cycles)

# Precompute residue-count tables
residue_counts = []
for c in cycles:
    counts = np.zeros(c, dtype=np.int32)
    for r in rails:
        for t in targets:
            counts[(t - r) % c] += 1
    residue_counts.append((c, counts))

K = compute_K(cycles)

z_values = []
all_scores = []
for run in range(n_runs):
    rng = random.Random(run * 12345 + 7)
    scores = np.empty(samples_per_run, dtype=np.int32)
    for i in range(samples_per_run):
        offset = rng.randrange(K)
        shift = offset * STEP
        total = 0
        for c, counts in residue_counts:
            total += counts[shift % c]
        scores[i] = total

    mean = float(np.mean(scores))
    std  = float(np.std(scores, ddof=0))
    if std > 1e-9:
        z = (obs - mean) / std
        z_values.append(z)
    all_scores.append(scores)

return z_values, obs, all_scores

=========================================================

METHOD 2: ANALYTICAL MEAN AND VARIANCE

=========================================================

def analytical_stats(rails, targets, cycles, verbose=True):
“””Exact E[S]; Var[S] exact when all joint periods <= 1e7,
else covariance is estimated by sampling.”””
obs = score_observed(rails, targets, cycles)

total_mean = 0.0
total_var_independent = 0.0

if verbose:
    print(f"\n  Per-cycle breakdown:")
    print(f"  {'Cycle':>8} {'Period':>8} {'E[hits]':>10} {'Var':>12} {'SD':>8}")

cycle_histograms = {}

for c in cycles:
    g = math.gcd(c, STEP)
    period = c // g

    hist = np.zeros(period, dtype=np.int64)
    for r in rails:
        for t in targets:
            diff = (t - r) % c
            if diff % g == 0:
                slot = (diff // g) % period
                hist[slot] += 1

    e_hits  = float(np.mean(hist))
    v_hits  = float(np.var(hist, ddof=0))
    sd_hits = math.sqrt(v_hits) if v_hits > 0 else 0.0

    total_mean += e_hits
    total_var_independent += v_hits
    cycle_histograms[c] = (g, period, hist)

    if verbose:
        print(f"  {c:>8} {period:>8} {e_hits:>10.4f} {v_hits:>12.4f} {sd_hits:>8.4f}")

# Cross-cycle covariance (numpy-vectorised)
total_cov = 0.0
n_cycle_pairs = 0

for i, c1 in enumerate(cycles):
    _g1, p1, h1 = cycle_histograms[c1]
    for c2 in cycles[i + 1:]:
        _g2, p2, h2 = cycle_histograms[c2]
        joint_period = compute_lcm([p1, p2])

        mu1 = float(np.mean(h1))
        mu2 = float(np.mean(h2))

        if joint_period <= 10_000_000:
            offsets = np.arange(joint_period, dtype=np.int64)
            vals1 = h1[offsets % p1].astype(np.float64)
            vals2 = h2[offsets % p2].astype(np.float64)
            e_product = float(np.mean(vals1 * vals2))
        else:
            rng = random.Random(42 + i * 1000 + n_cycle_pairs)
            n_sample = min(500_000, joint_period)
            offsets = np.array([rng.randrange(joint_period)
                                for _ in range(n_sample)], dtype=np.int64)
            vals1 = h1[offsets % p1].astype(np.float64)
            vals2 = h2[offsets % p2].astype(np.float64)
            e_product = float(np.mean(vals1 * vals2))

        cov = e_product - mu1 * mu2
        total_cov += cov
        n_cycle_pairs += 1

total_var = total_var_independent + 2.0 * total_cov
if total_var < 0:
    warnings.warn(f"Negative total_var ({total_var:.6f}) — clamping.")
    total_var = total_var_independent

total_std = math.sqrt(total_var) if total_var > 0 else 1e-12
z_analytical = (obs - total_mean) / total_std

if verbose:
    print(f"\n  Sum of individual variances: {total_var_independent:.4f}")
    print(f"  2 × total covariance:       {2 * total_cov:.4f}")
    print(f"  Total variance:             {total_var:.4f}")
    print(f"  Total std:                  {total_std:.4f}")
    print(f"\n  Observed: {obs}")
    print(f"  E[S]:     {total_mean:.4f}")
    print(f"  Analytical Z = ({obs} - {total_mean:.2f}) / "
          f"{total_std:.2f} = {z_analytical:+.4f}")

return z_analytical, obs, total_mean, total_std

=========================================================

METHOD 3: PER-FAMILY EXACT TESTS

=========================================================

def per_family_exact(rails, targets):
“””Test each family separately where K is small enough.”””
families = {
‘Year Types’: FAMILY_YEAR,
‘Key of 23’: FAMILY_KEY23,
‘Daniel/7-fold’: FAMILY_DANIEL,
}

results = {}
for fname, fcycles in families.items():
    K_family = compute_K(fcycles)
    obs      = score_observed(rails, targets, fcycles)

    if K_family <= 5_000_000:
        method = "EXACT"
        totals = np.zeros(K_family, dtype=np.int32)

        for c in fcycles:
            g      = math.gcd(c, STEP)
            period = c // g
            inv    = pow(STEP // g, -1, period)

            rails_arr = np.asarray(rails, dtype=np.int64)
            targ_arr  = np.asarray(targets, dtype=np.int64)
            diffs     = (targ_arr[:, None] - rails_arr[None, :]) % c
            mask      = (diffs % g) == 0
            valid     = diffs[mask] // g

            if valid.size:
                k0   = (valid * inv) % period
                hits = np.bincount(k0.astype(np.int64),
                                   minlength=period).astype(np.int32)
            else:
                hits = np.zeros(period, dtype=np.int32)

            totals += np.tile(hits, K_family // period)

        mean = float(totals.mean())
        std  = float(totals.std(ddof=0))
    else:
        method = "MC(500K)"
        residue_counts = []
        for c in fcycles:
            counts = np.zeros(c, dtype=np.int32)
            for r in rails:
                for t in targets:
                    counts[(t - r) % c] += 1
            residue_counts.append((c, counts))

        rng    = random.Random(42)
        scores = np.empty(500_000, dtype=np.int32)
        for i in range(500_000):
            offset = rng.randrange(K_family)
            shift  = offset * STEP
            total  = 0
            for c, counts in residue_counts:
                total += counts[shift % c]
            scores[i] = total

        mean = float(np.mean(scores))
        std  = float(np.std(scores, ddof=0))

    z = (obs - mean) / std if std > 1e-9 else 0.0
    p = 0.5 * math.erfc(z / math.sqrt(2.0))

    results[fname] = {
        'z': z, 'obs': obs, 'mean': mean, 'std': std,
        'K': K_family, 'method': method, 'p': p,
    }

    print(f"  {fname:>15}: Z = {z:+.4f}  obs={obs:>4} "
          f"mean={mean:.1f} std={std:.2f}  "
          f"K={K_family:,} ({method})")

return results

=========================================================

CHARTS

=========================================================

def plot_z_ladder(all_results):
“””Fig 1: Z-score progression across tiers for TRIO vs ALL.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
x = np.arange(n)

trio_z   = [all_results[t]['trio_mc_z_mean'] for t in tiers]
trio_lo  = [all_results[t]['trio_mc_ci'][0] for t in tiers]
trio_hi  = [all_results[t]['trio_mc_ci'][1] for t in tiers]
trio_a   = [all_results[t]['trio_analytical_z'] for t in tiers]

all_z    = [all_results[t]['all_mc_z_mean'] for t in tiers]
all_lo   = [all_results[t]['all_mc_ci'][0] for t in tiers]
all_hi   = [all_results[t]['all_mc_ci'][1] for t in tiers]
all_a    = [all_results[t]['all_analytical_z'] for t in tiers]

fig, ax = plt.subplots(figsize=(14, 5.5), constrained_layout=True)

# MC with CI bands
ax.fill_between(x, trio_lo, trio_hi, color=C_TRIO, alpha=0.15)
ax.plot(x, trio_z, 'o-', color=C_TRIO, lw=2, ms=6, label='TRIO [2300,2520,3430] MC')
ax.plot(x, trio_a, 's--', color=C_TRIO, lw=1.2, ms=5, alpha=0.6, label='TRIO Analytical')

ax.fill_between(x, all_lo, all_hi, color=C_ALL, alpha=0.12)
ax.plot(x, all_z, 'o-', color=C_ALL, lw=2, ms=6, label='ALL (20 cycles) MC')
ax.plot(x, all_a, 's--', color=C_ALL, lw=1.2, ms=5, alpha=0.6, label='ALL Analytical')

ax.axhline(0, color='#999999', lw=0.8)
ax.set_xticks(x)
ax.set_xticklabels(tiers, fontsize=10)
ax.set_xlabel('Prime-Quadruplet Tier')
ax.set_ylabel('Z-score')
ax.set_title('Z-Score Progression Across Tiers  ·  both_mod30 (B, M, −B, −M)')
ax.legend(fontsize=9, framealpha=0.9, edgecolor='#CCCCCC', ncol=2)
ax.grid(axis='y')

plt.savefig('z_ladder.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → z_ladder.png")

def plot_mc_spread(all_results):
“””Fig 2: Box + strip of MC seed Z-values (TRIO) across tiers.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
data = [all_results[t]['trio_mc_z_values'] for t in tiers]

fig, ax = plt.subplots(figsize=(14, 5), constrained_layout=True)

bp = ax.boxplot(data, patch_artist=True, widths=0.5,
                medianprops=dict(color='#222222', lw=1.5),
                flierprops=dict(marker='o', ms=3, markerfacecolor='#999'))
rng_jit = np.random.default_rng(0)

for i, (patch, tier) in enumerate(zip(bp['boxes'], tiers)):
    c = tier_color(i, n)
    patch.set_facecolor(c)
    patch.set_alpha(0.40)
    patch.set_edgecolor(c)
    jitter = rng_jit.normal(0, 0.07, len(data[i]))
    ax.scatter(np.full(len(data[i]), i + 1) + jitter, data[i],
               color=c, s=18, alpha=0.75, zorder=3,
               edgecolors='white', linewidths=0.3)

ax.axhline(0, color='#999999', lw=0.8)
ax.set_xticklabels(tiers, fontsize=9)
ax.set_ylabel('Z-score per seed')
ax.set_title(f'MC Seed Spread — TRIO [2300,2520,3430]  '
             f'({MC_RUNS} seeds × {MC_SAMPLES:,} samples)')
ax.grid(axis='y')

plt.savefig('mc_seed_spread.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → mc_seed_spread.png")

def plot_null_distributions(all_results):
“””Fig 3: Null-distribution histograms for ALL tiers (TRIO).”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
np_tiers = len(tiers)
ncols = 4
nrows = math.ceil(np_tiers / ncols)

fig, axes = plt.subplots(nrows, ncols, figsize=(5 * ncols, 3.8 * nrows),
                         constrained_layout=True, squeeze=False)
fig.suptitle(f'Null Distribution vs Observed — TRIO  '
             f'({MC_SAMPLES:,} samples, seed 0)',
             fontsize=14, fontweight='bold')

for idx, pn in enumerate(tiers):
    r, c_idx = divmod(idx, ncols)
    ax = axes[r][c_idx]
    scores = all_results[pn]['trio_mc_scores_seed0']
    obs    = all_results[pn]['trio_obs']
    col    = tier_color(idx, np_tiers)

    ax.hist(scores, bins=50, density=True, color=col,
            alpha=0.50, edgecolor='white', linewidth=0.3, label='Null')
    ax.axvline(obs, color=C_OBS, lw=2, ls='--',
               label=f'Obs = {obs}')
    ax.set_xlabel('Score')
    ax.set_ylabel('Density')
    ax.set_title(pn, fontsize=12)
    ax.legend(fontsize=8, framealpha=0.9, edgecolor='#CCCCCC')
    ax.grid(axis='y')

# Hide unused axes
for idx in range(np_tiers, nrows * ncols):
    r, c_idx = divmod(idx, ncols)
    axes[r][c_idx].set_visible(False)

plt.savefig('null_distributions.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → null_distributions.png")

def plot_obs_vs_expected(all_results):
“””Fig 4: Lollipop chart — Observed vs E[S] for TRIO across tiers.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)

fig, ax = plt.subplots(figsize=(14, 5), constrained_layout=True)

for i, t in enumerate(tiers):
    obs_v  = all_results[t]['trio_obs']
    mean_v = all_results[t]['trio_analytical_mean']
    col    = tier_color(i, n)

    ax.plot([i, i], [mean_v, obs_v], color=col, lw=2.5, zorder=2)
    ax.scatter(i, obs_v, s=80, color=col, zorder=3,
               edgecolors='white', linewidths=0.8,
               label='Observed' if i == 0 else '')
    ax.scatter(i, mean_v, s=80, color=col, zorder=3,
               marker='D', edgecolors='white', linewidths=0.8,
               alpha=0.5, label='E[S]' if i == 0 else '')

ax.set_xticks(range(n))
ax.set_xticklabels(tiers, fontsize=9)
ax.set_ylabel('Total hits')
ax.set_title('Observed vs E[S] — TRIO [2300,2520,3430]')
ax.legend(framealpha=0.9, edgecolor='#CCCCCC')
ax.grid(axis='y')

plt.savefig('obs_vs_expected.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → obs_vs_expected.png")

=========================================================

MAIN

=========================================================

def main():
tier_names = [f”P{k}” for k in range(3, 19)]
all_results = {}

# ── Metadata table ──
K_TRIO = compute_K(TRIO_CORE)
K_ALL  = compute_K(ALL_CYCLES)

print("\n" + "=" * 78)
print("  TIER METADATA")
print("=" * 78)
print(f"  {'Tier':<6} {'Quads':>6} {'Rails':>6} {'Targets':>8} "
      f"{'K(trio)':>14} {'K(all)':>14}")
print("  " + "-" * 68)
for pn in tier_names:
    quads = PRIME_QUAD_LISTS[pn]
    rails = build_rails(quads)
    print(f"  {pn:<6} {len(quads):>6} {len(rails):>6} {len(TARGETS):>8} "
          f"{K_TRIO:>14,} {K_ALL:>14,}")

# ── Main evaluation loop ──
for pn in tier_names:
    quads = PRIME_QUAD_LISTS[pn]
    rails = build_rails(quads)

    print("\n" + "=" * 78)
    print(f"  {pn} / both_mod30  ({len(rails)} rails from "
          f"{len(quads)} quadruplets, {len(TARGETS)} targets)")
    print("=" * 78)

    # ────────── TRIO_CORE (primary claim) ──────────
    print(f"\n{'─'*36}")
    print(f"  TRIO CORE: {TRIO_CORE}")
    print(f"{'─'*36}")

    print(f"\n  MC ({MC_RUNS} runs × {MC_SAMPLES:,} samples)")
    trio_zv, trio_obs, trio_scores = multi_seed_mc(
        rails, TARGETS, TRIO_CORE)

    trio_z_mean = float(np.mean(trio_zv))
    trio_z_std  = float(np.std(trio_zv, ddof=1)) if len(trio_zv) > 1 else 0.0
    trio_ci_lo  = trio_z_mean - 1.96 * trio_z_std / math.sqrt(max(len(trio_zv), 1))
    trio_ci_hi  = trio_z_mean + 1.96 * trio_z_std / math.sqrt(max(len(trio_zv), 1))

    print(f"  Observed: {trio_obs}")
    print(f"  Z: mean={trio_z_mean:+.4f}, std={trio_z_std:.4f}")
    print(f"  95% CI: [{trio_ci_lo:+.4f}, {trio_ci_hi:+.4f}]")

    print(f"\n  Analytical:")
    trio_z_a, _, trio_mean_a, trio_std_a = analytical_stats(
        rails, TARGETS, TRIO_CORE, verbose=True)

    # ────────── ALL_CYCLES (expanded cross-validation) ──────────
    print(f"\n{'─'*36}")
    print(f"  ALL CYCLES: {len(ALL_CYCLES)} cycles (expanded)")
    print(f"{'─'*36}")

    print(f"\n  MC ({MC_RUNS} runs × {MC_SAMPLES:,} samples)")
    all_zv, all_obs, all_scores = multi_seed_mc(
        rails, TARGETS, ALL_CYCLES)

    all_z_mean = float(np.mean(all_zv))
    all_z_std  = float(np.std(all_zv, ddof=1)) if len(all_zv) > 1 else 0.0
    all_ci_lo  = all_z_mean - 1.96 * all_z_std / math.sqrt(max(len(all_zv), 1))
    all_ci_hi  = all_z_mean + 1.96 * all_z_std / math.sqrt(max(len(all_zv), 1))

    print(f"  Observed: {all_obs}")
    print(f"  Z: mean={all_z_mean:+.4f}, std={all_z_std:.4f}")
    print(f"  95% CI: [{all_ci_lo:+.4f}, {all_ci_hi:+.4f}]")

    print(f"\n  Analytical:")
    all_z_a, _, all_mean_a, all_std_a = analytical_stats(
        rails, TARGETS, ALL_CYCLES, verbose=False)
    print(f"  Analytical Z = {all_z_a:+.4f}  "
          f"(E[S]={all_mean_a:.2f}, std={all_std_a:.2f})")

    # ────────── Per-family ──────────
    print(f"\n  Per-family tests:")
    family_results = per_family_exact(rails, TARGETS)

    # ────────── Summary ──────────
    print(f"\n  ╔══ SUMMARY {pn} ══╗")
    print(f"  ║ TRIO MC:   Z = {trio_z_mean:+.4f} "
          f"[{trio_ci_lo:+.4f}, {trio_ci_hi:+.4f}]")
    print(f"  ║ TRIO Anal: Z = {trio_z_a:+.4f}")
    print(f"  ║ ALL  MC:   Z = {all_z_mean:+.4f} "
          f"[{all_ci_lo:+.4f}, {all_ci_hi:+.4f}]")
    print(f"  ║ ALL  Anal: Z = {all_z_a:+.4f}")
    for fname, fdata in family_results.items():
        print(f"  ║  {fname:>14}: Z = {fdata['z']:+.4f} "
              f"({fdata['method']})")
    print(f"  ╚{'═' * (15 + len(pn))}╝")

    # Store for charts
    all_results[pn] = {
        'trio_mc_z_values':    trio_zv,
        'trio_mc_z_mean':      trio_z_mean,
        'trio_mc_z_std':       trio_z_std,
        'trio_mc_ci':          (trio_ci_lo, trio_ci_hi),
        'trio_mc_scores_seed0': trio_scores[0] if trio_scores else np.array([]),
        'trio_obs':            trio_obs,
        'trio_analytical_z':   trio_z_a,
        'trio_analytical_mean': trio_mean_a,
        'trio_analytical_std':  trio_std_a,

        'all_mc_z_mean':       all_z_mean,
        'all_mc_z_std':        all_z_std,
        'all_mc_ci':           (all_ci_lo, all_ci_hi),
        'all_mc_scores_seed0': all_scores[0] if all_scores else np.array([]),
        'all_obs':             all_obs,
        'all_analytical_z':    all_z_a,

        'family':              family_results,
    }

# ── Charts ──
print("\n" + "=" * 78)
print("  GENERATING CHARTS")
print("=" * 78)
plot_z_ladder(all_results)
plot_mc_spread(all_results)
plot_null_distributions(all_results)
plot_obs_vs_expected(all_results)

if name == “main“:
main()



!/usr/bin/env python3

“””

POLARITY COMPARISON — neg_mod30 vs pos_mod30

Companion to the generic both_mod30 validation script.

Purpose: Demonstrate that the two rail polarities contribute
asymmetrically to the signal, confirming the structural
correspondence between neg_mod30 and BC (negative) dates.

Rail systems tested per tier:
neg_mod30 : B, -B, -M (3 rails per quad)
pos_mod30 : B, M, -B (3 rails per quad)
both_mod30 : B, M, -B, -M (4 rails per quad — reference baseline)

Targets : Same 63 MT-only unsigned targets as the generic script.
(P2-normalized via decadal admission gate; no minus signs.)

Core claim : TRIO_CORE = [2300, 2520, 3430]
Expanded : ALL_CYCLES = Year + Key23 + Daniel + Ezekiel families

Tier naming : Pn denotes tier n of the curated build.
Sizes: P3 = 2; P4 = 4; for k >= 5, |Pk| = 4 + 3*(k-4).

Z-score method: Multi-seed MC (20 seeds x 100,000 samples) plus
analytical (exact mean; variance exact when joint periods <= 1e7,
else covariance is MC-estimated).
“””

import math
import random
import warnings
from functools import reduce
import numpy as np

— Colab / matplotlib setup —

try:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
HAS_MPL = True
plt.rcParams.update({
‘figure.facecolor’: ‘#FAFAF8’,
‘axes.facecolor’: ‘#FAFAF8’,
‘axes.edgecolor’: ‘#333333’,
‘axes.labelcolor’: ‘#222222’,
‘text.color’: ‘#222222’,
‘xtick.color’: ‘#444444’,
‘ytick.color’: ‘#444444’,
‘grid.color’: ‘#DDDDDD’,
‘grid.linestyle’: ‘–‘,
‘grid.alpha’: 0.7,
‘font.family’: ‘serif’,
‘font.size’: 11,
‘axes.titlesize’: 13,
‘axes.titleweight’: ‘bold’,
‘figure.titlesize’: 15,
‘figure.titleweight’:’bold’,
})
except ImportError:
HAS_MPL = False
print(“⚠ matplotlib not found — charts will be skipped.”)

=========================================================

COLOUR PALETTE

=========================================================

C_NEG = ‘#C0392B’ # warm red — neg_mod30
C_POS = ‘#2E86C1’ # cool blue — pos_mod30
C_BOTH = ‘#7D8C8E’ # neutral grey — both_mod30 reference
C_OBS = ‘#1B1B1B’ # near-black — observed marker

=========================================================

TARGETS (MT only: Cum ±Cainan + Regular; P2-normalized

via decadal admission gate; no minus signs)

#

These are the post-gate decade admissions produced from

MT Regular + MT Cumulative (±Cainan) using the P2

naturalization-before-gate protocol. This script does

not regenerate them; if the forwarded bands or the P2

gate are revised, TARGETS must be regenerated and rerun.

=========================================================

TARGETS = sorted(set([
160, 440, 530, 600,
1400, 1440, 1470, 1520, 1870, 2000, 2060, 2070,
2080, 2160, 2230, 2250, 2260, 2290, 2320, 2350, 2430, 2450,
2550, 2630, 2640, 2780, 3010, 3050, 3120, 3250, 3420, 3490,
3650, 3950, 3960, 3980, 4110, 4390, 4830, 4850, 5290, 5430,
5890, 6380, 6840, 7150, 7610, 8120, 8490, 8580, 8950, 9450,
9910, 10340, 10350, 10800, 10810, 11250, 11260, 11710, 11720, 12160,
12620, 13070, 13530, 14000, 14460
]))
print(f”Targets: {len(TARGETS)} dates”)

=========================================================

CYCLE FAMILIES

=========================================================

── Core claim: the standard trio ──

TRIO_CORE = [2300, 2520, 3430]

── Expanded families (cross-validation) ──

FAMILY_YEAR = [3360, 3540, 3600, 3610, 3640, 3650, 14610, 12900, 12960, 10000]
FAMILY_KEY23 = [2300, 2990, 6900]
FAMILY_DANIEL_REVELATION = [1000, 2520, 2550, 3430, 6660, 12000]
FAMILY_EZEKIEL = [1500, 1900, 3900, 4300]
ALL_CYCLES = FAMILY_YEAR + FAMILY_KEY23 + FAMILY_DANIEL_REVELATION + FAMILY_EZEKIEL

STEP = 30

=========================================================

PRIME QUADRUPLET TIERS (P3–P18)

#

Pn denotes tier n of the curated build.

Sizes: P3 = 2; P4 = 4; for k ≥ 5, |Pk| = 4 + 3·(k − 4).

=========================================================

PRIME_QUAD_LISTS = {
‘P3’: [101, 191],
‘P4’: [101, 191, 281, 911],
‘P5’: [101, 191, 281, 821, 911, 1091, 1751],
‘P6’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 2561, 2951],
‘P7’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2561, 2951, 4421, 4631],
‘P8’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 4421, 4631, 6491, 7661],
‘P9’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 4421, 4631, 6491, 7661, 9731, 9941],
‘P10’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 6491, 7661, 9731, 9941, 13181, 15371],
‘P11’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9731, 9941, 13181, 15371, 18821, 22601],
‘P12’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13181, 15371, 18821, 22601, 28241, 31811],
‘P13’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 18821, 22601, 28241, 31811, 41231, 43871],
‘P14’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951],
‘P15’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911],
‘P16’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 16061, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911, 88631, 90611],
‘P17’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 16061, 18041, 18821, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911, 88631, 90611, 106661, 107531],
‘P18’: [101, 191, 281, 821, 911, 1091, 1481, 1751, 1871, 2081, 2561, 2951, 3251, 3461, 4421, 4631, 5651, 6491, 7661, 9431, 9731, 9941, 13001, 13181, 15371, 15641, 15731, 16061, 18041, 18821, 18911, 22601, 28241, 31811, 41231, 43871, 56861, 56951, 72581, 72911, 88631, 90611, 106661, 107531, 125561, 126071],
}

── Tier sanity check: P3 = 2, P4 = 4, then +3 per tier ──

for k in range(3, 19):
pn = f”P{k}”
if pn not in PRIME_QUAD_LISTS:
continue
if k == 3:
expected = 2
elif k == 4:
expected = 4
else:
expected = 4 + 3 * (k – 4)
actual = len(PRIME_QUAD_LISTS[pn])
assert actual == expected, (
f”Tier {pn}: expected {expected} quads, got {actual}”
)
print(f”✓ All {len(PRIME_QUAD_LISTS)} tiers pass size check (P3=2, P4=4, +3/tier)”)

=========================================================

FOUNDATION-STRIPPED TIERS (P4–P18 without 101, 191)

#

101 and 191 are the P3 “foundation” quads (mod-210

sextuplet base). This variant removes them to test

whether the foundation drags signal down or contributes.

P3 is omitted entirely (would be empty).

=========================================================

FOUNDATION = {101, 191}
PRIME_QUAD_LISTS_STRIPPED = {}
for pn, quads in PRIME_QUAD_LISTS.items():
stripped = [q for q in quads if q not in FOUNDATION]
if stripped: # skip P3 (becomes empty)
PRIME_QUAD_LISTS_STRIPPED[pn] = stripped

print(f”✓ Stripped lists: {len(PRIME_QUAD_LISTS_STRIPPED)} tiers “
f”(P4: {len(PRIME_QUAD_LISTS_STRIPPED.get(‘P4’,[]))} quads, “
f”P18: {len(PRIME_QUAD_LISTS_STRIPPED.get(‘P18’,[]))} quads)”)

=========================================================

HELPERS

=========================================================

def compute_lcm(nums):
def lcm(a, b):
return abs(a * b) // math.gcd(a, b)
return reduce(lcm, nums, 1)

def build_rails(quads, config=”both_mod30″):
“””Generate rails from quadruplet starts.”””
rails = []
for Q in quads:
B = Q – 11
M = B + 30
if config == “no_mod30”: rails.extend([B, -B])
elif config == “neg_mod30”: rails.extend([B, -B, -M])
elif config == “pos_mod30”: rails.extend([B, M, -B])
elif config == “both_mod30”: rails.extend([B, M, -B, -M])
return rails

def score_observed(rails, targets, cycles):
total = 0
for c in cycles:
for r in rails:
for t in targets:
if (t – r) % c == 0:
total += 1
return total

def compute_K(cycles, step=STEP):
“””LCM of periods — the shift lattice cardinality.”””
periods = [c // math.gcd(c, step) for c in cycles]
return compute_lcm(periods)

=========================================================

MC + ANALYTICAL ENGINES

=========================================================

MC_SAMPLES = 100_000
MC_RUNS = 20

def multi_seed_mc(rails, targets, cycles, n_runs=MC_RUNS,
samples_per_run=MC_SAMPLES):
“””Run multiple independent MC trials → CI on Z.”””
obs = score_observed(rails, targets, cycles)

residue_counts = []
for c in cycles:
    counts = np.zeros(c, dtype=np.int32)
    for r in rails:
        for t in targets:
            counts[(t - r) % c] += 1
    residue_counts.append((c, counts))

K = compute_K(cycles)

z_values = []
all_scores = []
for run in range(n_runs):
    rng = random.Random(run * 12345 + 7)
    scores = np.empty(samples_per_run, dtype=np.int32)
    for i in range(samples_per_run):
        offset = rng.randrange(K)
        shift = offset * STEP
        total = 0
        for c, counts in residue_counts:
            total += counts[shift % c]
        scores[i] = total

    mean = float(np.mean(scores))
    std  = float(np.std(scores, ddof=0))
    if std > 1e-9:
        z = (obs - mean) / std
        z_values.append(z)
    all_scores.append(scores)

return z_values, obs, all_scores

def analytical_stats(rails, targets, cycles, verbose=False):
“””Exact E[S]; Var[S] exact when all joint periods <= 1e7,
else covariance is estimated by sampling.”””
obs = score_observed(rails, targets, cycles)

total_mean = 0.0
total_var_independent = 0.0
cycle_histograms = {}

for c in cycles:
    g = math.gcd(c, STEP)
    period = c // g

    hist = np.zeros(period, dtype=np.int64)
    for r in rails:
        for t in targets:
            diff = (t - r) % c
            if diff % g == 0:
                slot = (diff // g) % period
                hist[slot] += 1

    e_hits  = float(np.mean(hist))
    v_hits  = float(np.var(hist, ddof=0))

    total_mean += e_hits
    total_var_independent += v_hits
    cycle_histograms[c] = (g, period, hist)

total_cov = 0.0
n_cycle_pairs = 0

for i, c1 in enumerate(cycles):
    _g1, p1, h1 = cycle_histograms[c1]
    for c2 in cycles[i + 1:]:
        _g2, p2, h2 = cycle_histograms[c2]
        joint_period = compute_lcm([p1, p2])

        mu1 = float(np.mean(h1))
        mu2 = float(np.mean(h2))

        if joint_period <= 10_000_000:
            offsets = np.arange(joint_period, dtype=np.int64)
            vals1 = h1[offsets % p1].astype(np.float64)
            vals2 = h2[offsets % p2].astype(np.float64)
            e_product = float(np.mean(vals1 * vals2))
        else:
            rng = random.Random(42 + i * 1000 + n_cycle_pairs)
            n_sample = min(500_000, joint_period)
            offsets = np.array([rng.randrange(joint_period)
                                for _ in range(n_sample)], dtype=np.int64)
            vals1 = h1[offsets % p1].astype(np.float64)
            vals2 = h2[offsets % p2].astype(np.float64)
            e_product = float(np.mean(vals1 * vals2))

        cov = e_product - mu1 * mu2
        total_cov += cov
        n_cycle_pairs += 1

total_var = total_var_independent + 2.0 * total_cov
if total_var < 0:
    warnings.warn(f"Negative total_var ({total_var:.6f}) — clamping.")
    total_var = total_var_independent

total_std = math.sqrt(total_var) if total_var > 0 else 1e-12
z_analytical = (obs - total_mean) / total_std

if verbose:
    print(f"    Obs={obs}  E[S]={total_mean:.2f}  "
          f"std={total_std:.2f}  Z={z_analytical:+.4f}")

return z_analytical, obs, total_mean, total_std

=========================================================

EVALUATE ONE CONFIGURATION

=========================================================

def evaluate_config(config_name, quads, targets, cycles):
“””Run MC + analytical for one rail configuration. Returns dict.”””
rails = build_rails(quads, config_name)

# MC
z_values, obs, score_lists = multi_seed_mc(rails, targets, cycles)
z_mean = float(np.mean(z_values))
z_std  = float(np.std(z_values, ddof=1)) if len(z_values) > 1 else 0.0
ci_lo  = z_mean - 1.96 * z_std / math.sqrt(max(len(z_values), 1))
ci_hi  = z_mean + 1.96 * z_std / math.sqrt(max(len(z_values), 1))

# Analytical
z_anal, _, mean_a, std_a = analytical_stats(rails, targets, cycles)

return {
    'config':         config_name,
    'n_rails':        len(rails),
    'obs':            obs,
    'mc_z_mean':      z_mean,
    'mc_z_std':       z_std,
    'mc_ci':          (ci_lo, ci_hi),
    'mc_z_values':    z_values,
    'mc_scores_seed0': score_lists[0] if score_lists else np.array([]),
    'analytical_z':   z_anal,
    'analytical_mean': mean_a,
    'analytical_std':  std_a,
}

=========================================================

CHARTS

=========================================================

def plot_polarity_ladder(all_results):
“””Fig 1: Z-score progression — neg vs pos vs both, TRIO.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
x = np.arange(n)

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 10),
                                constrained_layout=True,
                                sharex=True)
fig.suptitle('Polarity Comparison — neg_mod30 vs pos_mod30 vs both_mod30',
             fontsize=16, fontweight='bold')

# ── Panel A: TRIO ──
for cfg, color, ls, marker in [
    ('neg_mod30',  C_NEG,  '-',  'o'),
    ('pos_mod30',  C_POS,  '-',  's'),
    ('both_mod30', C_BOTH, '--', 'D'),
]:
    z_vals = [all_results[t]['trio'][cfg]['mc_z_mean'] for t in tiers]
    ci_lo  = [all_results[t]['trio'][cfg]['mc_ci'][0] for t in tiers]
    ci_hi  = [all_results[t]['trio'][cfg]['mc_ci'][1] for t in tiers]

    ax1.fill_between(x, ci_lo, ci_hi, color=color, alpha=0.10)
    ax1.plot(x, z_vals, f'{marker}{ls}', color=color, lw=2, ms=6,
             label=f'{cfg}', alpha=0.9)

ax1.axhline(0, color='#999999', lw=0.8)
ax1.set_ylabel('Z-score (MC)')
ax1.set_title('A.  TRIO [2300, 2520, 3430]')
ax1.legend(fontsize=10, framealpha=0.9, edgecolor='#CCCCCC')
ax1.grid(axis='y')

# ── Panel B: ALL ──
for cfg, color, ls, marker in [
    ('neg_mod30',  C_NEG,  '-',  'o'),
    ('pos_mod30',  C_POS,  '-',  's'),
    ('both_mod30', C_BOTH, '--', 'D'),
]:
    z_vals = [all_results[t]['all'][cfg]['mc_z_mean'] for t in tiers]
    ci_lo  = [all_results[t]['all'][cfg]['mc_ci'][0] for t in tiers]
    ci_hi  = [all_results[t]['all'][cfg]['mc_ci'][1] for t in tiers]

    ax2.fill_between(x, ci_lo, ci_hi, color=color, alpha=0.10)
    ax2.plot(x, z_vals, f'{marker}{ls}', color=color, lw=2, ms=6,
             label=f'{cfg}', alpha=0.9)

ax2.axhline(0, color='#999999', lw=0.8)
ax2.set_ylabel('Z-score (MC)')
ax2.set_xlabel('Prime-Quadruplet Tier')
ax2.set_title(f'B.  ALL CYCLES ({len(ALL_CYCLES)} cycles)')
ax2.set_xticks(x)
ax2.set_xticklabels(tiers, fontsize=10)
ax2.legend(fontsize=10, framealpha=0.9, edgecolor='#CCCCCC')
ax2.grid(axis='y')

plt.savefig('polarity_ladder.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → polarity_ladder.png")

def plot_polarity_delta(all_results):
“””Fig 2: Delta Z (neg − pos) across tiers for TRIO and ALL.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
x = np.arange(n)

trio_delta = [all_results[t]['trio']['neg_mod30']['mc_z_mean']
              - all_results[t]['trio']['pos_mod30']['mc_z_mean']
              for t in tiers]
all_delta  = [all_results[t]['all']['neg_mod30']['mc_z_mean']
              - all_results[t]['all']['pos_mod30']['mc_z_mean']
              for t in tiers]

fig, ax = plt.subplots(figsize=(14, 5), constrained_layout=True)

w = 0.35
ax.bar(x - w/2, trio_delta, w, color=C_NEG, alpha=0.7,
       label='TRIO (neg − pos)', edgecolor='white', linewidth=0.5)
ax.bar(x + w/2, all_delta, w, color=C_POS, alpha=0.7,
       label='ALL (neg − pos)', edgecolor='white', linewidth=0.5)

ax.axhline(0, color='#999999', lw=1)
ax.set_xticks(x)
ax.set_xticklabels(tiers, fontsize=10)
ax.set_xlabel('Prime-Quadruplet Tier')
ax.set_ylabel('ΔZ  (neg_mod30 − pos_mod30)')
ax.set_title('Polarity Asymmetry: ΔZ = Z(neg) − Z(pos)')
ax.legend(fontsize=10, framealpha=0.9, edgecolor='#CCCCCC')
ax.grid(axis='y')

plt.savefig('polarity_delta.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → polarity_delta.png")

def plot_polarity_null_comparison(all_results):
“””Fig 3: Side-by-side null distributions for neg vs pos (TRIO),
selected tiers in a 4×4 grid.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
ncols = 4
nrows = math.ceil(n / ncols)

fig, axes = plt.subplots(nrows, ncols, figsize=(5 * ncols, 3.8 * nrows),
                         constrained_layout=True, squeeze=False)
fig.suptitle('Null Distributions — neg_mod30 vs pos_mod30 (TRIO)',
             fontsize=14, fontweight='bold')

for idx, pn in enumerate(tiers):
    r, c_idx = divmod(idx, ncols)
    ax = axes[r][c_idx]

    neg_scores = all_results[pn]['trio']['neg_mod30']['mc_scores_seed0']
    pos_scores = all_results[pn]['trio']['pos_mod30']['mc_scores_seed0']
    neg_obs    = all_results[pn]['trio']['neg_mod30']['obs']
    pos_obs    = all_results[pn]['trio']['pos_mod30']['obs']

    ax.hist(neg_scores, bins=40, density=True, color=C_NEG,
            alpha=0.40, edgecolor='white', linewidth=0.3, label='neg null')
    ax.hist(pos_scores, bins=40, density=True, color=C_POS,
            alpha=0.40, edgecolor='white', linewidth=0.3, label='pos null')

    ax.axvline(neg_obs, color=C_NEG, lw=2, ls='--',
               label=f'neg obs={neg_obs}')
    ax.axvline(pos_obs, color=C_POS, lw=2, ls=':',
               label=f'pos obs={pos_obs}')

    ax.set_xlabel('Score')
    ax.set_ylabel('Density')
    ax.set_title(pn, fontsize=12)
    ax.legend(fontsize=7, framealpha=0.9, edgecolor='#CCCCCC')
    ax.grid(axis='y')

for idx in range(n, nrows * ncols):
    r, c_idx = divmod(idx, ncols)
    axes[r][c_idx].set_visible(False)

plt.savefig('polarity_null_comparison.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → polarity_null_comparison.png")

def plot_observed_breakdown(all_results):
“””Fig 4: Stacked-style bar chart — observed hits per config.”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
x = np.arange(n)

fig, ax = plt.subplots(figsize=(14, 5), constrained_layout=True)

w = 0.25
for i, (cfg, color) in enumerate([
    ('neg_mod30', C_NEG), ('pos_mod30', C_POS), ('both_mod30', C_BOTH)
]):
    obs = [all_results[t]['trio'][cfg]['obs'] for t in tiers]
    ax.bar(x + (i - 1) * w, obs, w, color=color, alpha=0.80,
           label=cfg, edgecolor='white', linewidth=0.5)

ax.set_xticks(x)
ax.set_xticklabels(tiers, fontsize=10)
ax.set_xlabel('Prime-Quadruplet Tier')
ax.set_ylabel('Observed Hits (TRIO)')
ax.set_title('Observed Hits by Rail Configuration — TRIO [2300,2520,3430]')
ax.legend(fontsize=10, framealpha=0.9, edgecolor='#CCCCCC')
ax.grid(axis='y')

plt.savefig('polarity_observed.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → polarity_observed.png")

def plot_family_comparison(all_results):
“””Fig 5: Per-family Z-score progression across tiers (both_mod30).”””
if not HAS_MPL:
return

tiers = list(all_results.keys())
n = len(tiers)
x = np.arange(n)

# Colours and markers for each family
family_styles = {
    'TRIO':              {'color': '#1A1A2E', 'marker': 'o', 'lw': 3.0, 'ls': '-'},
    'Year Types':        {'color': '#E07A5F', 'marker': 's', 'lw': 1.8, 'ls': '-'},
    'Key of 23':         {'color': '#3D85C6', 'marker': '^', 'lw': 1.8, 'ls': '-'},
    'Daniel/Revelation': {'color': '#81B29A', 'marker': 'D', 'lw': 1.8, 'ls': '-'},
    'Ezekiel':           {'color': '#9B5DE5', 'marker': 'v', 'lw': 1.8, 'ls': '-'},
}

fig, ax = plt.subplots(figsize=(15, 7), constrained_layout=True)

for fam_name, style in family_styles.items():
    z_vals = []
    for t in tiers:
        fam_data = all_results[t].get('families', {}).get(fam_name)
        z_vals.append(fam_data['mc_z_mean'] if fam_data else float('nan'))

    ax.plot(x, z_vals,
            marker=style['marker'], linestyle=style['ls'],
            color=style['color'], lw=style['lw'], ms=7,
            label=fam_name, alpha=0.9)

ax.axhline(0, color='#999999', lw=0.8)
ax.set_xticks(x)
ax.set_xticklabels(tiers, fontsize=10)
ax.set_xlabel('Prime-Quadruplet Tier')
ax.set_ylabel('Z-score (MC, both_mod30)')
ax.set_title('Per-Family Z-Score Progression — both_mod30 baseline',
             fontsize=14, fontweight='bold')
ax.legend(fontsize=11, framealpha=0.9, edgecolor='#CCCCCC',
          loc='upper left')
ax.grid(axis='y')

plt.savefig('family_comparison.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → family_comparison.png")

def plot_foundation_comparison(all_results, stripped_results):
“””Fig 6: Full vs foundation-stripped Z-scores (both_mod30, TRIO).”””
if not HAS_MPL:
return

# Use tiers present in both
tiers = [t for t in all_results if t in stripped_results]
n = len(tiers)
x = np.arange(n)

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 10),
                                constrained_layout=True, sharex=True)
fig.suptitle('Foundation Test: Full vs Stripped (101, 191 removed)\n'
             'both_mod30 baseline',
             fontsize=14, fontweight='bold')

# Panel A: TRIO
z_full = [all_results[t]['trio']['both_mod30']['mc_z_mean'] for t in tiers]
z_strip = [stripped_results[t]['trio_z'] for t in tiers]

ax1.plot(x, z_full, 'o-', color='#7D8C8E', lw=2.5, ms=7,
         label='Full (with 101, 191)', alpha=0.9)
ax1.plot(x, z_strip, 's-', color='#E74C3C', lw=2.5, ms=7,
         label='Stripped (without 101, 191)', alpha=0.9)
ax1.axhline(0, color='#999999', lw=0.8)
ax1.set_ylabel('Z-score (MC)')
ax1.set_title('A.  TRIO [2300, 2520, 3430]')
ax1.legend(fontsize=11, framealpha=0.9, edgecolor='#CCCCCC')
ax1.grid(axis='y')

# Panel B: ALL
z_full_all = [all_results[t]['all']['both_mod30']['mc_z_mean'] for t in tiers]
z_strip_all = [stripped_results[t]['all_z'] for t in tiers]

ax2.plot(x, z_full_all, 'o-', color='#7D8C8E', lw=2.5, ms=7,
         label='Full (with 101, 191)', alpha=0.9)
ax2.plot(x, z_strip_all, 's-', color='#E74C3C', lw=2.5, ms=7,
         label='Stripped (without 101, 191)', alpha=0.9)
ax2.axhline(0, color='#999999', lw=0.8)
ax2.set_ylabel('Z-score (MC)')
ax2.set_xlabel('Prime-Quadruplet Tier')
ax2.set_title(f'B.  ALL CYCLES ({len(ALL_CYCLES)} cycles)')
ax2.set_xticks(x)
ax2.set_xticklabels(tiers, fontsize=10)
ax2.legend(fontsize=11, framealpha=0.9, edgecolor='#CCCCCC')
ax2.grid(axis='y')

plt.savefig('foundation_comparison.png', dpi=180, bbox_inches='tight',
            facecolor=fig.get_facecolor())
plt.show()
print("  ✓ Saved → foundation_comparison.png")

=========================================================

MAIN

=========================================================

def main():
tier_names = [f”P{k}” for k in range(3, 19)]
configs = [‘neg_mod30’, ‘pos_mod30’, ‘both_mod30’]

all_results = {}

# ── Metadata table ──
K_TRIO = compute_K(TRIO_CORE)
K_ALL  = compute_K(ALL_CYCLES)

print("\n" + "=" * 90)
print("  TIER METADATA — POLARITY COMPARISON")
print("=" * 90)
print(f"  {'Tier':<6} {'Quads':>6} "
      f"{'neg rails':>10} {'pos rails':>10} {'both rails':>11} "
      f"{'Targets':>8}")
print("  " + "-" * 78)
for pn in tier_names:
    quads = PRIME_QUAD_LISTS[pn]
    r_neg  = len(build_rails(quads, 'neg_mod30'))
    r_pos  = len(build_rails(quads, 'pos_mod30'))
    r_both = len(build_rails(quads, 'both_mod30'))
    print(f"  {pn:<6} {len(quads):>6} "
          f"{r_neg:>10} {r_pos:>10} {r_both:>11} "
          f"{len(TARGETS):>8}")

# ── Main evaluation loop ──
for pn in tier_names:
    quads = PRIME_QUAD_LISTS[pn]

    print("\n" + "=" * 90)
    print(f"  {pn}  ({len(quads)} quadruplets, {len(TARGETS)} targets)")
    print("=" * 90)

    tier_data = {'trio': {}, 'all': {}}

    for cfg in configs:
        rails = build_rails(quads, cfg)
        print(f"\n  ── {cfg} ({len(rails)} rails) ──")

        # TRIO
        print(f"    TRIO [{', '.join(str(c) for c in TRIO_CORE)}]:")
        trio_result = evaluate_config(cfg, quads, TARGETS, TRIO_CORE)
        print(f"      MC:   Z = {trio_result['mc_z_mean']:+.4f} "
              f"[{trio_result['mc_ci'][0]:+.4f}, "
              f"{trio_result['mc_ci'][1]:+.4f}]  "
              f"obs={trio_result['obs']}")
        print(f"      Anal: Z = {trio_result['analytical_z']:+.4f}  "
              f"E[S]={trio_result['analytical_mean']:.2f}")

        # ALL
        print(f"    ALL ({len(ALL_CYCLES)} cycles):")
        all_result = evaluate_config(cfg, quads, TARGETS, ALL_CYCLES)
        print(f"      MC:   Z = {all_result['mc_z_mean']:+.4f} "
              f"[{all_result['mc_ci'][0]:+.4f}, "
              f"{all_result['mc_ci'][1]:+.4f}]  "
              f"obs={all_result['obs']}")
        print(f"      Anal: Z = {all_result['analytical_z']:+.4f}  "
              f"E[S]={all_result['analytical_mean']:.2f}")

        tier_data['trio'][cfg] = trio_result
        tier_data['all'][cfg]  = all_result

    # ── Per-family evaluation (both_mod30 baseline) ──
    family_defs = {
        'TRIO':              TRIO_CORE,
        'Year Types':        FAMILY_YEAR,
        'Key of 23':         FAMILY_KEY23,
        'Daniel/Revelation': FAMILY_DANIEL_REVELATION,
        'Ezekiel':           FAMILY_EZEKIEL,
    }
    tier_data['families'] = {}
    print(f"\n  ── Per-family (both_mod30, {len(build_rails(quads, 'both_mod30'))} rails) ──")
    for fam_name, fam_cycles in family_defs.items():
        fam_result = evaluate_config('both_mod30', quads, TARGETS, fam_cycles)
        tier_data['families'][fam_name] = fam_result
        print(f"    {fam_name:>20}: Z = {fam_result['mc_z_mean']:+.4f}  "
              f"obs={fam_result['obs']:>4}  "
              f"({len(fam_cycles)} cycles)")

    # ── Summary ──
    print(f"\n  ╔══ SUMMARY {pn} — TRIO ══╗")
    for cfg in configs:
        d = tier_data['trio'][cfg]
        print(f"  ║ {cfg:>12}: Z = {d['mc_z_mean']:+.4f}  "
              f"obs={d['obs']:>4}  ({d['n_rails']} rails)")
    print(f"  ╚{'═' * 32}╝")

    print(f"  ╔══ SUMMARY {pn} — ALL ══╗")
    for cfg in configs:
        d = tier_data['all'][cfg]
        print(f"  ║ {cfg:>12}: Z = {d['mc_z_mean']:+.4f}  "
              f"obs={d['obs']:>4}  ({d['n_rails']} rails)")
    print(f"  ╚{'═' * 31}╝")

    all_results[pn] = tier_data

# ── Grand summary table ──
print("\n" + "=" * 90)
print("  GRAND SUMMARY — TRIO Z-SCORES (MC)")
print("=" * 90)
print(f"  {'Tier':<6} {'neg_mod30':>12} {'pos_mod30':>12} "
      f"{'both_mod30':>12} {'Δ(neg−pos)':>12}")
print("  " + "-" * 56)
for pn in tier_names:
    zn = all_results[pn]['trio']['neg_mod30']['mc_z_mean']
    zp = all_results[pn]['trio']['pos_mod30']['mc_z_mean']
    zb = all_results[pn]['trio']['both_mod30']['mc_z_mean']
    print(f"  {pn:<6} {zn:>+12.4f} {zp:>+12.4f} "
          f"{zb:>+12.4f} {zn - zp:>+12.4f}")

print(f"\n  {'Tier':<6} {'neg_mod30':>12} {'pos_mod30':>12} "
      f"{'both_mod30':>12} {'Δ(neg−pos)':>12}")
print("  " + "-" * 56)
print("  GRAND SUMMARY — ALL CYCLES Z-SCORES (MC)")
print("  " + "-" * 56)
for pn in tier_names:
    zn = all_results[pn]['all']['neg_mod30']['mc_z_mean']
    zp = all_results[pn]['all']['pos_mod30']['mc_z_mean']
    zb = all_results[pn]['all']['both_mod30']['mc_z_mean']
    print(f"  {pn:<6} {zn:>+12.4f} {zp:>+12.4f} "
          f"{zb:>+12.4f} {zn - zp:>+12.4f}")

# ── Per-family grand summary (both_mod30) ──
fam_names = ['TRIO', 'Year Types', 'Key of 23', 'Daniel/Revelation', 'Ezekiel']
print("\n" + "=" * 90)
print("  GRAND SUMMARY — PER-FAMILY Z-SCORES (MC, both_mod30)")
print("=" * 90)
hdr = f"  {'Tier':<6}"
for fn in fam_names:
    hdr += f" {fn:>18}"
print(hdr)
print("  " + "-" * (6 + 19 * len(fam_names)))
for pn in tier_names:
    row = f"  {pn:<6}"
    for fn in fam_names:
        z = all_results[pn]['families'][fn]['mc_z_mean']
        row += f" {z:>+18.4f}"
    print(row)

# ═══════════════════════════════════════════════════════
# FOUNDATION-STRIPPED SWEEP  (both_mod30 only)
# ═══════════════════════════════════════════════════════
stripped_tier_names = [f"P{k}" for k in range(4, 19)]
stripped_results = {}

print("\n" + "=" * 90)
print("  FOUNDATION-STRIPPED SWEEP  (101, 191 removed; both_mod30)")
print("=" * 90)
print(f"  {'Tier':<6} {'Full quads':>11} {'Stripped':>9} "
      f"{'Full rails':>11} {'Stripped':>9}")
print("  " + "-" * 52)
for pn in stripped_tier_names:
    full_q = PRIME_QUAD_LISTS[pn]
    strip_q = PRIME_QUAD_LISTS_STRIPPED[pn]
    full_r = len(build_rails(full_q, 'both_mod30'))
    strip_r = len(build_rails(strip_q, 'both_mod30'))
    print(f"  {pn:<6} {len(full_q):>11} {len(strip_q):>9} "
          f"{full_r:>11} {strip_r:>9}")

for pn in stripped_tier_names:
    quads = PRIME_QUAD_LISTS_STRIPPED[pn]
    rails = build_rails(quads, 'both_mod30')

    # TRIO
    trio_r = evaluate_config('both_mod30', quads, TARGETS, TRIO_CORE)
    # ALL
    all_r = evaluate_config('both_mod30', quads, TARGETS, ALL_CYCLES)

    stripped_results[pn] = {
        'trio_z':    trio_r['mc_z_mean'],
        'trio_obs':  trio_r['obs'],
        'trio_mean': trio_r['analytical_mean'],
        'all_z':     all_r['mc_z_mean'],
        'all_obs':   all_r['obs'],
        'all_mean':  all_r['analytical_mean'],
        'n_quads':   len(quads),
        'n_rails':   len(rails),
    }
    print(f"\n  {pn} stripped ({len(quads)} quads, {len(rails)} rails):"
          f"  TRIO Z = {trio_r['mc_z_mean']:+.4f}  "
          f"obs={trio_r['obs']}"
          f"  |  ALL Z = {all_r['mc_z_mean']:+.4f}  "
          f"obs={all_r['obs']}")

# ── Grand comparison: full vs stripped ──
print("\n" + "=" * 90)
print("  GRAND SUMMARY — FULL vs STRIPPED (both_mod30, TRIO)")
print("=" * 90)
print(f"  {'Tier':<6} {'Full Z':>10} {'Strip Z':>10} "
      f"{'ΔZ':>10} {'Full obs':>10} {'Strip obs':>10}")
print("  " + "-" * 60)
for pn in stripped_tier_names:
    zf = all_results[pn]['trio']['both_mod30']['mc_z_mean']
    zs = stripped_results[pn]['trio_z']
    of = all_results[pn]['trio']['both_mod30']['obs']
    os_ = stripped_results[pn]['trio_obs']
    print(f"  {pn:<6} {zf:>+10.4f} {zs:>+10.4f} "
          f"{zs - zf:>+10.4f} {of:>10} {os_:>10}")

print(f"\n  {'Tier':<6} {'Full Z':>10} {'Strip Z':>10} "
      f"{'ΔZ':>10} {'Full obs':>10} {'Strip obs':>10}")
print("  " + "-" * 60)
print("  GRAND SUMMARY — FULL vs STRIPPED (both_mod30, ALL)")
print("  " + "-" * 60)
for pn in stripped_tier_names:
    zf = all_results[pn]['all']['both_mod30']['mc_z_mean']
    zs = stripped_results[pn]['all_z']
    of = all_results[pn]['all']['both_mod30']['obs']
    os_ = stripped_results[pn]['all_obs']
    print(f"  {pn:<6} {zf:>+10.4f} {zs:>+10.4f} "
          f"{zs - zf:>+10.4f} {of:>10} {os_:>10}")

# ── Charts ──
print("\n" + "=" * 90)
print("  GENERATING CHARTS")
print("=" * 90)
plot_polarity_ladder(all_results)
plot_polarity_delta(all_results)
plot_polarity_null_comparison(all_results)
plot_observed_breakdown(all_results)
plot_family_comparison(all_results)
plot_foundation_comparison(all_results, stripped_results)

if name == “main“:
main()




For Part 1, File_00 to File_30, see https://490d.com/the-490d-unified-chronology-knowledge-graph-repository/