pueoBuilder
Loading...
Searching...
No Matches
Introduction to the Simulation
  • This documentation should hopefully help you with running a simulation using simulatePueo.
  • If it doesn't, feel free to complain directly to Christoph or on the #pueo_simulations Slack channel :)
  • If you worry that people may judge you for asking a "dumb question" (which you really should not be!), there is also the #idontgetit Slack channel where you can ask questions anonymously.

Running a Simulation

  • After installation, go to the directory that contains all the executables:
    cd $PUEO_UTIL_INSTALL_DIR/bin
    (If you forgot what $PUEO_UTIL_INSTALL_DIR is, see Step 1: install location).
  • In the directory, you will find
    • the executables simulatePueo and reSimulatePueo, and
    • a folder called config/ containing some configuration files, for instance pueo.conf
  • You can see the command line arguments that simulatePueo expects by typing ./simulatePueo -h, but the really important ones for now are
    Flags Purpose
    -i The name of the file containing the simulation settings. By default, the directory ${PUEO_UTIL_INSTALL_DIR}/bin/config/ will be searched first, and then, upon failure, some other places.
    -r The "run number" of the simulation, which will determine the names of the output files. This also sets the seeds for the random number generators, so (everything else being equal) simulations with the same run number should give the same results every time.
    -o The output directory, where the simulation results will be written to.
    If the directory does not exist, it will be created.
    Note
    Technically, only -i is strictly necessary, since -r and -o have default values. Still, it is still highly recommended to set the other two.
  • Below are some more optional command line flags. They overwrite settings that can be changed in pueo.conf so are not really necessary. Nonetheless, they can be pretty handy:
    Flags Purpose
    -n The number of events to be simulated.
    -e The \(\log_{10}\) of the neutrino energy to be simulated.
    -t The path to the file containing the trigger settings.
    Again, the program will first search in ${PUEO_UTIL_INSTALL_DIR}/bin/config/.
  • As an example, let's run a simulation of 1k neutrinos at 100 EeV ( \(10^{20}\) electron volts):

    ./simulatePueo -i pueo.conf -r 420 -o ~/pueo_temporary -n 1000 -e 20

    This might take a little while to run, so be patient.
    Don't worry if the vast majority of neutrinos don't trigger, that's normal.

    Remarks
    You may also notice that it takes some time for the simulation to really get going. That's because the program is generating a bunch of noise waveforms to estimate the thresholds that the trigger simulation will use.
    You can turn this off and force the program to use the values in the trigger settings file (by default ${PUEO_UTIL_INSTALL_DIR}/bin/config/triggerSettings.txt). But, be aware that these may or may not (most likely not!) be the correct values, so you should only do this if the actual trigger perfomance is not important for what you are doing.
  • Congratulations, you just ran your first simulation using simulatePueo! In the directory you specified with the output flag, you will find a new "run directory" (e.g. ${HOME}/pueo_temporary/run420/, if you followed the above example).
  • Inside the run directory, you will find six files ($r means the run number):
    File Name Content
    SimulatedPueoEventFile$r.root Waveforms
    (same format used by the real PUEO payload)
    SimulatedPueoTruthFile$r.root Same as above, plus the truth
    SimulatedPueoHeadFile$r.root Header
    (same format used by the real PUEO payload)
    SimulatedPueoGpsFile$r.root Navigation data
    (same format used by the real PUEO payload)
    IceFinal_$r_allTree.root Simulation results, split into passTree and allTree
    (format specified by the nicemc::Event class)
    gitversion.txt PueoSim version (git commit hash) used by the simulation
    The IceFinal file parallels the "real data format" files(SimulatedPueo*File.root).
    This is referred to as "dual output".

What's going on under the hood?

  • The PUEO software suite consists of several repositories housed by pueoBuilder .
  • Below, we list these "submodules" more-or-less according to how they depend on each other.
    Repository Dependency Purpose
    pueo-data Stores information about the PUEO payload
    (eg. antenna positions, amplifier responses).
    pueoEvent pueo-data A framework for interfacing with the SimulatedPueo*File.root data.
    RootFftwWrapper Fast Fourier transform
    AntarcticaRoot RootFftwWrapper Handles geographic information about Antarctica
    (eg. ice thickness).
    NiceMC AntarcticaRoot Simulates the processes that produce the radio signals
    (eg. neutrino interactions, Askaryan emissions, and signal propagation).
    PueoSim NiceMC & pueoEvent Simulates the detector itself and its subsystems
    (eg. antennas, amplifiers and the triggers).
  • Finally, pueoAnalysisTools contains scripts that makes analysis plots. This repository depends on PueoSim.

