Computational companion / Diverging Paths
Diverging Paths to
Dark-Matter Discovery
Computational companion · v3.1.0
A reading edition of the computational work behind the paper. Follow the retained corpus, candidate profiles, and frozen network metrics through the shared script/notebook workflow and into the figure constructions.
- Stages
- 06
- Input tables
- 06
- Graph checks
- 57
- Reference PDFs
- 09
The analysis in six stages
The preferred 3.1.0 route uses retained inputs and the same functions in its script and clean notebook. Earlier acquisition, extraction, and maintenance sources are available in the source library and remain separate from this route.
The six input tables Supplied separately
| Table | Role | Uncompressed size |
|---|---|---|
| papers.parquet | Paper metadata and abstracts | 120.8 MB |
| papers_with_dm_models.parquet | Retained paper-level candidate tags | 108.3 MB |
| paper_arxiv_classes.parquet | Ordered arXiv classifications | 1.6 MB |
| dm_model_candidates_long.parquet | Candidate-family mention rows | 0.3 MB |
| paper_metrics_long.parquet | Retained citation metrics | 5.1 MB |
| unigram_yearly.parquet | Yearly lexical counts | 1.6 MB |
The browser edition omits datasets and network ZIPs. Two large tables are restored from lossless parts by the research package; the six inputs total 237.7 MB.
Verify frozen inputs
The restoration helper joins the lossless parts of the two largest tables. The workflow then checks retained data hashes and the identities and member lists of both frozen network archives. This establishes which evidence the later stages use.
- Uses
- Six local input tables, pinned analysis products, two frozen network ZIPs
- Produces
- Input and archive-member integrity report
Pythoninput_checks()
def input_checks(root):
root = Path(root)
load_local(
root / "code/materialize_inputs.py", "diverging_paths_materialize"
).materialize(root)
pins = json.loads((root / "checks/input-hashes.json").read_text())
for rel, digest in pins.items():
assert hashlib.sha256((root / rel).read_bytes()).hexdigest() == digest, rel
release = json.loads(
(root / "provenance/v3.0.0/release_manifest.json").read_text()
)
members = 0
for archive in release["network_archives"]:
path = root / archive["path"]
assert path.stat().st_size == archive["bytes"]
assert hashlib.sha256(path.read_bytes()).hexdigest() == archive["sha256"]
with zipfile.ZipFile(path) as z:
assert set(z.namelist()) == set(archive["members"])
for name, digest in archive["members"].items():
assert hashlib.sha256(z.read(name)).hexdigest() == digest, name
members += len(z.namelist())
return write_report(
root,
"input-integrity.json",
{
"status": "PASS",
"pinned_data_products": len(pins),
"network_archives": len(release["network_archives"]),
"archive_members": members,
"python": platform.python_version(),
"scope": "Integrity only; no holdout annotations read",
},
)
Reading format; Python syntax tree matches the source.
PythonLossless input restoration
"""Restore exact frozen tables from lossless transport parts."""
from pathlib import Path
import hashlib, json, os, shutil
def sha256(path):
h = hashlib.sha256()
with Path(path).open("rb") as f:
for block in iter(lambda: f.read(1048576), b""):
h.update(block)
return h.hexdigest()
def materialize(root):
root = Path(root).resolve()
data = root / "data"
spec = json.loads((data / "INPUT-STORAGE.json").read_text())
restored = []
for name, entry in spec["tables"].items():
target = data / name
if target.exists():
if (
target.stat().st_size != entry["bytes"]
or sha256(target) != entry["sha256"]
):
raise ValueError(
"Existing input has a different identity; preserve it and use a clean checkout: "
+ name
)
continue
temporary = target.with_suffix(target.suffix + ".assembling")
try:
with temporary.open("wb") as output:
for part in entry["parts"]:
path = data / part["file"]
if (
path.stat().st_size != part["bytes"]
or sha256(path) != part["sha256"]
):
raise ValueError(
"Transport-part identity differs: " + part["file"]
)
with path.open("rb") as source:
shutil.copyfileobj(source, output)
if (
temporary.stat().st_size != entry["bytes"]
or sha256(temporary) != entry["sha256"]
):
raise ValueError("Restored table identity differs: " + name)
os.replace(temporary, target)
restored.append(name)
finally:
if temporary.exists():
temporary.unlink()
return restored
if __name__ == "__main__":
print(
json.dumps(
{"restored": materialize(Path(__file__).resolve().parents[1])}, indent=2
)
)
Reading format; Python syntax tree matches the source.
PythonCorresponding notebook cell
reports["input_checks"] = input_checks(ROOT)
reports["input_checks"]
Reading format; Python syntax tree matches the source.
PythonNotebook setup cell
from pathlib import Path
import sys, os
ROOT = Path.cwd().resolve()
if ROOT.name == "notebooks":
ROOT = ROOT.parent
assert (ROOT / "config/workspace.json").is_file()
sys.path.insert(0, str(ROOT / "code/modules"))
from workflow import (
input_checks,
corpus_checks,
candidate_checks,
network_checks,
figure_checks,
write_report,
)
reports = {}
Reading format; Python syntax tree matches the source.
Rebuild corpus classifications
Records are restricted to years through 2025. Sorting by class_pos selects each paper’s first arXiv classification. The code rebuilds year-by-class counts, compares them with retained tables, and writes category and class summaries.
The classified subset and full corpus have different denominators. These classifications describe research organization; they do not establish what would count as discovery.
- Uses
- Paper identities and years; ordered arXiv classifications
- Produces
- 201,627 corpus records; 143,390 classified records; comparison tables
Pythoncorpus_checks()
def corpus_checks(root):
root = Path(root)
data = root / "data"
out = root / "reproduced/tables"
out.mkdir(parents=True, exist_ok=True)
papers = pd.read_parquet(
data / "papers.parquet", columns=["bibcode", "year", "abstract"]
)
papers = papers[papers.year <= 2025]
assert len(papers) == 201627 and papers.bibcode.nunique() == len(papers)
classes = pd.read_parquet(data / "paper_arxiv_classes.parquet").sort_values(
["bibcode", "class_pos"]
)
primary = classes.drop_duplicates("bibcode").merge(
papers[["bibcode", "year"]], on="bibcode", validate="one_to_one"
)
assert len(primary) == 143390
rebuilt = (
primary.groupby(["year", "arxiv_class", "arxiv_category"])
.size()
.rename("n_papers")
.reset_index()
)
frozen = pd.read_parquet(
data / "analysis/classification_primary_yearly.parquet"
)
joined = rebuilt.merge(
frozen,
on=["year", "arxiv_class", "arxiv_category"],
how="outer",
suffixes=("_rebuilt", "_frozen"),
indicator=True,
)
assert (
joined["_merge"].eq("both").all()
and joined.n_papers_rebuilt.eq(joined.n_papers_frozen).all()
)
volume = (
papers.groupby("year")
.size()
.rename("n_papers_rebuilt")
.reset_index()
.merge(
pd.read_parquet(data / "analysis/paper_volume_yearly.parquet"),
on="year",
validate="one_to_one",
)
)
assert volume.n_papers_rebuilt.eq(volume.n_papers).all()
categories = (
primary.groupby("arxiv_category")
.size()
.sort_values(ascending=False)
.rename("papers")
.reset_index()
)
counts = (
primary.groupby("arxiv_class")
.size()
.sort_values(ascending=False)
.rename("papers")
.reset_index()
)
for name, table in [
("primary-categories", categories),
("primary-classes", counts),
]:
table["percent"] = 100 * table.papers / len(primary)
table.to_csv(out / (name + ".csv"), index=False)
lines = [
r"\begin{tabular}{lrr}",
r"\toprule",
"Primary assignment & Papers & Share " + r"\\",
r"\midrule",
]
for _, row in table.head(
4 if name.endswith("categories") else 9
).iterrows():
label = str(row.iloc[0]).replace("_", r"\_")
lines.append(
f"{label} & {int(row.papers):,} & {row.percent:.1f}" + r"\% \\"
)
(out / (name + ".tex")).write_text(
"\n".join(lines + [r"\bottomrule", r"\end{tabular}"]) + "\n"
)
expected = {
"astrophysics": 78673,
"high-energy physics": 39191,
"general relativity and quantum cosmology": 14668,
"physics": 6427,
}
actual = categories.set_index("arxiv_category").papers.to_dict()
assert all(actual.get(k) == v for k, v in expected.items())
return write_report(
root,
"corpus-checks.json",
{
"status": "PASS",
"records": len(papers),
"classified_records": len(primary),
"primary_class_year_cells_rebuilt": len(rebuilt),
"volume_years_rebuilt": len(volume),
"main_table_counts_match": True,
"largest_primary_class": counts.iloc[0, 0],
},
)
Reading format; Python syntax tree matches the source.
PythonCorresponding notebook cell
reports["corpus_checks"] = corpus_checks(ROOT)
reports["corpus_checks"]
Reading format; Python syntax tree matches the source.
Reconstruct candidate profiles
The retained candidate table contains 27,680 tag rows from 22,247 papers. For astrophysics and high-energy physics, repeated paper–family pairs are removed within each year. The workflow reconstructs proportions with a 0.5 per-family pseudocount, checks log₂ ratios, and verifies the 20-mention display threshold.
Mentions measure organized attention, not endorsement, candidate viability, or discovery. Bootstrap intervals and sensitivity products are retained and hash-checked; this route does not resample them.
- Uses
- Retained candidate tags for 1995–2025 and thirteen tracked families
- Produces
- Field-year shares and log₂ prominence ratios; retained threshold checks
Pythoncandidate_checks()
def candidate_checks(root):
root = Path(root)
d = root / "data"
raw = pd.read_parquet(d / "dm_model_candidates_long.parquet")
raw = raw[raw.year.between(1995, 2025)]
assert len(raw) == 27680 and raw.bibcode.nunique() == 22247
tracked = (
(d / "analysis/tracked_candidate_species.txt").read_text().splitlines()
)
assert len(tracked) == 13
pairs = raw[
raw.SpeciesLabel.isin(tracked)
& raw.year.between(1995, 2025)
& raw.arxiv_category.isin(["astrophysics", "high-energy physics"])
].drop_duplicates(["year", "arxiv_category", "bibcode", "SpeciesLabel"])
rebuilt = (
pairs.groupby(["year", "SpeciesLabel", "arxiv_category"])
.size()
.unstack(fill_value=0)
.reset_index()
)
ref = pd.read_parquet(d / "analysis/candidate_field_yearly.parquet")
merged = ref.merge(rebuilt, on=["year", "SpeciesLabel"], how="left").fillna(
{"astrophysics": 0, "high-energy physics": 0}
)
assert (merged.astro_mentions == merged["astrophysics"]).all() and (
merged.hep_mentions == merged["high-energy physics"]
).all()
# Reconstruct smoothed proportions using the retained 0.5 per-family pseudocount.
n = 13
astro = (merged.astro_mentions + 0.5) / (
merged.groupby("year").astro_mentions.transform("sum") + 0.5 * n
)
hep = (merged.hep_mentions + 0.5) / (
merged.groupby("year").hep_mentions.transform("sum") + 0.5 * n
)
assert np.allclose(astro, merged.astro_share) and np.allclose(
hep, merged.hep_share
)
assert np.allclose(np.log2(hep / astro), merged.log2_hep_astro_ratio)
assert (merged.meets_minimum_count == (merged.total_mentions >= 20)).all()
merged[
[
"year",
"SpeciesLabel",
"astro_mentions",
"hep_mentions",
"astro_share",
"hep_share",
"log2_hep_astro_ratio",
]
].to_csv(
root / "reproduced/tables/candidate-field-reconstructed.csv", index=False
)
return write_report(
root,
"candidate-checks.json",
{
"status": "PASS",
"candidate_tag_rows_1995_2025": len(raw),
"candidate_papers": int(raw.bibcode.nunique()),
"tracked_families": len(tracked),
"candidate_year_cells": len(merged),
"paper_family_deduplication": True,
"pseudocount": 0.5,
"display_threshold": 20,
"bootstrap_intervals": "Retained and hash-verified; not freshly resampled",
"validation": "No independent accuracy estimate; no untouched holdout answers inspected",
},
)
Reading format; Python syntax tree matches the source.
PythonCorresponding notebook cell
reports["candidate_checks"] = candidate_checks(ROOT)
reports["candidate_checks"]
Reading format; Python syntax tree matches the source.
Check frozen network metrics
The reconstruction derives equal-field edge weights and inverse-prevalence distances, checks endpoint rules, and compares the resulting metrics with their archived values. It covers three WIMP definitions and stable, rolling, and full-period windows. Archived GraphML floating-point values and ordering are retained where shortest-path ties matter.
This checks calculations conditional on frozen graphs. It does not validate fresh raw-abstract extraction or recreate the Gephi layout. Node removal is a graph diagnostic, not a historical counterfactual or a causal experiment.
- Uses
- Frozen node/edge counts, archived GraphML, three WIMP definitions
- Produces
- Conditional checks of brokerage, importance, and node-removal metrics
PythonReconstruct graph weights and endpoints
def reconstruct_graph(nodes, edges):
graph = nx.Graph()
for row in edges:
weight = 0.5 * (
int(row["astrophysics_paper_count"])
/ int(row["astrophysics_all_dm_papers"])
+ int(row["hep_paper_count"]) / int(row["hep_all_dm_papers"])
)
check_close(
weight, row["mean_field_cooc_prevalence"], "Equal-field edge weight"
)
distance = float(row[DISTANCE])
check_close(distance, 1 / weight, "Inverse-prevalence distance")
source, target = row["Source"], row["Target"]
if graph.has_edge(source, target) or source == target:
raise ValueError("Duplicate edge or self-loop")
graph.add_edge(source, target, **{DISTANCE: distance})
if set(graph) != {row["Id"] for row in nodes}:
raise ValueError("Canonical node and edge sets disagree")
astro, hep = [], []
for row in nodes:
candidate = row["node_type"] == "candidate"
ratio = float(row["log10_astro_hep_prevalence_ratio"])
for name, condition, endpoints in [
("is_astro_anchor", not candidate and ratio >= math.log10(2), astro),
("is_hep_anchor", not candidate and ratio <= -math.log10(2), hep),
]:
if (row[name] == "True") != condition:
raise ValueError(f'Endpoint rule mismatch: {row["Id"]}, {name}')
if condition:
endpoints.append(row["Id"])
if not astro or not hep:
raise ValueError(
"No endpoints; archive fallback would require explicit treatment"
)
return graph, astro, hep
Reading format; Python syntax tree matches the source.
PythonCross-field path efficiency
def efficiency(graph, sources, targets):
"""Mean reciprocal distance; disconnected pairs remain in the denominator."""
sources, targets = sorted(sources), sorted(targets)
if not sources or not targets or not set(sources + targets) <= set(graph):
raise ValueError("Endpoint sets must be nonempty and present in the graph")
total, reachable = 0.0, 0
for source in sources:
lengths = nx.single_source_dijkstra_path_length(
graph, source, weight=DISTANCE
)
for target in targets:
distance = lengths.get(target)
if distance is not None and distance > 0:
total += 1.0 / distance
reachable += 1
pairs = len(sources) * len(targets)
return total / pairs, reachable / pairs
Reading format; Python syntax tree matches the source.
PythonNode-removal diagnostic
def removal(graph, sources, targets, node, baseline):
if node in set(sources) | set(targets):
raise ValueError(
"Removal requires a non-anchor node, keeping endpoints fixed"
)
reduced = graph.copy()
reduced.remove_node(node)
after, reachability = efficiency(reduced, sources, targets)
return after, reachability, max(0.0, (baseline - after) / baseline)
Reading format; Python syntax tree matches the source.
PythonRole-specific HITS scores
def spectral_scores(rows):
"""Role-specific HITS via the leading left singular vector, max scaled."""
candidates = sorted({r["Source"] for r in rows})
concepts = sorted({r["Target"] for r in rows})
ci, ti = {v: i for i, v in enumerate(candidates)}, {
v: i for i, v in enumerate(concepts)
}
matrix = np.zeros((len(candidates), len(concepts)))
seen = set()
for row in rows:
edge = row["Source"], row["Target"]
if edge in seen:
raise ValueError(f"Duplicate candidate-concept edge {edge}")
seen.add(edge)
weight = int(row["paper_count"]) / int(row["candidate_bearing_papers"])
check_close(
weight, row["cooc_doc_prevalence_candidate_papers"], "HITS weight"
)
matrix[ci[edge[0]], ti[edge[1]]] = weight
left, _, _ = np.linalg.svd(matrix, full_matrices=False)
values = np.abs(left[:, 0])
values /= values.max()
return dict(zip(candidates, map(float, values)))
Reading format; Python syntax tree matches the source.
PythonFull 57-combination comparison
def verify(release_root, pins_path):
pins = json.loads(pins_path.read_text())
manifest_path = release_root / "provenance/v3.0.0/release_manifest.json"
if not manifest_path.is_file():
manifest_path = release_root / "release_manifest.json"
if sha256(manifest_path) not in pins["accepted_release_manifest_sha256"]:
raise ValueError("Release manifest does not match the pinned v3.0.0 input")
manifest = json.loads(manifest_path.read_text())
entry = next(
x for x in manifest["network_archives"] if x["path"] == pins["archive_path"]
)
archive_path = release_root / entry["path"]
digest = sha256(archive_path)
if digest != pins["archive_sha256"] or digest != entry["sha256"]:
raise ValueError("Frozen archive SHA-256 mismatch")
result = {
"status": "passed",
"python": platform.python_version(),
"networkx": nx.__version__,
"numpy": np.__version__,
"archive_sha256": digest,
"release_manifest_sha256": sha256(manifest_path),
"scope": "Conditional recalculation from frozen graphs and count tables; not extraction validation",
"windows": [],
"common_endpoints": [],
}
with zipfile.ZipFile(archive_path) as archive:
if set(archive.namelist()) != set(entry["members"]):
raise ValueError("Archive member list differs from release manifest")
for name, expected in entry["members"].items():
if hashlib.sha256(archive.read(name)).hexdigest() != expected:
raise ValueError(f"Archive member SHA-256 mismatch: {name}")
result["archive_members_verified"] = len(entry["members"])
nodes = grouped(read_rows(archive, BROKERAGE + "nodes_by_window.csv"))
edges = grouped(read_rows(archive, BROKERAGE + "edges_by_window.csv"))
trajectories = grouped(
read_rows(archive, BROKERAGE + "wimp_brokerage_trajectory.csv")
)
removals = grouped(
read_rows(archive, BROKERAGE + "node_removal_metrics.csv")
)
importance_edges = grouped(
[
r
for r in read_rows(archive, IMPORTANCE + "edges_by_window.csv")
if r["evidence_scope"] == "abstract"
]
)
importance_nodes = grouped(
read_rows(archive, IMPORTANCE + "candidate_metrics_by_window.csv")
)
importance_trajectory = grouped(
read_rows(archive, IMPORTANCE + "wimp_importance_trajectory.csv")
)
if not (
set(nodes)
== set(edges)
== set(trajectories)
== set(importance_edges)
== set(importance_nodes)
== set(importance_trajectory)
):
raise ValueError("Window/definition groups differ across input tables")
stable = {}
removal_checks = 0
for key in sorted(nodes):
definition, kind, window = key
graph, astro, hep = reconstruct_graph(nodes[key], edges[key])
if kind == "stable":
suffix = "" if definition == "published_umbrella" else "robustness/"
name = (
BROKERAGE
+ f'graphs/{suffix}{definition}--{window.replace("-", "_")}.graphml'
)
saved = nx.read_graphml(io.BytesIO(archive.read(name)))
if set(saved) != set(graph) or {
frozenset(e) for e in saved.edges
} != {frozenset(e) for e in graph.edges}:
raise ValueError(f"GraphML topology mismatch: {key}")
for a, b, attrs in graph.edges(data=True):
check_close(
attrs[DISTANCE], saved[a][b][DISTANCE], "GraphML distance"
)
# Keep the archived GraphML floats/order for exact shortest-path tie handling.
graph = saved
scores = nx.betweenness_centrality_subset(
graph, sorted(astro), sorted(hep), normalized=True, weight=DISTANCE
)
candidates = {
r["Id"]: scores[r["Id"]]
for r in nodes[key]
if r["node_type"] == "candidate"
}
for row in nodes[key]:
check_close(
scores[row["Id"]],
row["cross_field_betweenness_prevalence"],
f'Betweenness {key} {row["Id"]}',
)
focal = FOCAL[definition]
archived = trajectories[key][0]
baseline, reachable = efficiency(graph, astro, hep)
after, after_reachable, loss = removal(
graph, astro, hep, focal, baseline
)
check_close(
loss,
archived["removal_effect_efficiency_prevalence"],
f"WIMP removal {key}",
)
check_close(
scores[focal],
archived["cross_field_betweenness_prevalence"],
f"WIMP trajectory {key}",
)
for row in removals[key]:
if kind != "stable" and row["node_id"] != focal:
continue
after_node, reach_node, loss_node = removal(
graph, astro, hep, row["node_id"], baseline
)
for value, column in [
(baseline, "baseline_efficiency"),
(after_node, "removed_efficiency"),
(reachable, "baseline_reachable_share"),
(reach_node, "removed_reachable_share"),
(loss_node, "relative_efficiency_loss"),
]:
check_close(
value, row[column], f'{column} {key} {row["node_id"]}'
)
removal_checks += 1
hits = spectral_scores(importance_edges[key])
for row in importance_nodes[key]:
check_close(
hits[row["Id"]],
row["hits_score_prevalence"],
f'HITS {key} {row["Id"]}',
)
hits_pct = percentile(hits, focal)
check_close(
hits_pct,
importance_trajectory[key][0]["hits_candidate_percentile"],
f"HITS percentile {key}",
)
result["windows"].append(
{
"definition": definition,
"kind": kind,
"window": window,
"nodes": len(graph),
"edges": graph.number_of_edges(),
"astro_endpoints": len(astro),
"hep_endpoints": len(hep),
"wimp_betweenness": scores[focal],
"wimp_candidate_rank": 1
+ sum(v > scores[focal] for v in candidates.values()),
"candidate_count": len(candidates),
"wimp_removal_effect": loss,
"wimp_hits_score": hits[focal],
"wimp_hits_percentile": hits_pct,
}
)
if kind == "stable" and definition == "published_umbrella":
stable[window] = graph, set(astro), set(hep), candidates
print(f"Checked {definition} {kind} {window}", flush=True)
common_astro = set.intersection(*(v[1] for v in stable.values()))
common_hep = set.intersection(*(v[2] for v in stable.values()))
for row in read_rows(
archive, BROKERAGE + "common_endpoint_sensitivity.csv"
):
graph, _, _, candidates = stable[row["window"]]
scores = nx.betweenness_centrality_subset(
graph,
sorted(common_astro),
sorted(common_hep),
normalized=True,
weight=DISTANCE,
)
baseline, reachable = efficiency(graph, common_astro, common_hep)
focal = FOCAL["published_umbrella"]
after, after_reachable, loss = removal(
graph, common_astro, common_hep, focal, baseline
)
rank = 1 + sum(scores[n] > scores[focal] for n in candidates)
for value, column in [
(len(common_astro), "common_astro_endpoint_count"),
(len(common_hep), "common_hep_endpoint_count"),
(scores[focal], "common_endpoint_betweenness"),
(rank, "common_endpoint_candidate_rank"),
(baseline, "common_endpoint_baseline_efficiency"),
(after, "common_endpoint_removed_efficiency"),
(loss, "common_endpoint_removal_effect"),
(reachable, "common_endpoint_baseline_reachable_share"),
(after_reachable, "common_endpoint_removed_reachable_share"),
]:
check_close(
value, row[column], f'Common endpoints {row["window"]} {column}'
)
result["common_endpoints"].append(
{
"window": row["window"],
"astro_endpoints": len(common_astro),
"hep_endpoints": len(common_hep),
"betweenness": scores[focal],
"candidate_rank": rank,
"removal_effect": loss,
}
)
result["node_removal_rows_recalculated"] = removal_checks
result["betweenness_nodes_checked"] = sum(map(len, nodes.values()))
result["hits_candidates_checked"] = sum(map(len, importance_nodes.values()))
return result
Reading format; Python syntax tree matches the source.
PythonWorkflow entry for network checks
def network_checks(root):
root = Path(root)
mod = load_local(
root / "code/network-reconstruction/recompute_metrics.py",
"damadi_network_recompute",
)
report = mod.verify(root, root / "code/network-reconstruction/inputs.json")
assert report["status"] == "passed" and len(report["windows"]) == 57
path = root / "reproduced/network-metrics.json"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(report, indent=2, allow_nan=False) + "\n")
return {
"status": "PASS",
"windows": len(report["windows"]),
"nodes_checked": report["betweenness_nodes_checked"],
"removal_rows": report["node_removal_rows_recalculated"],
"scope": report["scope"],
}
Reading format; Python syntax tree matches the source.
PythonCorresponding notebook cell
reports["network_checks"] = network_checks(ROOT)
reports["network_checks"]
Reading format; Python syntax tree matches the source.
Render figures and check exports
The main R source constructs Figures 1–3 at their designated dimensions. The SI source renders statistical companions. Network presentation code preserves non-text drawing operations and source label positions while changing typography to STIX.
The gallery below contains nine supplied normalized PDF references. Four statistical SI references remain retained manuscript artwork and are distinct from regenerated SI companions. Figure 5 is a supplied conceptual assessment, outside this computational export route.
- Uses
- Frozen statistical products, saved network presentations, bundled STIX fonts
- Produces
- Nine generated PDF companions; dimension, source, and table checks
Pythonfigure_checks()
def figure_checks(root, render=True):
root = Path(root)
if render:
subprocess.run(
["Rscript", str(root / "code/04-build-figures.R")], cwd=root, check=True
)
mod = load_local(
root / "code/modules/network_graphics.py", "damadi_network_graphics"
)
mod.export_all(root)
from pypdf import PdfReader
files = sorted((root / "reproduced/stepwise-figures").glob("*.pdf")) + sorted(
(root / "reproduced/figures").glob("*.pdf")
)
assert len(files) == 9, len(files)
for file in files:
assert len(PdfReader(file).pages) == 1
config = json.loads((root / "config/main-figures.json").read_text())
assert (
hashlib.sha256(
(root / "code/02-main-figures-stepwise.R").read_bytes()
).hexdigest()
== config["active_script_sha256"]
)
for name, dimensions in config["figures"].items():
page = PdfReader(root / "reproduced/stepwise-figures" / name).pages[0]
actual = [
float(page.mediabox.width) * 25.4 / 72,
float(page.mediabox.height) * 25.4 / 72,
]
assert np.allclose(actual, dimensions, atol=0.02), (name, actual)
for name, digest in config["table_sha256"].items():
assert (
hashlib.sha256(
(root / "reproduced/tables" / name).read_bytes()
).hexdigest()
== digest
), name
return write_report(
root,
"figure-checks.json",
{
"status": "PASS",
"pdfs": len(files),
"statistical_renderings": 7,
"network_presentations": 2,
"network_geometry": "Unchanged",
"main_figure_source_sha256": config["source_script_sha256"],
"main_figure_dimensions_mm": config["figures"],
"main_tables_byte_identical_to_retained_fragments": True,
"authority": "Main Figures 1–3 regenerated from the user-designated script at final arXiv dimensions, with the preprint class colors fixed explicitly and bundled STIX typography. Four SI manuscript figures remain retained preprint assets; separate SI R companions remain available.",
},
)
Reading format; Python syntax tree matches the source.
RR · assemble research classifications
composition_plot_wide_guide <- (
(broad_plot +
one_row_guides +
theme(legend.position = "top", legend.justification = "left")) +
(paper_plot_wide +
one_row_guides +
theme(legend.position = "top", legend.justification = "left")) +
(papers_strip + theme(legend.position = "none")) +
guide_area() +
plot_layout(
design = "
DD
AB
CC
",
widths = c(1, 1.55),
heights = c(0.5, 9.3, 0.7),
guides = "keep",
axes = "collect"
) +
plot_annotation(
title = "Frequency of primary research classifications",
subtitle = "arXiv class and category − 2010-2025",
)
) &
theme(
legend.box = "horizontal",
legend.direction = "horizontal",
legend.byrow = TRUE,
#legend.justification = "center",
legend.key.spacing = grid::unit(1, "pt"),
legend.spacing.x = grid::unit(3, "pt"),
legend.text = element_text(size = 9, margin = margin(l = 3, r = 10)),
legend.margin = margin(0, 0, 0, 0),
plot.title = element_text(
size = 11, family = REPORT_FONT,
hjust = 0.05, vjust = 0.0
),
plot.subtitle = element_text(
size = 9, family = REPORT_FONT,
hjust = 0.045, vjust = 0.0
),
plot.tag = element_text(size = 7, family = REPORT_FONT),
plot.tag.position = c(0.01, 0.98),
axis.title.x = element_blank(),
plot.margin = margin(0, 7, 1, 0)
)
composition_plot_wide_guide <- composition_plot_wide_guide &
theme(
plot.background = element_blank(),
panel.background = element_blank(),
legend.background = element_blank(),
legend.box.background = element_blank()
)
if (interactive()) print(composition_plot_wide_guide)
if (SAVE_OUTPUTS) {
save_stepwise_pdf(composition_plot_wide_guide, "fig-research-classifications.pdf", 165, 90, bg = "transparent")
}
Exact source text.
RR · candidate prominence plot
MIN_TOTAL_MENTIONS <- 20L
candidate_field_plot <- candidate_field |>
mutate(SpeciesLabel = stringr::str_replace(SpeciesLabel, fixed("Sterile nu"), "Sterile ν"))
stopifnot(all(
candidate_field_plot$meets_minimum_count ==
(candidate_field_plot$total_mentions >= MIN_TOTAL_MENTIONS)
))
species_order <- candidate_field_plot |>
filter(year >= 1995, year <= 2025, total_mentions >= MIN_TOTAL_MENTIONS) |>
group_by(SpeciesLabel) |>
summarise(
mean_ratio = weighted.mean(log2_hep_astro_ratio, w = total_mentions, na.rm = TRUE),
.groups = "drop"
) |>
arrange(mean_ratio) |>
pull(SpeciesLabel)
log_ratio_data <- candidate_field_plot |>
filter(year >= 1995, year <= 2025, SpeciesLabel %in% species_order) |>
mutate(
SpeciesLabel = factor(SpeciesLabel, levels = species_order),
shown_ratio = if_else(total_mentions >= MIN_TOTAL_MENTIONS, log2_hep_astro_ratio, NA_real_)
)
div <- c(
"#00429d", "#2b57a7", "#426cb0", "#5681b9", "#6997c2",
"#7daeca", "#93c4d2", "#abdad9", "#caefdf", "#ffffe0",
"#ffe2ca", "#ffc4b4", "#ffa59e", "#f98689", "#ed6976",
"#dd4c65", "#ca2f55", "#b11346", "#93003a"
)
log_ratio_plot <- log_ratio_data |>
ggplot(aes(year, SpeciesLabel, fill = shown_ratio)) +
geom_tile(color = "white", linewidth = 0.15, alpha = 0.85) +
scale_x_continuous(
breaks = seq(1995, 2025, 2),
expand = expansion(mult = c(0.01, 0))
) +
scale_fill_gradientn(
colours = div,
name = "Share ratio",
limits = c(-log2(10), log2(10)),
breaks = c(-log2(10), -log2(3), 0, log2(3), log2(10)),
labels = c("10× Astro", "3× Astro", "1×", "3× HEP", "10× HEP"),
oob = scales::squish,
na.value = NA,
guide = guide_colorbar(
direction = "horizontal",
title.position = "top",
title.hjust = 0,
title.vjust = -0.3,
barwidth = grid::unit(70, "mm"),
barheight = grid::unit(3.5, "mm"),
ticks.colour = "white"
)
) +
labs(
x = NULL,
y = NULL,
title = "Relative prominence of candidates",
subtitle = "Log2 ratio of HEP to astrophysics shares, 1995-2025"
) +
theme_minimal(base_family = REPORT_FONT, base_size = 11) +
theme(
plot.title = element_text(size = 11, family = REPORT_FONT, hjust = 0),
plot.subtitle = element_text(
size = 8, family = REPORT_FONT, hjust = 0, vjust = 2.0),
plot.margin = margin(2, 5, 5, 0),
panel.grid.major = element_line(color = "#282828", linewidth = 0.05),
panel.grid.minor = element_blank(),
legend.margin = margin(-7, 0, 0, 0),
legend.text = element_text(size = 8, family = REPORT_FONT, color = "black"),
legend.title = element_text(size = 8, family = REPORT_FONT, color = "black"),
legend.position = "bottom",
plot.background = element_blank(),
panel.background = element_blank(),
legend.background = element_blank(),
legend.box.background = element_blank()
)
if (interactive()) print(log_ratio_plot)
if (SAVE_OUTPUTS) {
save_stepwise_pdf(log_ratio_plot, "fig-candidate-prominence.pdf", 156, 80, bg = "transparent")
}
Exact source text.
RR · candidate composition plot
tracked_species <- stringr::str_replace(tracked_species, fixed("Sterile nu"), "Sterile ν")
candidate_norm <- candidates |>
mutate(SpeciesLabel = stringr::str_replace(SpeciesLabel, fixed("Sterile nu"), "Sterile ν")) |>
filter(
year >= 1995,
year <= 2025,
arxiv_category %in% names(FIELD_LABELS),
SpeciesLabel %in% tracked_species
) |>
distinct(year, arxiv_category, bibcode, SpeciesLabel) |>
count(year, arxiv_category, SpeciesLabel, name = "n") |>
group_by(year, arxiv_category) |>
mutate(share_tracked_candidates = n / sum(n)) |>
ungroup() |>
mutate(
field = recode(arxiv_category, !!!FIELD_LABELS),
SpeciesLabel = factor(SpeciesLabel, levels = tracked_species)
)
candidate_colors <- setNames(
khroma::color("batlow", type = "qualitative", reverse = TRUE)(length(tracked_species)),
tracked_species
)
p_norm <- candidate_norm |>
ggplot(aes(year, share_tracked_candidates, fill = SpeciesLabel)) +
geom_area(position = "fill", alpha = 0.89, linewidth = 0.15, color = "white") +
facet_wrap(~ field, ncol = 2, scales = "fixed") +
scale_fill_manual(values = candidate_colors, name = NULL, drop = FALSE) +
scale_x_continuous(
breaks = seq(1995, 2025, 5),
expand = expansion(mult = c(0.01, 0))
) +
scale_y_continuous(
labels = scales::percent_format(accuracy = 1),
expand = expansion(mult = c(0.01, 0))
) +
labs(x = NULL,
title = "Share of paper-candidate-family mentions",
subtitle = "Normalized to total mentions in each field, 1995-2025",
y = NULL) +
theme_minimal(base_size = 11, base_family = REPORT_FONT) +
theme(
panel.spacing = grid::unit(1.5, "lines"),
plot.margin = margin(0, 0, 0, 0),
strip.background = element_rect(color = NA, fill = NA),
strip.text = element_text(color = "#141414", size = 10, family = REPORT_FONT),
strip.text.x.bottom = element_text(hjust = 0.5, vjust = 0.5),
axis.ticks.x = element_blank(),
legend.position = "bottom",
legend.key.spacing.y = grid::unit(0.2, "lines")
) +
guides(fill = guide_legend(
nrow = 1,
byrow = TRUE,
title.position = "bottom",
title.hjust = 0.5,
label.position = "bottom",
override.aes = list(alpha = 1, size = 1.5, shape = 15),
keywidth = grid::unit(5, "pt"),
keyheight = grid::unit(10, "pt")
))
candidate_robustness <- p_norm +
patchwork::plot_layout(widths = 1, axes = "collect", guides = "keep") &
theme(
plot.title = element_text(size = 10, color = "black", hjust = 0, vjust = -2.8),
plot.subtitle = element_text(size = 9, color = "black", hjust = 0, vjust = -1.0),
plot.margin = margin(2, 12, 5, 0),
legend.margin = margin(-5, 0, 0, 0),
legend.position = "bottom",
legend.box = "horizontal",
#legend.box.just = "left",
panel.grid.major = element_line(color = "black", linewidth = 0.15),
panel.grid.minor = element_blank(),
plot.background = element_blank(),
panel.background = element_blank(),
legend.background = element_blank(),
legend.box.background = element_blank(),
legend.key.spacing = grid::unit(2.0, "pt"),
legend.text = element_text(size = 7.7, margin = margin(t = 2.5, l = 0.7, r = 0.7, unit = "pt")),
legend.title = element_text(size = 9, family = BASE_FONT, color = "black", hjust = 0)
)
if (interactive()) print(candidate_robustness)
if (SAVE_OUTPUTS) {
Exact source text.
PythonPreserve network geometry; retype labels
def normalize_one(source, destination, font_dir):
source = Path(source)
destination = Path(destination)
font_dir = Path(font_dir)
original = fitz.open(source)
page = original[0]
assert len(original) == 1 and page.rotation == 0
overlays = []
for block in page.get_text("dict")["blocks"]:
for line in block.get("lines", []):
assert abs(line["dir"][1]) < 1e-8 and line["dir"][0] > 0
for span in line["spans"]:
font = span["font"]
face = (
"math"
if "Math" in font
else (
"italic"
if "Italic" in font
else (
"medium"
if "IBM" in font or "Bold" in font or "Medium" in font
else "regular"
)
)
)
overlays.append(
{
"text": span["text"],
"origin": span["origin"],
"bbox": span["bbox"],
"size": span["size"],
"color": span["color"],
"face": face,
"source_font": font,
}
)
reader = PdfReader(source)
writer = PdfWriter()
writer.clone_document_from_reader(reader)
fingerprints = []
visited = set()
def clean(stream, resources, label):
key = id(stream)
if key in visited:
return
visited.add(key)
content = ContentStream(stream, writer)
before = []
after = []
kept = []
for operands, op in content.operations:
if op == b"Tr":
assert (
float(operands[0]) < 4
), "Text clipping requires explicit treatment"
if op not in TEXT_OPS:
before.append((repr(operands), op.decode("latin1")))
kept.append((operands, op))
after.append((repr(operands), op.decode("latin1")))
assert before == after
fingerprints.append(
{
"stream": label,
"nontext_operations": len(before),
"sha256": hashlib.sha256(repr(before).encode()).hexdigest(),
}
)
content.operations = kept
stream.set_data(content.get_data())
if "/Font" in resources:
del resources["/Font"]
for name, value in resources.get("/XObject", {}).items():
obj = value.get_object()
if obj.get("/Subtype") == "/Form":
clean(
obj,
obj.get("/Resources", resources).get_object(),
label + "/" + str(name),
)
pdfpage = writer.pages[0]
# Flatten the page content array into one stream without changing drawing operations.
contents = ContentStream(pdfpage.get_contents(), writer)
pdfpage[NameObject("/Contents")] = writer._add_object(contents)
clean(contents, pdfpage["/Resources"].get_object(), "page")
overlay = fitz.open()
newpage = overlay.new_page(width=page.rect.width, height=page.rect.height)
faces = {
"regular": "STIXTwoText-Regular.ttf",
"italic": "STIXTwoText-Italic.ttf",
"medium": "STIXTwoText-Medium.ttf",
"math": "STIXTwoMath-Regular.otf",
}
fonts = {k: fitz.Font(fontfile=str(font_dir / v)) for k, v in faces.items()}
for k, v in faces.items():
newpage.insert_font(fontname="DAMADI" + k, fontfile=str(font_dir / v))
for span in overlays:
text = span["text"]
face = span["face"]
font = fonts[face]
assert all(c.isspace() or font.has_glyph(ord(c)) for c in text), (
text,
face,
)
width = font.text_length(text, fontsize=span["size"])
source_width = span["bbox"][2] - span["bbox"][0]
factor = source_width / width if width > 0 else 1
origin = fitz.Point(span["origin"])
rgb = fitz.sRGB_to_pdf(span["color"])
newpage.insert_text(
origin,
text,
fontsize=span["size"],
fontname="DAMADI" + face,
color=rgb,
morph=(origin, fitz.Matrix(factor, 1)),
)
span["horizontal_scale"] = factor
overlay_writer = PdfWriter()
overlay_writer.clone_document_from_reader(
PdfReader(io.BytesIO(overlay.tobytes()))
)
# MuPDF's CFF insertion needs an explicit UTF-16 mapping for non-BMP math letters.
math_chars = sorted(
{c for span in overlays if span["face"] == "math" for c in span["text"]}
)
if math_chars:
pairs = [
f'<{fonts["math"].has_glyph(ord(c)):04X}> <{c.encode("utf-16-be").hex().upper()}>'
for c in math_chars
]
cmap = (
"/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n/CMapName /DAMADI-Math-Unicode def\n/CMapType 2 def\n1 begincodespacerange\n<0000> <FFFF>\nendcodespacerange\n"
+ str(len(pairs))
+ " beginbfchar\n"
+ "\n".join(pairs)
+ "\nendbfchar\nendcmap\nCMapName currentdict /CMap defineresource pop\nend\nend\n"
)
stream = DecodedStreamObject()
stream.set_data(cmap.encode())
overlay_writer.pages[0]["/Resources"]["/Font"]["/DAMADImath"].get_object()[
NameObject("/ToUnicode")
] = overlay_writer._add_object(stream)
pdfpage.merge_page(overlay_writer.pages[0])
writer.add_metadata(
{
"/Title": "DAMADI STIX presentation of retained network figure",
"/Author": "Simon Allzén",
"/Subject": "Original graph geometry and source label positions retained; STIX typography only",
}
)
destination.parent.mkdir(parents=True, exist_ok=True)
with destination.open("wb") as output:
writer.write(output)
rendered = fitz.open(destination)
expected = "".join(x["text"] for x in overlays)
# Verify every source label's characters remain in the presentation text layer.
actual = rendered[0].get_text()
from collections import Counter
assert Counter(c for c in expected if not c.isspace()) == Counter(
c for c in actual if not c.isspace()
)
return {
"source": source.name,
"pdf": destination.name,
"label_spans": overlays,
"nontext_stream_fingerprints": fingerprints,
"all_nontext_operations_unchanged": True,
"source_label_characters_retained": True,
"font_sizes_and_origins_retained": True,
"width_mm": page.rect.width * 25.4 / 72,
"height_mm": page.rect.height * 25.4 / 72,
}
Reading format; Python syntax tree matches the source.
RBatch wrapper for the stepwise R sources
#!/usr/bin/env Rscript
# Thin batch wrapper; the stepwise routes contain the complete plotting workflow.
arg <- grep("^--file=", commandArgs(FALSE), value = TRUE)
code_dir <- if (length(arg)) dirname(normalizePath(gsub("~+~", " ", sub("^--file=", "", arg[[1]]), fixed = TRUE))) else file.path(getwd(), "code")
for (name in c("02-main-figures-stepwise.R", "03-si-figures-stepwise.R")) {
source(file.path(code_dir, name), local = new.env(parent = globalenv()))
}
Exact source text.
PythonCorresponding notebook cell
if os.environ.get("DAMADI_ANALYSIS_ONLY") == "1":
reports["figure_checks"] = {
"status": "PASS",
"skipped": True,
"reason": "Numerical-only mode; no graphical checks claimed",
}
else:
reports["figure_checks"] = figure_checks(ROOT)
reports["figure_checks"]
Reading format; Python syntax tree matches the source.
Record completion and scope
The command-line route gathers the stage reports and records their scope. The clean notebook invokes the same functions and asserts completion before writing its own report. Numerical-only mode explicitly skips graphical checks.
No research analysis has been executed for this HTML edition. The displayed numbers and PDFs are supplied reference products; the checks performed here concern source identity and presentation.
- Uses
- Reports from input, corpus, candidate, network, and optional graphics stages
- Produces
- reproduction.json or notebook-checks.json in a separate verification directory
PythonShared command-line orchestration
def run(root, render=True):
root = Path(root).resolve()
reports = {}
for name, fn in [
("inputs", input_checks),
("corpus", corpus_checks),
("candidates", candidate_checks),
("network", network_checks),
]:
print("STEP:", name, flush=True)
reports[name] = fn(root)
reports["figures"] = (
figure_checks(root)
if render
else {
"status": "PASS",
"skipped": True,
"reason": "Numerical-only mode; no graphical checks claimed",
}
)
return write_report(
root,
"reproduction.json",
{
"status": "PASS",
"entry": "E.04--MS-DA-CR",
"reports": reports,
"limits": "Frozen-input reconstruction. No new retrieval, raw-abstract NLP extraction, new annotation, holdout inspection, causal validation or bootstrap resampling.",
},
)
Reading format; Python syntax tree matches the source.
PythonWrite a verification report
def write_report(root, name, value):
path = Path(root) / "verification" / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
json.dumps(value, ensure_ascii=False, indent=2, allow_nan=False) + "\n"
)
return value
Reading format; Python syntax tree matches the source.
PythonCommand-line entry point
#!/usr/bin/env python3
from pathlib import Path
import sys, os
root = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(root / "code/modules"))
from workflow import run
print(run(root, render=os.environ.get("DAMADI_ANALYSIS_ONLY") != "1")["status"])
Reading format; Python syntax tree matches the source.
PythonCorresponding notebook cell
assert all(item["status"] == "PASS" for item in reports.values())
write_report(
ROOT,
"notebook-checks.json",
{"status": "PASS", "clean_kernel": True, "reports": reports},
)
Reading format; Python syntax tree matches the source.
What the retained products report
Counts and contrasts come from the supplied workflow and analysis summary. Their display here does not certify a fresh numerical reconstruction.
| Quantity | Supplied value |
|---|---|
| Full corpus through 2025 | 201,627 |
| Primary-classified papers | 143,390 |
| Candidate papers · 1995–2025 | 22,247 |
| Candidate tag rows · 1995–2025 | 27,680 |
| Tracked candidate families | 13 |
| Frozen graph/window combinations | 57 |
Candidate-profile contrast
| Comparison | Supplied Jensen–Shannon divergence |
|---|---|
| 1995-2004 | 0.32563 |
| 2016-2025 | 0.29295 |
| Late minus early | -0.03268 |
| Retained contrast interval | -0.09546 to -0.01795 |
The retained late-minus-early contrast is negative. The result does not support increasing candidate-profile divergence. Different field profiles and declining WIMP prominence should not be conflated with growing statistical separation.
Scope of the network checks
The reconstruction compares 57 definition/window combinations with archived metrics. Its three focal definitions are explicit generic WIMP, the published WIMP umbrella, and canonical WIMP core. It checks cross-field betweenness, role-specific importance, and removal diagnostics conditional on frozen graphs and count tables.
From products to presentation
The original normalized PDFs are displayed directly, with neutral colors adapted to the archive theme. Downloads preserve the supplied PDF bytes. Main figures appear below; supplementary references are available in the disclosure.
Research classifications
Annual primary arXiv research classifications and their composition. Primary assignments and broader assignment counts remain distinguishable.
Candidate prominence
Field-year prominence contrasts between high-energy physics and astrophysics. The supplied code retains the 0.5 pseudocount and minimum-count display rule.
Candidate composition
Shares of paper–candidate-family mentions, normalized within each field. These profiles describe attention across thirteen tracked families.
Cross-field brokerage
Saved network geometry and label positions are preserved in the supplied STIX presentation. The graph represents discourse relations rather than evidential or causal dependence.
Supplementary references · five PDFs
Classification sensitivity
The supplied manuscript reference is retained unchanged. The R source separately constructs the statistical companion from frozen products.
Candidate counts
Retained raw-count display for the candidate analysis. The reference PDF and the separate R construction remain distinguishable.
Candidate-profile distances
Retained candidate-distribution distances and uncertainty. Existing bootstrap products are presented as supplied, not resampled for this edition.
Lexical comparisons
Retained lexical-comparison figure. The upstream lexical extraction is separate from the normalized frozen-input checking route.
Node-removal diagnostics
Saved node-removal presentation with its geometry retained. Removing a node probes a frozen graph; it is not a historical counterfactual.
Read the implementation
49 Python, R, shell, and C files are available, including 15 active workflow, setup, and checking sources. Earlier pipeline sources are labeled separately. Individual reading views load when opened; original source downloads retain their exact bytes.
| File | Role | Language | Lines |
|---|---|---|---|
| Numerical entry point Active workflow / checks | Python | 7 | |
| Main statistical figure construction Active workflow / checks | R | 630 | |
| Supplementary statistical companions Active workflow / checks | R | 882 | |
| Stepwise R batch wrapper Active workflow / checks | R | 7 | |
| Private clean-kernel notebook runner Active workflow / checks | Python | 21 | |
| Restore exact split inputs Active workflow / checks | Python | 34 | |
| Network geometry and STIX presentation Active workflow / checks | Python | 82 | |
| Process-local Quartz font registration Active workflow / checks | R | 20 | |
| CoreText helper Active workflow / checks | C | 16 | |
| Shared six-stage checking workflow Active workflow / checks | Python | 107 | |
| Frozen graph metrics and comparison checks Active workflow / checks | Python | 285 | |
| Deterministic reconstruction tests Active workflow / checks | Python | 72 | |
| Fixed-package identity check Active workflow / checks | Python | 16 | |
| Analysis/full/notebook mode driver Active workflow / checks | Shell | 28 | |
| Pinned Python environment setup Active workflow / checks | Shell | 10 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Shell | 4 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | R | 242 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | R | 523 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | R | 506 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | R | 889 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 463 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 69 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 401 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 350 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 284 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 183 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 1733 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Shell | 27 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 1 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 299 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 43 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 87 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 92 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 165 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 1 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 1 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 20 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Shell | 4 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Shell | 5 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 79 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 24 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 415 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 554 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 303 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 2236 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 406 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 369 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Python | 323 | |
| Earlier acquisition, extraction, analysis, or maintenance source Earlier pipeline / support | Shell | 71 |
No matching files.
Supplied reference tables
Record-level datasets, saved-output upstream notebooks, large keyness tables, network archives, and validation-answer files are omitted. These remain separate from this reading edition.
Identify the material
- Supplied source package
- diverging-paths · 3.1.0
- Scientific baseline
- Zenodo v3.0.0
- Analysis cutoff
- 2025
- Source code license
- MIT
The scientific baseline DOI ↗ identifies the earlier deposited evidence. The concept DOI ↗ identifies the version lineage. This reading edition uses the supplied 3.1.0 source folder and does not assign it a new version DOI.
Reproduction requirements and limits
- The preferred package environment uses Python 3.11. The numerical-only route does not need R; the approved graphical route uses macOS Quartz, R packages, compiler support, and bundled STIX fonts.
- The clean notebook has six numbered stages plus setup, seven code cells, and no saved outputs.
- No acquisition, raw-abstract extraction, new annotation, independent accuracy estimate, unused holdout evaluation, ontology change, or bootstrap resampling is performed for this edition.
- The normalized references and retained v3.0.0 artwork remain distinct. The conceptual assessment in main Figure 5 is supplied artwork rather than a computational result.
Source integrity and presentation checks
Copied files are checked against the supplied release manifest and their recorded hashes. Python reading formatting is syntax-tree checked. These checks protect the reading edition; they do not reproduce the scientific analysis.
- Inspected source checkout
- efae0a78dff372acf32025287e423dc523248f40
- Source checkout state
- Clean at inspection
- Source release manifest SHA-256
- 737c4b65853a28b065e9c5a0cfb86b0215a07ed3b18d7b6632770129155b9ee6