Development
How do I write my own output module?
An essential requirement of any output module is its ability to receive any message of the framework. This can be implemented
by defining a private filter
function for the module as described in Section 4.6. This
function will be called for every new message dispatched within the framework, and should contain code to decide whether to
discard or cache a message for processing. Heavy-duty tasks such as handling data should not be performed in the filter
routine, but deferred to the run
function of the respective output module. The filter
function should only decide whether
to keep a message for processing or to discard it before the run
function.
How do I process data from multiple detectors?
When developing a new Allpix Squared module which processes data from multiple detectors, e.g. as the simulation of a track
trigger module, this module has to be of type unique as described in Section 4.4. As a
detector module, it would always only have access to the information linked to the specific detector is has been
instantiated for. The module should then request all messages of the desired type using the messenger call bindMulti
as
described in Section 4.6. For PixelHit messages, an example code would be:
TrackTriggerModule(Configuration&, Messenger* messenger, GeometryManager* geo_manager) {
messenger->bindMulti<MCTrackMessage>(this, MsgFlags::NONE);
}
std::vector<std::shared_ptr<PixelHitMessage>> messages;
The correct detectors have then to be selected in the run
function of the module implementation.
How do I calculate an efficiency in a module?
Calculating efficiencies always requires a reference. For hit detection efficiencies in Allpix Squared, this could be the
Monte Carlo truth information available via the MCParticle objects. Since the framework only runs modules, if all input
message requirements are satisfied, the message flags described in
Section 4.6 have to be set up accordingly. For the hit efficiency example,
two different message types are required, and the Monte Carlo truth should always be required (using MsgFlags::REQUIRED
)
while the PixelHit message should be optional:
MyModule::MyModule(Configuration& config, Messenger* messenger, std::shared_ptr<Detector> detector)
: Module(config, detector), detector_(std::move(detector)) {
// Bind messages
messenger->bindSingle<PixelHitMessage>(this);
messenger->bindSingle<MCParticleMessage>(this, MsgFlags::REQUIRED);
}
How do I add a new sensor material?
When adding a new sensor material, additions at several positions in the code are necessary:
-
Add material to list of available sensor materials in
src/core/geometry/DetectorModel.hpp
. -
If not available yet, add material to the Geant4 material manager (
src/modules/GeometryBuilderGeant4/MaterialManager.cpp
). See examples of either using a material known to Geant4 or defining compositions in the code. It should be noted that the key of thematerials_
map needs to match the name of the sensor material defined in the previous step, transformed to lower case letters. -
Define default values for the material properties listed in
src/physics/MaterialProperties.hpp
. -
Add the list of material properties to the corresponding section of the user manual (
doc/usermanual/chapters/06_models/01_material_properties.md
).
Any contribution to the framework in terms of new sensor material definitions is welcome and can be added via a dedicated merge request in the repository [@ap2-repo].