The Simulation Script: simulatePueo.cc

  • In the previous section, we did a test run using the executable simulatePueo.
  • The source code of this binary is located at pueoBuilder/components/PueoSim/test/simulatePueo.cc.
  1. The first couple of lines reads in the configuration files for the simulations:

    • nicemc::CommandLineOptions tells the nicemc::Settings object to read the config file:
      nicemc::Settings settings;
      nicemc::CommandLineOptions clOpts(argc, argv, settings);
      Also, it overwrites any settings that were set with the command line parameters (-e 20 -n 1000 in the example above).
    • Then, the pueoSim::TriggerSettings object reads the settings for the trigger (which are stored in triggerSettings.txt, separate from pueo.conf):
      pueoSim::TriggerSettings triggerSettings(
      &settings.getSettings()->strings.at("TriggerSettingsFilename")
      );
      std::vector<pueoSim::TriggerParameters> triggers = triggerSettings.GetTriggerSettings();
    Remarks
    There is a reason why you have to access the settings in such a roundabout way: By hiding the settings behind the getSettings() method, the nicemc::Settings object knows when someone has accessed these settings and will no longer allow any changes to them.
    This ensures that the settings that are written into the output are actually the ones used by the simulation.
  2. The next few lines create two detector objects that simulate the main instrument and the low-frequency instrument (the latter can be toggled by the environment variable PUEO_LF)
    bool enable_LF = false;
    char * pueo_lf = getenv("PUEO_LF");
    if (pueo_lf && !strcmp(pueo_lf,"1"))
    {
    std::cout << "LF enabled via env variable!" << std::endl;
    enable_LF = true;
    }
    auto MI = std::make_shared<pueoSim::Pueo>(&settings, &triggers[0]);
    auto LF = std::make_shared<pueoSim::Pueo_LF>(&settings);
    and store them inside a vector
    std::vector<std::shared_ptr<nicemc::Detector>> detectorVector;
    detectorVector.push_back(MI);
    if (enable_LF)
    detectorVector.push_back(LF);
    The rest of the simulation code will iterate over this vector and simulate all detectors in it.
  3. Finally, the script creates a class to enable dual-output
    pueoSim::PueoSimOutput output (&*MI, enable_LF ? nullptr : nullptr, &settings);
    and sets up nicemc::SimulationRunner, which manages the bulk of the simulation.
    nicemc::SimulationRunner simulationRunner(
    &settings,
    detectorVector,
    &output
    );
    simulationRunner.fullSimulation(
    settings.getSettings()->integers.at("Number of neutrinos")
    );
  4. The last few lines just print out the duration of the simulation.

The SimulationRunner

  • The class nicemc::SimulationRunner manages the simulation at the highest level, making sure that the correct methods from other classes are called in the right order.
  • Its constructor takes
    • a pointer to the simulation settings (&settings),
    • a vector holding pointers to the detectors we want to simulate (detectorVector), and
    • a pointer to the dual-output writer (optional).
  • To run a simulation, simply call the method fullSimulation() and it will take care of the rest.
  • The method rerunSimulation() can be used to resimulate events from an output file of a previous simulation. More on that later...

EventGenerator and EventSimulator

Internally, most of the simulation is handled by two classes.

  1. As the name suggests, the class nicemc::EventGenerator is responsible for generating a neutrino event; that is, it sets the initial conditions (eg. neutrino direction, flavor and interaction position).
  2. The class nicemc::EventSimulator then simulates the radio signal using the initial conditions. This simulation is completely deterministic (except for the thermal noise), meaning that for the same initial conditions, it should always produce the same result.

The simulation of a neutrino event is split into distinct steps, each of which handled by a method either in EventGenerator or EventSimulator:

  • EventGenerator:
    1. Generate randomized neutrino properties (eg. flavor, direction and interaction position).
    2. Generate a dummy event object that only contains default values.
      This is useful when simulating things other than neutrinos, like pulsers or noise.
    3. Calculate neutrino properties (eg. weights) that follow deterministically from step 1.
  • EventSimulator:
    1. Carries out raytracing to find the signal path from the interaction point to the detector.
    2. Checks cut criteria
      (eg. existence of a ray path, the "chance in hell" cut, and a cut on the neutrino weight).
    3. Generates radio signals.
    4. Propagates signal from the source to the detector.
    5. Simulates the detector response to the signal
      (though most of this is handled by the corresponding detector class in PueoSim).

Determinism and Resimulating Events

  • NiceMC and PueoSim use seeded (pseudo)random number generators (RNG) whose seeds are based on the run number r. Thus, rerunning a simulation with the same r should always give the same results.
  • When changes to the code are expected modify the behavior of the simulation, this random nature of the simulation can make it difficult to judge if the modification behaves as expected. To solve this problem, NiceMC can use the output file from a simulation as an input file and resimulate the same events.
  • The source code that handles the resimulation is located at PueoSim/test/reSimulatePueo.cc, which gets compiled and installed to the same directory as simulatePueo.
  • reSimulatePueo only needs the -i flag, which in this case points towards the output file we want to resimulate instead of the config file.
  • If you compare reSimulatePueo.cc against simulatePueo.cc, you will notice that they are mostly the same except for a few key differences, discussed below.
  1. The nicemc::Settings object reads the simulation settings from the IceFinal file itself,
    instead of a config file (ie. pueo.conf).
    • This ensures that both simulations use the exact same settings.
    • That said, the trigger settings are still read from the actual text file
      (config/triggerSettings.txt), whose path is specified in simulation settings.
  2. The script calls rerunSimulation() instead of fullSimulation().
    The method rerunSimulation() takes 3 parameters:
    parameter name Purpose
    inputFile Name of the IceFinal file we want to resimulate
    onlyTriggered If true, events are read from the passTree of the IceFinal file, which contains only triggered ("passed") events.
    If false, events are read from allTree, which contains all events.
    level Defaults to 0. This specifies which steps from the simulation chain should be resimulated, and which should be read from the IceFinal file.
  • The last of these parameters needs some explaining.
    • Instead of only reading in the randomly generated neutrino properties, specifying a level allows you to read in more simulation results so that they don't need to be regenerated.
    • This can be useful to check for unintended impacts to the simulation pipeline downstream of the intended changes.
    • The steps that can be skipped with level are:
      step Purpose
      0 Only read in the event properties that are randomly generated
      (eg. event time, neutrino direction, interaction position).
      All else are resimulated, including the deterministic neutrino properties calculated using the random ones.
      1 Also read in the neutrino properties that follow deterministically from the randomly generated ones.
      2 Also read raytracing results
      4 Also read the generated radio signals
      5 Also read signal propagation to the detector (including the antenna response to the radio signal), leaving only the detector simulation to be resimulated.
      Todo
      why is a 3 missing?
      Note
      All options larger than 2 require the option onlyTriggered to be true, since some of the required properties are only saved in the passTree.