diff --git a/projects/detector/private/DetectorModel.cxx b/projects/detector/private/DetectorModel.cxx index 2a130b76..d4e67e89 100644 --- a/projects/detector/private/DetectorModel.cxx +++ b/projects/detector/private/DetectorModel.cxx @@ -267,11 +267,11 @@ void DetectorModel::LoadDetectorModel(std::string const & detector_model) { else if(fexists(path_ + "/densities/" + detector_model + ".dat")) { fname = path_ + "/densities/" + detector_model + ".dat"; } - else if(fexists(path_ + "/DetectorParams/" + detector_model)) { - fname = path_ + "/DetectorParams/" + detector_model; + else if(fexists(path_ + "/Detectors/" + detector_model)) { + fname = path_ + "/Detectors/" + detector_model; } - else if(fexists(path_ + "/DetectorParams/" + detector_model + ".dat")) { - fname = path_ + "/DetectorParams/" + detector_model + ".dat"; + else if(fexists(path_ + "/Detectors/" + detector_model + ".dat")) { + fname = path_ + "/Detectors/" + detector_model + ".dat"; } else if(fexists(path_ + "/" + detector_model)) { fname = path_ + "/" + detector_model; @@ -287,7 +287,7 @@ void DetectorModel::LoadDetectorModel(std::string const & detector_model) { // if the detectormodel file doesn't exist, stop simulation if(in.fail()){ - throw(std::runtime_error("Failed to open " + fname + " Set correct DetectorParamsPath.")); + throw(std::runtime_error("Failed to open " + fname + " Set correct DetectorsPath.")); } ClearSectors(); @@ -1482,11 +1482,11 @@ void DetectorModel::LoadConcentricShellsFromLegacyFile(std::string model_fname, else if(fexists(path_ + "/densities/" + model_fname + ".dat")) { fname = path_ + "/densities/" + model_fname + ".dat"; } - else if(fexists(path_ + "/DetectorParams/" + model_fname)) { - fname = path_ + "/DetectorParams/" + model_fname; + else if(fexists(path_ + "/Detectors/" + model_fname)) { + fname = path_ + "/Detectors/" + model_fname; } - else if(fexists(path_ + "/DetectorParams/" + model_fname + ".dat")) { - fname = path_ + "/DetectorParams/" + model_fname + ".dat"; + else if(fexists(path_ + "/Detectors/" + model_fname + ".dat")) { + fname = path_ + "/Detectors/" + model_fname + ".dat"; } else if(fexists(path_ + "/" + model_fname)) { fname = path_ + "/" + model_fname; @@ -1502,7 +1502,7 @@ void DetectorModel::LoadConcentricShellsFromLegacyFile(std::string model_fname, // if the detectormodel file doesn't exist, stop simulation if(in.fail()){ - throw(std::runtime_error("Failed to open " + fname + " Set correct DetectorParamsPath.")); + throw(std::runtime_error("Failed to open " + fname + " Set correct DetectorsPath.")); } ClearSectors(); diff --git a/projects/injection/private/test/CCM_HNL_TEST.cxx b/projects/injection/private/test/CCM_HNL_TEST.cxx index 3d97efc6..288663c1 100644 --- a/projects/injection/private/test/CCM_HNL_TEST.cxx +++ b/projects/injection/private/test/CCM_HNL_TEST.cxx @@ -60,8 +60,8 @@ bool inelastic = true; std::string tot_xsec_table_path = "/home/nwkamp/Research/Pheno/Neutrissimos2/Sandbox/xsec_tables/tot_xsec_Enu/"; std::string diff_xsec_table_path = "/home/nwkamp/Research/Pheno/Neutrissimos2/Sandbox/xsec_tables/"; -std::string material_file = "/home/nwkamp/Research/CCM/DipoleAnalysis/sources/LeptonInjectorDevPrivate/resources/DetectorParams/materials/CCM.dat"; -std::string detector_file = "/home/nwkamp/Research/CCM/DipoleAnalysis/sources/LeptonInjectorDevPrivate/resources/DetectorParams/densities/PREM_ccm.dat"; +std::string material_file = "/home/nwkamp/Research/CCM/DipoleAnalysis/sources/LeptonInjectorDevPrivate/resources/Detectors/materials/CCM.dat"; +std::string detector_file = "/home/nwkamp/Research/CCM/DipoleAnalysis/sources/LeptonInjectorDevPrivate/resources/Detectors/densities/PREM_ccm.dat"; double hnl_mass = 0.01375; // in GeV; The HNL mass we are injecting double dipole_coupling = 1.0e-6; // in GeV^-1; the effective dipole coupling strength diff --git a/projects/injection/private/test/Injector_TEST.cxx b/projects/injection/private/test/Injector_TEST.cxx index 620ee5e2..cde44f24 100644 --- a/projects/injection/private/test/Injector_TEST.cxx +++ b/projects/injection/private/test/Injector_TEST.cxx @@ -212,18 +212,18 @@ TEST(Injector, Generation) using ParticleType = Particle::ParticleType; #ifdef AUSTIN - std::string material_file = "/home/austin/programs/LIDUNE/sources/LeptonInjectorDUNE/resources/DetectorParams/materials/Minerva.dat"; - std::string detector_file = "/home/austin/programs/LIDUNE/sources/LeptonInjectorDUNE/resources/DetectorParams/densities/PREM_minerva.dat"; + std::string material_file = "/home/austin/programs/LIDUNE/sources/LeptonInjectorDUNE/resources/Detectors/materials/Minerva.dat"; + std::string detector_file = "/home/austin/programs/LIDUNE/sources/LeptonInjectorDUNE/resources/Detectors/densities/PREM_minerva.dat"; std::string flux_file = "/home/austin/nu-dipole/fluxes/LE_FHC_numu.txt"; z_samp = false; in_invGeV = false; #else - std::string material_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/DetectorParams/materials/Minerva.dat"; - std::string detector_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/DetectorParams/densities/PREM_minerva.dat"; + std::string material_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/Detectors/materials/Minerva.dat"; + std::string detector_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/Detectors/densities/PREM_minerva.dat"; std::string flux_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/Sandbox/NUMI_Flux_Tables/ME_FHC_numu.txt"; if(miniboone) { - material_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/DetectorParams/materials/MiniBooNE.dat"; - detector_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/DetectorParams/densities/PREM_miniboone.dat"; + material_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/Detectors/materials/MiniBooNE.dat"; + detector_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/Detectors/densities/PREM_miniboone.dat"; flux_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/Sandbox/BNB_Flux_Tables/BNB_numu_flux.txt"; inelastic = true; } diff --git a/projects/interactions/private/test/ElasticScattering_TEST.cxx b/projects/interactions/private/test/ElasticScattering_TEST.cxx index 7848a381..c623c22a 100644 --- a/projects/interactions/private/test/ElasticScattering_TEST.cxx +++ b/projects/interactions/private/test/ElasticScattering_TEST.cxx @@ -58,12 +58,12 @@ TEST(ElasticScattering, Generation) using ParticleType = Particle::ParticleType; #ifdef AUSTIN - std::string material_file = "/home/austin/programs/LIDUNE/sources/LeptonInjectorDUNE/resources/DetectorParams/materials/Minerva.dat"; - std::string detector_file = "/home/austin/programs/LIDUNE/sources/LeptonInjectorDUNE/resources/DetectorParams/densities/PREM_minerva.dat"; + std::string material_file = "/home/austin/programs/LIDUNE/sources/LeptonInjectorDUNE/resources/Detectors/materials/Minerva.dat"; + std::string detector_file = "/home/austin/programs/LIDUNE/sources/LeptonInjectorDUNE/resources/Detectors/densities/PREM_minerva.dat"; std::string flux_file = "/home/austin/nu-dipole/fluxes/LE_FHC_numu.txt"; #else - std::string material_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/DetectorParams/materials/Minerva.dat"; - std::string detector_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/DetectorParams/densities/PREM_minerva.dat"; + std::string material_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/Detectors/materials/Minerva.dat"; + std::string detector_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/sources/LeptonInjectorDUNE/resources/Detectors/densities/PREM_minerva.dat"; std::string flux_file = "/home/nwkamp/Research/Pheno/Neutrissimos2/Sandbox/NUMI_Flux_Tables/ME_FHC_numu.txt"; #endif diff --git a/python/LIController.py b/python/LIController.py index c79fb238..51540c39 100644 --- a/python/LIController.py +++ b/python/LIController.py @@ -40,21 +40,8 @@ def __init__(self, events_to_inject, experiment, seed=0): self.events = [] # Find the density and materials files - materials_file = os.path.join( - self.resources_dir, "DetectorParams", "materials", f"{experiment}.dat" - ) - if experiment in ["ATLAS", "dune", "IceCube"]: - detector_model_file = os.path.join( - self.resources_dir, - "DetectorParams", - "densities", - f"PREM_{experiment}.dat", - ) - else: - detector_model_file = os.path.join( - self.resources_dir, "DetectorParams", "densities", f"{experiment}.dat" - ) - + materials_file = _util.get_material_model_path(experiment) + detector_model_file = _util.get_detector_model_path(experiment) print(detector_model_file) self.detector_model = _detector.DetectorModel() diff --git a/python/LIDarkNews.py b/python/LIDarkNews.py index c05a4cb6..ccfc2113 100644 --- a/python/LIDarkNews.py +++ b/python/LIDarkNews.py @@ -45,7 +45,7 @@ def __init__( if self.table_dir is None: self.table_dir = os.path.join( resources_dir, - "CrossSectionTables", + "CrossSections", "DarkNewsTables", datetime.datetime.now().strftime("%Y_%m_%d__%H:%M"), ) @@ -110,7 +110,9 @@ def __init__( table_subdirs += "%s_" % str(x) table_subdirs += "/" self.decays.append( - PyDarkNewsDecay(dec_case, table_dir=os.path.join(self.table_dir, table_subdirs)) + PyDarkNewsDecay( + dec_case, table_dir=os.path.join(self.table_dir, table_subdirs) + ) ) def SaveCrossSectionTables(self, fill_tables_at_exit=True): @@ -176,7 +178,9 @@ def __init__( total_xsec_file = os.path.join(self.table_dir, "total_cross_sections.npy") if os.path.exists(total_xsec_file): self.total_cross_section_table = np.load(total_xsec_file) - diff_xsec_file = os.path.join(self.table_dir, "differential_cross_sections.npy") + diff_xsec_file = os.path.join( + self.table_dir, "differential_cross_sections.npy" + ) if os.path.exists(diff_xsec_file): self.differential_cross_section_table = np.load(diff_xsec_file) @@ -185,29 +189,31 @@ def __init__( # Sorts and redefines scipy interpolation objects def _redefine_interpolation_objects(self, total=False, diff=False): if total: - self.total_cross_section_table = np.sort( - self.total_cross_section_table, axis=0 + if len(self.total_cross_section_table) <= 1: return + idxs = np.argsort( + self.total_cross_section_table[:,0] + ) + self.total_cross_section_table = self.total_cross_section_table[idxs] + self.total_cross_section_interpolator = CubicSpline( + self.total_cross_section_table[:, 0], + self.total_cross_section_table[:, 1], ) - if len(self.total_cross_section_table) > 1: - self.total_cross_section_interpolator = CubicSpline( - self.total_cross_section_table[:, 0], - self.total_cross_section_table[:, 1], - ) if diff: - self.differential_cross_section_table = np.sort( - self.differential_cross_section_table, axis=0 + if len(self.differential_cross_section_table) <= 1: return + idxs = np.lexsort( + (self.differential_cross_section_table[:,1], + self.differential_cross_section_table[:,0]) ) - if len(self.differential_cross_section_table) > 1: - # If we only have two energy points, don't try to construct interpolator - if len(np.unique(self.differential_cross_section_table[:, 0])) <= 2: - return - self.differential_cross_section_interpolator = ( - CloughTocher2DInterpolator( - self.differential_cross_section_table[:, :2], - self.differential_cross_section_table[:, 2], - rescale=True, - ) + self.differential_cross_section_table = self.differential_cross_section_table[idxs] + # If we only have two energy points, don't try to construct interpolator + if len(np.unique(self.differential_cross_section_table[:, 0])) <= 2: return + self.differential_cross_section_interpolator = ( + CloughTocher2DInterpolator( + self.differential_cross_section_table[:, :2], + self.differential_cross_section_table[:, 2], + rescale=True, ) + ) # Check whether we have close-enough entries in the intrepolation tables def _interpolation_flags(self, inputs, mode): @@ -231,10 +237,10 @@ def _interpolation_flags(self, inputs, mode): return False, False, -1 # bools to keep track of whether to use a single point or interpolate - UseSinglePoint = True + UseSinglePoint = False Interpolate = True # First check whether we have a close-enough single point - closest_idx = np.argmin(np.sum(np.abs(interp_table[:, :-1] - inputs))) + closest_idx = np.argmin(np.sum(np.abs(interp_table[:, :-1] - inputs),axis=-1)) diff = (interp_table[closest_idx, :-1] - inputs) / inputs if np.all(np.abs(diff) < self.tolerance): UseSinglePoint = True @@ -316,7 +322,7 @@ def FillInterpolationTables(self, total=True, diff=True): self.total_cross_section_table, [[E, xsec]], axis=0 ) num_added_points += 1 - E *= 1 + self.interp_tolerance + E *= (1 + self.interp_tolerance) if diff: # interaction record to calculate Q2 bounds interaction = LI.dataclasses.InteractionRecord() @@ -348,8 +354,8 @@ def FillInterpolationTables(self, total=True, diff=True): axis=0, ) num_added_points += 1 - z *= 1 + self.interp_tolerance - E *= 1 + self.interp_tolerance + z *= (1 + self.interp_tolerance) + E *= (1 + self.interp_tolerance) self._redefine_interpolation_objects(total=total, diff=diff) return num_added_points @@ -357,11 +363,15 @@ def FillInterpolationTables(self, total=True, diff=True): def SaveInterpolationTables(self, total=True, diff=True): if total: self._redefine_interpolation_objects(total=True) - with open(os.path.join(self.table_dir, "total_cross_sections.npy"), "wb") as f: + with open( + os.path.join(self.table_dir, "total_cross_sections.npy"), "wb" + ) as f: np.save(f, self.total_cross_section_table) if diff: self._redefine_interpolation_objects(diff=True) - with open(os.path.join(self.table_dir, "differential_cross_sections.npy"), "wb") as f: + with open( + os.path.join(self.table_dir, "differential_cross_sections.npy"), "wb" + ) as f: np.save(f, self.differential_cross_section_table) ##### START METHODS FOR SERIALIZATION ######### diff --git a/python/_util.py b/python/_util.py index 3a362652..2338bb5b 100644 --- a/python/_util.py +++ b/python/_util.py @@ -1,8 +1,10 @@ import os +import re import sys THIS_DIR = os.path.abspath(os.path.dirname(__file__)) + # From pyzolib/paths.py (https://bitbucket.org/pyzo/pyzolib/src/tip/paths.py) def appdata_dir(appname=None, roaming=False): """appdata_dir(appname=None, roaming=False) @@ -60,6 +62,7 @@ def appdata_dir(appname=None, roaming=False): # Done return path + # from imageio # https://github.com/imageio/imageio/blob/65d79140018bb7c64c0692ea72cb4093e8d632a0/imageio/core/util.py def resource_dirs(): @@ -162,3 +165,372 @@ def has_module(module_name): except ImportError: return False return True + + +_VERSION_PATTERN = r""" + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P
                                          # pre-release
+            [-_\.]?
+            (?P(a|b|c|rc|alpha|beta|pre|preview))
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+"""
+
+_version_regex = re.compile(
+    r"^\s*" + _VERSION_PATTERN + r"\s*$",
+    re.VERBOSE | re.IGNORECASE,
+)
+
+_MODEL_PATTERN = (
+    r"""
+    (?P
+        (?:
+            [a-zA-Z0-9]+
+        )
+        |
+        (?:
+            (?:[a-zA-Z0-9]+(?:[-_\.][a-zA-Z0-9]+)*(?:[-_\.][a-zA-Z]+[a-zA-Z0-9]*))?
+        )
+    )
+    (?:
+        -
+        (?P"""
+    + _VERSION_PATTERN
+    + r"))?"
+)
+
+def decompose_version(version):
+    # Break the version string into its components
+    matches = _version_regex.match(version)
+    if matches is None:
+        return dict()
+    else:
+        return matches.groupdict()
+
+
+def normalize_version(version):
+    # Normalize the version string
+    d = decompose_version(version)
+    n_version = ""
+
+    # Add epoch if present
+    if d["epoch"] is not None:
+        n_version += str(int(d["epoch"])) + "!"
+
+    # Add release segment
+    if d["release"] is not None:
+        # Remove leading zeros from each segment
+        n_version += ".".join(
+            [str(int(s)) for s in d["release"].strip(". ").lower().split(".")]
+        )
+
+    # Add pre-release segment
+    if d["pre"] is not None:
+        if d["pre_l"] is not None:
+            # Add pre-release label
+            if d["pre_l"] in ["a", "alpha"]:
+                n_version += "a"
+            elif d["pre_l"] in ["b", "beta"]:
+                n_version += "b"
+            elif d["pre_l"] in ["c", "rc", "pre", "preview"]:
+                n_version += "rc"
+            # Add pre-release number
+            if d["pre_n"] is not None:
+                n_version += str(int(d["pre_n"]))
+
+    # Add post-release segment
+    if d["post"] is not None:
+        n_version += ".post"
+        # Add post-release number
+        if d["post_n1"] is not None:
+            n_version += str(int(d["post_n1"]))
+        elif d["post_n2"] is not None:
+            n_version += str(int(d["post_n2"]))
+
+    # Add dev-release segment
+    if d["dev"] is not None:
+        n_version += ".dev"
+        # Add dev-release number
+        if d["dev_n"] is not None:
+            n_version += str(int(d["dev_n"]))
+
+    # Add local segment
+    if d["local"] is not None:
+        n_version += "+"
+        segments = []
+        # Local segment can contain letters and numbers
+        for s in d["local"].lower().split("."):
+            # Remove leading zeros from each segment if it is a number
+            try:
+                segments.append(str(int(s)))
+            except:
+                segments.append(s)
+        # Join the segments with a dot
+        n_version += ".".join(segments)
+    return n_version
+
+
+def tokenize_version(version):
+    # Tokenize the version string
+    d = decompose_version(normalize_version(version))
+    tokens = []
+    tokens = dict()
+
+    if d["epoch"] is not None:
+        # Add epoch if present
+        tokens["epoch"] = int(d["epoch"])
+    else:
+        # Default epoch is 0
+        tokens["epoch"] = 0
+
+    # Add release segment
+    if d["release"] is not None:
+        # Remove leading zeros from each segment
+        tokens["release"] = tuple(
+            [int(s) for s in d["release"].strip(". ").lower().split(".")]
+        )
+
+    # Add pre-release segment
+    if d["pre"] is not None:
+        # Pre-release segment starts with 0 to indicate that it is present
+        # Because a pre-release version comes before a release version
+        pre_token = [0]
+
+        if d["pre_l"] is not None:
+            if d["pre_l"] in ["a", "alpha"]:
+                pre_token.append(1)
+            elif d["pre_l"] in ["b", "beta"]:
+                pre_token.append(2)
+            elif d["pre_l"] in ["c", "rc", "pre", "preview"]:
+                pre_token.append(3)
+            if d["pre_n"] is not None:
+                pre_token.append(int(d["pre_n"]))
+            else:
+                pre_token.append(0)
+            tokens["pre"] = tuple(pre_token)
+        else:
+            tokens["pre"] = tuple(pre_token)
+    else:
+        # Pre-release segment starts with 1 if not present to indicate that it is not present
+        # Because a release version comes after a pre-release version
+        tokens["pre"] = (1,)
+
+    # Add post-release segment
+    if d["post"] is not None:
+        # If post-release segment is present, it starts with 1
+        # Because a post-release version comes after its corresponding (pre-)release version
+        post_token = [1]
+        if d["post_n1"] is not None:
+            post_token.append(int(d["post_n1"]))
+        elif d["post_n2"] is not None:
+            post_token.append(int(d["post_n2"]))
+        else:
+            post_token.append(0)
+        tokens["post"] = tuple(post_token)
+    else:
+        # If post-release segment is not present, it starts with 0
+        # Because a post-release version comes after its corresponding (pre-)release version
+        tokens["post"] = (0,)
+
+    # Add dev-release segment
+    if d["dev"] is not None:
+        # If dev-release segment is present, it starts with 0
+        # Because a dev-release version comes before its corresponding (pre-,post-)release version
+        dev_token = [0]
+        if d["dev_n"] is not None:
+            dev_token.append(int(d["dev_n"]))
+        else:
+            dev_token.append(0)
+        tokens["dev"] = tuple(dev_token)
+    else:
+        # If dev-release segment is not present, it starts with 1
+        # Because a dev-release version comes before its corresponding (pre-,post-)release version
+        tokens["dev"] = (1,)
+
+    # Add local segment
+    if d["local"] is not None:
+        # If local segment is present, it starts with 1
+        # Because a local version comes after its corresponding (pre-,post-,dev-)release version
+        local_token = [1]
+        for s in d["local"].lower().split("."):
+            try:
+                local_token.append((1, int(s)))
+            except:
+                local_token.append((0, s))
+        tokens["local"] = tuple(local_token)
+    else:
+        # If local segment is not present, it starts with 0
+        # Because a local version comes after its corresponding (pre-,post-,dev-)release version
+        tokens["local"] = (0,)
+
+    # Return the tokenized version
+    token_list = [
+        tokens["epoch"],
+        tokens["release"],
+        tokens["pre"],
+        tokens["post"],
+        tokens["dev"],
+        tokens["local"],
+    ]
+
+    return tuple(token_list)
+
+
+def _get_model_path(model_name, prefix=None, suffix=None, is_file=True, must_exist=True):
+    # Get the path to the model file
+    _model_regex = re.compile(
+        r"^\s*" + _MODEL_PATTERN + ("" if suffix is None else r"(?:" + suffix + r")?") + r"\s*$",
+        re.VERBOSE | re.IGNORECASE,
+    )
+    if suffix is None:
+        suffix = ""
+    # Get the path to the resources directory
+    resources_dir = resource_package_dir()
+    base_dir = resources_dir
+
+    # Add prefix if present
+    if prefix is not None:
+        base_dir = os.path.join(base_dir, prefix)
+
+    # Get the model name and version
+    d = _model_regex.match(model_name)
+    if d is None:
+        raise ValueError("Invalid model name: {}".format(model_name))
+    d = d.groupdict()
+    model_name = d["model_name"]
+    version = d["version"]
+
+    # Search for the model folder in the resources directory
+    model_names = [
+        f for f in os.listdir(base_dir) if not os.path.isfile(os.path.join(base_dir, f))
+    ]
+    model_names = [f for f in model_names if f.lower().startswith(model_name.lower())]
+
+    folder_exists = False
+
+    if len(model_names) == 0 and must_exist:
+        # Whoops, we didn't find the model folder!
+        raise ValueError(
+            "No model folders found for {}\nSearched in ".format(model_name, base_dir)
+        )
+    elif len(model_names) == 0 and not must_exist:
+        # Let's use the provided model name as the folder name
+        model_name = model_name
+    elif len(model_names) == 1:
+        # We found the model folder!
+        folder_exists = True
+        model_name = model_names[0]
+    else:
+        # Multiple model folders found, we cannot decide which one to use
+        raise ValueError(
+            "Multiple directories found for {}\nSearched in ".format(
+                model_name, base_dir
+            )
+        )
+
+    if folder_exists:
+        # Search for the model file in the model folder
+        model_files = [
+            f
+            for f in os.listdir(os.path.join(base_dir, model_name))
+            if is_file == os.path.isfile(os.path.join(base_dir, model_name, f))
+        ]
+    else:
+        model_files = []
+
+    # From the found model files, extract the model versions
+    model_versions = []
+    for f in model_files:
+        d = _model_regex.match(f)
+        if d is not None:
+            if d.groupdict()["version"] is not None:
+                model_versions.append(normalize_version(d.groupdict()["version"]))
+            else:
+                print(ValueError(
+                    "Input model file has no version: {}\nSearched in ".format(
+                        f, os.path.join(base_dir, model_name)
+                    )
+                ))
+        elif f.lower().startswith(model_name.lower()):
+            print(ValueError(
+                "Unable to parse version from {}\nFound in ".format(
+                    f, os.path.join(base_dir, model_name)
+                )
+            ))
+
+    # Raise an error if no model file is found and we require it to exist
+    if len(model_versions) == 0 and must_exist:
+        raise ValueError(
+            "No model found for {}\nSearched in ".format(
+                model_name, os.path.join(base_dir, model_name)
+            )
+        )
+
+    if version is None and must_exist:
+        # If no version is provided, use the latest version
+        version_idx, version = max(
+            enumerate(model_versions), key=lambda x: tokenize_version(x[1])
+        )
+        model_file_name = model_files[version_idx]
+    elif version is None and not must_exist:
+        # If no version is provided and we don't require it to exist, default to v1
+        version = "v1"
+        model_file_name = "{}-v{}{}".format(model_name, version, suffix)
+    else:
+        # A version is provided
+        version = normalize_version(version)
+        if must_exist:
+            # If the version must exist, raise an error if it doesn't
+            if version not in model_versions:
+                raise ValueError(
+                    "No model found for {}-{}\nSearched in ".format(
+                        model_name, version, os.path.join(base_dir, model_name)
+                    )
+                )
+            version_idx = model_versions.index(version)
+            model_file_name = model_files[version_idx]
+        else:
+            # The version doesn't have to exist
+            if version in model_versions:
+                # If the version exists, use it
+                version_idx = model_versions.index(version)
+                model_file_name = model_files[version_idx]
+            else:
+                # Otherwise use the provided version
+                model_file_name = "{}-v{}{}".format(model_name, version, suffix)
+
+    return os.path.join(base_dir, model_name, model_file_name)
+
+
+def get_detector_model_path(model_name, must_exist=True):
+    return _get_model_path(model_name, prefix="Detectors/densities", suffix=".dat", is_file=True, must_exist=must_exist)
+
+
+def get_material_model_path(model_name, must_exist=True):
+    return _get_model_path(model_name, prefix="Detectors/materials", suffix=".dat", is_file=True, must_exist=must_exist)
+
+
+def get_cross_section_model_path(model_name, must_exist=True):
+    return _get_model_path(model_name, prefix="CrossSections", is_file=False, must_exist=must_exist)
diff --git a/resources/CrossSectionTables/DISSplines/test_xs.fits b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nu_CC_iso.fits
similarity index 99%
rename from resources/CrossSectionTables/DISSplines/test_xs.fits
rename to resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nu_CC_iso.fits
index 80778f92..57249127 100644
Binary files a/resources/CrossSectionTables/DISSplines/test_xs.fits and b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nu_CC_iso.fits differ
diff --git a/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nu_NC_iso.fits b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nu_NC_iso.fits
new file mode 100644
index 00000000..2329f077
Binary files /dev/null and b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nu_NC_iso.fits differ
diff --git a/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nubar_CC_iso.fits b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nubar_CC_iso.fits
new file mode 100644
index 00000000..09c97ccc
Binary files /dev/null and b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nubar_CC_iso.fits differ
diff --git a/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nubar_NC_iso.fits b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nubar_NC_iso.fits
new file mode 100644
index 00000000..e9d2b492
Binary files /dev/null and b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/dsdxdy_nubar_NC_iso.fits differ
diff --git a/resources/CrossSectionTables/DISSplines/test_xs_total.fits b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nu_CC_iso.fits
similarity index 99%
rename from resources/CrossSectionTables/DISSplines/test_xs_total.fits
rename to resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nu_CC_iso.fits
index e96db5da..5bf561f8 100644
Binary files a/resources/CrossSectionTables/DISSplines/test_xs_total.fits and b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nu_CC_iso.fits differ
diff --git a/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nu_NC_iso.fits b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nu_NC_iso.fits
new file mode 100644
index 00000000..da536121
Binary files /dev/null and b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nu_NC_iso.fits differ
diff --git a/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nubar_CC_iso.fits b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nubar_CC_iso.fits
new file mode 100644
index 00000000..5ab8a3d4
Binary files /dev/null and b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nubar_CC_iso.fits differ
diff --git a/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nubar_NC_iso.fits b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nubar_NC_iso.fits
new file mode 100644
index 00000000..64009675
Binary files /dev/null and b/resources/CrossSections/CSMSDISSplines/CSMSDISSplines-v1.0/sigma_nubar_NC_iso.fits differ
diff --git a/resources/CrossSectionTables/DarkNewsTables/README.md b/resources/CrossSections/DarkNewsTables/README.md
similarity index 100%
rename from resources/CrossSectionTables/DarkNewsTables/README.md
rename to resources/CrossSections/DarkNewsTables/README.md
diff --git a/resources/DetectorParams/densities/FLATCORE_5.568.dat b/resources/DetectorParams/densities/FLATCORE_5.568.dat
deleted file mode 100644
index ccd297b0..00000000
--- a/resources/DetectorParams/densities/FLATCORE_5.568.dat
+++ /dev/null
@@ -1,29 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   upper_radius[m] label[string] MediumType[string] number_of_parameters[int] parameters[double]...
-#    - Data must be in ascending order in upper_radius
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 7 lines with labels
-#      "innercore_boundary", "coremantle_boundary", "moho_boundary", 
-#      "rockice_boundary", "iceair_boundary", "earth_radius", and "atmo_radius"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_parameters is the number of params for polynominal density function
-#    - parameters : ex.
-#       for 3 parameters p0, p1, p2 and distance from Earth's center x :
-#       density = p0 + p1*x + p2*x*x 
-#
-#       CAUTION : the unit of density must be [g/cm3] (CGS unit)
-#
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-
-1221500 innercore_boundary    INNERCORE   1   5.56837052290423795e+00
-3480000 coremantle_boundary   OUTERCORE   1   5.56837052290423795e+00 
-
diff --git a/resources/DetectorParams/densities/PREM_ATLAS.dat b/resources/DetectorParams/densities/PREM_ATLAS.dat
deleted file mode 100644
index 77130def..00000000
--- a/resources/DetectorParams/densities/PREM_ATLAS.dat
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format as a context free grammar:
-#   [line] -> [entry] [comment]
-#   [comment] ->
-#   [comment] -> #(string comment)
-#   [entry] ->
-#   [entry] -> [object]
-#   [entry] -> [detector]
-#   [detector] -> detector (double x) (double y) (double z)
-#   [object] -> object [shape] [label] [material name] [density distribution]
-#   [shape] -> [sphere]
-#   [shape] -> [box]
-#   [shape] -> [cylinder]
-#   [sphere] -> sphere [shape coords] [rotation angles] (double radius)
-#   [box] -> box [shape coords] [rotation angles] (double dx) (double dy) (double dz)
-#   [cylinder] -> cylinder [shape coords] [rotation angles] (double or) (double ir) (double z) #or is radius, ir inner radius, z is height
-#   [shape coords] -> (double x) (double y) (double z)
-#   [rotation angles] -> (double alpha) (double beta) (double gamma) # ZXZr convention Euler angles
-#   [label] -> (string label)
-#   [material name] -> (string material)
-#   [density distribution] -> [constant]
-#   [density distribution] -> [radial polynomial]
-#   [constant] -> constant (double density)
-#   [radial polynomial] -> radial_polynomial [axis coords] [polynomial]
-#   [axis coords] -> (double x) (double y) (double z)
-#   [polynomial] -> (int n_params) [polynomial {n_params}]
-#   [polynomial {n_params}] -> (double param_n) [polynomial {n_params-1}]
-#   [polynomial {1}] -> (double param_1)
-#
-#   format notes:
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - for overlapping objects the object defined later in the file is given precidence
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_parameters is the number of params for polynominal density function
-#    - parameters : ex.
-#       for 3 parameters p0, p1, p2 and distance from Earth's center x :
-#       density = p0 + p1*x + p2*x*x
-#
-#       CAUTION : the unit of density must be [g/cm3] (CGS unit)
-#
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-# 
-
-
-object sphere    0 0 0   0 0 0    6478000    atmo_radius           AIR         radial_polynomial 0 0 0    1    0.000811   # 0.673atm x 1.205e-3(g/cm3 for 1atm)
-object sphere    0 0 0   0 0 0    6371324    rockair_boundary      ROCK        radial_polynomial 0 0 0    1    2.650      # surface of bed rock, 1.0 x 2.65
-object sphere    0 0 0   0 0 0    6356000    inner_crust           ROCK        radial_polynomial 0 0 0    1    2.900
-object sphere    0 0 0   0 0 0    6346600    moho_boundary         MANTLE      radial_polynomial 0 0 0    2    2.691     1.08679956050855438e-07   # surface of mantle
-object sphere    0 0 0   0 0 0    6151000    upper_transition      MANTLE      radial_polynomial 0 0 0    2    7.1089    -5.97159001726573544e-07
-object sphere    0 0 0   0 0 0    5971000    middle_transition     MANTLE      radial_polynomial 0 0 0    2    11.2494   -1.26036728927954783e-06
-object sphere    0 0 0   0 0 0    5771000    lower_transition      MANTLE      radial_polynomial 0 0 0    2    5.3197    -2.32867681682624407e-07
-object sphere    0 0 0   0 0 0    5701000    lowermantle_boundary  MANTLE      radial_polynomial 0 0 0    4    7.9565    -1.01649662533354259e-06   1.36199775701391389e-13    -1.19131495406828110e-20
-object sphere    0 0 0   0 0 0    3480000    coremantle_boundary   OUTERCORE   radial_polynomial 0 0 0    4    12.5815   -1.98367603202009108e-07   -8.97421093229181259e-14   -2.13773109929070169e-20
-object sphere    0 0 0   0 0 0    1221500    innercore_boundary    INNERCORE   radial_polynomial 0 0 0    3    13.0885   0                          -2.17742748697875934e-13
-
-
-# just a placeholder, need a volume to detect passing muons
-# treat muon system as a big cylinder sensitive volume
-object cylinder 0 0 6371234      0 1.57 0   11 0 22        muon_system  AIR     constant    0.000811
-# hcal in the middle (or=3.82, ir=2.30, length=12.3)
-object cylinder 0 0 6371234      0 1.57 0   3.82 2.30 12.3  tilecal      TILECAL constant    7.83
-
-# just a test to see how things vary with different geometry
-#object sphere 0 0 6371234      0 0 0   22        muon_system  AIR     constant    0.000811
-
-# declare center of the detector for columndepth lepton injector
-detector         0 0 6371234
-
diff --git a/resources/DetectorParams/densities/PREM_dune.dat b/resources/DetectorParams/densities/PREM_dune.dat
deleted file mode 100644
index 491bbbdc..00000000
--- a/resources/DetectorParams/densities/PREM_dune.dat
+++ /dev/null
@@ -1,39 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   upper_radius[m] label[string] MediumType[string] number_of_parameters[int] parameters[double]...
-#    - Data must be in ascending order in upper_radius
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 7 lines with labels
-#      "innercore_boundary", "coremantle_boundary", "moho_boundary", 
-#      "rockice_boundary", "iceair_boundary", "earth_radius", and "atmo_radius"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_parameters is the number of params for polynominal density function
-#    - parameters : ex.
-#       for 3 parameters p0, p1, p2 and distance from Earth's center x :
-#       density = p0 + p1*x + p2*x*x 
-#
-#       CAUTION : the unit of density must be [g/cm3] (CGS unit)
-#
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-
-1221500 innercore_boundary    INNERCORE   3    13.0885   0                          -2.17742748697875934e-13  
-3480000 coremantle_boundary   OUTERCORE   4    12.5815   -1.98367603202009108e-07   -8.97421093229181259e-14   -2.13773109929070169e-20 
-5701000 lowermantle_boundary  MANTLE      4    7.9565    -1.01649662533354259e-06   1.36199775701391389e-13    -1.19131495406828110e-20 
-5771000 lower_transition      MANTLE      2    5.3197    -2.32867681682624407e-07
-5971000 middle_transition     MANTLE      2    11.2494   -1.26036728927954783e-06
-6151000 upper_transition      MANTLE      2    7.1089    -5.97159001726573544e-07
-6346600 moho_boundary         MANTLE      2    2.691     1.08679956050855438e-07   # surface of mantle
-6356000 inner_crust           ROCK        1    2.900    
-6371324 rockice_boundary      ROCK        1    2.650      # surface of bed rock, 1.0 x 2.65
-6371324 clearice_boundary     ICE         1    0.0   # 200m below ice surface, 1.005 x 0.917
-6371324 iceair_boundary       ICE         1    0.0   # surface of ice, 0.832 x 0.917
-6478000 atmo_radius           AIR         1    0.000811   # 0.673atm x 1.205e-3(g/cm3 for 1atm) 
-
diff --git a/resources/DetectorParams/densities/PREM_mmc_DUNE.dat b/resources/DetectorParams/densities/PREM_mmc_DUNE.dat
deleted file mode 100644
index 1559f6ff..00000000
--- a/resources/DetectorParams/densities/PREM_mmc_DUNE.dat
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format as a context free grammar:
-#   [line] -> [entry] [comment]
-#   [comment] ->
-#   [comment] -> #(string comment)
-#   [entry] ->
-#   [entry] -> [object]
-#   [entry] -> [detector]
-#   [detector] -> detector (double x) (double y) (double z)
-#   [object] -> object [shape] [label] [material name] [density distribution]
-#   [shape] -> [sphere]
-#   [shape] -> [box]
-#   [sphere] -> sphere [shape coords] (double radius)
-#   [box] -> box [shape coords] (double dx) (double dy) (double dz)
-#   [shape coords] -> (double x) (double y) (double z)
-#   [label] -> (string label)
-#   [material name] -> (string material)
-#   [density distribution] -> [constant]
-#   [density distribution] -> [radial polynomial]
-#   [constant] -> constant (double density)
-#   [radial polynomial] -> radial_polynomial [axis coords] [polynomial]
-#   [axis coords] -> (double x) (double y) (double z)
-#   [polynomial] -> (int n_params) [polynomial {n_params}]
-#   [polynomial {n_params}] -> (double param_n) [polynomial {n_params-1}]
-#   [polynomial {1}] -> (double param_1)
-#
-#   format notes:
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - for overlapping objects the object defined later in the file is given precidence
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_parameters is the number of params for polynominal density function
-#    - parameters : ex.
-#       for 3 parameters p0, p1, p2 and distance from Earth's center x :
-#       density = p0 + p1*x + p2*x*x
-#
-#       CAUTION : the unit of density must be [g/cm3] (CGS unit)
-#
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-
-object sphere    0 0 0       1221500    innercore_boundary    INNERCORE   radial_polynomial 0 0 0    3    13.0885   0                          -2.17742748697875934e-13
-object sphere    0 0 0       3480000    coremantle_boundary   OUTERCORE   radial_polynomial 0 0 0    4    12.5815   -1.98367603202009108e-07   -8.97421093229181259e-14   -2.13773109929070169e-20
-object sphere    0 0 0       5701000    lowermantle_boundary  MANTLE      radial_polynomial 0 0 0    4    7.9565    -1.01649662533354259e-06   1.36199775701391389e-13    -1.19131495406828110e-20
-object sphere    0 0 0       5771000    lower_transition      MANTLE      radial_polynomial 0 0 0    2    5.3197    -2.32867681682624407e-07
-object sphere    0 0 0       5971000    middle_transition     MANTLE      radial_polynomial 0 0 0    2    11.2494   -1.26036728927954783e-06
-object sphere    0 0 0       6151000    upper_transition      MANTLE      radial_polynomial 0 0 0    2    7.1089    -5.97159001726573544e-07
-object sphere    0 0 0       6346600    moho_boundary         MANTLE      radial_polynomial 0 0 0    2    2.691     1.08679956050855438e-07   # surface of mantle
-object sphere    0 0 0       6356000    inner_crust           ROCK        radial_polynomial 0 0 0    1    2.900
-object sphere    0 0 0       6371324    rockair_boundary      ROCK        radial_polynomial 0 0 0    1    2.650      # surface of bed rock, 1.0 x 2.65
-object sphere    0 0 0       6478000    atmo_radius           AIR         radial_polynomial 0 0 0    1    0.000811   # 0.673atm x 1.205e-3(g/cm3 for 1atm)
-object rectangle 0 0 6369844 14 58.2 12 dune_far_detector     LAR         constant                        1.396
-detector         0 0 6369844
diff --git a/resources/DetectorParams/densities/README b/resources/DetectorParams/densities/README
deleted file mode 100644
index 8c3756aa..00000000
--- a/resources/DetectorParams/densities/README
+++ /dev/null
@@ -1,11 +0,0 @@
-#-------------------------------------------------------
-# EarthModel density files
-#
-# Aug. 14 2014 Kotoyo Hoshina 
-#-------------------------------------------------------
-
-PLEASE USE
-Standard Earth Density Model : PREM_mmm.dat
-
-Do not use any other models for most of analysis, they are very artificial!
-
diff --git a/resources/DetectorParams/densities/legacy/PREM.dat b/resources/DetectorParams/densities/legacy/PREM.dat
deleted file mode 100644
index db3a2331..00000000
--- a/resources/DetectorParams/densities/legacy/PREM.dat
+++ /dev/null
@@ -1,34 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   upper_radius[m] label[string] MediumType[string] number_of_parameters[int] parameters[double]...
-#    - Data must be in ascending order in upper_radius
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 7 lines with labels
-#      "innercore_boundary", "coremantle_boundary", "moho_boundary", 
-#      "rockice_boundary", "iceair_boundary", "earth_radius", and "atmo_radius"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_parameters is the number of params for polynominal density function
-#    - parameters : ex.
-#       for 3 parameters p0, p1, p2 and distance from Earth's center x :
-#       density = p0 + p1*x + p2*x*x 
-#
-#       CAUTION : the unit of density must be [g/cm3] (CGS unit)
-#
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-
-1221500 innercore_boundary    INNERCORE   3    13.0885   0                          -2.17742748697875934e-13  
-3480000 coremantle_boundary   OUTERCORE   4    12.5815   -1.98367603202009108e-07   -8.97421093229181259e-14   -2.13773109929070169e-20 
-5701000 lowermantle_boundary  MANTLE      4    7.9565    -1.01649662533354259e-06   1.36199775701391389e-13    -1.19131495406828110e-20 
-5771000 lower_transition      MANTLE      2    5.3197    -2.32867681682624407e-07
-5971000 middle_transition     MANTLE      2    11.2494   -1.26036728927954783e-06
-6151000 upper_transition      MANTLE      2    7.1089    -5.97159001726573544e-07
-6346600 moho_boundary         MANTLE      2    2.691     1.08679956050855438e-07   # surface of mantle
-
diff --git a/resources/DetectorParams/densities/legacy/PREM_mmc.dat b/resources/DetectorParams/densities/legacy/PREM_mmc.dat
deleted file mode 100644
index 4e7eb134..00000000
--- a/resources/DetectorParams/densities/legacy/PREM_mmc.dat
+++ /dev/null
@@ -1,39 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   upper_radius[m] label[string] MediumType[string] number_of_parameters[int] parameters[double]...
-#    - Data must be in ascending order in upper_radius
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 7 lines with labels
-#      "innercore_boundary", "coremantle_boundary", "moho_boundary", 
-#      "rockice_boundary", "iceair_boundary", "earth_radius", and "atmo_radius"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_parameters is the number of params for polynominal density function
-#    - parameters : ex.
-#       for 3 parameters p0, p1, p2 and distance from Earth's center x :
-#       density = p0 + p1*x + p2*x*x 
-#
-#       CAUTION : the unit of density must be [g/cm3] (CGS unit)
-#
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-
-1221500 innercore_boundary    INNERCORE   3    13.0885   0                          -2.17742748697875934e-13  
-3480000 coremantle_boundary   OUTERCORE   4    12.5815   -1.98367603202009108e-07   -8.97421093229181259e-14   -2.13773109929070169e-20 
-5701000 lowermantle_boundary  MANTLE      4    7.9565    -1.01649662533354259e-06   1.36199775701391389e-13    -1.19131495406828110e-20 
-5771000 lower_transition      MANTLE      2    5.3197    -2.32867681682624407e-07
-5971000 middle_transition     MANTLE      2    11.2494   -1.26036728927954783e-06
-6151000 upper_transition      MANTLE      2    7.1089    -5.97159001726573544e-07
-6346600 moho_boundary         MANTLE      2    2.691     1.08679956050855438e-07   # surface of mantle
-6356000 inner_crust           ROCK        1    2.900    
-6371324 rockice_boundary      ROCK        1    2.650      # surface of bed rock, 1.0 x 2.65
-6373934 clearice_boundary     ICE         1    0.921585   # 200m below ice surface, 1.005 x 0.917
-6374134 iceair_boundary       ICE         1    0.762944   # surface of ice, 0.832 x 0.917
-6478000 atmo_radius           AIR         1    0.000811   # 0.673atm x 1.205e-3(g/cm3 for 1atm) 
-
diff --git a/resources/DetectorParams/densities/legacy/mmc.dat b/resources/DetectorParams/densities/legacy/mmc.dat
deleted file mode 100644
index 4c8a0289..00000000
--- a/resources/DetectorParams/densities/legacy/mmc.dat
+++ /dev/null
@@ -1,32 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   upper_radius[m] label[string] MediumType[string] number_of_parameters[int] parameters[double]...
-#    - Data must be in ascending order in upper_radius
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 7 lines with labels
-#      "innercore_boundary", "coremantle_boundary", "moho_boundary", 
-#      "rockice_boundary", "iceair_boundary", "earth_radius", and "atmo_radius"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_parameters is the number of params for polynominal density function
-#    - parameters : ex.
-#       for 3 parameters p0, p1, p2 and distance from Earth's center x :
-#       density = p0 + p1*x + p2*x*x 
-#
-#       CAUTION : the unit of density must be [g/cm3] (CGS unit)
-
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-
-6356000 inner_crust           ROCK        1    2.900    
-6371324 rockice_boundary      ROCK        1    2.650      # surface of bed rock, 1.0 x 2.65
-6373934 clearice_boundary     ICE         1    0.921585   # 200m below ice surface, 1.005 x 0.917
-6374134 iceair_boundary       ICE         1    0.762944   # surface of ice, 0.832 x 0.917
-6478000 atmo_radius           AIR         1    0.000811   # 0.673atm x 1.205e-3(g/cm3 for 1atm) 
-
diff --git a/resources/DetectorParams/materials/AtomicData.csv b/resources/DetectorParams/materials/AtomicData.csv
deleted file mode 100644
index ebf917fc..00000000
--- a/resources/DetectorParams/materials/AtomicData.csv
+++ /dev/null
@@ -1,118 +0,0 @@
-1 1.007
-2 4.002
-3 6.941
-4 9.012
-5 10.811
-6 12.011
-7 14.007
-8 15.999
-9 18.998
-10 20.18
-11 22.99
-12 24.305
-13 26.982
-14 28.086
-15 30.974
-16 32.065
-17 35.453
-18 39.948
-19 39.098
-20 40.078
-21 44.956
-22 47.867
-23 50.942
-24 51.996
-25 54.938
-26 55.845
-27 58.933
-28 58.693
-29 63.546
-30 65.38
-31 69.723
-32 72.64
-33 74.922
-34 78.96
-35 79.904
-36 83.798
-37 85.468
-38 87.62
-39 88.906
-40 91.224
-41 92.906
-42 95.96
-43 98.0
-44 101.07
-45 102.906
-46 106.42
-47 107.868
-48 112.411
-49 114.818
-50 118.71
-51 121.76
-52 127.6
-53 126.904
-54 131.293
-55 132.905
-56 137.327
-57 138.905
-58 140.116
-59 140.908
-60 144.242
-61 145.0
-62 150.36
-63 151.964
-64 157.25
-65 158.925
-66 162.5
-67 164.93
-68 167.259
-69 168.934
-70 173.054
-71 174.967
-72 178.49
-73 180.948
-74 183.84
-75 186.207
-76 190.23
-77 192.217
-78 195.084
-79 196.967
-80 200.59
-81 204.383
-82 207.2
-83 208.98
-84 210.0
-85 210.0
-86 222.0
-87 223.0
-88 226.0
-89 227.0
-90 232.038
-91 231.036
-92 238.029
-93 237.0
-94 244.0
-95 243.0
-96 247.0
-97 247.0
-98 251.0
-99 252.0
-100 257.0
-101 258.0
-102 259.0
-103 262.0
-104 261.0
-105 262.0
-106 266.0
-107 264.0
-108 267.0
-109 268.0
-110 271.0
-111 272.0
-112 285.0
-113 284.0
-114 289.0
-115 288.0
-116 292.0
-117 295.0
-118 294.0
diff --git a/resources/DetectorParams/materials/Fe_Core.dat b/resources/DetectorParams/materials/Fe_Core.dat
deleted file mode 100644
index f13cb446..00000000
--- a/resources/DetectorParams/materials/Fe_Core.dat
+++ /dev/null
@@ -1,30 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   MediumType[string] number_of_materials[int]
-#   material_pdg[int] weight[double]
-#   .....
-#
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 6 materials
-#      "INNERCORE", "OUTERCORE", "MANTLE", 
-#      "ROCK", "ICE", "AIR", and "VACUUM"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_materials is the number of atm type in the medium
-#    - weight must be normalized to 1 within a MediumType
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-INNERCORE 1 # Fe
-1000260560    1.0000000     # Fe56 100%
-
-OUTERCORE 1 # Fe
-1000260560    1.0000000     # Fe56 100%
-
-
-
diff --git a/resources/DetectorParams/materials/MiniBooNE.dat b/resources/DetectorParams/materials/MiniBooNE.dat
deleted file mode 100644
index fe70d08b..00000000
--- a/resources/DetectorParams/materials/MiniBooNE.dat
+++ /dev/null
@@ -1,33 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   MediumType[string] number_of_materials[int]
-#   material_pdg[int] weight[double]
-#   .....
-#
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 6 materials
-#      "INNERCORE", "OUTERCORE", "MANTLE", 
-#      "ROCK", "ICE", "AIR", and "VACUUM"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_materials is the number of atm type in the medium
-#    - weight must be normalized to 1 within a MediumType
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-MINERAL_OIL 2 # MB Detector Medium
-1000010010    0.1438253     # H1 14.4%
-1000060120    0.8561715     # C12 85.6%
-
-AIR 2       # N2 + O2
-1000070140    0.7562326     # N2 78% in volume
-1000080160    0.2437674     # O2 22% in volume
-
-ROCK  2     # SiO2
-1000140280    0.4674349     # Si, 33%
-1000080160    0.5325651     # 20, 66%
diff --git a/resources/DetectorParams/materials/SiO2_Mantle.dat b/resources/DetectorParams/materials/SiO2_Mantle.dat
deleted file mode 100644
index ac7778c7..00000000
--- a/resources/DetectorParams/materials/SiO2_Mantle.dat
+++ /dev/null
@@ -1,28 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   MediumType[string] number_of_materials[int]
-#   material_pdg[int] weight[double]
-#   .....
-#
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 6 materials
-#      "INNERCORE", "OUTERCORE", "MANTLE", 
-#      "ROCK", "ICE", "AIR", and "VACUUM"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_materials is the number of atm type in the medium
-#    - weight must be normalized to 1 within a MediumType
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-MANTLE  2   # SiO2
-1000140280    0.4674349     # Si, 33% 
-1000080160    0.5325651     # 20, 66%
-
-
-
diff --git a/resources/DetectorParams/materials/Standard.dat b/resources/DetectorParams/materials/Standard.dat
deleted file mode 100644
index f8ed549c..00000000
--- a/resources/DetectorParams/materials/Standard.dat
+++ /dev/null
@@ -1,48 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   MediumType[string] number_of_materials[int]
-#   material_pdg[int] weight[double]
-#   .....
-#
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 6 materials
-#      "INNERCORE", "OUTERCORE", "MANTLE", 
-#      "ROCK", "ICE", "AIR", and "VACUUM"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_materials is the number of atm type in the medium
-#    - weight must be normalized to 1 within a MediumType
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-ICE   2     # H20
-1000080160    0.8881016     # 0, 88.8% in weight  
-1000010010    0.1118984     # 2H, 11% in weight
-
-ROCK  2     # SiO2
-1000140280    0.4674349     # Si, 33% 
-1000080160    0.5325651     # 20, 66%
-
-INNERCORE 1 # Fe
-1000260560    1.0000000     # Fe56 100%
-
-OUTERCORE 1 # Fe
-1000260560    1.0000000     # Fe56 100%
-
-MANTLE  2   # SiO2
-1000140280    0.4674349     # Si, 33% 
-1000080160    0.5325651     # 20, 66%
-
-AIR 2       # N2 + O2
-1000070140    0.7562326     # N2 78% in volume
-1000080160    0.2437674     # O2 22% in volume
-
-VACUUM 1    # dummy, H
-1000010010    1.0000000     # N2 78% in volume
-
-
diff --git a/resources/DetectorParams/materials/Standard_Air.dat b/resources/DetectorParams/materials/Standard_Air.dat
deleted file mode 100644
index 7919bfd7..00000000
--- a/resources/DetectorParams/materials/Standard_Air.dat
+++ /dev/null
@@ -1,30 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   MediumType[string] number_of_materials[int]
-#   material_pdg[int] weight[double]
-#   .....
-#
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 6 materials
-#      "INNERCORE", "OUTERCORE", "MANTLE", 
-#      "ROCK", "ICE", "AIR", and "VACUUM"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_materials is the number of atm type in the medium
-#    - weight must be normalized to 1 within a MediumType
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-AIR 2       # N2 + O2
-1000070140    0.7562326     # N2 78% in volume
-1000080160    0.2437674     # O2 22% in volume
-
-VACUUM 1    # dummy, H
-1000010010    1.0000000     # N2 78% in volume
-
-
diff --git a/resources/DetectorParams/materials/Standard_RockIce.dat b/resources/DetectorParams/materials/Standard_RockIce.dat
deleted file mode 100644
index 7b11b634..00000000
--- a/resources/DetectorParams/materials/Standard_RockIce.dat
+++ /dev/null
@@ -1,30 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   MediumType[string] number_of_materials[int]
-#   material_pdg[int] weight[double]
-#   .....
-#
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 6 materials
-#      "INNERCORE", "OUTERCORE", "MANTLE", 
-#      "ROCK", "ICE", "AIR", and "VACUUM"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_materials is the number of atm type in the medium
-#    - weight must be normalized to 1 within a MediumType
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-ICE   2     # H20
-1000080160    0.8881016     # 0, 88.8% in weight  
-1000010010    0.1118984     # 2H, 11% in weight
-
-ROCK  2     # SiO2
-1000140280    0.4674349     # Si, 33% 
-1000080160    0.5325651     # 20, 66%
-
diff --git a/resources/DetectorParams/old_formats/PREM_legacy.dat b/resources/DetectorParams/old_formats/PREM_legacy.dat
deleted file mode 100644
index a27db30c..00000000
--- a/resources/DetectorParams/old_formats/PREM_legacy.dat
+++ /dev/null
@@ -1,31 +0,0 @@
-# 
-# crust model file
-# PREM (legacy nugen setup)
-#
-#
-#   format :
-#   upper_radius[m] density[g/cm^3] label[string]
-#    - Data must be in ascending order in upper_radius
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 5 lines with labels
-#      "moho_boundary", "rockice_boundary",
-#      "iceair_boundary", "earth_radius", and "atmo_radius"
-#    - density must be the density up to the defined radius 
-#      except for "moho_boundary"
-#    - density of "moho_boundary" should be same as
-#      the density of next layer
-#    - "earth_radius" is NOT the geophysical boundary.
-#      This is the definition that all simulation program
-#      regards "the radius of the Earth".
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-6346600 2.900 moho_boundary
-6356000 2.900 inner_crust       
-6375000 2.650 rockice_boundary     # Official PREM is 2.6 
-6378000 0.930 iceair_boundary      # ice (most thick part)
-6378000 0.930 earth_radius         # earth radius for simulation
-6478000 0.000 atmo_radius
-
diff --git a/resources/DetectorParams/old_formats/PREM_legacy_mmcnewice.dat b/resources/DetectorParams/old_formats/PREM_legacy_mmcnewice.dat
deleted file mode 100644
index ab0f7996..00000000
--- a/resources/DetectorParams/old_formats/PREM_legacy_mmcnewice.dat
+++ /dev/null
@@ -1,32 +0,0 @@
-# 
-# crust model file
-# PREM (legacy nugen bedrock) + mmc ice
-#
-#
-#   format :
-#   upper_radius[m] density[g/cm^3] label[string]
-#    - Data must be in ascending order in upper_radius
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 5 lines with labels
-#      "moho_boundary", "rockice_boundary",
-#      "iceair_boundary", "earth_radius", and "atmo_radius"
-#    - density must be the density up to the defined radius 
-#      except for "moho_boundary"
-#    - density of "moho_boundary" should be same as
-#      the density of next layer
-#    - "earth_radius" is NOT the geophysical boundary.
-#      This is the definition that all simulation program
-#      regards "the radius of the Earth".
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-6346600 2.900 moho_boundary
-6356000 2.900 inner_crust       
-6375000 2.650 rockice_boundary     # Official PREM is 2.6 
-6377610 0.917 light_ice_boundary   # 200m below ice surface
-6377810 0.757 iceair_boundary      # surface of ice, 0.825 x 0.917
-6377810 0.757 earth_radius         # earth radius for simulation
-6481676 0.000811 atmo_radius       # 0.673atm x 1.205e-3(g/cm3 for 1atm) 
-
diff --git a/resources/DetectorParams/old_formats/PREM_mmc.dat b/resources/DetectorParams/old_formats/PREM_mmc.dat
deleted file mode 100644
index 5df24228..00000000
--- a/resources/DetectorParams/old_formats/PREM_mmc.dat
+++ /dev/null
@@ -1,34 +0,0 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#
-#   format :
-#   upper_radius[m] density[g/cm^3] label[string]
-#    - Data must be in ascending order in upper_radius
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 5 lines with labels
-#      "moho_boundary", "rockice_boundary",
-#      "iceair_boundary", "earth_radius", and "atmo_radius"
-#    - density must be the density up to the defined radius 
-#      except for "moho_boundary"
-#    - density of "moho_boundary" should be same as
-#      the density of next layer
-#    - "earth_radius" is NOT the geophysical boundary.
-#      This is the definition that all simulation program
-#      regards "the radius of the Earth".
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
-
-
-6346600 2.900    moho_boundary
-6356000 2.900    inner_crust           # 
-6371324 2.650    rockice_boundary      # surface of bed rock, 1.0 x 2.65
-6373934 0.921585 clearice_boundary     # 200m below ice surface, 1.005 x 0.917
-6374134 0.762944 iceair_boundary       # surface of ice, 0.832 x 0.917
-6374134 0.762944 earth_radius          # user-defined earth radius
-6478000 0.000811 atmo_radius           # 0.673atm x 1.205e-3(g/cm3 for 1atm) 
-
diff --git a/resources/Detectors/densities/ATLAS/ATLAS-v1.dat b/resources/Detectors/densities/ATLAS/ATLAS-v1.dat
new file mode 100644
index 00000000..e75a2b07
--- /dev/null
+++ b/resources/Detectors/densities/ATLAS/ATLAS-v1.dat
@@ -0,0 +1,30 @@
+# Detector model file
+# Detector: ATLAS
+# Version: v1
+# Material model file: ATLAS-v1.dat
+# Date: 2023-05-02
+# Authors: Alex Wen
+# Notes:
+#   Uses PREM model of the Earth
+#   ATLAS is modeled only as AIR and iron
+
+object sphere    0 0 0   0 0 0    6478000    atmo_radius           AIR         radial_polynomial 0 0 0    1    0.000811   # 0.673atm x 1.205e-3(g/cm3 for 1atm)
+object sphere    0 0 0   0 0 0    6371324    rockair_boundary      ROCK        radial_polynomial 0 0 0    1    2.650      # surface of bed rock, 1.0 x 2.65
+object sphere    0 0 0   0 0 0    6356000    inner_crust           ROCK        radial_polynomial 0 0 0    1    2.900
+object sphere    0 0 0   0 0 0    6346600    moho_boundary         MANTLE      radial_polynomial 0 0 0    2    2.691     1.08679956050855438e-07   # surface of mantle
+object sphere    0 0 0   0 0 0    6151000    upper_transition      MANTLE      radial_polynomial 0 0 0    2    7.1089    -5.97159001726573544e-07
+object sphere    0 0 0   0 0 0    5971000    middle_transition     MANTLE      radial_polynomial 0 0 0    2    11.2494   -1.26036728927954783e-06
+object sphere    0 0 0   0 0 0    5771000    lower_transition      MANTLE      radial_polynomial 0 0 0    2    5.3197    -2.32867681682624407e-07
+object sphere    0 0 0   0 0 0    5701000    lowermantle_boundary  MANTLE      radial_polynomial 0 0 0    4    7.9565    -1.01649662533354259e-06   1.36199775701391389e-13    -1.19131495406828110e-20
+object sphere    0 0 0   0 0 0    3480000    coremantle_boundary   OUTERCORE   radial_polynomial 0 0 0    4    12.5815   -1.98367603202009108e-07   -8.97421093229181259e-14   -2.13773109929070169e-20
+object sphere    0 0 0   0 0 0    1221500    innercore_boundary    INNERCORE   radial_polynomial 0 0 0    3    13.0885   0                          -2.17742748697875934e-13
+
+# just a placeholder, need a volume to detect passing muons
+# treat muon system as a big cylinder sensitive volume
+object cylinder 0 0 6371234      0 1.57 0   11 0 22        muon_system  AIR     constant    0.000811
+# hcal in the middle (or=3.82, ir=2.30, length=12.3)
+object cylinder 0 0 6371234      0 1.57 0   3.82 2.30 12.3  tilecal      TILECAL constant    7.83
+
+# declare center of the detector for columndepth lepton injector
+detector         0 0 6371234
+
diff --git a/resources/DetectorParams/densities/CCM.dat b/resources/Detectors/densities/CCM/CCM-v1.dat
similarity index 94%
rename from resources/DetectorParams/densities/CCM.dat
rename to resources/Detectors/densities/CCM/CCM-v1.dat
index e79103fc..4143815b 100644
--- a/resources/DetectorParams/densities/CCM.dat
+++ b/resources/Detectors/densities/CCM/CCM-v1.dat
@@ -1,3 +1,12 @@
+# Detector model file
+# Detector: CCM
+# Version: v1
+# Material model file: CCM-v1.dat
+# Date: 2023-03-18
+# Authors: Nicholas Kamp
+# Notes:
+#   Uses PREM model of the Earth, assumes a single far detector with the liquid argon embedded directly in the roc
+
 # Detector Hall
 object box    0 0 0           0 0 0      100 100 100    surr_air           AIR         constant    0.001225   # 0.673atm x 1.205e-3(g/cm3 for 1atm)
 # adjust floor z pos if necessary: this is a guess
diff --git a/resources/Detectors/densities/DUNEFD/DUNEFD-v1.dat b/resources/Detectors/densities/DUNEFD/DUNEFD-v1.dat
new file mode 100644
index 00000000..72b38de8
--- /dev/null
+++ b/resources/Detectors/densities/DUNEFD/DUNEFD-v1.dat
@@ -0,0 +1,22 @@
+# Detector model file
+# Detector: DUNEFD
+# Version: v1
+# Material model file: DUNEFD-v1.dat
+# Date: 2021-04-13
+# Authors: Austin Schneider
+# Notes:
+#   Uses PREM model of the Earth
+#   Assumes a single far detector, modeled as box of liquid argon embedded directly in the rock
+
+object sphere    0 0 0       1221500    innercore_boundary    INNERCORE   radial_polynomial 0 0 0    3    13.0885   0                          -2.17742748697875934e-13
+object sphere    0 0 0       3480000    coremantle_boundary   OUTERCORE   radial_polynomial 0 0 0    4    12.5815   -1.98367603202009108e-07   -8.97421093229181259e-14   -2.13773109929070169e-20
+object sphere    0 0 0       5701000    lowermantle_boundary  MANTLE      radial_polynomial 0 0 0    4    7.9565    -1.01649662533354259e-06   1.36199775701391389e-13    -1.19131495406828110e-20
+object sphere    0 0 0       5771000    lower_transition      MANTLE      radial_polynomial 0 0 0    2    5.3197    -2.32867681682624407e-07
+object sphere    0 0 0       5971000    middle_transition     MANTLE      radial_polynomial 0 0 0    2    11.2494   -1.26036728927954783e-06
+object sphere    0 0 0       6151000    upper_transition      MANTLE      radial_polynomial 0 0 0    2    7.1089    -5.97159001726573544e-07
+object sphere    0 0 0       6346600    moho_boundary         MANTLE      radial_polynomial 0 0 0    2    2.691     1.08679956050855438e-07   # surface of mantle
+object sphere    0 0 0       6356000    inner_crust           ROCK        radial_polynomial 0 0 0    1    2.900
+object sphere    0 0 0       6371324    rockair_boundary      ROCK        radial_polynomial 0 0 0    1    2.650      # surface of bed rock, 1.0 x 2.65
+object sphere    0 0 0       6478000    atmo_radius           AIR         radial_polynomial 0 0 0    1    0.000811   # 0.673atm x 1.205e-3(g/cm3 for 1atm)
+object rectangle 0 0 6369844 14 58.2 12 dune_far_detector     LAR         constant                        1.396
+detector         0 0 6369844
diff --git a/resources/DetectorParams/densities/PREM_IceCube.dat b/resources/Detectors/densities/IceCube/IceCube-v1.dat
similarity index 87%
rename from resources/DetectorParams/densities/PREM_IceCube.dat
rename to resources/Detectors/densities/IceCube/IceCube-v1.dat
index d201eb0a..401b76d9 100644
--- a/resources/DetectorParams/densities/PREM_IceCube.dat
+++ b/resources/Detectors/densities/IceCube/IceCube-v1.dat
@@ -1,3 +1,14 @@
+# Detector model file
+# Detector: IceCube
+# Version: v1
+# Material model file: IceCube-v1.dat
+# Date: 2014-08-14
+# Authors: Kotoyo Hoshina
+# Notes:
+#   Uses PREM model of the Earth
+#   Assumes ice is a spherical cap on the earth
+#   Assumes IceCube is in clear ice
+
 object sphere    0 0 0   0 0 0    6478000    atmo_radius           AIR         radial_polynomial 0 0 0    1    0.000811   # 0.673atm x 1.205e-3(g/cm3 for 1atm)
 object sphere    0 0 0   0 0 0    6374134    iceair_boundary       ICE         radial_polynomial 0 0 0    1    0.762944   # surface of ice, 0.832 x 0.917
 object sphere    0 0 0   0 0 0    6373934    clearice_boundary     ICE         radial_polynomial 0 0 0    1    0.921585   # 200m below ice surface, 1.005 x 0.917
@@ -14,6 +25,5 @@ object sphere    0 0 0   0 0 0    1221500    innercore_boundary    INNERCORE   r
 # IceCube detector: 1km^3 cylinder of ice
 object cylinder  0 0 6372184  0 0 0  564.19 0 1000  icecube        ICE         radial_polynomial 0 0 0    1    0.921585  # same as rockice
 
-
 # center of detector at IceCube
-detector      0 0 6372184
\ No newline at end of file
+detector      0 0 6372184
diff --git a/resources/DetectorParams/densities/MINERvA.dat b/resources/Detectors/densities/MINERvA/MINERvA-v1.dat
similarity index 96%
rename from resources/DetectorParams/densities/MINERvA.dat
rename to resources/Detectors/densities/MINERvA/MINERvA-v1.dat
index cc515459..04c630b9 100644
--- a/resources/DetectorParams/densities/MINERvA.dat
+++ b/resources/Detectors/densities/MINERvA/MINERvA-v1.dat
@@ -1,3 +1,13 @@
+# Detector model file
+# Detector: MINERvA
+# Version: v1
+# Material model file: MINERvA-v1.dat
+# Date: 2023-03-01
+# Authors: Nicholas Kamp
+# Notes:
+#   Includes the veto shield, ECAL, and nuclear targets
+#
+
 # Dirt
 object box       0 0 -100            0 0 0      100 100 300    surr_earth           ROCK         constant    2.900 
 
diff --git a/resources/DetectorParams/densities/MiniBooNE.dat b/resources/Detectors/densities/MiniBooNE/MiniBooNE-v1.dat
similarity index 71%
rename from resources/DetectorParams/densities/MiniBooNE.dat
rename to resources/Detectors/densities/MiniBooNE/MiniBooNE-v1.dat
index 2d196dd9..55af2e39 100644
--- a/resources/DetectorParams/densities/MiniBooNE.dat
+++ b/resources/Detectors/densities/MiniBooNE/MiniBooNE-v1.dat
@@ -1,3 +1,13 @@
+# Detector model file
+# Detector: MiniBooNE
+# Version: v1
+# Material model file: MiniBooNE-v1.dat
+# Date: 2022-04-01
+# Authors: Nicholas Kamp
+# Notes:
+#   Assumes MinBooNE is a sphere of mineral oil suspended in air
+#
+
 # Dirt
 object box       0 0 -250            0 0 0      100 100 600    surr_earth           ROCK         constant    2.900 
 
diff --git a/resources/Detectors/densities/README b/resources/Detectors/densities/README
new file mode 100644
index 00000000..c0f77191
--- /dev/null
+++ b/resources/Detectors/densities/README
@@ -0,0 +1,42 @@
+# detector model files
+#
+#   format as a context free grammar:
+#   [line] -> [entry] [comment]
+#   [comment] ->
+#   [comment] -> #(string comment)
+#   [entry] ->
+#   [entry] -> [object]
+#   [entry] -> [detector]
+#   [detector] -> detector (double x) (double y) (double z)
+#   [object] -> object [shape] [label] [material name] [density distribution]
+#   [shape] -> [sphere]
+#   [shape] -> [box]
+#   [sphere] -> sphere [shape coords] (double radius)
+#   [box] -> box [shape coords] (double dx) (double dy) (double dz)
+#   [shape coords] -> (double x) (double y) (double z)
+#   [label] -> (string label)
+#   [material name] -> (string material)
+#   [density distribution] -> [constant]
+#   [density distribution] -> [radial polynomial]
+#   [constant] -> constant (double density)
+#   [radial polynomial] -> radial_polynomial [axis coords] [polynomial]
+#   [axis coords] -> (double x) (double y) (double z)
+#   [polynomial] -> (int n_params) [polynomial {n_params}]
+#   [polynomial {n_params}] -> (double param_n) [polynomial {n_params-1}]
+#   [polynomial {1}] -> (double param_1)
+#
+#   format notes:
+#    - no space before first column
+#    - delimiter must be whitespaces
+#    - for overlapping, objects the object defined later in the file is given precidence
+#    - "material name" must be consistent with those defined in the material file
+#    - number_of_parameters is the number of params for polynominal density function
+#    - parameters : ex.
+#       for 3 parameters p0, p1, p2 and distance from Earth's center x :
+#       density = p0 + p1*x + p2*x*x
+#
+#       CAUTION : the unit of density must be [g/cm3] (CGS unit)
+#
+#    - lines start from '#' or whitespace are treated
+#      as comments
+#
diff --git a/resources/DetectorParams/materials/ATLAS.dat b/resources/Detectors/materials/ATLAS/ATLAS-v1.dat
similarity index 55%
rename from resources/DetectorParams/materials/ATLAS.dat
rename to resources/Detectors/materials/ATLAS/ATLAS-v1.dat
index 11a541b5..d6cd3a57 100644
--- a/resources/DetectorParams/materials/ATLAS.dat
+++ b/resources/Detectors/materials/ATLAS/ATLAS-v1.dat
@@ -1,23 +1,9 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   MediumType[string] number_of_materials[int]
-#   material_pdg[int] weight[double]
-#   .....
-#
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 6 materials
-#      "INNERCORE", "OUTERCORE", "MANTLE", 
-#      "ROCK", "ICE", "AIR", and "VACUUM"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_materials is the number of atm type in the medium
-#    - weight must be normalized to 1 within a MediumType
-#    - lines start from '#' or whitespace are treated
-#      as comments
+# Material model file
+# Detector: ATLAS
+# Version: v1
+# Date: 2023-05-02
+# Authors: Alex Wen
+# Notes:
 #
 
 ICE   2     # H20
diff --git a/resources/DetectorParams/materials/CCM.dat b/resources/Detectors/materials/CCM/CCM-v1.dat
similarity index 65%
rename from resources/DetectorParams/materials/CCM.dat
rename to resources/Detectors/materials/CCM/CCM-v1.dat
index c0d4d2b8..8a9595d8 100644
--- a/resources/DetectorParams/materials/CCM.dat
+++ b/resources/Detectors/materials/CCM/CCM-v1.dat
@@ -1,24 +1,10 @@
-# 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   MediumType[string] number_of_materials[int]
-#   material_pdg[int] weight[double]
-#   .....
-#
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 6 materials
-#      "INNERCORE", "OUTERCORE", "MANTLE", 
-#      "ROCK", "ICE", "AIR", and "VACUUM"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_materials is the number of atm type in the medium
-#    - weight must be normalized to 1 within a MediumType
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
+# Material model file
+# Detector: CCM
+# Version: v1
+# Date: 2023-03-18
+# Authors: Nicholas Kamp
+# Notes:
+#   Uses PREM model of the Earth, assumes a single far detector with the liquid argon embedded directly in the roc
 
 ARGON 1 # CCM Argon
 1000180400    1.0000000     # Ar40 100.0%%
diff --git a/resources/DetectorParams/materials/IceCube.dat b/resources/Detectors/materials/DUNEFD/DUNEFD-v1.dat
similarity index 69%
rename from resources/DetectorParams/materials/IceCube.dat
rename to resources/Detectors/materials/DUNEFD/DUNEFD-v1.dat
index 68ce603e..00f55bf4 100644
--- a/resources/DetectorParams/materials/IceCube.dat
+++ b/resources/Detectors/materials/DUNEFD/DUNEFD-v1.dat
@@ -1,3 +1,11 @@
+# Material model file
+# Detector: DUNEFD
+# Version: v1
+# Date: 2024-01-23
+# Authors: Austin Schneider
+# Notes:
+#
+
 ICE   2     # H20
 1000080160    0.8881016     # 0, 88.8% in weight  
 1000010010    0.1118984     # 2H, 11% in weight
@@ -20,5 +28,5 @@ AIR 2       # N2 + O2
 1000070140    0.7562326     # N2 78% in volume
 1000080160    0.2437674     # O2 22% in volume
 
-VACUUM 1    # dummy, H
-1000010010    1.0000000     # N2 78% in volume
\ No newline at end of file
+LAR 1 # Liquid Argon is just Ar2, isotopic composition is predominantly Ar40
+1000180400    1.0000000     # Ar40 100.0%%
diff --git a/resources/Detectors/materials/IceCube/IceCube-v1.dat b/resources/Detectors/materials/IceCube/IceCube-v1.dat
new file mode 100644
index 00000000..d52c790b
--- /dev/null
+++ b/resources/Detectors/materials/IceCube/IceCube-v1.dat
@@ -0,0 +1,29 @@
+# Material model file
+# Detector: IceCube
+# Version: v1
+# Date: 2014-08-14
+# Authors: Kotoyo Hoshina
+# Notes:
+#   The VACUUM definition has been removed from this file since it conflicts with the default material definition in the DetectorModel class
+
+ICE   2     # H20
+1000080160    0.8881016     # 0, 88.8% in weight  
+1000010010    0.1118984     # 2H, 11% in weight
+
+ROCK  2     # SiO2
+1000140280    0.4674349     # Si, 33% 
+1000080160    0.5325651     # 20, 66%
+
+INNERCORE 1 # Fe
+1000260560    1.0000000     # Fe56 100%
+
+OUTERCORE 1 # Fe
+1000260560    1.0000000     # Fe56 100%
+
+MANTLE  2   # SiO2
+1000140280    0.4674349     # Si, 33% 
+1000080160    0.5325651     # 20, 66%
+
+AIR 2       # N2 + O2
+1000070140    0.7562326     # N2 78% in volume
+1000080160    0.2437674     # O2 22% in volume
diff --git a/resources/DetectorParams/materials/MINERvA.dat b/resources/Detectors/materials/MINERvA/MINERvA-v1.dat
similarity index 67%
rename from resources/DetectorParams/materials/MINERvA.dat
rename to resources/Detectors/materials/MINERvA/MINERvA-v1.dat
index eb36e7ab..001a31c0 100644
--- a/resources/DetectorParams/materials/MINERvA.dat
+++ b/resources/Detectors/materials/MINERvA/MINERvA-v1.dat
@@ -1,24 +1,10 @@
+# Material model file
+# Detector: MINERvA
+# Version: v1
+# Date: 2023-03-01
+# Authors: Nicholas Kamp
+# Notes:
 # 
-# crust model file
-# PREM + mmc crust setup
-# crust data is consistent with MMC mediadef.
-#
-#   format :
-#   MediumType[string] number_of_materials[int]
-#   material_pdg[int] weight[double]
-#   .....
-#
-#    - no space before first column
-#    - delimiter must be whitespaces
-#    - data must include at least 6 materials
-#      "INNERCORE", "OUTERCORE", "MANTLE", 
-#      "ROCK", "ICE", "AIR", and "VACUUM"
-#    - MediumType must be consistent with EarthModelService::MediumType
-#    - number_of_materials is the number of atm type in the medium
-#    - weight must be normalized to 1 within a MediumType
-#    - lines start from '#' or whitespace are treated
-#      as comments
-#
 
 SCINTILLATOR 4 # MINERvA Scintillator
 1000010010    0.0760000     # H1 7.6%
diff --git a/resources/Detectors/materials/MiniBooNE/MiniBooNE-v1.dat b/resources/Detectors/materials/MiniBooNE/MiniBooNE-v1.dat
new file mode 100644
index 00000000..6351b719
--- /dev/null
+++ b/resources/Detectors/materials/MiniBooNE/MiniBooNE-v1.dat
@@ -0,0 +1,19 @@
+# Material model file
+# Detector: MiniBooNE
+# Version: v1
+# Date: 2022-04-01
+# Authors: Nicholas Kamp
+# Notes:
+#
+
+MINERAL_OIL 2 # MB Detector Medium
+1000010010    0.1438253     # H1 14.4%
+1000060120    0.8561715     # C12 85.6%
+
+AIR 2       # N2 + O2
+1000070140    0.7562326     # N2 78% in volume
+1000080160    0.2437674     # O2 22% in volume
+
+ROCK  2     # SiO2
+1000140280    0.4674349     # Si, 33%
+1000080160    0.5325651     # 20, 66%
diff --git a/resources/Detectors/materials/README b/resources/Detectors/materials/README
new file mode 100644
index 00000000..a5a4dba5
--- /dev/null
+++ b/resources/Detectors/materials/README
@@ -0,0 +1,16 @@
+# 
+# material model file
+#
+#   format :
+#   MediumType[string] number_of_materials[int]
+#   material_pdg[int] weight[double]
+#   .....
+#
+#    - no space before first column
+#    - delimiter must be whitespaces
+#    - MediumType must be consistent with the detector model files
+#    - number_of_materials is the number of atm type in the medium
+#    - weight must be normalized to 1 within a MediumType
+#    - lines start from '#' or whitespace are treated
+#      as comments
+#
diff --git a/resources/Examples/Example1/DIS_IceCube.py b/resources/Examples/Example1/DIS_IceCube.py
index d03962ff..87981247 100644
--- a/resources/Examples/Example1/DIS_IceCube.py
+++ b/resources/Examples/Example1/DIS_IceCube.py
@@ -20,13 +20,16 @@
 # Particle to inject
 primary_type = LI.dataclasses.Particle.ParticleType.NuMu
 
+cross_section_model = "CSMSDISSplines"
+
+xsfiledir = _util.get_cross_section_model_path(cross_section_model)
+
 # Cross Section Model
-xsfiledir = os.path.join(resources_dir, "CrossSectionTables", "DISSplines")
 target_type = LI.dataclasses.Particle.ParticleType.Nucleon
 
 DIS_xs = LI.interactions.DISFromSpline(
-    os.path.join(xsfiledir, "test_xs.fits"),
-    os.path.join(xsfiledir, "test_xs_total.fits"),
+    os.path.join(xsfiledir, "dsdxdy_nu_CC_iso.fits"),
+    os.path.join(xsfiledir, "sigma_nu_CC_iso.fits"),
     [primary_type],
     [target_type],
 )
@@ -64,6 +67,4 @@
 
 events = controller.GenerateEvents()
 
-controller.SaveEvents(
-    "IceCube_DIS.hdf5"
-)
+controller.SaveEvents("IceCube_DIS.hdf5")
diff --git a/resources/Examples/Example2/DipolePortal_CCM.py b/resources/Examples/Example2/DipolePortal_CCM.py
index 0702c219..39445185 100644
--- a/resources/Examples/Example2/DipolePortal_CCM.py
+++ b/resources/Examples/Example2/DipolePortal_CCM.py
@@ -1,83 +1,96 @@
 import os
+import sys
 import numpy as np
 
 import leptoninjector as LI
-import sys
-sys.path.insert(1,'/n/holylfs05/LABS/arguelles_delgado_lab/Everyone/nkamp/LIV2/sources/LeptonInjector/python')
-from LIController import LIController
- 
-LI_SRC = os.environ.get('LEPTONINJECTOR_SRC')
+from leptoninjector import _util
+from leptoninjector.LIController import LIController
+
+import DarkNews
+
+darknews_version = _util.normalize_version(DarkNews.__version__)
+
+resources_dir = _util.resource_package_dir()
 
-# Define a DarkNews model 
+# Define a DarkNews model
 model_kwargs = {
-    'm4': 0.02,
-    'mu_tr_mu4': 2.5e-6, #1e-6, # GeV^-1
-    'UD4': 0,
-    'Umu4': 0,
-    'epsilon': 0.0,
-    'gD': 0.0,
-    'decay_product':'photon',
-    'noHC':True,
-    'HNLtype':"dirac",
+    "m4": 0.02,
+    "mu_tr_mu4": 2.5e-6,  # 1e-6, # GeV^-1
+    "UD4": 0,
+    "Umu4": 0,
+    "epsilon": 0.0,
+    "gD": 0.0,
+    "decay_product": "photon",
+    "noHC": True,
+    "HNLtype": "dirac",
 }
 
 # Number of events to inject
 events_to_inject = 1000
 
 # Expeirment to run
-experiment = 'CCM'
+experiment = "CCM"
 
 # Define the controller
-controller = LIController(events_to_inject,
-                          experiment)
+controller = LIController(events_to_inject, experiment)
 
 # Particle to inject
 primary_type = LI.dataclasses.Particle.ParticleType.NuMu
 
+xs_path = _util.get_cross_section_model_path(f"DarkNewsTables-v{darknews_version}", must_exist=False)
 # Define DarkNews Model
-table_dir = LI_SRC+'/resources/CrossSectionTables/DarkNewsTables/Dipole_M%2.2f_mu%2.2e/'%(model_kwargs['m4'],model_kwargs['mu_tr_mu4'])
-controller.InputDarkNewsModel(primary_type,
-                              table_dir,
-                              model_kwargs)
+table_dir = os.path.join(
+    xs_path,
+    "Dipole_M%2.2f_mu%2.2e" % (model_kwargs["m4"], model_kwargs["mu_tr_mu4"]),
+)
+controller.InputDarkNewsModel(primary_type, table_dir, model_kwargs)
 
 # Primary distributions
 primary_injection_distributions = {}
 primary_physical_distributions = {}
 
 # energy distribution
-nu_energy = 0.02965 # from pi+ DAR
+nu_energy = 0.02965  # from pi+ DAR
 edist = LI.distributions.Monoenergetic(nu_energy)
-primary_injection_distributions['energy'] = edist
-primary_physical_distributions['energy'] = edist
+primary_injection_distributions["energy"] = edist
+primary_physical_distributions["energy"] = edist
 
-# Flux normalization: 
+# Flux normalization:
 # using the number quoted in 2105.14020, 4.74e9 nu/m^2/s / (6.2e14 POT/s) * 4*pi*20m^2 to get nu/POT
 flux_units = LI.distributions.NormalizationConstant(3.76e-2)
-primary_physical_distributions['flux_units'] = flux_units
+primary_physical_distributions["flux_units"] = flux_units
 
 # direction distribution: cone from lower W target
-opening_angle = np.arctan(12/23.); # slightly larger than CCM
+opening_angle = np.arctan(12 / 23.0)
+# slightly larger than CCM
 lower_target_origin = LI.math.Vector3D(0, 0, -0.241)
 detector_origin = LI.math.Vector3D(23, 0, -0.65)
 lower_dir = detector_origin - lower_target_origin
 lower_dir.normalize()
-lower_inj_ddist = LI.distributions.Cone(lower_dir,opening_angle)
-phys_ddist = LI.distributions.IsotropicDirection() # truly we are isotropicprimary_injection_distributions['direction'] = direction_distribution
-primary_injection_distributions['direction'] = lower_inj_ddist
-primary_physical_distributions['direction'] = phys_ddist
+lower_inj_ddist = LI.distributions.Cone(lower_dir, opening_angle)
+phys_ddist = (
+    LI.distributions.IsotropicDirection()
+)  # truly we are isotropicprimary_injection_distributions['direction'] = direction_distribution
+primary_injection_distributions["direction"] = lower_inj_ddist
+primary_physical_distributions["direction"] = phys_ddist
 
 # Position distribution: consider neutrinos from a point source
 max_dist = 25
-lower_pos_dist = LI.distributions.PointSourcePositionDistribution(lower_target_origin, max_dist, set(controller.GetDetectorModelTargets()[0]))
-primary_injection_distributions['position'] = lower_pos_dist
+lower_pos_dist = LI.distributions.PointSourcePositionDistribution(
+    lower_target_origin, max_dist, set(controller.GetDetectorModelTargets()[0])
+)
+primary_injection_distributions["position"] = lower_pos_dist
 
 # SetProcesses
-controller.SetProcesses(primary_type,
-                        primary_injection_distributions,
-                        primary_physical_distributions)
+controller.SetProcesses(
+    primary_type, primary_injection_distributions, primary_physical_distributions
+)
 
 controller.Initialize()
 
 events = controller.GenerateEvents()
 
-controller.SaveEvents('output/CCM_Dipole_M%2.2f_mu%2.2e_example.hdf5'%(model_kwargs['m4'],model_kwargs['mu_tr_mu4']))
\ No newline at end of file
+controller.SaveEvents(
+    "output/CCM_Dipole_M%2.2f_mu%2.2e_example.hdf5"
+    % (model_kwargs["m4"], model_kwargs["mu_tr_mu4"])
+)
diff --git a/resources/Examples/Example2/DipolePortal_MINERvA.py b/resources/Examples/Example2/DipolePortal_MINERvA.py
index 95bab090..1101691d 100644
--- a/resources/Examples/Example2/DipolePortal_MINERvA.py
+++ b/resources/Examples/Example2/DipolePortal_MINERvA.py
@@ -6,6 +6,10 @@
 from leptoninjector import _util
 from leptoninjector.LIController import LIController
 
+import DarkNews
+
+darknews_version = _util.normalize_version(DarkNews.__version__)
+
 resources_dir = _util.resource_package_dir()
 
 # Define a DarkNews model
@@ -33,11 +37,10 @@
 # Particle to inject
 primary_type = LI.dataclasses.Particle.ParticleType.NuMu
 
+xs_path = _util.get_cross_section_model_path(f"DarkNewsTables-v{darknews_version}", must_exist=False)
 # Define DarkNews Model
 table_dir = os.path.join(
-    resources_dir,
-    "CrossSectionTables",
-    "DarkNewsTables",
+    xs_path,
     "Dipole_M%2.2f_mu%2.2e" % (model_kwargs["m4"], model_kwargs["mu_tr_mu4"]),
 )
 controller.InputDarkNewsModel(primary_type, table_dir, model_kwargs)
diff --git a/resources/Examples/Example2/DipolePortal_MiniBooNE.py b/resources/Examples/Example2/DipolePortal_MiniBooNE.py
index 34d0e759..0eebc981 100644
--- a/resources/Examples/Example2/DipolePortal_MiniBooNE.py
+++ b/resources/Examples/Example2/DipolePortal_MiniBooNE.py
@@ -6,6 +6,12 @@
 
 resources_dir = _util.resource_package_dir()
 
+import DarkNews
+
+darknews_version = _util.normalize_version(DarkNews.__version__)
+
+resources_dir = _util.resource_package_dir()
+
 # Define a DarkNews model
 model_kwargs = {
     "m4": 0.47,  # 0.140,
@@ -31,11 +37,10 @@
 # Particle to inject
 primary_type = LI.dataclasses.Particle.ParticleType.NuMu
 
+xs_path = _util.get_cross_section_model_path(f"DarkNewsTables-v{darknews_version}", must_exist=False)
 # Define DarkNews Model
 table_dir = os.path.join(
-    resources_dir,
-    "CrossSectionTables",
-    "DarkNewsTables",
+    xs_path,
     "Dipole_M%2.2f_mu%2.2e" % (model_kwargs["m4"], model_kwargs["mu_tr_mu4"]),
 )
 controller.InputDarkNewsModel(primary_type, table_dir, model_kwargs)