Skip to content

Add detector geometries: Lake Geneva, KM3NeT-ORCA, ND280, SINE, UNDINE#101

Closed
austinschneider wants to merge 1 commit into
chore/ci-and-packagingfrom
feat/detectors-resources
Closed

Add detector geometries: Lake Geneva, KM3NeT-ORCA, ND280, SINE, UNDINE#101
austinschneider wants to merge 1 commit into
chore/ci-and-packagingfrom
feat/detectors-resources

Conversation

@austinschneider

Copy link
Copy Markdown
Collaborator

Stack: PR 3 of 14

This PR is part of a 14-PR stack decomposing dev/HNL_DIS into reviewable chunks.

  • Base: chore/ci-and-packaging
  • Head: feat/detectors-resources

Merge order: chore/ci-and-packaging should land before this PR.

Squashed contents

Squashed diff for paths:

  • resources/detectors
  • resources/examples
  • resources/fluxes/T2K_Kaons
  • python/_util.py

Source commits on dev/HNL_DIS_clean that contributed:
088b1cd (Nicholas Kamp): move around the HNL DIS fits files
23fa85c (Nicholas Kamp): Allow underscores in model names
eb78b84 (Nicholas Kamp): _util bug fixes and KM3Net renaming

Notes

  • This branch is the squashed cumulative diff of the listed source commits. Per-commit history is browsable on dev/HNL_DIS_clean.
  • Large .fits data files have been removed from the branch and are packaged separately.

Squashed diff for paths:
  - resources/detectors
  - resources/examples
  - resources/fluxes/T2K_Kaons
  - python/_util.py

Source commits on dev/HNL_DIS_clean that contributed:
  088b1cd (Nicholas Kamp): move around the HNL DIS fits files
  23fa85c (Nicholas Kamp): Allow underscores in model names
  eb78b84 (Nicholas Kamp): _util bug fixes and KM3Net renaming

