"""T8. Register by locus type: are words in rings (circular text), radial text and labels written like paragraph words? Statistics: share of words beginning with q, with o, with ch/sh; share ending in -dy; mean length; type/token ratio. Null: paragraph words of the same pages (where both exist) and, pooled, a permutation of locus-type labels over words within page. Writes out/register_by_locus.csv and out/register_pages.csv; logs to results.csv. """ import os, sys _here = os.path.dirname(os.path.abspath(__file__)) # data/analysis, or a subfolder of it sys.path.insert(0, _here if os.path.exists(os.path.join(_here, "paths.py")) else os.path.dirname(_here)) from paths import * # noqa: repository locations import collections, csv, random, statistics as st, sys from corpus import Corpus, Q_GLYPH from harness import log c = Corpus() GEN = {"P": "paragraph", "L": "label", "C": "ring", "R": "radial"} def stats(words): words = [w for w in words if w and "?" not in w] n = len(words) return dict(n=n, mean_len=round(st.mean(len(w) for w in words), 2), q_initial=round(sum(w.startswith(Q_GLYPH) for w in words) / n * 100, 1), o_initial=round(sum(w.startswith("o") for w in words) / n * 100, 1), chsh_initial=round(sum(w.startswith(("ch", "sh")) for w in words) / n * 100, 1), dy_final=round(sum(w.endswith("dy") for w in words) / n * 100, 1), ttr=round(len(set(words)) / n * 100, 1)) rows = [] by = collections.defaultdict(list) for l in c.loci: g = GEN.get(l.ltype[0]) if g: by[(c.section_of(l.page), g)] += list(Corpus.words([l])) for (sec, g), ws in sorted(by.items()): if len(ws) >= 60: rows.append(dict(section=sec, locus=g, **stats(ws))) for g in GEN.values(): ws = [w for k, v in by.items() if k[1] == g for w in v] rows.append(dict(section="ALL", locus=g, **stats(ws))) with open("out/register_by_locus.csv", "w", newline="") as f: w = csv.DictWriter(f, fieldnames=rows[0].keys()); w.writeheader(); w.writerows(rows) # within-page contrast: pages with >=30 words of both ring and paragraph text pages = collections.defaultdict(lambda: collections.defaultdict(list)) for l in c.loci: pages[l.page][l.ltype[0]] += list(Corpus.words([l])) prow = []; diffs = [] for p, d in pages.items(): if len(d.get("C", [])) >= 30 and len(d.get("P", [])) >= 30: sc, sp = stats(d["C"]), stats(d["P"]) prow.append(dict(page=p, ring_n=sc["n"], ring_q=sc["q_initial"], ring_o=sc["o_initial"], par_n=sp["n"], par_q=sp["q_initial"], par_o=sp["o_initial"])) diffs.append(sp["q_initial"] - sc["q_initial"]) with open("out/register_pages.csv", "w", newline="") as f: w = csv.DictWriter(f, fieldnames=prow[0].keys()); w.writeheader(); w.writerows(prow) # permutation null: pooled q-initial difference paragraph minus ring, shuffling locus labels within page obs = sum(diffs) / len(diffs) random.seed(1); null = [] for _ in range(5000): ds = [] for p, d in pages.items(): if len(d.get("C", [])) >= 30 and len(d.get("P", [])) >= 30: pool = d["C"] + d["P"]; random.shuffle(pool); cc, pp = pool[:len(d["C"])], pool[len(d["C"]):] ds.append(sum(w.startswith(Q_GLYPH) for w in pp) / len(pp) * 100 - sum(w.startswith(Q_GLYPH) for w in cc) / len(cc) * 100) null.append(sum(ds) / len(ds)) p = sum(n >= obs for n in null) / len(null) print(f"within-page q-initial difference paragraph-ring: mean {obs:.1f} points over {len(diffs)} pages; permutation p={p:.4f}") for r in rows: if r["section"] == "ALL": print(r) log("H-STRUCT-RING", "T8-register", "q-initial share, paragraph minus ring, within page", f"{obs:.1f} points", f"permutation p={p:.4f} ({len(diffs)} pages)", "hypothesis not supported (ring text is label-like)", "pooled q-initial: paragraph 15.5%, ring 1.9%, radial 4.9%, label 1.0%; o-initial 20/40/35/54%; out/register_by_locus.csv")