Event Generator Core Dump
Information on how the event generators interface to the rest of the code. This is email that I sent to Peter S. that needs to be integrated into the rest of the information.
Navigate to the "Getting started" page in the computing section of the mu2e internal page. Click on "Running G4 within art: the first examples" There is also some information on the old plone site. The "Annotated Cheat sheet" might prove useful: http://mu2e-plone.fnal.gov/Members/kutschke/InstructionsForTheFirstTrialOfTheFramework The following is relative to the code that you untarred in the "Running G4 .... " link above. > ls EventGenerator See inc and src subdirectories. The advice is this: any .h file that you want other packages to see, must go into inc/. Any .h file that you do not want other packages to see should go into src/ but everything will still work if you put it in inc/ > cd EventGenerator/src See EventGenerator_plugin.cc and a bunch of other .cc files. See also a file named SConscript. This is like a makefile. The operation of SCons is to a) for each file named XXXXX_plugin.cc, create a shared library named lib/libXXXX_plugin.so ( relative to the root of the checked out code.) b) for all other .cc files, add them to a shared library named lib/libEventGenerator.so ( create the library if necessary ) The file EventGenerator_plugin.cc is an example of a framework module. This is the thing that can be scheduled by the framework. This happens to contain both the header and the implementation. It also contains two lines at the end that are part of the magic that makes this a module: using mu2e::EventGenerator; DEFINE_FWK_MODULE(EventGenerator); The class name EventGenerator must match the base part of the filename (EventGenerator_plugin.cc The class EventGenerator inherits from art::EDProducer. This says that it is a framework module, in particular that it is a framework Producer Module. A producer module can and must add information to the event. The constructor takes a "parameter set" object from which you can extract run time information. Here we use it to access a file with configuration information for the generator. THe parameter set information is persisted in the output file. Instead of passing in the configuration info via this file, I could have used the parameter set mechanism to pass in the configuration items one at a time. Both would work fine - I am guessing here that the configuration file will be easier to read than the way that parameter set info is specified. In the constructor, the class advertises that it produces an object of type: ToyGenParticleCollection. I stuck the Toy in there to remind us that this is probably not the final generated particle class. The class ToyGenParticleCollection is defined in: ToyDP/inc and ToyDP/src. The abbreviation DP is "Data Product" which is framework-speak for "A thing that I can add to the event". When the framework calls the produce() method of EventGenerator, if it does not add a ToyGenParticleCollection to the event, then the framework with throw an exception. From the framework point of view, it is OK to add an empty collection to the event. Now look at the body of the beginRun method. Ignore the arguments for now. The first of the body line is: // Get access to the geometry system. art::Service
geom; This does not do anything but if we had run dependent geometry this would be how to access it. The next line creates a parser for the configuration file: SimpleConfig config(_inputfile); The next lines create the sub-generators that we talked about: _particleGun = auto_ptr (new ParticleGun(config)); _conversionGun = auto_ptr (new ConversionGun(config)); _cosmicToy = auto_ptr (new CosmicToy(config)); _piCapture = auto_ptr (new PiCapture(config)); This should be smarter - only create the ones that are requested in the config file. I could have put the above into the beginJob method or event the constructor. But I am guessing that at some time we might have run dependence in the generator configuration. So we might some day need to change or reconfigure the generators on run boundaries. For each of the subgenerators, the constructor takes the config file as an argument. The produce() method is the part of the module that gets called once per event. It creates an empty ToyGenParticleCollection. Then it calls each subgenerator in turn. Each subgenerator recives the ToyGenParticleCollection as an arugment. Finally the produce method puts the completed ToyGenHitsCollection into the Event. Note that the put method takes ownership of the collection - this is acheived via the use of auto_ptr. So the pointer p becomes undefined after the put. If you try to use it, the code will throw an exception. The handle, q, returned by the put method allows you to read information from the container but will throw if you try to write to it. Now look at my PiCapture class. This just shoots photons from the target. Look at the header file, EventGenerator/inc/PiCapture.hh It inherits from EventGenerator/inc/GeneratorBase.hh This anticipates that EventGenerator will someday handle its subgenerators generically. Now look at EventGenerator/src/PiCapture.cc First there are some lines defining constants. We need a proper home for these. // Need a home for these. Can we use the root version? static const int pdg_electron = 11; static const int pdg_muon = 13; static const int pdg_gamma = 22; // Also need a home for this - the cycle time of the debuncher. static const double tcycle = 1694.; Here the 1694 is the cycle time of the Debuncher ring, in ns. The constructor looks in its run time config file to find the mean number of photons to make in each event. Next it books a histogram. The gymnastics with TFileService is because the system uses root for event IO. Since root has a ton of global state if you use root "native" you will break the IO system unless you are careful to put it back the way you found it. The TFileService insulates you from this. I hope that the syntax is clear enough - it just calls the constructor of TH1D with some bookkeeping around it. TFileService does one additional thing. In the root histogram file it makes a uniquely named subdirectory for each instance of each module. All of the histograms made by a module end up in this subdirectory. And I do mean each instance of each module. In a given framework job you can invoke a given module multiple times, changing the run time configuration each time. Each instance gets its own histogram directory. And the event data output of each instance is carefully labeled to describe which instance created it. Now move on to the generate method. It simply returns if we asked for a mean of zero or smaller. Next it accesses the target geometry. It does NOT access the G4 copy of the geometry. Instead it access the framework version of the geometry. The target geometry is defined in: /TargetGeom/inc and TargetGeom/src The parameter values for the geometry are in: Mu2eG4/test/geom_*.txt At the momment there are no targets in G4. There will be soon. They will be created from the framework copy of the geometry, which is the authoritative version. Then draw a number of particles from a Poisson, generate each in turn and add it to the event. The generate unit sphere code is found in: #include "Mu2eUtilities/inc/RandomUnitSphere.hh and src/ The ToyGenParticle class is found in: ToyDP/inc/ToyGenParticle.hh I guess I should make the data members private and provide accessors. This class is missing one thing: there is no mother daughter info. Right now I don't see any application inside an event generator for Mu2e to need that. Do you? The generator ID class is defined in: ToyDP/inc/GenId.hh and src/ It basically exists to map enums to strings. Once we start using this for real we will need to decide on what the correct list of values is. When we run G4, the file Mu2eG4/src/PrimaryGeneratorAction.cc contains the code that pulls the ToyGenParticleCollection out of the event and copies it into G4. Let me know if you have any questions: Rob
|Security, Privacy, Legal|