Additional source commit:
  bea39f9 (Ming-Shau Liu): SIREN ND280+ MODULE ADDITION (#73)

Co-authored-by: Ming-Shau Liu <123968200+mingshauliu@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 28, 2026 04:28
@austinschneider austinschneider force-pushed the chore/ci-and-packaging branch from d00f148 to f15cfc2 Compare April 28, 2026 04:34
@austinschneider austinschneider force-pushed the feat/detectors-resources branch from da5daf5 to 4112bfa Compare April 28, 2026 04:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds new detector geometry/material resources and tabulated flux resources (T2K kaons), plus small utility updates to support model naming and on-demand flux file generation.

Changes:

  • Add detector geometry/material resource files for SINE, UNDINE, ND280, and KM3NeT-ORCA; extend IceCube geometry with DeepCore and an enlarged fiducial shell.
  • Add T2K kaon flux resource data and a FluxCalculator.py to generate particle-specific flux files.
  • Update Python utilities to allow underscores in model names and to load/generate tabulated flux files from resources.

Reviewed changes

Copilot reviewed 18 out of 20 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
resources/fluxes/T2K_Kaons/T2K_Kaons-v1.0/test.ipynb Notebook used to generate/inspect flux ratios and plots.
resources/fluxes/T2K_Kaons/T2K_Kaons-v1.0/ratio.dat Tabulated ratio data used for _bar scaling.
resources/fluxes/T2K_Kaons/T2K_Kaons-v1.0/kaon-flux-data.dat Input kaon flux data (log-scale values).
resources/fluxes/T2K_Kaons/T2K_Kaons-v1.0/TOT_PLUS_NUMU.dat Source flux table used to compute ratio data.
resources/fluxes/T2K_Kaons/T2K_Kaons-v1.0/TOT_MINUS_NUMUBAR.dat Source flux table used to compute ratio data.
resources/fluxes/T2K_Kaons/T2K_Kaons-v1.0/FluxCalculator.py Adds code to generate derived tabulated flux files from packaged data.
resources/examples/example2/PaperPlots.ipynb Formatting/metadata cleanup in plotting notebook.
resources/examples/additional_paper_plots/PaperPlots.ipynb Updates cross-section plotting/reweighting workflow and adds extra rate/diagnostic cells.
resources/detectors/UNDINE/UNDINE-v1/materials.dat Adds material composition definitions for UNDINE resources.
resources/detectors/UNDINE/UNDINE-v1/densities.dat Adds UNDINE geometry (air/rock/lake + cylinder detector) with densities.
resources/detectors/SINE/SINE-v1/materials.dat Adds material composition definitions for SINE resources.
resources/detectors/SINE/SINE-v1/densities.dat Adds SINE geometry (container panels) with densities.
resources/detectors/ND280/ND280-v1/materials.dat Adds ND280 materials definitions for detailed detector composition.
resources/detectors/ND280/ND280-v1/densities.dat Adds ND280 geometry layout with densities and fiducial definition.
resources/detectors/KM3NeTORCA/KM3NeTORCA-v1/materials.dat Adds ORCA material definitions (water/rock/mantle/core/air).
resources/detectors/KM3NeTORCA/KM3NeTORCA-v1/densities.dat Adds ORCA PREM-based geometry and cylindrical detector.
resources/detectors/IceCube/IceCube-v1/densities.dat Adds DeepCore + enlarged shell and switches fiducial to enlarged shell.
python/_util.py Allows underscores in model names; adds helpers to locate/generate tabulated flux files via FluxCalculator.py.
Comments suppressed due to low confidence (1)

resources/fluxes/T2K_Kaons/T2K_Kaons-v1.0/test.ipynb:1

  • This notebook is committed with execution counts and a large embedded PNG output, which bloats the repo and produces noisy diffs. Consider clearing outputs (execution_count: null, empty outputs) before committing and using an output-stripping tool (e.g., pre-commit nbstripout) to keep resources lightweight.
{

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread python/_util.py
Comment on lines +772 to +782
abs_flux_dir = get_tabulated_flux_model_path(model_name,must_exist=must_exist)
# require existence of FluxCalculator.py
FluxCalculatorFile = os.path.join(abs_flux_dir,"FluxCalculator.py")
assert(os.path.isfile(FluxCalculatorFile))
spec = importlib.util.spec_from_file_location("FluxCalculator", FluxCalculatorFile)
FluxCalculator = importlib.util.module_from_spec(spec)
sys.modules["FluxCalculator"] = FluxCalculator
spec.loader.exec_module(FluxCalculator)
flux_file = FluxCalculator.MakeFluxFile(tag,abs_flux_dir)
del sys.modules["FluxCalculator"] # remove flux directory from the system
return flux_file

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function body is over-indented (8 spaces) relative to the def line, which will raise an IndentationError (or create unintended nesting depending on surrounding code). Re-indent the body to a single level (4 spaces) and ensure consistent formatting with the rest of the module.

Suggested change
abs_flux_dir = get_tabulated_flux_model_path(model_name,must_exist=must_exist)
# require existence of FluxCalculator.py
FluxCalculatorFile = os.path.join(abs_flux_dir,"FluxCalculator.py")
assert(os.path.isfile(FluxCalculatorFile))
spec = importlib.util.spec_from_file_location("FluxCalculator", FluxCalculatorFile)
FluxCalculator = importlib.util.module_from_spec(spec)
sys.modules["FluxCalculator"] = FluxCalculator
spec.loader.exec_module(FluxCalculator)
flux_file = FluxCalculator.MakeFluxFile(tag,abs_flux_dir)
del sys.modules["FluxCalculator"] # remove flux directory from the system
return flux_file
abs_flux_dir = get_tabulated_flux_model_path(model_name,must_exist=must_exist)
# require existence of FluxCalculator.py
FluxCalculatorFile = os.path.join(abs_flux_dir,"FluxCalculator.py")
assert(os.path.isfile(FluxCalculatorFile))
spec = importlib.util.spec_from_file_location("FluxCalculator", FluxCalculatorFile)
FluxCalculator = importlib.util.module_from_spec(spec)
sys.modules["FluxCalculator"] = FluxCalculator
spec.loader.exec_module(FluxCalculator)
flux_file = FluxCalculator.MakeFluxFile(tag,abs_flux_dir)
del sys.modules["FluxCalculator"] # remove flux directory from the system
return flux_file

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +11
def bar_scaling(abs_flux_dir, m_n_min=0.002, m_n_max=0.4, m_n_step=25):


# Energy in GeV
m_n, ratio = np.loadtxt(os.path.join(abs_flux_dir,'ratio.dat'), usecols=(0, 1), unpack=True)

extended_m_n = np.arange(m_n_min, m_n_max + m_n_step, m_n_step)

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

np.arange(m_n_min, m_n_max + m_n_step, m_n_step) with the default m_n_step=25 and m_n_max=0.4 produces an array with (effectively) a single point, so bar_scale(...) becomes nearly constant and the scaling will be wrong. Use a step size consistent with the ratio.dat domain resolution (or rename the parameter to reflect it), e.g., a small float step, or derive the extended grid from the input m_n spacing.

Suggested change
def bar_scaling(abs_flux_dir, m_n_min=0.002, m_n_max=0.4, m_n_step=25):
# Energy in GeV
m_n, ratio = np.loadtxt(os.path.join(abs_flux_dir,'ratio.dat'), usecols=(0, 1), unpack=True)
extended_m_n = np.arange(m_n_min, m_n_max + m_n_step, m_n_step)
def bar_scaling(abs_flux_dir, m_n_min=0.002, m_n_max=0.4, m_n_step=None):
# Energy in GeV
m_n, ratio = np.loadtxt(os.path.join(abs_flux_dir,'ratio.dat'), usecols=(0, 1), unpack=True)
if m_n_step is None:
m_n_diffs = np.diff(m_n)
positive_diffs = m_n_diffs[m_n_diffs > 0]
if positive_diffs.size > 0:
m_n_step = positive_diffs.min()
else:
m_n_step = max(m_n_max - m_n_min, np.finfo(float).eps)
else:
m_n_step = float(m_n_step)
if m_n_step <= 0:
raise ValueError("m_n_step must be positive")
extended_m_n = np.arange(m_n_min, m_n_max + m_n_step * 0.5, m_n_step)

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +9
def bar_scaling(abs_flux_dir, m_n_min=0.002, m_n_max=0.4, m_n_step=25):


# Energy in GeV
m_n, ratio = np.loadtxt(os.path.join(abs_flux_dir,'ratio.dat'), usecols=(0, 1), unpack=True)

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

np.arange(m_n_min, m_n_max + m_n_step, m_n_step) with the default m_n_step=25 and m_n_max=0.4 produces an array with (effectively) a single point, so bar_scale(...) becomes nearly constant and the scaling will be wrong. Use a step size consistent with the ratio.dat domain resolution (or rename the parameter to reflect it), e.g., a small float step, or derive the extended grid from the input m_n spacing.

Suggested change
def bar_scaling(abs_flux_dir, m_n_min=0.002, m_n_max=0.4, m_n_step=25):
# Energy in GeV
m_n, ratio = np.loadtxt(os.path.join(abs_flux_dir,'ratio.dat'), usecols=(0, 1), unpack=True)
def bar_scaling(abs_flux_dir, m_n_min=0.002, m_n_max=0.4, m_n_step=None):
# Energy in GeV
m_n, ratio = np.loadtxt(os.path.join(abs_flux_dir,'ratio.dat'), usecols=(0, 1), unpack=True)
if m_n.size < 2:
raise ValueError("ratio.dat must contain at least two mass points to build bar scaling")
if m_n_step is None:
m_n_diffs = np.diff(m_n)
positive_diffs = m_n_diffs[m_n_diffs > 0]
if positive_diffs.size == 0:
raise ValueError("ratio.dat must contain increasing mass values to derive m_n_step")
m_n_step = np.min(positive_diffs)

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +46
print(f'Enhance tag "{tag}" is invalid')
exit(0)

if particle not in ["numu", "numubar"]:
print("%s particle specified in tag %s is not valid"%(particle))
exit(0)

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling exit(0) inside a library-style helper can terminate the entire host process (including downstream tools/tests) and makes failures hard to handle. Prefer raising a typed exception (e.g., ValueError) with a clear message so callers (like python/_util.py) can catch and report it.

Suggested change
print(f'Enhance tag "{tag}" is invalid')
exit(0)
if particle not in ["numu", "numubar"]:
print("%s particle specified in tag %s is not valid"%(particle))
exit(0)
raise ValueError(f'Enhance tag "{tag}" is invalid')
if particle not in ["numu", "numubar"]:
raise ValueError('%s particle specified in tag %s is not valid' % (particle, tag))

Copilot uses AI. Check for mistakes.
Comment thread python/_util.py


def get_tabulated_flux_model_path(model_name, must_exist=True):
return _get_model_path(model_name,prefix="Fluxes", is_file=False, must_exist=must_exist)

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resources path shown in this PR is resources/fluxes/... (lowercase), but this helper uses prefix=\"Fluxes\". On case-sensitive filesystems this can prevent locating flux models. Align the prefix argument with the actual on-disk directory naming/convention used by _get_base_directory (e.g., \"fluxes\" if it maps directly to resources/fluxes).

Suggested change
return _get_model_path(model_name,prefix="Fluxes", is_file=False, must_exist=must_exist)
return _get_model_path(model_name,prefix="fluxes", is_file=False, must_exist=must_exist)

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,25 @@
# Material model file
# Detector: LakeGeneva

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header says Detector: LakeGeneva, but this file sits under resources/detectors/UNDINE/.... This looks like a copy/paste header mismatch and can confuse downstream users auditing detector configs. Update the header detector name to UNDINE (and similarly audit other headers in this PR for correct detector naming).

Suggested change
# Detector: LakeGeneva
# Detector: UNDINE

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,25 @@
# Material model file
# Detector: SurfaceGeneva

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header says Detector: SurfaceGeneva, but this file is under resources/detectors/SINE/.... If this is intended to be the SINE detector, update the header to match SINE to avoid ambiguity when these resources are consumed.

Suggested change
# Detector: SurfaceGeneva
# Detector: SINE

Copilot uses AI. Check for mistakes.
# Detector: UNDINE (UNDerwater Integrated Neutrino Detector)
# Version: v1
# Material model file: UNDINE_LHCb_North-v1.dat
# Date: 2024-10-3

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date formatting is inconsistent (2024-10-3 vs YYYY-MM-DD used elsewhere). For consistency and easier parsing/validation, use zero-padded dates (e.g., 2024-10-03).

Suggested change
# Date: 2024-10-3
# Date: 2024-10-03

Copilot uses AI. Check for mistakes.
LEAD 3
1000822080 0.77528090 # Pb208
1000260560 0.20224719 # Fe56
1000240520 0.02247191 # Fe56

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 93's isotope code 1000240520 corresponds to Z=24 (Cr), but the comment says Fe56. Either the isotope code or the comment is wrong; please correct this to avoid incorrect interpretation of the material composition (and to prevent accidental physics mistakes if someone later updates values based on comments).

Suggested change
1000240520 0.02247191 # Fe56
1000240520 0.02247191 # Cr52

Copilot uses AI. Check for mistakes.
" primary_type = numubar if \"bar\" in k else numu\n",
" plt.plot(erange,[primary_xs[k].GetCrossSectionsForTarget(target_type)[0].TotalCrossSection(primary_type,e) for e in erange],label=labels[k])\n",
"si_xsfiledir = siren.utilities.get_cross_section_model_path(cross_section_model)\n",
"li_xsfiledir = \"/cvmfs/icecube.opensciencegrid.org/data/neutrino-generator/cross_section_data/csms_differential_v1.0/\"\n",

Copilot AI Apr 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

li_xsfiledir is defined but never used (the loop iterates only over [si_xsfiledir]). If the intent is to compare SIREN-packaged vs CVMFS tables, consider including li_xsfiledir in the loop or removing it to avoid dead code in the example notebook.

Suggested change
"li_xsfiledir = \"/cvmfs/icecube.opensciencegrid.org/data/neutrino-generator/cross_section_data/csms_differential_v1.0/\"\n",

Copilot uses AI. Check for mistakes.
@austinschneider

Copy link
Copy Markdown
Collaborator Author

Closing to reopen from the commit author's account so they can be added as a reviewer. Branch unchanged; will be re-linked from the new PR shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants