ATLAS Offline Software
Loading...
Searching...
No Matches
HGTD_SmearedDigitizationTool.cxx
Go to the documentation of this file.
1
10
12
14#include "CLHEP/Random/RandGauss.h"
15#include "CLHEP/Random/RandomEngine.h"
19#include "InDetSimEvent/SiHit.h"
22
23#include "TFile.h"
24#include "TTree.h"
25
27 const std::string& type, const std::string& name, const IInterface* parent) :
28 PileUpToolBase(type, name, parent) {
29}
30
32
34
35 ATH_MSG_DEBUG("HGTD_SmearedDigitizationTool::initialize()");
36
37 // Get the HGTD Detector Manager
38 ATH_CHECK(detStore()->retrieve(m_hgtd_det_manager, "HGTD"));
39
40 // Get the HGTD ID helper
41 ATH_CHECK(detStore()->retrieve(m_hgtd_idhelper, "HGTD_ID"));
42
43 // locate the PileUpMergeSvc
44 ATH_CHECK(m_merge_svc.retrieve());
45
46 if (m_write_tree) {
47 ATH_CHECK(m_hist_svc.retrieve());
48 m_output_file = std::make_unique<TFile>("HGTD_SmearedDigiOutput.root", "RECREATE");
49 m_tree = std::make_unique<TTree>("SmearedDigiTree", "SmearedDigiTree");
50 m_tree->Branch("m_x_hit", &m_x_hit);
51 m_tree->Branch("m_y_hit", &m_y_hit);
52 m_tree->Branch("m_x_entry_hit", &m_x_entry_hit);
53 m_tree->Branch("m_y_entry_hit", &m_y_entry_hit);
54 m_tree->Branch("m_z_entry_hit", &m_z_entry_hit);
55 m_tree->Branch("m_x_exit_hit", &m_x_exit_hit);
56 m_tree->Branch("m_y_exit_hit", &m_y_exit_hit);
57 m_tree->Branch("m_z_exit_hit", &m_z_exit_hit);
58 m_tree->Branch("m_x_cluster_global", &m_x_cluster_global);
59 m_tree->Branch("m_y_cluster_global", &m_y_cluster_global);
60 m_tree->Branch("m_z_cluster_global", &m_z_cluster_global);
61 m_tree->Branch("m_x_hit_smeared", &m_x_hit_smeared);
62 m_tree->Branch("m_y_hit_smeared", &m_y_hit_smeared);
63 m_tree->Branch("m_hit_time", &m_hit_time);
64 m_tree->Branch("m_hit_time_smeared", &m_hit_time_smeared);
65 m_tree->Branch("m_err_x_hit", &m_err_x_hit);
66 m_tree->Branch("m_err_y_hit", &m_err_y_hit);
67
68 ATH_CHECK(m_hist_svc->regTree("HGTD_ClusterSmearedDigi", m_tree.get()));
69 }
70
71 return StatusCode::SUCCESS;
72}
73
74// Finalize method:
76
77 ATH_MSG_DEBUG("HGTD_SmearedDigitizationTool::finalize()");
78
79 if (m_write_tree) {
80 m_output_file->cd();
81 m_tree->Write();
82 m_output_file->Close();
83 }
84
85 return StatusCode::SUCCESS;
86}
87
88StatusCode HGTD_SmearedDigitizationTool::processAllSubEvents(const EventContext& ctx) {
89
90 ATH_MSG_DEBUG("[HGTD_SmearedDigitizationTool::processAllSubEvents]");
91
92 auto cluster_container =
93 new ClusterContainer_t(m_hgtd_idhelper->wafer_hash_max());
94
95 cluster_container->cleanup();
96
97 ATH_CHECK(evtStore()->record(cluster_container, m_cluster_name));
98
99 auto timed_hit_collection = setupTimedHitCollection();
100 HGTD_DetElement_RIO_Map_t det_element_rio_map;
102 timed_hit_collection,
103 det_element_rio_map));
104
105 // TODO: also needs an EventContext (is it the equivalent of createAndStoreRIOs in SiSmearedDigitizationTool)?
106 ATH_CHECK(fillClusterContainer (det_element_rio_map,
107 *cluster_container));
108
109 return StatusCode::SUCCESS;
110}
111
112StatusCode
114
116 ATH_CHECK((evtStore()->retrieve(prd_truth_coll, m_prd_truth_coll_name)));
117 } else {
118 prd_truth_coll = new PRD_MultiTruthCollection;
119 ATH_CHECK(evtStore()->record(prd_truth_coll, m_prd_truth_coll_name));
120 }
121
122 return StatusCode::SUCCESS;
123}
124
127 // Define Hit Collection
128 TimedHitCollection<SiHit> timed_hit_coll;
129
130 // get the container(s)
131 typedef PileUpMergeSvc::TimedList<SiHitCollection>::type TimedHitCollList_t;
132
133 // this is a list<pair<time_t, DataLink<SCTUncompressedHitCollection> > >
134 TimedHitCollList_t hit_coll_list;
135 unsigned int num_si_hits(0);
136 if (!(m_merge_svc
137 ->retrieveSubEvtsData(m_si_hit_collection_name.value(), hit_coll_list,
138 num_si_hits)
139 .isSuccess()) and
140 hit_coll_list.empty()) {
141 ATH_MSG_ERROR("Could not fill TimedHitCollList_t");
142 return timed_hit_coll;
143 }
144
145 ATH_MSG_DEBUG(hit_coll_list.size() << " SiHitCollections with key "
146 << m_si_hit_collection_name << " found");
147
148 timed_hit_coll.reserve(num_si_hits);
149
150 // loop on the hit collections
151 for(auto hit_coll : hit_coll_list) {
152 const SiHitCollection* si_collection(hit_coll.second);
153 timed_hit_coll.insert(hit_coll.first, si_collection);
154 ATH_MSG_DEBUG("SiHitCollection found with " << si_collection->size()
155 << " hits");
156 }
157 return timed_hit_coll;
158}
159
160StatusCode
162 TimedHitCollection<SiHit>& timed_hit_collection,
163 HGTD_DetElement_RIO_Map_t& det_element_rio_map)
164{
165 ATH_MSG_DEBUG("--- HGTD_SmearedDigitizationTool: in digitize() ---");
166
167 // Set the RNG to use for this event.
168 ATHRNG::RNGWrapper* rngWrapper = m_rndm_svc->getEngine(this);
169 rngWrapper->setSeed(name(), ctx);
170 CLHEP::HepRandomEngine* rndmEngine = rngWrapper->getEngine(ctx);
171
172 PRD_MultiTruthCollection* prd_truth_coll = nullptr;
173 ATH_CHECK(retrieveTruth(prd_truth_coll));
174
175 // i, e are iterator and end of one detector element
177
178 while (timed_hit_collection.nextDetectorElement(i, e) and i != e) {
179 const TimedHitPtr<SiHit>& hit(*i++);
180
181 // FIXME should I cut on the deposited energy??
182 // n electrons = hit->energyLoss() / electron ionisation energy
183 // n * e * gain > 4fCs
184
185 int endcap = hit->getBarrelEndcap();
186 int layer = hit->getLayerDisk();
187 int phi_module = hit->getPhiModule();
188 int eta_module = hit->getEtaModule();
189
190 ATH_MSG_DEBUG("HGTD DetectorElement --> endcap "
191 << endcap << ", layer_disk " << layer << ", phi_module "
192 << phi_module << ", eta_module " << eta_module);
193
194 const InDetDD::SolidStateDetectorElementBase* curr_det_element =
195 m_hgtd_det_manager->getDetectorElement(endcap, layer, phi_module,
196 eta_module);
197
198 if (!curr_det_element) {
199 ATH_MSG_ERROR("could not get detector element for SolidStateDetector");
200 continue;
201 }
202
203 IdentifierHash wafer_id =
204 m_hgtd_idhelper->wafer_hash(curr_det_element->identify());
205
206 HepGeom::Point3D<double> hit_loc_start_pos = hit->localStartPosition();
207 HepGeom::Point3D<double> hit_loc_end_pos = hit->localEndPosition();
208
209 HepGeom::Point3D<double> hit_glob_start_pos =
210 curr_det_element->hitLocalToLocal3D(hit_loc_start_pos);
211 HepGeom::Point3D<double> hit_glob_end_pos =
212 curr_det_element->hitLocalToLocal3D(hit_loc_end_pos);
213
214 double globa_entry_x = hit_glob_start_pos.x();
215 double globa_entry_y = hit_glob_start_pos.y();
216 m_x_entry_hit = globa_entry_x;
217 m_y_entry_hit = globa_entry_y;
218 m_z_entry_hit = hit_glob_start_pos.z();
219
220 double globa_exit_x = hit_glob_end_pos.x();
221 double globa_exit_y = hit_glob_end_pos.y();
222 m_x_exit_hit = globa_exit_x;
223 m_y_exit_hit = globa_exit_y;
224 m_z_exit_hit = hit_glob_end_pos.z();
225
226 double dist_x = std::abs(std::abs(globa_exit_x) - std::abs(globa_entry_x));
227 double dist_y = std::abs(std::abs(globa_exit_y) - std::abs(globa_entry_y));
228
229 Amg::Vector2D local_entry(globa_entry_x, globa_entry_y);
230 Amg::Vector2D local_exit(globa_exit_x, globa_exit_y);
231
232 // get the identifier of the entry and the exit
233 Identifier entry_id = curr_det_element->identifierOfPosition(local_entry);
234 Identifier exit_id = curr_det_element->identifierOfPosition(local_exit);
235
236 // now get the cellIds and check whether they're valid
237 InDetDD::SiCellId entry_cell_id =
238 curr_det_element->cellIdFromIdentifier(entry_id);
239 InDetDD::SiCellId exit_cell_id =
240 curr_det_element->cellIdFromIdentifier(exit_id);
241
242 ATH_MSG_DEBUG("--- HGTD_SmearedDigitizationTool: entryId "
243 << entry_id << " --- exitId " << exit_id);
244 ATH_MSG_DEBUG("--- HGTD_SmearedDigitizationTool: entryCellId "
245 << entry_cell_id << " --- exitCellId " << exit_cell_id);
246
247 if (not entry_cell_id.isValid() or not exit_cell_id.isValid()) {
248 continue;
249 }
250
251 // the intersecetion id and cellId of it. yes, this is correct
252 double intersection_x = 0.5 * (globa_entry_x + globa_exit_x);
253 double intersection_y = 0.5 * (globa_entry_y + globa_exit_y);
254 m_x_hit = intersection_x;
255 m_y_hit = intersection_y;
256
257 // calculate how many pixels the particle crosses in x and y direction
258 double times_x = floor(dist_x / m_pitch_x);
259 double times_y = floor(dist_y / m_pitch_y);
260
261 double sigma_x = m_pitch_x / std::sqrt(12);
262 double sigma_y = m_pitch_y / std::sqrt(12);
263
264 int element_x = times_x + 1;
265 int element_y = times_y + 1;
266
267 // Smear pixel in x and y direction
268 // FIXME make sure the length width dimensions are correct!!!
270 intersection_x = smearPosition(intersection_x, sigma_x,
271 curr_det_element->width() / 2.,
272 rndmEngine);
273 intersection_y = smearPosition(intersection_y, sigma_y,
274 curr_det_element->length() / 2.,
275 rndmEngine);
276 }
277 m_x_hit_smeared = intersection_x;
278 m_y_hit_smeared = intersection_y;
279
280 Amg::Vector2D intersection(intersection_x, intersection_y);
281
282 Identifier intersection_id =
283 curr_det_element->identifierOfPosition(intersection);
284
285 // the pixel positions and other elements for the geometrical clustering
286 std::vector<Identifier> rdo_list = {intersection_id};
287
288 InDetDD::SiCellId current_cell_id =
289 curr_det_element->cellIdFromIdentifier(intersection_id);
290
291 if (!current_cell_id.isValid()) {
292 continue;
293 }
294
295 double length_x = element_x * m_pitch_x;
296 double length_y = element_y * m_pitch_y;
297
298 InDet::SiWidth si_width(Amg::Vector2D(element_x, element_y),
299 Amg::Vector2D(length_x, length_y));
300
301 AmgSymMatrix(2) covariance;
302 covariance.setIdentity();
303 covariance(Trk::locX, Trk::locX) = sigma_x * sigma_x;
304 covariance(Trk::locY, Trk::locY) = sigma_y * sigma_y;
305 Amg::MatrixX cluster_err = Amg::MatrixX(covariance);
306
307 float hit_time = hit->meanTime();
308 m_hit_time = hit_time;
309 if (m_smear_mean_time) {
310 hit_time = smearMeanTime(hit_time, m_time_res, rndmEngine);
311 }
312 m_hit_time_smeared = hit_time;
313
314 std::vector<int> tot_vec = {0}; // dummy, not used in reco currently
315
316 Cluster_t* cluster = new Cluster_t(intersection_id, intersection, std::move(rdo_list),
317 si_width, curr_det_element, std::move(cluster_err),
318 hit_time, m_time_res, std::move(tot_vec));
319
320 m_x_cluster_global = (cluster->globalPosition()).x();
321 m_y_cluster_global = (cluster->globalPosition()).y();
322 m_z_cluster_global = (cluster->globalPosition()).z();
325
326 if (m_write_tree) {
327 m_tree->Fill();
328 }
329
330 det_element_rio_map.insert(
331 std::pair<IdentifierHash, const Cluster_t*>(wafer_id, cluster));
332
333 ATH_CHECK(fillMultiTruthCollection(prd_truth_coll, cluster, hit, ctx));
334
335 } // END while
336 return StatusCode::SUCCESS;
337}
338
340 float boundary, CLHEP::HepRandomEngine * rndmEngine) {
341 ATH_MSG_DEBUG("[HGTD_SmearedDigitizationTool::smearPosition] pos: "
342 << pos << " sig: " << sig << " boundary: " << boundary);
343 float smeared_pos = pos;
344 float smear_para = 0.;
345 if (sig != 0.) {
346 do {
347 smear_para = CLHEP::RandGauss::shoot(rndmEngine, 0., sig);
348
349 } while (std::abs(smeared_pos + smear_para) > boundary);
350 smeared_pos += smear_para;
351 }
352 return smeared_pos;
353}
354
355float HGTD_SmearedDigitizationTool::smearMeanTime(float time, float time_res, CLHEP::HepRandomEngine * rndmEngine) {
356 return time + CLHEP::RandGauss::shoot(rndmEngine, 0., time_res);
357}
358
360
361 const HepMcParticleLink trk_link = HepMcParticleLink::getRedirectedLink(hit->particleLink(), hit.eventId(), ctx); // This link should now correctly resolve to the TruthEvent McEventCollection in the main StoreGateSvc.
362
363 ATH_MSG_DEBUG("Truth map filling with cluster "
364 << *cluster << " and link = " << trk_link);
365
366 if (trk_link.isValid()) {
368 map->insert(std::make_pair(cluster->identify(), trk_link));
369 }
370 }
371
372 return StatusCode::SUCCESS;
373}
374
376 ClusterContainer_t& cluster_container) {
378 "--- HGTD_SmearedDigitizationTool: in fillClusterContainer() ---");
379 using RIO_map_t = HGTD_DetElement_RIO_Map_t;
380
381 RIO_map_t::iterator i = det_element_rio_map.begin();
382 RIO_map_t::iterator e = det_element_rio_map.end();
383
384 for (; i != e; i = det_element_rio_map.upper_bound(i->first)) {
385
386 std::pair<RIO_map_t::iterator, RIO_map_t::iterator> range;
387 range = det_element_rio_map.equal_range(i->first);
388
389 RIO_map_t::iterator first_det_elem = range.first;
390
391 IdentifierHash wafer_id = first_det_elem->first;
392
393 const InDetDD::SolidStateDetectorElementBase* det_element =
394 m_hgtd_det_manager->getDetectorElement(wafer_id);
395
396 ClusterCollection_t* cluster_coll = new ClusterCollection_t(wafer_id);
397 cluster_coll->setIdentifier(det_element->identify());
398
399 for (RIO_map_t::iterator iter = range.first; iter != range.second; ++iter) {
400
401 Cluster_t* cluster = const_cast<Cluster_t*>((*iter).second);
402 cluster->setHashAndIndex(cluster_coll->identifyHash(),
403 cluster_coll->size());
404 cluster_coll->push_back(cluster);
405 }
406
407 if (cluster_container.addCollection(cluster_coll, wafer_id)
408 .isFailure()) {
409 ATH_MSG_WARNING("Could not add collection to Identifiable container!");
410 }
411 } // end for
412
413 return StatusCode::SUCCESS;
414}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define AmgSymMatrix(dim)
AtlasHitsVector< SiHit > SiHitCollection
A wrapper class for event-slot-local random engines.
Definition RNGWrapper.h:56
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
Definition RNGWrapper.h:169
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition RNGWrapper.h:134
size_type size() const
value_type push_back(value_type pElem)
size_type size() const noexcept
virtual const Amg::Vector3D & globalPosition() const
float smearPosition(float pos, float sig, float boundary, CLHEP::HepRandomEngine *rndmEngine)
TimedHitCollection< SiHit > setupTimedHitCollection()
StatusCode fillClusterContainer(HGTD_DetElement_RIO_Map_t &det_element_rio_map, ClusterContainer_t &cluster_container)
StatusCode digitize(const EventContext &ctx, TimedHitCollection< SiHit > &timed_hit_collection, HGTD_DetElement_RIO_Map_t &det_element_rio_map)
HGTD_SmearedDigitizationTool(const std::string &type, const std::string &name, const IInterface *parent)
std::multimap< IdentifierHash, const Cluster_t * > HGTD_DetElement_RIO_Map_t
StatusCode fillMultiTruthCollection(PRD_MultiTruthCollection *, Cluster_t *, const TimedHitPtr< SiHit > &, const EventContext &)
const HGTD_DetectorManager * m_hgtd_det_manager
virtual StatusCode initialize() override
float smearMeanTime(float time, float time_res, CLHEP::HepRandomEngine *rndmEngine)
virtual StatusCode processAllSubEvents(const EventContext &ctx) override
ServiceHandle< IAthRNGSvc > m_rndm_svc
Random number service.
StatusCode retrieveTruth(PRD_MultiTruthCollection *&prd_truth_coll)
virtual StatusCode finalize() override
ServiceHandle< PileUpMergeSvc > m_merge_svc
virtual StatusCode addCollection(const T *coll, IdentifierHash hashId) override final
insert collection into container with id hash if IDC should not take ownership of collection,...
This is a "hash" representation of an Identifier.
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
bool isValid() const
Test if its in a valid state.
Definition SiCellId.h:136
Class to hold geometrical description of a solid state detector element.
double length() const
Length in eta direction (z - barrel, r - endcap)
HepGeom::Point3D< double > hitLocalToLocal3D(const HepGeom::Point3D< double > &hitPosition) const
Same as previuos method but 3D.
double width() const
Methods from design (inline)
virtual SiCellId cellIdFromIdentifier(const Identifier &identifier) const =0
SiCellId from Identifier.
virtual Identifier identify() const override final
identifier of this detector element (inline)
Identifier identifierOfPosition(const Amg::Vector2D &localPos) const
Full identifier of the cell for a given position: assumes a raw local position (no Lorentz shift)
A PRD is mapped onto all contributing particles.
Gaudi::Property< int > m_vetoPileUpTruthLinks
PileUpToolBase(const std::string &type, const std::string &name, const IInterface *parent)
void reserve(unsigned int numberOfHits)
reserve a timed vector numberOfHits in size.
bool nextDetectorElement(const_iterator &b, const_iterator &e)
sets an iterator range with the hits of current detector element returns a bool when done
TimedVector::const_iterator const_iterator
void insert(const PileUpTimeEventIndex &timeEventIndex, const AtlasHitsVector< HIT > *inputCollection)
a smart pointer to a hit that also provides access to the extended timing info of the host event.
Definition TimedHitPtr.h:18
unsigned short eventId() const
the index of the component event in PileUpEventInfo.
Definition TimedHitPtr.h:47
virtual IdentifierHash identifyHash() const override final
Identifier identify() const
return the identifier
void setHashAndIndex(unsigned short collHash, unsigned short objIndex)
TEMP for testing: might make some classes friends later ...
const Amg::MatrixX & localCovariance() const
return const ref to the error matrix
STL class.
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:114
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Eigen::Matrix< double, 2, 1 > Vector2D
bool ignoreTruthLink(const T &p, bool vetoPileUp)
Helper function for SDO creation in PileUpTools.
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
std::list< value_t > type
type of the collection of timed data object