LArSoft
v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
|
Example name: | AnalysisExample |
---|---|
Type: | LArSoft module |
Author: | Bill Seligman (selig) man@ nevis .col umbia .edu |
Created on: | August 7, 2017 |
This is a detailed supplement to the brief notes in README.md
. These notes explain why things are done in a certain way in AnalysisExample_module.cc
(if you followed directions, you've renamed it by now). Believe it or not, it's to teach you something useful.
"Gosh, there's so much to read!" There are a number of guides (see the links below) that can give you the basic commands to type in. The goal of this tutorial is to explain the reasons why those commands work. That way you know what to change and when to change them.
As noted on the web page, "Simplicity is not a virtue of LArSoft." There's a natural tendency to treat a complex software package as a "black box" and not understand what goes on inside. Hopefully all these comments and details will help you open the black box when you need it.
Why the "_module" part of the name? So you'll remember to use the DEFINE_ART_MODULE macro in the file; it's near the end. This lets you use the name of this class in a "module_type" statement in a .fcl file; there's an example in the sample .fcl file in this directory.
Also, the name will help the system to compile it in its own library and not to mix with modules from the same source directory.
I put in a couple of examples of how to use associations near the end of the code: https://cdcvs.fnal.gov/redmine/projects/larsoft/wiki/Using_art_in_LArSoft#artAssns
These examples are intended to be sketches, not the full-blown n-tuple creation examples earlier in the code. It should be enough to get you started as you follow the LArSoft reconstruction chain, either forwards or backwards.
The code in the .cc file fetches simb::MCParticle and sim::SimChannel objects directly. Since that code was written, two services have been created that reads those objects for you, along with simb::MCTruth objects. These are cheat::BackTrackerService, and cheat::ParticleInventoryService.
To use this service, get a handle to cheat::BackTrackerService in the same way you get a handle to art::TFileService in the .cc file, then use that handle to invoke any of the methods in ${LARSIM_INC}/larsim/MCCheater/BackTrackerService.h.
So why not use that service in AnalysisExample? Because for the work you'll be doing, you'll probably won't be just reading in the simulated particles and channels; you'll probably be creating n-tuples and histograms based on other LArSoft objects. You'll still use the same methods to read in those objects that are shown in the .cc file: create an art::Handle to a std::vector, then use art::Event::GetByLabel to fill the vector.
Also, importing data products via services will make experts mutter about good practises. The rule is that if your module uses a data product, it should fetch it by itself. BackTracker is still appreciated for its ability to recover connections between reconstructed and generated particles.
Sounds a bit complicated? It can be. That's why there are examples in the code, plus comments in the .fcl file to help you understand how the code connects to job control file.
Keep BackTracker in mind; it's a handy tool. But learn I/O from this example and from the wiki page at https://cdcvs.fnal.gov/redmine/projects/larsoft/wiki/Using_art_in_LArSoft
If you want to do dE/dx studies using this code as a starting point, then you're going to need to put the following line at the end of the .fcl script (e.g., prodsingle.fcl) you use to generate events:
``` services.LArG4Parameters.KeepEMShowerDaughters: true ```
Why? In LArG4, by default, if a particle is a typical product of e-m processes (bremmstrahlung, pair production, etc.) the particle ID stored in the channels and hits is that of the "eve" particle; that is, the ultimate mother particle that interacted in an "interesting" way before converting into an e-m shower. That's a reasonable thing to do if you're working on reconstructing showers.
But for dE/dx studies, it becomes confusing; the particle you're tracking seems to have energy losses throughout the volume of the detector. You want to distinguish the particle of interest from any of its daughter particles. Setting the above flag will store the original Geant4 track ID for each daughter's energy deposits, so you can easily exclude them as shown in the code.
So what's all this stuff about vectors, maps, range-based for loops, and iterators?
They're part of an important extension to C++ called STL, the Standard Template Library. (Bonus geek credits if you first read "STL" as "slower than light.") Vectors and maps are used extensively in LArSoft; occasionally other STL containers are used as well.
When you first come into contact with STL classes, there's a tendency to treat them like FORTRAN arrays (if you learned programming before 1995) or like Python dictionaries (if you learned programming after 2005). If you use the same techniques to handle vectors and maps as you did in those other languages, you'll get slow, inefficient code that may waste large amounts of memory.
Obviously, you can't learn all about STL in a single code example. What I've tried to do is demonstrate some basics: use iterators to step through STL containers (vectors, maps, lists, etc.); don't copy an entire object when you can copy a pointer or an address; use "auto" to save on typing; use "const" to protect your data; take advantage of STL's built-in algorithms when you can (like fast binary searches on sorted containers).
To make things a bit more complicated, in Sep-2012 we started using a C++ compiler that enabled the additional language features in C++11. The code examples attempt to illustrate what you can now do with these new features, including the "auto" keyword and range-based for loops.
When you start asking, "Why does this method return an entire map instead of some kind of pointer to the map? Are they at least considering move semantics?" then you know you've mastered STL, memory management, and the new extensions to C++.
"Gosh, AnalysisExample_module.cc is so loooooong! It's got many layers of nested loops. Couldn't you have prepared something shorter?"
Perhaps. But every analysis program or script I've seen has contained multiple levels of control structures like this ones you see here. Unlike Algorithms, Tools, or Services, which are often optimized for efficiency, analysis programs just grow and grow and grow. There's not much incentive to break-out functionality into sub-modules (as we do with DetectorDiagonal).
Conclusion: This is the kind of code you will write. Feel free to write better! (And don't forget the comments!)