diff --git a/km3buu/ctrl.py b/km3buu/ctrl.py index b587306c9c6f99322a001df66c4faf1d7b3225d0..d696530dec1c1f3c5c18be24d1c0fa55c9c94af3 100644 --- a/km3buu/ctrl.py +++ b/km3buu/ctrl.py @@ -12,7 +12,7 @@ __maintainer__ = "Johannes Schumann" __email__ = "jschumann@km3net.de" __status__ = "Development" -import os +from shutil import copy from spython.main import Client from os.path import join, abspath, basename, isdir, isfile from tempfile import NamedTemporaryFile, TemporaryDirectory @@ -47,7 +47,7 @@ $CONTAINER_GIBUU_EXEC < {1}; """ -def run_jobcard(jobcard, outdir, fluxfile=None): +def run_jobcard(jobcard, outdir): """ Method for run @@ -58,8 +58,6 @@ def run_jobcard(jobcard, outdir, fluxfile=None): of a jobcard object or a path to a jobcard outdir: str The path to the directory the output should be written to. - fluxfile: str - Filepath of the custom flux file if initNeutrino/nuExp = 99 """ input_dir = TemporaryDirectory() outdir = abspath(outdir) @@ -73,10 +71,11 @@ def run_jobcard(jobcard, outdir, fluxfile=None): if "neutrino_induced" in jobcard and "nuexp" in jobcard[ "neutrino_induced"] and jobcard["neutrino_induced"]["nuexp"] == 99: + fluxfile = jobcard["neutrino_induced"]["FileNameflux"] if fluxfile is None or not isfile(fluxfile): raise IOError("Fluxfile not found!") tmp_fluxfile = join(input_dir.name, basename(fluxfile)) - os.system("cp %s %s" % (fluxfile, tmp_fluxfile)) + copy(abspath(fluxfile), tmp_fluxfile) log.info("Set FileNameFlux to: %s" % tmp_fluxfile) jobcard["neutrino_induced"]["FileNameflux"] = tmp_fluxfile with open(jobcard_fpath, "w") as f: diff --git a/km3buu/data/template.job b/km3buu/data/template.job new file mode 100644 index 0000000000000000000000000000000000000000..23d2a6bc41d0258f8f095eb857d523505569a958 --- /dev/null +++ b/km3buu/data/template.job @@ -0,0 +1,48 @@ +&input + numtimesteps = 200 + eventtype = 5 + delta_t = 0.2 + localensemble = .true. + freezerealparticles = .true. + lrf_equals_calc_frame = .true. +/ + +&neutrino_induced + nuxsectionmode = 16 + includedis = .true. + includedelta = .true. + includeres = .true. + includeqe = .true. + include1pi = .true. + include2p2hqe = .true. + include2pi = .false. + include2p2hdelta = .false. + printabsorptionxs = .true. + nuexp = 10 +/ + + +&nl_fluxcuts + energylimit_for_qsrec = .true. +/ + +&nl_neutrino_energyflux + eflux_min = 0.1 + eflux_max = 50.0 +/ + +&neutrinoanalysis + outputevents = .false. +/ + +&pythia + parp(91) = 0.44 +/ + +&eventoutput + eventformat = 4 +/ + +&propagation + rungekuttaorder = 2 +/ diff --git a/km3buu/jobcard.py b/km3buu/jobcard.py index edb3e4c4c84619a62e552203da0aeacba9cfcee2..0e5ddaaf7e16f0df9ae39803ec9a4a7935c4961b 100644 --- a/km3buu/jobcard.py +++ b/km3buu/jobcard.py @@ -13,7 +13,7 @@ __email__ = "jschumann@km3net.de" __status__ = "Development" import f90nml -from os.path import basename +from os.path import basename, dirname, abspath, join, isfile try: from StringIO import StringIO @@ -58,18 +58,14 @@ class Jobcard(f90nml.Namelist): input_path: str The input path pointing to the GiBUU lookup data which should be used """ - def __init__(self, *args, **kwargs): - if "filename" in kwargs: - self.filename = kwargs["filename"] - del kwargs["filename"] - else: - self.filename = DEFAULT_JOBCARD_FILENAME + def __init__(self, + *args, + filename=DEFAULT_JOBCARD_FILENAME, + input_path=INPUT_PATH, + **kwargs): super(Jobcard, self).__init__(*args, **kwargs) - if "input_path" in kwargs: - self.input_path = str(input_path) - del kwargs["input_path"] - else: - self.input_path = INPUT_PATH + self.filename = filename + self.input_path = INPUT_PATH self.__getitem__("input")["path_to_input"] = self.input_path def __getitem__(self, key): @@ -93,61 +89,81 @@ def read_jobcard(filepath): return Jobcard(f90nml.read(filepath), filename=basename(filepath)) -def generate_neutrino_jobcard_template( - process, - flavour, - energy, - target, - write_events=False, - do_decay=False, - input_path=INPUT_PATH): # pragma: no cover +def generate_neutrino_jobcard(events, + process, + flavour, + energy, + target, + write_pert=True, + write_real=False, + do_decay=False, + photon_propagation=True, + fluxfile=None, + input_path=INPUT_PATH): # pragma: no cover """ Generate a jobcard for neutrino interaction Parameters ---------- + events: int + Simulated number of neutrino events process: str Interaction channel ["CC", "NC", "antiCC", "antiNC"] flavour: str Flavour ["electron", "muon", "tau"] - energy: float - Initial energy of the neutrino in GeV + energy: tuple + Initial energy range of the neutrino in GeV target: (int, int) - (Z, A) describing the target nukleon + (Z, A) describing the target nucleon + write_pert: boolean (default: True) + Write perturbative particles + write_real: boolean (default: False) + Write real particles + do_decay: boolean (default: False) + Decay final state particles using PYTHIA + photon_propagation: boolean (default: True) + Propagate photons and write it out + fluxfile: str (default: None) + Fluxfile, 1st col energy [GeV] and 2nd col flux [A.U.] input_path: str The input path pointing to the GiBUU lookup data which should be used """ - jc = Jobcard(input_path) + jc = read_jobcard(join(dirname(abspath(__file__)), "data/template.job")) + jc["input"]["path_to_input"] = input_path # NEUTRINO jc["neutrino_induced"]["process_ID"] = PROCESS_LOOKUP[process.lower()] - jc["neutrino_induced"]["flavour_ID"] = FLAVOR_LOOKUP[flavour.lower()] - jc["neutrino_induced"]["nuXsectionMode"] = 6 - jc["neutrino_induced"]["includeDIS"] = True - jc["neutrino_induced"]["includeDELTA"] = True - jc["neutrino_induced"]["includeRES"] = True - jc["neutrino_induced"]["includeQE"] = True - jc["neutrino_induced"]["include1pi"] = True - jc["neutrino_induced"]["include2p2hQE"] = True - jc["neutrino_induced"]["include2pi"] = False - jc["neutrino_induced"]["include2p2hDelta"] = False - jc["neutrino_inducted"]["printAbsorptionXS"] = True - # INPUT - jc["input"]["numTimeSteps"] = 0 - jc["input"]["eventtype"] = 5 - jc["input"]["numEnsembles"] = 100000 - jc["input"]["delta_T"] = 0.2 - jc["input"]["localEnsemble"] = True - jc["input"]["num_runs_SameEnergy"] = 1 + jc["neutrino_induced"]["flavor_ID"] = FLAVOR_LOOKUP[flavour.lower()] # TARGET - jc["target"]["Z"] = target[0] - jc["target"]["A"] = target[1] + jc["target"]["target_Z"] = target[0] + jc["target"]["target_A"] = target[1] + # EVENTS + run_events = int(100000 / target[1]) + if events < run_events: + run_events = events + runs = 1 + else: + runs = events // run_events + jc["input"]["numEnsembles"] = run_events + jc["input"]["num_runs_SameEnergy"] = runs + # ENERGY + jc["nl_neutrino_energyflux"]["eflux_min"] = energy[0] + jc["nl_neutrino_energyflux"]["eflux_max"] = energy[1] # DECAY if do_decay: for i in DECAYED_HADRONS: key = "stabilityFlag({:d})".format(i) jc["ModifyParticles"][key] = 4 jc["pythia"]["MDCY(102,1)"] = 1 + # FLUX + if fluxfile is not None: + if not isfile(fluxfile): + raise IOError("Fluxfile {} not found!") + jc["neutrino_induced"]["nuexp"] = 99 + jc["neutrino_induced"]["FileNameflux"] = fluxfile + # OUTPUT + jc["eventoutput"]["writeperturbativeparticles"] = write_pert + jc["eventoutput"]["writerealparticles"] = write_real # MISC - jc["neutrinoAnalysis"]["outputEvents"] = write_events - jc["insertion"]["propagateNoPhoton"] = False + jc["insertion"]["propagateNoPhoton"] = not photon_propagation + return jc diff --git a/km3buu/tests/test_ctrl.py b/km3buu/tests/test_ctrl.py index 51efdaaa55ee75508bdb2b8e4fc7576fdd425d26..6d310997f9ed47d15bc61544adde20dc6a1e0700 100644 --- a/km3buu/tests/test_ctrl.py +++ b/km3buu/tests/test_ctrl.py @@ -33,9 +33,9 @@ class TestCTRLbyJobcardFile(unittest.TestCase): ene = np.linspace(0.1, 20, 100) writer = csv.writer(f, delimiter=' ') writer.writerows(zip(ene, np.power(ene, -1))) - self.retval = run_jobcard(self.filename, - self.output_dir.name, - fluxfile=self.flux_file.name) + jc = read_jobcard(self.filename) + jc["neutrino_induced"]["FileNameFlux"] = self.flux_file.name + self.retval = run_jobcard(jc, self.output_dir.name) log = get_logger("ctrl.py") log.setLevel("INFO") diff --git a/km3buu/tests/test_jobcard.py b/km3buu/tests/test_jobcard.py index e5c0f339f5080f81ae278fafc0e8adaf029b820e..708f7e85ac204decaed5f4ac6d9385442c0d25b1 100644 --- a/km3buu/tests/test_jobcard.py +++ b/km3buu/tests/test_jobcard.py @@ -12,7 +12,8 @@ __status__ = "Development" import unittest import numpy as np -from km3buu.jobcard import Jobcard, INPUT_PATH +from km3buu.jobcard import * +from tempfile import TemporaryFile class TestJobcard(unittest.TestCase): @@ -42,3 +43,53 @@ class TestJobcard(unittest.TestCase): expected_line = "def = 42" assert ctnt.find("&ABC") == -1 assert ctnt.find(expected_line) == -1 + + +class TestNeutrinoJobcard(unittest.TestCase): + def setUp(self): + self.test_fluxfile = TemporaryFile() + self.test_Z = np.random.randint(0, 100) + self.test_A = np.random.randint(0, 100) + self.test_energy_min = np.random.uniform(0.0, 100.0) + self.test_energy_max = np.random.uniform(self.test_energy_min, 100.0) + self.photon_propagation_flag = np.random.choice([True, False]) + self.do_decay = np.random.choice([True, False]) + self.test_jobcard = generate_neutrino_jobcard( + 1000, + "CC", + "electron", (self.test_energy_min, self.test_energy_max), + (self.test_Z, self.test_A), + do_decay=self.do_decay, + photon_propagation=self.photon_propagation_flag, + fluxfile=self.test_fluxfile.name, + input_path="/test") + + def test_input_path(self): + self.assertEqual("/test", self.test_jobcard["input"]["path_to_input"]) + + def test_target(self): + self.assertEqual(self.test_Z, self.test_jobcard["target"]["target_Z"]) + self.assertEqual(self.test_A, self.test_jobcard["target"]["target_A"]) + + def test_energy(self): + self.assertAlmostEqual( + self.test_energy_min, + self.test_jobcard["nl_neutrino_energyflux"]["eflux_min"]) + self.assertAlmostEqual( + self.test_energy_max, + self.test_jobcard["nl_neutrino_energyflux"]["eflux_max"]) + + def test_flux(self): + self.assertEqual(self.test_fluxfile.name, + self.test_jobcard["neutrino_induced"]["FileNameflux"]) + self.assertEqual(self.test_jobcard["neutrino_induced"]["nuexp"], 99) + # Test flat flux + flat_flux_jobcard = generate_neutrino_jobcard( + 1000, "CC", "electron", + (self.test_energy_min, self.test_energy_max), + (self.test_Z, self.test_A)) + self.assertEqual(flat_flux_jobcard["neutrino_induced"]["nuexp"], 10) + + def test_photon_propagation_flag(self): + self.assertEqual(self.test_jobcard["insertion"]["propagateNoPhoton"], + not self.photon_propagation_flag)