Commit 70714a2b authored by Tadej Novak's avatar Tadej Novak
Browse files

Merge branch 'hgtd_digitool_21p9' into '21.9'

HGTD digi tool

See merge request !46396
parents 0fb91904 d1532cad
################################################################################
# Package: HGTD_Digitization
################################################################################
# Declare the package name:
atlas_subdir( HGTD_Digitization )
# External dependencies:
# find_package( Boost COMPONENTS filesystem thread system )
find_package( CLHEP )
# find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
atlas_add_component( HGTD_Digitization
src/*.cxx
src/components/*.cxx
INCLUDE_DIRS HGTD_Digitization ${CLHEP_INCLUDE_DIRS}
LINK_LIBRARIES ${CLHEP_LIBRARIES} PileUpToolsLib HGTD_RawData
HitManagement AthenaBaseComps ReadoutGeometryBase SiDigitization
HGTD_Identifier HGTD_ReadoutGeometry GeneratorObjects GaudiKernel
InDetSimData InDetSimEvent AthenaKernel)
atlas_install_headers( HGTD_Digitization )
/**
* Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration.
*
* @file HGTD_Digitization/HGTD_DigitizationTool.h
*
* @author Tao Wang <tao.wang@cern.ch>
* @author Alexander Leopold <alexander.leopold@cern.ch>
*
* @date August, 2021
*
* @brief
*
* TODO:
* - FIXME: For Rel22: change IAtRndmGenSvc to IAthRNGSvc!!!
*
* - the time window set in the digitization has an impact on the luminosity
* studies and should be agreed on with the relevant subgroups!
* - there is no addition of random hits due to noise yet, once this is added
* simulateNoisePerDetectorElement can be implemented
*/
#ifndef HGTD_DIGITZATION_HGTD_DIGITZATIONTOOL_H
#define HGTD_DIGITZATION_HGTD_DIGITZATIONTOOL_H
#include "PileUpTools/PileUpToolBase.h"
#include "AthenaKernel/IAtRndmGenSvc.h"
// #include "HGTD_Digitization/IHGTD_SurfaceChargesGenerator.h"
#include "HGTD_RawData/HGTD_RDOCollection.h"
#include "HGTD_RawData/HGTD_RDOContainer.h"
#include "HitManagement/TimedHitCollection.h"
#include "InDetSimEvent/SiHitCollection.h"
#include <memory>
#include <string>
class HGTD_ID;
class HGTD_DetectorManager;
class SiChargedDiodeCollection;
class InDetSimDataCollection;
class IFrontEnd;
class ISiChargedDiodesProcessorTool;
namespace CLHEP {
class HepRandomEngine;
}
static const InterfaceID IID_IHGTD_DigitizationTool("HGTD_DigitizationTool", 1,
0);
class HGTD_DigitizationTool : virtual public IPileUpTool,
public PileUpToolBase {
public:
static const InterfaceID& interfaceID();
HGTD_DigitizationTool(const std::string& type, const std::string& name,
const IInterface* parent);
//////////////////////////////////////////////////////////////////////////////
/*** Methods completing the IPileUpTool interfaces ***/
virtual StatusCode initialize() override final;
virtual StatusCode processAllSubEvents() override final;
virtual StatusCode prepareEvent(unsigned int) override final;
virtual StatusCode
processBunchXing(int bunch_xing, SubEventIterator sub_event_itr,
SubEventIterator sub_event_itr_end) override final;
virtual StatusCode mergeEvent() override final;
//////////////////////////////////////////////////////////////////////////////
private:
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// WORKHORSES //////////////////////////////
/** @brief Retrieve the SiHit collection and place it in a TimedHitCollection.
*/
StatusCode retrieveHitCollection();
StatusCode digitizeHitsPerDetectorElement();
/** @brief FIXME: will be implemented once we know how much noise we expect.
*
*/
// StatusCode simulateNoisePerDetectorElement();
/** @brief Step by step processor tools applied on diodes.
* These should simulate: Preamplifier -> Discriminator -> TDC.
* Is called within digitizeHitsPerDetectorElement.
*
* Used tools: FrontEndTool, which calls the Amplifier inside
*/
void applyProcessorTools(SiChargedDiodeCollection*);
std::unique_ptr<HGTD::HGTD_RDOCollection>
createRDOCollection(SiChargedDiodeCollection*);
StatusCode storeRDOCollection(std::unique_ptr<HGTD::HGTD_RDOCollection>);
// inserts the created SDO elements into the m_sdo_collection object.
void createAndStoreSDO(SiChargedDiodeCollection* collection);
//////////////////////////////////////////////////////////////////////////////
ServiceHandle<PileUpMergeSvc> m_merge_svc;
const HGTD_ID* m_id_helper;
const HGTD_DetectorManager* m_det_mgr;
HGTD::HGTD_RDOContainer* m_hgtd_rdo_container;
InDetSimDataCollection* m_sdo_collection;
std::string m_output_sdo_coll_name;
/** @brief In order to process all element rather than just those with hits we
* create a vector to keep track of which elements have been processed.
* This is useful for adding random noise (?!)
* NB. an element is an hgtd module */
std::vector<bool> m_processed_elements;
/** @brief Name of the sub event SiHit collection. */
std::string m_input_collection_name;
// NB: even though it is a flat collection, it acts more like a container,
// since the actual collections can be retrieved one by one with the
// nextDetectorElement method.
std::unique_ptr<TimedHitCollection<SiHit>> m_timed_hit_coll;
// FIXME is this meant as a "keapalive" vector?
std::vector<SiHitCollection*> m_hit_coll_ptrs;
/** @brief This collection stores the energy deposits in their
* digitized form, all the tools are run over it. */
// TODO: maybe this can be a local member??
// std::unique_ptr<SiChargedDiodeCollection> m_charged_diodes;
/** @brief Only SiHits within the defined time window are processed in the
* digitization procedure, the rest is discarded. Given in ns.*/
float m_active_time_window;
ServiceHandle<IAtRndmGenSvc> m_rndm_svc;
CLHEP::HepRandomEngine* m_rndm_engine;
// ToolHandle<IHGTD_SurfaceChargesGenerator> m_hgtd_surf_charge_gen;
ToolHandle<IFrontEnd> m_hgtd_front_end_tool;
std::list<ISiChargedDiodesProcessorTool*> m_diode_processor_tools;
};
inline const InterfaceID& HGTD_DigitizationTool::interfaceID() {
return IID_IHGTD_DigitizationTool;
}
#endif // HGTD_DIGITZATION_HGTD_DIGITZATIONTOOL_H
/**
* Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration.
*
* @file HGTD_Digitization/src/HGTD_DigitizationTool.cxx
*
* @author Tao Wang <tao.wang@cern.ch>
* @author Alexander Leopold <alexander.leopold@cern.ch>
*
* @date August, 2021
*
* @brief
*/
#include "HGTD_Digitization/HGTD_DigitizationTool.h"
#include "HGTD_Identifier/HGTD_ID.h"
#include "HGTD_ReadoutGeometry/HGTD_DetectorManager.h"
#include "InDetSimData/InDetSimDataCollection.h"
#include "InDetSimEvent/SiHit.h"
#include "PileUpTools/PileUpMergeSvc.h"
#include "PileUpTools/PileUpTypeHelper.h"
#include "SiDigitization/IFrontEnd.h"
#include "SiDigitization/ISiChargedDiodesProcessorTool.h"
#include "SiDigitization/SiChargedDiodeCollection.h"
static constexpr unsigned int
crazyParticleBarcode(std::numeric_limits<int32_t>::max());
HGTD_DigitizationTool::HGTD_DigitizationTool(const std::string& type,
const std::string& name,
const IInterface* parent)
: PileUpToolBase(type, name, parent),
m_merge_svc("PileUpMergeSvc", name),
m_id_helper(nullptr),
m_det_mgr(nullptr),
m_hgtd_rdo_container(nullptr),
m_sdo_collection(nullptr),
m_output_sdo_coll_name("HGTD_SDO_Map"),
m_input_collection_name("HGTD_Hits"),
m_timed_hit_coll(nullptr),
m_active_time_window(10000),
m_rndm_svc("AtRndmGenSvc", name),
m_rndm_engine(nullptr),
// m_hgtd_surf_charge_gen("HGTD_SurfaceChargesGenerator", this),
m_hgtd_front_end_tool("HGTD_FrontEndTool", this) {
declareProperty("MergeSvc", m_merge_svc,
"Merge service used in Pixel & HGTD digitization");
declareProperty("InputCollecionName", m_input_collection_name = "HGTD_Hits",
"Name of the collection that is digitized");
declareProperty("ActiveTimeWindow", m_active_time_window = 10000,
"Hits within this time window are used for digitization");
declareProperty("RndmSvc", m_rndm_svc,
"Random Number Service used in HGTD & Pixel digitization");
// declareProperty("HGTD_SurfaceChargesGenerator", m_hgtd_surf_charge_gen,
// "Choice of using a more detailed charge drift model");
declareProperty("HGTD_FrontEndTool", m_hgtd_front_end_tool,
"Tool for pulse shape simulation");
declareProperty("OutputSDOName", m_output_sdo_coll_name = "HGTD_SDO_Map",
"Output SDO container name");
}
StatusCode HGTD_DigitizationTool::initialize() {
ATH_CHECK(detStore()->retrieve(m_id_helper, "HGTD_ID"));
ATH_CHECK(detStore()->retrieve(m_det_mgr, "HGTD"));
ATH_CHECK(m_merge_svc.retrieve());
ATH_CHECK(m_rndm_svc.retrieve());
m_rndm_engine = m_rndm_svc->GetEngine("HGTD_Digitization");
// ATH_CHECK(m_hgtd_surf_charge_gen.retrieve());
// m_hgtd_surf_charge_gen->setRandomEngine(m_rndm_engine);
ATH_CHECK(m_hgtd_front_end_tool.retrieve());
m_hgtd_front_end_tool->setRandomEngine(m_rndm_engine);
// add the front end to the set of tools used for diode processing
m_diode_processor_tools.push_back(&(*m_hgtd_front_end_tool));
return StatusCode::SUCCESS;
}
StatusCode HGTD_DigitizationTool::processAllSubEvents() {
ATH_MSG_DEBUG("processAllSubEvents");
if (prepareEvent(0).isFailure()) {
return StatusCode::FAILURE;
}
ATH_MSG_DEBUG("Begin digitizeAllHits");
if (retrieveHitCollection().isSuccess()) {
ATH_CHECK(digitizeHitsPerDetectorElement());
} else {
ATH_MSG_DEBUG("retrieveHitCollection found no hits");
}
// FIXME: needs to be added once noise/selftriggering has to go in
// ATH_CHECK(simulateNoisePerDetectorElement());
ATH_MSG_DEBUG("processAllSubEvents successful!");
return StatusCode::SUCCESS;
}
StatusCode
HGTD_DigitizationTool::processBunchXing(int bunch_xing,
SubEventIterator sub_event_itr,
SubEventIterator sub_event_itr_end) {
ATH_MSG_DEBUG("HGTD_DigitizationTool::processBunchXing " << bunch_xing);
SubEventIterator loc_sub_event_itr = sub_event_itr;
for (; loc_sub_event_itr != sub_event_itr_end; loc_sub_event_itr++) {
StoreGateSvc& store_gate_svc = *loc_sub_event_itr->ptr()->evtStore();
ATH_MSG_DEBUG("SubEvt StoreGate "
<< store_gate_svc.name() << " :"
<< " bunch crossing : " << bunch_xing << " time offset : "
<< loc_sub_event_itr->time() << " event number : "
<< loc_sub_event_itr->ptr()->eventNumber()
<< " run number : " << loc_sub_event_itr->ptr()->runNumber());
const SiHitCollection* hit_coll(nullptr);
if (store_gate_svc.retrieve(hit_coll, m_input_collection_name)
.isFailure()) {
ATH_MSG_ERROR("SubEvent HGTD SiHitCollection not found in StoreGate "
<< store_gate_svc.name());
return StatusCode::FAILURE;
}
ATH_MSG_DEBUG("SiHitCollection found with " << hit_coll->size() << " hits");
PileUpTimeEventIndex time_idx(loc_sub_event_itr->time(),
loc_sub_event_itr->index(),
pileupTypeMapper(loc_sub_event_itr->type()));
// FIXME do I really need this?
SiHitCollection* hit_coll_cpy = new SiHitCollection(*hit_coll);
m_timed_hit_coll->insert(time_idx, hit_coll_cpy);
m_hit_coll_ptrs.push_back(hit_coll_cpy);
}
return StatusCode::SUCCESS;
}
StatusCode HGTD_DigitizationTool::mergeEvent() {
ATH_MSG_VERBOSE("HGTD_DigitizationTool::mergeEvent()");
ATH_CHECK(digitizeHitsPerDetectorElement());
// FIXME: needs to be added once noise/selftriggering has to go in
// ATH_CHECK(simulateNoisePerDetectorElement());
for (std::vector<SiHitCollection*>::iterator it = m_hit_coll_ptrs.begin();
it != m_hit_coll_ptrs.end(); it++) {
(*it)->Clear();
delete (*it);
}
m_hit_coll_ptrs.clear();
ATH_MSG_DEBUG("Digitize success!");
return StatusCode::SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
StatusCode HGTD_DigitizationTool::prepareEvent(unsigned int /*index*/) {
ATH_MSG_DEBUG("HGTD_DigitizationTool::prepareEvent()");
// Create the IdentifiableContainer to contain the digit collections Create
// a new RDO container
m_hgtd_rdo_container =
new HGTD::HGTD_RDOContainer(m_id_helper->wafer_hash_max());
// register RDO container with storegate
ATH_CHECK(evtStore()->record(m_hgtd_rdo_container, "HGTD_RDOs"));
// Create a map for the SDO and register it into StoreGate
m_sdo_collection = new InDetSimDataCollection();
ATH_CHECK(evtStore()->record(m_sdo_collection, m_output_sdo_coll_name));
m_processed_elements.clear(); // FIXME not sure I need this vector??
m_processed_elements.resize(m_id_helper->wafer_hash_max(), false);
m_timed_hit_coll = std::make_unique<TimedHitCollection<SiHit>>();
return StatusCode::SUCCESS;
}
StatusCode HGTD_DigitizationTool::retrieveHitCollection() {
ATH_MSG_DEBUG("HGTD_DigitizationTool::retrieveHitCollection()");
using TimedHitCollList_t = PileUpMergeSvc::TimedList<SiHitCollection>::type;
TimedHitCollList_t timed_hit_coll_list;
unsigned int n_si_hits(0);
if (m_merge_svc
->retrieveSubEvtsData(m_input_collection_name, timed_hit_coll_list,
n_si_hits)
.isFailure() and
timed_hit_coll_list.size() == 0) { // FIXME is the size check relevant??
ATH_MSG_ERROR("Could not fill TimedHitCollList_t");
return StatusCode::FAILURE;
} else {
ATH_MSG_DEBUG(" SiHitCollections with key "
<< m_input_collection_name << " of size "
<< timed_hit_coll_list.size() << " found");
}
// create a new hits collection
m_timed_hit_coll = std::make_unique<TimedHitCollection<SiHit>>(n_si_hits);
// now merge all collections into one
TimedHitCollList_t::iterator coll_itr(timed_hit_coll_list.begin());
TimedHitCollList_t::iterator coll_itr_end(timed_hit_coll_list.end());
while (coll_itr != coll_itr_end) {
// FIXME removed m_HardScatterSplittingMode and
// m_HardScatterSplittingSkipper until we have confirmed we need this
const SiHitCollection* collection(coll_itr->second);
m_timed_hit_coll->insert(coll_itr->first, collection);
ATH_MSG_DEBUG("SiTrackerHitCollection found with"
<< collection->size()
<< " hits"); // loop on the hit collections
++coll_itr;
}
return StatusCode::SUCCESS;
}
StatusCode HGTD_DigitizationTool::digitizeHitsPerDetectorElement() {
ATH_MSG_DEBUG("HGTD_DigitizationTool::digitizeHitsPerDetectorElement");
// the iterators mark the start and end of si hits that belong to one
// collection which means that they were found on the same detector element
// (module)
TimedHitCollection<SiHit>::const_iterator coll_itr;
TimedHitCollection<SiHit>::const_iterator coll_itr_end;
// the nextDetectorElement method sets the iterators to a range belonging to
// one module, so we iterate over modules (detector elements) in the while
// loop
while (m_timed_hit_coll->nextDetectorElement(coll_itr, coll_itr_end)) {
const TimedHitPtr<SiHit>& fist_hit = *coll_itr;
Identifier id = m_id_helper->wafer_id(
fist_hit->getBarrelEndcap(), fist_hit->getLayerDisk(),
fist_hit->getPhiModule(), fist_hit->getEtaModule());
// get the det element from the manager
HGTD_DetectorElement* det_elem = m_det_mgr->getDetectorElement(id);
// FIXME check for null??
// create a diode collection holding the digitized hits
// FIXME (init once outside the while loop and use clear and set det elem??)
std::unique_ptr<SiChargedDiodeCollection> charged_diode_coll =
std::make_unique<SiChargedDiodeCollection>(det_elem);
// charged_diode_coll->setDetectorElement(det_elem);
// set the current detector element for the charge generator
// m_hgtd_surf_charge_gen->setDetectorElement(det_elem);
///////////////// LOOP TO FILL A COLLECTION /////////////////
// Loop over the hits on the selected detector element and created charged
// diodes
for (; coll_itr != coll_itr_end; coll_itr++) {
const TimedHitPtr<SiHit>& current_hit = *coll_itr;
// skip hits that are far away in time
if (std::abs(current_hit->meanTime()) >
m_active_time_window * CLHEP::ns) {
continue;
}
// use the surface charge generator to produce the charged diode
// and add it to the charged diode collection
// m_hgtd_surf_charge_gen->createSurfaceChargesFromHit(
// current_hit, charged_diode_coll.get());
} // END LOOP over hits
////////////////////////////////////////////////////////////////
// now that the charges have been built, apply all digitization tools
applyProcessorTools(charged_diode_coll.get());
// TODO: at this point, the RDOs and SDOs need to be created!!!
std::unique_ptr<HGTD::HGTD_RDOCollection> rdo_collection =
createRDOCollection(charged_diode_coll.get());
ATH_CHECK(storeRDOCollection(std::move(rdo_collection)));
createAndStoreSDO(charged_diode_coll.get());
// done with this detector element
// charged_diode_coll->clear(); //might be needed when moving ptr out
ATH_MSG_DEBUG("charges filled for module " << id);
} // END LOOP over detector elements
return StatusCode::SUCCESS;
}
void HGTD_DigitizationTool::applyProcessorTools(
SiChargedDiodeCollection* charged_diodes) {
ATH_MSG_DEBUG("applyProcessorTools()");
int processorNumber = 0;
std::list<ISiChargedDiodesProcessorTool*>::iterator provessor_itr =
m_diode_processor_tools.begin();
for (; provessor_itr != m_diode_processor_tools.end(); ++provessor_itr) {
(*provessor_itr)->process(*charged_diodes);
processorNumber++;
ATH_MSG_DEBUG("Applied processor # " << processorNumber);
}
return;
}
StatusCode HGTD_DigitizationTool::storeRDOCollection(
std::unique_ptr<HGTD::HGTD_RDOCollection> coll) {
// Create the RDO collection
if (m_hgtd_rdo_container
->addCollection(coll.release(), coll->identifierHash())
.isFailure()) {
ATH_MSG_FATAL("HGTD RDO collection could not be added to container!");
return StatusCode::FAILURE;
}
return StatusCode::SUCCESS;
}
std::unique_ptr<HGTD::HGTD_RDOCollection>
HGTD_DigitizationTool::createRDOCollection(
SiChargedDiodeCollection* charged_diodes) {
IdentifierHash idHash_de = charged_diodes->identifyHash();
std::unique_ptr<HGTD::HGTD_RDOCollection> rdo_collection =
std::make_unique<HGTD::HGTD_RDOCollection>(idHash_de);
// need the DE identifier
const Identifier id_de = charged_diodes->identify();
rdo_collection->setIdentifier(id_de);
SiChargedDiodeIterator i_chargedDiode = charged_diodes->begin();
SiChargedDiodeIterator i_chargedDiode_end = charged_diodes->end();
for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
InDetDD::SiReadoutCellId readout_cell =
(*i_chargedDiode).second.getReadoutCell();
int eta_index = readout_cell.etaIndex();
int phi_index = readout_cell.phiIndex();
const Identifier id_readout =
m_id_helper->pixel_id(charged_diodes->identify(), eta_index, phi_index);
SiChargedDiode& diode = (*i_chargedDiode).second;
const SiTotalCharge& charge = diode.totalCharge();
// this is the time of the main charge. For now this might be OK as long as
// the toal deposit just gets transformed into "one charge", but will need a
// change in the future!!
float toa = charge.time();
int dummy_tot = 256;
int dummy_bcid = 0;
int dummy_l1a = 0;
int dummy_l1id = 0;
std::unique_ptr<HGTD::HGTD_RDO> p_rdo = std::make_unique<HGTD::HGTD_RDO>(
id_readout, toa, dummy_tot, dummy_bcid, dummy_l1a, dummy_l1id);
rdo_collection->push_back(p_rdo.release());
}
return rdo_collection;
}
void HGTD_DigitizationTool::createAndStoreSDO(
SiChargedDiodeCollection* charged_diodes) {
using list_t = SiTotalCharge::list_t;
std::vector<InDetSimData::D