FluxReader reads flux files, or Dk2Nu files, and outputs their contents as a set of distributions, called Spectra. The user specifies a set of files to read and the types of spectra to produce. FluxReader keeps a list of Detector and branch names that it will use. Both of these are stored as a std::set, so duplicates are ignored. When reading through actual files, it only searches for branches that it needs, and for every neutrino ray entry in the flux files, it projects the ray to each detector location all at once before filling histograms. Each entry is stored in a local Dk2Nu object, and this object is given to each Spectra for filling.


The FluxReader constructor has three arguments, the first of which is required. This argument is a string that contains the location of the flux file(s) to read. The string can contain standard shell wildcard characters, such as the asterisk (*).

  FluxReader *fr = new FluxReader("/nova/ana/users/rhatcher/dk2nu-data/fullsplit/generic*.root");

The remaining constructor arguments allow the user to choose a subset of files to run over. The first of the optional arguments (second overall) is an integer that specifies the maximum number of files to run over. The last argument is an integer that specifies how many files to skip. This is useful because the wildcard string is always expanded the same way, assuming there have been no file name changes, deletions, or additions. If the user wants to run over 300 files total, in 100 file increments, this could be done by setting up FluxReader (in three different files!) in the following way.

  FluxReader *fr = new FluxReader("/nova/ana/users/rhatcher/dk2nu-data/fullsplit/generic*.root", 100);
  FluxReader *fr = new FluxReader("/nova/ana/users/rhatcher/dk2nu-data/fullsplit/generic*.root", 100, 100);
  FluxReader *fr = new FluxReader("/nova/ana/users/rhatcher/dk2nu-data/fullsplit/generic*.root", 100, 200);

Finally, if a user wants to use all files after a skipping a specific number, the second argument (the number of files) should be set to 0, while the third argument should be set to the number of files to skip. A value of 0 for the second argument tells FluxReader to use all files that remain after skipping the specified number. This command would run over all files after the first 150.

  FluxReader *fr = new FluxReader("/nova/ana/users/rhatcher/dk2nu-data/fullsplit/generic*.root", 0, 150);

General Use

After a FluxReader object has been constructed, the user creates a list of spectra to produce using the AddSpectra functions, and finally uses ReadFlux to actually fill and write out the Spectra. There is a function call to AddSpectra for each type of Spectra.

For the standard one, two, and three dimensional distributions, the function calls all have the same structure. The first argument is a Parameters object, and the second is a title, as a std::string. The given title will become the output file directory name, and it will be part of each histogram's name as well. The next set of three arguments sets up each histogram axis. The first of the three axis arguments is an axis label, given as a std::string. The next is a std::vector<double> of bin edges. For equally sized bins, the Utilities function Bins is very useful. The last of the axis arguments is a Var object that determines what is filled into the histogram. A typical call to AddSpectra for a one dimensional histogram appears below. The label "enu" is the title and will be the output directory name. Each histogram will have an axis label of "Energy (GeV)," the x axis will consist of 100 bins from 0 to 10, and the variable kEnergy is filled into the histogram.

  // Assuming we have a Parameters object called params...
  fr->AddSpectra(params, "enu", "Energy (GeV)", Bins(100, 0., 10.), kEnergy);

To create a two or three dimensional set of distributions, simply add another set of the three axis arguments after the first set for the y axis, and add one more for the z axis. In the two dimensional example below, the x axis plots the neutrino parent moment along the beam axis in 120 equally sized 1 GeV bins, and the y axis plots the momentum transverse to the beam in 40 equally size 0.1 GeV bins.

  fr->AddSpectra(params, "pTpz", "p_{z} (GeV)", Bins(120, 0., 120.), kpz,
                                 "p_{T} (GeV)", Bins(40,  0., 4.),   kpT);

There other type of spectra that can be created is one which plots a variable at one detector location on the x axis, and the same variable at a different detector on the y axis. The version of AddSpectra for this type of distribution begins with the same two arguments as each of the others. However, after these arguments, the next two are the names of the x axis and y axis detector as std::string. These names must match one of the detectors in the Parameters object given earlier in the function call. After these arguments, the next three are the three standard axis arguments. The example below will create a set of distributions plotting neutrino energy at the NOvA Near Detector on the x axis, and neutrino energy at the NOvA Far Detector on the y axis.

  fr->AddSpectra(params, "bmmat", "nova_nd", "nova_fd", "Energy(GeV)", Bins(100, 0., 10.), kEnergy);

For every call to AddSpectra, there exist two arguments which are optional. No matter which version of AddSpectra is being used, these optional arguments always come at the end. The first is a Weight object. If this argument is left blank, a default weight is applied, but the user may specify one here. The last argument is a set of external weights. The input here must inherit from a TObject, but that includes pretty much everyting, including every root histogram type, TGraph, TSpline, etc. To actually make use of these external however, a Weight object must be provided in the first optional argument, and it must specify how to apply the external weights. See Demo2_VarWeight.C for an example of using external weights.

The other publicly accessible function is ReadFlux. When this function is called, every set of distributions set up by calls to AddSpectra will get filled. The only argument is to ReadFlux is a TDirectory*, though most commonly the input will be a TFile*. This means that the user must open a file for output, and then provide this to ReadFlux. This is demonstrated below.

  TFile* out = new TFile("/nova/ana/users/gkafka/FluxReader/output.root", "RECREATE");