MINOS · Phys. Rev. D 81, 072002 (2010)

Neutrino and antineutrino inclusive charged-current cross section measurements with the MINOS near detector

Model inputs MINOS 2010 cross sections Reproduced

The νμ (3–50 GeV) and ν̄μ (5–50 GeV) inclusive charged-current cross sections per nucleon of isoscalar iron, σ/E, and their ratio r = σ(ν̄)/σ(ν) (the paper's tables, from the arXiv source), compared with the cross sections carried by Newtrinos.jl (module xsec): the ten GENIE tunes of generator_sigma on ⁵⁶Fe, corrected to an isoscalar nucleon with each tune's free proton and neutron cross sections (isoscalar_correction: −2.3 % for ν, +2.1 % for ν̄), and the nominal model of CorrelatedXsec (the mean of the tunes) with its prior 1σ band. The neutrino cross section lies at the upper edge of the data (χ² = 19.5 for 13 bins; 8.0 with the prior band; the tunes give 5–46). The antineutrino cross section between 6 and 16 GeV, and with it the ratio, lies 5–8 % below all tunes (nominal χ² = 16.8/11 for ν̄ and 26.7/11 for r); the prior band of the ratio is ±3 % in this region, including the 3 % ν̄/ν uncertainty of DIS (xsec_nubar_dis_ratio), and with it χ² = 9.2 (ν̄) and 12.8 (r).

Figures

σ(ν̄μ)/σ(νμ) on isoscalar iron: MINOS vs the GENIE tunes and the CorrelatedXsec nominal with its prior 1σ band · Fig. 12 (left)

Paper · Fig. 12 (left)
Original: σ(ν̄μ)/σ(νμ) on isoscalar iron: MINOS vs the GENIE tunes and the CorrelatedXsec nominal with its prior 1σ band

Original figure: MINOS, Phys. Rev. D 81, 072002 (2010), Fig. 12 (left), doi:10.1103/PhysRevD.81.072002. Not our work; shown for comparison, all rights with the authors and publisher.

Newtrinos.jl
Reproduction: σ(ν̄μ)/σ(νμ) on isoscalar iron: MINOS vs the GENIE tunes and the CorrelatedXsec nominal with its prior 1σ band

νμ CC σ/E per isoscalar nucleon of iron · Fig. 10 (left)

Paper · Fig. 10 (left)
Original: νμ CC σ/E per isoscalar nucleon of iron

Original figure: MINOS, Phys. Rev. D 81, 072002 (2010), Fig. 10 (left), doi:10.1103/PhysRevD.81.072002. Not our work; shown for comparison, all rights with the authors and publisher.

Newtrinos.jl
Reproduction: νμ CC σ/E per isoscalar nucleon of iron

ν̄μ CC σ/E per isoscalar nucleon of iron · Fig. 10 (right)

Paper · Fig. 10 (right)
Original: ν̄μ CC σ/E per isoscalar nucleon of iron

Original figure: MINOS, Phys. Rev. D 81, 072002 (2010), Fig. 10 (right), doi:10.1103/PhysRevD.81.072002. Not our work; shown for comparison, all rights with the authors and publisher.

Newtrinos.jl
Reproduction: ν̄μ CC σ/E per isoscalar nucleon of iron

Known limitations

Reproduce

  1. git clone https://github.com/Newtrinos-org/Newtrinos.jl.git && cd Newtrinos.jl && git checkout 78e71c310b
  2. Download reproduce.jl and the data/ folder of this entry into an empty directory.
  3. julia -t 8 --project=/path/to/Newtrinos.jl reproduce.jl
# MINOS νμ and ν̄μ inclusive CC cross sections per nucleon of isoscalar iron, σ/E for 3–50 GeV, and their ratio
# (PRD 81, 072002 (2010); tables from the arXiv:0910.2201 source in data/), compared with the cross sections of
# Newtrinos.jl (module `xsec`): the GENIE tunes (`generator_sigma`, ⁵⁶Fe, corrected to an isoscalar nucleon with each
# tune's free p/n cross sections, `isoscalar_correction`) and the reference model of `CorrelatedXsec` with its prior
# 1σ band (ν, ν̄ and their ratio sampled jointly).
# Run from this directory with the Newtrinos.jl environment at the pinned commit:
#   julia --project=<path to Newtrinos.jl> reproduce.jl
using Newtrinos, CairoMakie, CSV, DataFrames, Printf, Statistics, Random, Distributions

cd(@__DIR__); mkpath("ours"); mkpath("results")
const X = Newtrinos.xsec

d = CSV.read("data/minos_table.csv", DataFrame; comment = "#")
r = CSV.read("data/minos_ratio.csv", DataFrame; comment = "#")
dn, db = d[d.nu .== "nu", :], d[d.nu .== "nubar", :]

tab = X.load_table()
E = 10 .^ range(log10(0.2), log10(60), length = 300)   # down to the threshold region
at(v, e = E) = X.at_energies(tab.E, v, e)
TUNES = Symbol.(sort(tab.tunes))
iso(t, anti, e = E) = at(X.isoscalar_correction(t, 26, 56, :numu, anti), e)
σ_tune(t, anti, e = E) = at(sum(X.generator_sigma(t, :Fe, :numu, anti, :CC)), e) .* iso(t, anti, e)

xs = X.configure(X.CorrelatedXsec())
ref = xs.cfg.reference
sig = Dict(anti => (f = xs.sigma(E; flavour = :numu, anti, current = :CC, target = :Fe); c = iso(ref, anti); p -> f(p) .* c) for anti in (false, true))
# bin averages (flat in E) for the data bins, and the model at the bin-average energies for the ratio
binE(lo, hi) = collect(range(lo, hi, length = 21))
sig_bins(dd, anti) = [(f = xs.sigma(binE(lo, hi); flavour = :numu, anti, current = :CC, target = :Fe); c = iso(ref, anti, binE(lo, hi)); p -> mean(f(p) .* c))
                      for (lo, hi) in zip(dd.E_lo, dd.E_hi)]
bins = (nu = sig_bins(dn, false), nubar = sig_bins(db, true))
sig_r = Dict(anti => (f = xs.sigma(r.E_mean; flavour = :numu, anti, current = :CC, target = :Fe); c = iso(ref, anti, r.E_mean); p -> f(p) .* c) for anti in (false, true))

rng = MersenneTwister(1)
draw() = map(p -> p isa Distribution ? rand(rng, p) : p, xs.priors)
samples = [draw() for _ in 1:500]
q(M, a) = [quantile(filter(!isnan, row), a) for row in eachrow(M)]   # ratios are undefined where a draw has σ = 0
band = Dict(anti => (M = reduce(hcat, [sig[anti](p) for p in samples]); (lo = q(M, 0.16), hi = q(M, 0.84))) for anti in (false, true))
Rs = reduce(hcat, [sig[true](p) ./ sig[false](p) for p in samples])
rband = (lo = q(Rs, 0.16), hi = q(Rs, 0.84))
p0 = xs.params

ticks = ([0.2, 0.5, 1, 2, 5, 10, 20, 50], ["0.2", "0.5", "1", "2", "5", "10", "20", "50"])
function panel_sigma(pos, anti, dd, lab, lims)
    ax = Axis(pos, xscale = log10, xlabel = "E_ν (GeV)", ylabel = "$lab CC σ / E (10⁻³⁸ cm²/GeV per nucleon)",
              title = "MINOS $lab, isoscalar Fe", limits = (0.2, 60, lims...), xticks = ticks)
    band!(ax, E, band[anti].lo, band[anti].hi, color = (:dodgerblue, 0.25), label = "CorrelatedXsec prior 1σ")
    for (i, t) in enumerate(TUNES)
        lines!(ax, E, σ_tune(t, anti), color = (Makie.wong_colors()[mod1(i, 7)], 0.8), linewidth = 1, label = "GENIE $(t)")
    end
    lines!(ax, E, sig[anti](p0), color = :dodgerblue, linewidth = 2.5, label = "nominal ($(ref))")
    errorbars!(ax, dd.E_mean, dd.sigma_over_E, dd.total, color = :black, whiskerwidth = 4)
    scatter!(ax, dd.E_mean, dd.sigma_over_E, color = :black, label = "MINOS (stat ⊕ syst ⊕ norm)")
    ax
end
function panel_ratio(pos)
    ax = Axis(pos, xscale = log10, xlabel = "E_ν (GeV)", ylabel = "σ(ν̄μ) / σ(νμ)", title = "MINOS ratio r, isoscalar Fe",
              limits = (0.2, 60, 0.2, 0.6), xticks = ticks)
    band!(ax, E, rband.lo, rband.hi, color = (:dodgerblue, 0.25), label = "CorrelatedXsec prior 1σ")
    for (i, t) in enumerate(TUNES)
        lines!(ax, E, σ_tune(t, true) ./ σ_tune(t, false), color = (Makie.wong_colors()[mod1(i, 7)], 0.8), linewidth = 1, label = "GENIE $(t)")
    end
    lines!(ax, E, sig[true](p0) ./ sig[false](p0), color = :dodgerblue, linewidth = 2.5, label = "nominal ($(ref))")
    errorbars!(ax, r.E_mean, r.r, r.total, color = :black, whiskerwidth = 4)
    scatter!(ax, r.E_mean, r.r, color = :black, label = "MINOS (total)")
    ax
end
for (name, mk) in (("nu", pos -> panel_sigma(pos, false, dn, "νμ", (0.0, 1.05))),
                   ("nubar", pos -> panel_sigma(pos, true, db, "ν̄μ", (0.0, 0.42))), ("ratio", panel_ratio))
    fig = Figure(size = (800, 470))
    ax = mk(fig[1, 1])
    Legend(fig[1, 2], ax, framevisible = false, labelsize = 9)
    save("ours/$(name).png", fig)
end

# χ²: σ/E with stat ⊕ syst (MINOS normalised ν above 30 GeV to the world average; the normalisation error is common
# to all bins and is left out), and the ratio with its total errors; reference with and without its prior band
chi2(data, err, m, extra = 0) = sum((data .- m) .^ 2 ./ (err .^ 2 .+ extra .^ 2))
err_ss(dd) = sqrt.(dd.stat .^ 2 .+ dd.sys .^ 2)
mref = (nu = [f(p0) for f in bins.nu], nubar = [f(p0) for f in bins.nubar])
msd = (nu = [std([f(p) for p in samples]) for f in bins.nu], nubar = [std([f(p) for p in samples]) for f in bins.nubar])
rref = sig_r[true](p0) ./ sig_r[false](p0)
rsd = [std(col) for col in eachrow(reduce(hcat, [sig_r[true](p) ./ sig_r[false](p) for p in samples]))]
rows = [(model = "$(ref) (nominal)", chi2_nu = chi2(dn.sigma_over_E, err_ss(dn), mref.nu), chi2_nubar = chi2(db.sigma_over_E, err_ss(db), mref.nubar),
         chi2_ratio = chi2(r.r, r.total, rref), chi2_nu_band = chi2(dn.sigma_over_E, err_ss(dn), mref.nu, msd.nu),
         chi2_nubar_band = chi2(db.sigma_over_E, err_ss(db), mref.nubar, msd.nubar), chi2_ratio_band = chi2(r.r, r.total, rref, rsd))]
binavg(t, anti, dd) = [mean(σ_tune(t, anti, binE(lo, hi))) for (lo, hi) in zip(dd.E_lo, dd.E_hi)]
for t in TUNES
    push!(rows, (model = string(t), chi2_nu = chi2(dn.sigma_over_E, err_ss(dn), binavg(t, false, dn)),
                 chi2_nubar = chi2(db.sigma_over_E, err_ss(db), binavg(t, true, db)),
                 chi2_ratio = chi2(r.r, r.total, σ_tune(t, true, r.E_mean) ./ σ_tune(t, false, r.E_mean)),
                 chi2_nu_band = NaN, chi2_nubar_band = NaN, chi2_ratio_band = NaN))
end
out = DataFrame(rows)
out.ndf_nu .= nrow(dn); out.ndf_nubar .= nrow(db); out.ndf_ratio .= nrow(r)
CSV.write("results/chi2.csv", out)
CSV.write("results/ratio.csv", DataFrame(E = r.E_mean, data = r.r, err = r.total, reference = round.(rref, digits = 4), prior_1sigma = round.(rsd, digits = 4)))
show(stdout, out, allrows = true, allcols = true); println()

Provenance

Newtrinos.jl commit78e71c310b (xsec (generator_sigma, isoscalar_correction, CorrelatedXsec))
Run date2026-10-12T14:43:11Z
Wall time1.7 min (4 threads)
Julia1.12.5
MachineAMD EPYC 7702P 64-Core Processor, 128 hardware threads, Linux
Environmentnewtrinos_Manifest.toml · run.toml

Downloads

CSV files hold one row per scan point: the scanned and profiled parameters (sin2_theta23, dm2_32 in eV², dcp in rad, nuisance parameters), dchi2 = −2Δ log L and the log-likelihood. JLD2 files contain the full NewtrinosResult objects.

FileSizeSHA-256
ours/nu.png238.3 kB5a84faee6bed…
ours/nubar.png227.9 kBca5053dc7a3a…
ours/ratio.png205.9 kBa5217f144397…
results/chi2.csv1.2 kBee8284197344…
results/ratio.csv367 B64bc3a1575d9…