How Stuff Works

It is a frequent occurrence for experts to receive emails with roughly formed questions. The answers to these questions sometimes range far and wide, often covering vast swaths of the offline code base. This page is an attempt to collect some of those answers in to a vague semblance of order. It is likely that details here will fall out of date, so perusers are encouraged to watch for inconsistencies and make edits or contact the authors when necessary.

Time - Event

Event Time

Event times are stored in the art::Event (i.e. trigger window) as an art::Timestamp. It is unique to each event and stores the actual trigger time. The actual time is stored as a unix time. To access day, month, year, etc, the unix time can be passed to localtime() or gmtime() (UTC) if you #include <ctime>. Here is an example based on the code in CAFMaker:

 art::Timestamp ts = evt.time();
 const time_t timeSec = ts.timeHigh();
 struct tm* timeStruct = localtime(&timeSec);

 unsigned short year            = timeStruct->tm_year + 1900;
 unsigned short month           = timeStruct->tm_mon + 1;
 unsigned short day             = timeStruct->tm_mday;
 unsigned short doy             = timeStruct->tm_yday + 1;
 unsigned short hour            = timeStruct->tm_hour + 1;
 unsigned short minute          = timeStruct->tm_min;
 unsigned short second          = timeStruct->tm_sec;

Reconstructed Time

The standard rb::CellHit objects only know their time relative to the time of trigger issuance. For rb::CellHit objects, TNS() returns duration between trigger issuance and the reconstructed hit time. For rb::Cluster and derived classes (e.g. rb::Prong, rb::Track, ) the MeanTNS(), MinTNS() and MaxTNS() member functions can usually provide the desired information. These functions all automatically use the timing calibration from Calibrator. More information can be found on the doxygen pages for CellHit and Cluster.

The Database

Not all of the information required to run reconstruction is available in the input file. There are many bits of information which we store in a database, for example, channel masks, calibration constants. When a reconstruction job runs, it contacts the database to retrieve such information. Most requests are sent to a web server which fetches the information from the database and returns the result. Requests can fail because either the web server or database itself is stressed.

Numu Selection and Characterization

Users often ask questions like "where do I find the muons?" You can't ask about a muon, you can only ask about slices, tracks and their reconstructed quantities. Here's how things work:

  1. We run a slicer, it sorts hits into slices (aka clusters) that are correlated in space/time. Each slice gets it's own entry in the CAF. Details about the slice are stored in the slc branch in CAF.
  2. We make lines with trackers, many different kinds. For muons, KalmanTrack is the most time-honored example. The output is stored in CAF in the trk.kalman branch. Currently, 2D and 3D tracks are stored together in the same vector and distinguishable by the trk.kalman[i].view variable: 0 for x view, 1 for y view, 2 for 3D.
  3. We run particle identification (PID) algorithms on the reconstructed tracks. For muons, we use something called ReMId, with output stored in the sel.remid branch in the CAFs. For each track in the trk.kalman vector, there is a matching entry in the sel.remid.muid vector with the same index. A track with a higher PID value (sel.remid.muid[i].pid) is more muon-like. The preferred cut is 0.75. ReMId performance is considerably better for 3D tracks since it relies on attenuation calibration, so 2D ones should be avoided. In CAF, we store sel.remid.bestpididx, which defaults to 999 if there is no ReMId output; in that case is -5. As long as there is in fact ReMId outut, will be in the range [0,1] or -1. The negative value means that ReMId didn't find any mip-like hits, so there is nothing muon-like about the track. Details on ReMId are in DocDB 11206.
  4. We run a module for energy estimation called NumuEnergy, with CAF output stored in energy.numusimp. The module produces energy estimates given several hypotheses, e.g. ND/FD, QE/non-QE. Most of the energies are for estimating the neutrino energy; energy estimates for tracks using a muon hypothesis are also written out. Details can be found in the numu energy estimator tech note, DocDB 11208.
  5. We run a QE/non-QE selector called QePId that makes the distinction based on the amount of hadronic energy and some other characteristic variables. In CAF the information is stored in the sel.qepid branch. A larger QePID value ( indicates that the event is more QE-like, but the optimal cut depends on whether there are one or two reconstructed tracks. The cut is 0.45 for the one track sample and 0.4 for the two track sample; interactions with more than two reconstructed tracks are generally not QE. Details on QePId can be found in DocDB 11207.