Commit 7641c90d authored by Tadej Novak's avatar Tadej Novak
Browse files

Merge branch 'hgtd_charge_and_frontend_21p9' into '21.9'

HGTD Digi: SurfaceChargeGenerator and FrontEndTool

See merge request !46475
parents 848bcf7a 3ec2a619
......@@ -17,6 +17,6 @@ atlas_add_component( HGTD_Digitization
LINK_LIBRARIES ${CLHEP_LIBRARIES} PileUpToolsLib HGTD_RawData
HitManagement AthenaBaseComps ReadoutGeometryBase SiDigitization
HGTD_Identifier HGTD_ReadoutGeometry GeneratorObjects GaudiKernel
InDetSimData InDetSimEvent AthenaKernel)
InDetSimData InDetSimEvent AthenaKernel AtlasCLHEP_RandomGenerators)
atlas_install_headers( HGTD_Digitization )
......@@ -25,7 +25,7 @@
#include "PileUpTools/PileUpToolBase.h"
#include "AthenaKernel/IAtRndmGenSvc.h"
// #include "HGTD_Digitization/IHGTD_SurfaceChargesGenerator.h"
#include "HGTD_Digitization/IHGTD_SurfaceChargesGenerator.h"
#include "HGTD_RawData/HGTD_RDOCollection.h"
#include "HGTD_RawData/HGTD_RDOContainer.h"
#include "HitManagement/TimedHitCollection.h"
......@@ -52,7 +52,7 @@ 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);
......@@ -132,11 +132,6 @@ private:
// 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;
......@@ -145,7 +140,7 @@ private:
CLHEP::HepRandomEngine* m_rndm_engine;
// ToolHandle<IHGTD_SurfaceChargesGenerator> m_hgtd_surf_charge_gen;
ToolHandle<IHGTD_SurfaceChargesGenerator> m_hgtd_surf_charge_gen;
ToolHandle<IFrontEnd> m_hgtd_front_end_tool;
......
/**
* Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration.
*
* @file HGTD_Digitization/HGTD_FrontEndTool.h
*
* @author Tao Wang <tao.wang@cern.ch>
*
* @date September, 2021
*
* @brief Simulation of the HGTD front-end electronics
*
* TODO: this class doesn't do anything yet, Tao will add the pulse shape!
*/
#ifndef HGTD_DIGITIZATION_HGTD_FRONTEND_H
#define HGTD_DIGITIZATION_HGTD_FRONTEND_H
#include "AthenaBaseComps/AthAlgTool.h"
#include "SiDigitization/IFrontEnd.h"
#include "GaudiKernel/ToolHandle.h"
#include "SiDigitization/SiChargedDiodeCollection.h"
class HGTD_FrontEndTool : public AthAlgTool, virtual public IFrontEnd {
public:
/** constructor */
HGTD_FrontEndTool(const std::string& type, const std::string& name,
const IInterface* parent);
/** Destructor */
virtual ~HGTD_FrontEndTool() {}
void process(SiChargedDiodeCollection& collection) const;
inline void setRandomEngine(CLHEP::HepRandomEngine* rndm_engine) {
m_rndm_engine = rndm_engine;
}
private:
CLHEP::HepRandomEngine* m_rndm_engine;
};
#endif
/**
* Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration.
*
* @file HGTD_Digitization/HGTD_SurfaceChargesGenerator.h
*
* @author Tao Wang <tao.wang@cern.ch>
* @author Alexander Leopold <alexander.leopold@cern.ch>
*
* @date September, 2021
*
* @brief Deposited energy stored in SiHits gets transformed into charges
* created in the active material.
*
* FIXME:
* - for the estimation of the deposited charge, the total energy loss is
* dividied by the mean ionization energy in Silicon. This should be refined, in
* ITk specific tools are used for this!
*/
#ifndef HGTD_SURFACECHARGESGENERATOR_H
#define HGTD_SURFACECHARGESGENERATOR_H
#include "AthenaBaseComps/AthAlgTool.h"
#include "HGTD_Digitization/IHGTD_SurfaceChargesGenerator.h"
#include <string>
class HGTD_SurfaceChargesGenerator
: public AthAlgTool,
public virtual IHGTD_SurfaceChargesGenerator {
public:
/** constructor */
HGTD_SurfaceChargesGenerator(const std::string& type, const std::string& name,
const IInterface* parent);
/** Destructor */
virtual ~HGTD_SurfaceChargesGenerator() = default;
/** AlgTool initialize */
StatusCode initialize() override;
virtual void createSurfaceChargesFromHit(
const TimedHitPtr<SiHit>& timed_hit_ptr,
SiChargedDiodeCollection* diode_coll,
const InDetDD::SolidStateDetectorElementBase* element,
CLHEP::HepRandomEngine* rndm_engine) const override;
private:
// TODO: where do we get this from?
FloatProperty m_small_step_length; /*um*/
float m_diffusion_constant;
// TODO what does the BooleanProperty allow to do?
BooleanProperty m_needs_mc_evt_coll_helper{false};
};
#endif // HGTD_DIGITZATION_HGTD_SURFACECHARGESGENERATOR_H
/**
* Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration.
*
* @file HGTD_Digitization/IHGTD_SurfaceChargesGenerator.h
*
* @author Tao Wang <tao.wang@cern.ch>
* @author Alexander Leopold <alexander.leopold@cern.ch>
*
* @date September, 2021
*
* @brief Interface for the Surface charge generation tool.
*
* TODO: - Methods used in InDet like
*
* virtual void setComTime(float comTime) = 0;
* virtual void setFixedTime(float fixedTime) = 0;
* virtual void setCosmicsRun(bool cosmicsRun) = 0;
* virtual void setComTimeFlag(bool useComTime) = 0;
*
* might be needed in the future!
*
*/
#ifndef HGTD_DIGITZATION_IHGTD_SURFACECHARGESGENERATOR_H
#define HGTD_DIGITZATION_IHGTD_SURFACECHARGESGENERATOR_H
#include "GaudiKernel/IAlgTool.h"
#include "HitManagement/TimedHitPtr.h"
#include "InDetSimEvent/SiHit.h"
#include "SiDigitization/SiChargedDiodeCollection.h"
#include "SiDigitization/SiSurfaceCharge.h"
namespace InDetDD {
class SolidStateDetectorElementBase;
}
namespace CLHEP {
class HepRandomEngine;
}
class IHGTD_SurfaceChargesGenerator : virtual public IAlgTool {
public:
// Destructor:
virtual ~IHGTD_SurfaceChargesGenerator() {}
virtual void
createSurfaceChargesFromHit(const TimedHitPtr<SiHit>& hit,
SiChargedDiodeCollection* diode_coll,
const InDetDD::SolidStateDetectorElementBase* ele,
CLHEP::HepRandomEngine* rndmEngine) const = 0;
// Creates the InterfaceID and interfaceID() method
DeclareInterfaceID(IHGTD_SurfaceChargesGenerator, 1, 0);
};
#endif // HGTD_DIGITZATION_IHGTD_SURFACECHARGESGENERATOR_H
......@@ -41,7 +41,7 @@ HGTD_DigitizationTool::HGTD_DigitizationTool(const std::string& type,
m_active_time_window(10000),
m_rndm_svc("AtRndmGenSvc", name),
m_rndm_engine(nullptr),
// m_hgtd_surf_charge_gen("HGTD_SurfaceChargesGenerator", this),
m_hgtd_surf_charge_gen("HGTD_SurfaceChargesGenerator", this),
m_hgtd_front_end_tool("HGTD_FrontEndTool", this) {
declareProperty("MergeSvc", m_merge_svc,
......@@ -52,8 +52,8 @@ HGTD_DigitizationTool::HGTD_DigitizationTool(const std::string& type,
"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_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",
......@@ -72,8 +72,7 @@ StatusCode HGTD_DigitizationTool::initialize() {
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_surf_charge_gen.retrieve());
ATH_CHECK(m_hgtd_front_end_tool.retrieve());
m_hgtd_front_end_tool->setRandomEngine(m_rndm_engine);
......@@ -230,9 +229,8 @@ StatusCode HGTD_DigitizationTool::retrieveHitCollection() {
m_timed_hit_coll->insert(coll_itr->first, collection);
ATH_MSG_DEBUG("SiTrackerHitCollection found with"
<< collection->size()
<< " hits"); // loop on the hit collections
ATH_MSG_DEBUG("SiTrackerHitCollection found with" << collection->size()
<< " hits");
++coll_itr;
}
return StatusCode::SUCCESS;
......@@ -265,10 +263,6 @@ StatusCode HGTD_DigitizationTool::digitizeHitsPerDetectorElement() {
// 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
......@@ -285,14 +279,14 @@ StatusCode HGTD_DigitizationTool::digitizeHitsPerDetectorElement() {
// 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());
m_hgtd_surf_charge_gen->createSurfaceChargesFromHit(
current_hit, charged_diode_coll.get(), det_elem, m_rndm_engine);
} // 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!!!
// at this point, the RDOs and SDOs need to be created!!!
std::unique_ptr<HGTD::HGTD_RDOCollection> rdo_collection =
createRDOCollection(charged_diode_coll.get());
......@@ -300,8 +294,6 @@ StatusCode HGTD_DigitizationTool::digitizeHitsPerDetectorElement() {
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
......@@ -446,13 +438,12 @@ void HGTD_DigitizationTool::createAndStoreSDO(
// if the charge has already hit the Diode add it to the deposit
if (theDeposit != depositsR_end) {
// (*theDeposit).second += charge_list_itr->charge();
(*theDeposit).second += charge_list_itr->time();
} else { // create a new deposit
InDetSimData::Deposit deposit(trkLink, charge_list_itr->charge());
deposits.push_back(deposit);
}
} //END LOOP charges within diode
} // END LOOP charges within diode
// add the simdata object to the map if the deposit originated from a
// particle to which the truth information was kept. Can be HS and PU.
......@@ -466,5 +457,5 @@ void HGTD_DigitizationTool::createAndStoreSDO(
m_sdo_collection->insert(std::make_pair(
id_readout, InDetSimData(deposits, (*i_chargedDiode).second.flag())));
}
} //END LOOP charged diodes
} // END LOOP charged diodes
}
/**
* Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration.
*
* @file HGTD_Digitization/src/HGTD_FrontEndTool.cxx
*
* @author Tao Wang <tao.wang@cern.ch>
*
* @date September, 2021
*/
#include "HGTD_Digitization/HGTD_FrontEndTool.h"
#include "AthenaKernel/IAtRndmGenSvc.h"
#include "CLHEP/Random/RandFlat.h"
#include "CLHEP/Random/RandGaussZiggurat.h"
#include "CLHEP/Random/RandPoisson.h"
#include <algorithm>
#include <iostream>
HGTD_FrontEndTool::HGTD_FrontEndTool(const std::string& type,
const std::string& name,
const IInterface* parent)
: AthAlgTool(type, name, parent), m_rndm_engine(nullptr) {
declareInterface<IFrontEnd>(this);
}
void HGTD_FrontEndTool::process(
SiChargedDiodeCollection& /*collection*/) const {
// FIXME only commented out for now, Tao will use this when adding his code
// if (collection.empty()) {
// ATH_MSG_DEBUG(
// "HGTD_FrontEndTool::process() Empty Charged Diode Collection");
// return;
// }
// for each of the charged diodes, set the time after creating the time pulse
// SiChargedDiodeIterator i_chargedDiode = collection.begin();
// SiChargedDiodeIterator i_chargedDiode_end = collection.end();
// for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
// SiChargedDiode& diode = (*i_chargedDiode).second;
// check if the charge is above threshold
// I cut on minimal eloss in active region, using a value agreed on by HGTD
// Sensor as well as ASIC group
// generate the pulse
// apply the discriminator
// set the new time
// }
}
/**
* Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration.
*
* @file HGTD_Digitization/HGTD_SurfaceChargesGenerator.h
*
* @author Tao Wang <tao.wang@cern.ch>
* @author Alexander Leopold <alexander.leopold@cern.ch>
*
* @date September, 2021
*
* @brief
*
*/
#include "HGTD_Digitization/HGTD_SurfaceChargesGenerator.h"
#include "AtlasCLHEP_RandomGenerators/RandGaussZiggurat.h"
#include "CLHEP/Random/RandomEngine.h"
#include "CLHEP/Units/SystemOfUnits.h"
#include "GeneratorObjects/HepMcParticleLink.h"
#include "GeneratorObjects/McEventCollectionHelper.h"
#include "ReadoutGeometryBase/DetectorDesign.h"
#include "ReadoutGeometryBase/SiLocalPosition.h"
#include "ReadoutGeometryBase/SolidStateDetectorElementBase.h"
#include "SiDigitization/SiChargedDiodeCollection.h"
HGTD_SurfaceChargesGenerator::HGTD_SurfaceChargesGenerator(
const std::string& type, const std::string& name, const IInterface* parent)
: AthAlgTool(type, name, parent),
m_small_step_length(1),
m_diffusion_constant(.007),
m_needs_mc_evt_coll_helper(false) {
declareProperty("SmallStepLength", m_small_step_length = 1);
declareProperty("DiffusionConstant", m_diffusion_constant);
declareProperty("UseMcEventCollectionHelper",
m_needs_mc_evt_coll_helper = false);
}
StatusCode HGTD_SurfaceChargesGenerator::initialize() {
ATH_MSG_DEBUG("HGTD_SurfaceChargesGenerator::initialize()");
m_small_step_length.setValue(m_small_step_length.value() * CLHEP::micrometer);
return StatusCode::SUCCESS;
}
void HGTD_SurfaceChargesGenerator::createSurfaceChargesFromHit(
const TimedHitPtr<SiHit>& timed_hit_ptr,
SiChargedDiodeCollection* diode_coll,
const InDetDD::SolidStateDetectorElementBase* element,
CLHEP::HepRandomEngine* rndm_engine) const {
const SiHit& hit = *timed_hit_ptr;
// check the status of truth information for this SiHit
// some Truth information is cut for pile up events
HepMcParticleLink trklink(hit.particleLink());
if (m_needs_mc_evt_coll_helper) {
trklink.setEventCollection(
McEventCollectionHelper::getMcEventCollectionHMPLEnumFromPileUpType(
timed_hit_ptr.pileupType(), &msg()));
}
SiCharge::Process hitproc(SiCharge::track);
if (hit.trackNumber() != 0) {
if (not trklink.isValid()) {
hitproc = SiCharge::cut_track;
}
}
double sensor_thickness = element->design().thickness();
int readout_side = element->design().readoutSide();
double pixel_size_x = element->design().phiPitch();
double pixel_size_y = element->design().etaPitch();
const CLHEP::Hep3Vector start_pos(hit.localStartPosition());
const CLHEP::Hep3Vector end_pos(hit.localEndPosition());
CLHEP::Hep3Vector direction = end_pos - start_pos;
double deposit_length = direction.mag();
int n_steps = deposit_length / m_small_step_length + 1;
direction.setMag(deposit_length / static_cast<float>(n_steps));
double tot_eloss = hit.energyLoss();
// FIXME using the mean ionization energy in Silicon
const float tot_charge = tot_eloss / (3.62 * CLHEP::eV);
double charge_per_step = tot_charge / static_cast<float>(n_steps);
// FIXME is this correct? does the eventTime include a "later" truth event and
// the meanTime is just the TOF?
float time_of_flight = timed_hit_ptr.eventTime() + hit.meanTime();
// FIXME needed to check for deposits in guardrings. This should be taken over
// by the module design class and not hardcoded here!
float x_offset = 9.75;
float y_offset = 19.5;
for (int i_step = 0; i_step < n_steps; i_step++) {
CLHEP::Hep3Vector surface_pos = start_pos + i_step * direction;
// Distance between charge and readout side. p_design->readoutSide() is
// +1 if readout side is in +ve depth axis direction and visa-versa.
// FIXME ask Noemi about what happens here
double spess =
0.5 * sensor_thickness - readout_side * surface_pos[SiHit::xDep];
if (spess < 0) {
spess = 0; // FIXME this means I am on the surface already?
}
// diffusion sigma
// FIXME where is the 0.3 from?
double rdif = m_diffusion_constant * std::sqrt(spess / 0.3);
// position at the surface, adding smearing
// FIXME currently no Lorentz angle considered, can be studied in the future
double surf_pos_x = surface_pos[SiHit::xEta] +
rdif * CLHEP::RandGaussZiggurat::shoot(rndm_engine);
double surf_pos_y = surface_pos[SiHit::xPhi] +
rdif * CLHEP::RandGaussZiggurat::shoot(rndm_engine);
// if the deposit is outside the guard ring, don't consider it
if (fabs(surf_pos_x) > x_offset or fabs(surf_pos_y) > y_offset) {
continue;
}
// FIXME this should be handled by the module design class in the future
float interpad = 50 * CLHEP::micrometer;
int bin_x = floor(fabs(surf_pos_x + x_offset) / pixel_size_x);
int bin_y = floor(fabs(surf_pos_y + y_offset) / pixel_size_y);
float pos_x_inpixel =
fabs(surf_pos_x + x_offset) - float(bin_x) * pixel_size_x;
float pos_y_inpixel =
fabs(surf_pos_y + y_offset) - float(bin_y) * pixel_size_y;
bool is_interpad_x =
(pos_x_inpixel < interpad or pos_x_inpixel > (pixel_size_x - interpad));
bool is_interpad_y =
(pos_y_inpixel < interpad or pos_y_inpixel > (pixel_size_y - interpad));
// check if the charge is sitting in the interpad region
if (is_interpad_x or is_interpad_y) {
ATH_MSG_DEBUG("INTERPAD DETECTED!!!");
ATH_MSG_DEBUG("surf_pos_x=" << surf_pos_x
<< ", surf_pos_y=" << surf_pos_y);
continue;
}
// charges deposited within the active sensor get added
const InDetDD::SiLocalPosition position(
element->hitLocalToLocal(surf_pos_x, surf_pos_y));
SiSurfaceCharge surface_charge(
position, SiCharge(charge_per_step, time_of_flight, hitproc,
trklink)); // FIXME is this obj even needed?
InDetDD::SiCellId cell_id =
element->cellIdOfPosition(surface_charge.position());
if (cell_id.isValid()) {
// add this charge to the collection (or merge in existing charged
// diode)
diode_coll->add(cell_id, surface_charge.charge());
}
} // END LOOP over steps
}
#include "GaudiKernel/DeclareFactoryEntries.h"
// #include "HGTD_Digitization/HGTD_FrontEndTool.h"
#include "HGTD_Digitization/HGTD_DigitizationTool.h"
// #include "HGTD_Digitization/HGTD_SurfaceChargesGenerator.h"
#include "HGTD_Digitization/HGTD_FrontEndTool.h"
#include "HGTD_Digitization/HGTD_SurfaceChargesGenerator.h"
DECLARE_TOOL_FACTORY(HGTD_DigitizationTool)
// DECLARE_TOOL_FACTORY(HGTD_SurfaceChargesGenerator)
// DECLARE_TOOL_FACTORY(HGTD_FrontEndTool)
DECLARE_TOOL_FACTORY(HGTD_SurfaceChargesGenerator)
DECLARE_TOOL_FACTORY(HGTD_FrontEndTool)
DECLARE_FACTORY_ENTRIES(HGTD_Digitization) {
DECLARE_ALGTOOL(HGTD_DigitizationTool)
// DECLARE_ALGTOOL(HGTD_SurfaceChargesGenerator)
// DECLARE_ALGTOOL(HGTD_FrontEndTool)
DECLARE_ALGTOOL(HGTD_SurfaceChargesGenerator)
DECLARE_ALGTOOL(HGTD_FrontEndTool)
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment