Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Fun4AllDstPileupMerger.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Fun4AllDstPileupMerger.cc
1 
7 
8 #include "PHG4Hit.h" // for PHG4Hit
9 #include "PHG4HitContainer.h"
10 #include "PHG4Hitv1.h"
11 #include "PHG4Particle.h" // for PHG4Particle
12 #include "PHG4Particlev3.h"
13 #include "PHG4TruthInfoContainer.h"
14 #include "PHG4VtxPoint.h" // for PHG4VtxPoint
15 #include "PHG4VtxPointv1.h"
16 
17 #include <phhepmc/PHHepMCGenEvent.h> // for PHHepMCGenEvent
19 
20 #include <phool/PHCompositeNode.h>
21 #include <phool/PHIODataNode.h> // for PHIODataNode
22 #include <phool/PHNode.h> // for PHNode
23 #include <phool/PHNodeIterator.h> // for PHNodeIterator
24 #include <phool/PHNodeOperation.h>
25 #include <phool/PHObject.h> // for PHObject
26 #include <phool/getClass.h>
27 
28 #include <TObject.h>
29 
30 #pragma GCC diagnostic push
31 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
32 #include <HepMC/GenEvent.h>
33 #pragma GCC diagnostic pop
34 
35 #include <climits>
36 #include <iostream>
37 #include <iterator>
38 #include <utility>
39 
40 // convenient aliases for deep copying nodes
41 namespace
42 {
43  using PHG4Particle_t = PHG4Particlev3;
44  using PHG4VtxPoint_t = PHG4VtxPointv1;
45  using PHG4Hit_t = PHG4Hitv1;
46 
48  class FindG4HitContainer : public PHNodeOperation
49  {
50  public:
52  using ContainerMap = std::map<std::string, PHG4HitContainer *>;
53 
55  const ContainerMap &containers() const
56  {
57  return m_containers;
58  }
59 
60  protected:
62  void perform(PHNode *node) override
63  {
64  // check type name. Only load PHIODataNode
65  if (node->getType() != "PHIODataNode") return;
66 
67  // cast to IODataNode and check data
68  auto ionode = static_cast<PHIODataNode<TObject> *>(node);
69  auto data = dynamic_cast<PHG4HitContainer *>(ionode->getData());
70  if (data)
71  {
72  m_containers.insert(std::make_pair(node->getName(), data));
73  }
74  }
75 
76  private:
78  ContainerMap m_containers;
79  };
80 
81 } // namespace
82 
83 //_____________________________________________________________________________
85 {
86  // hep mc
87  m_geneventmap = findNode::getClass<PHHepMCGenEventMap>(dstNode, "PHHepMCGenEventMap");
88  if (!m_geneventmap)
89  {
90  std::cout << "Fun4AllDstPileupMerger::load_nodes - creating PHHepMCGenEventMap" << std::endl;
92  dstNode->addNode(new PHIODataNode<PHObject>(m_geneventmap, "PHHepMCGenEventMap", "PHObject"));
93  }
94 
95  // find all G4Hit containers under dstNode
96  FindG4HitContainer nodeFinder;
97  PHNodeIterator(dstNode).forEach(nodeFinder);
98  m_g4hitscontainers = nodeFinder.containers();
99 
100  // g4 truth info
101  m_g4truthinfo = findNode::getClass<PHG4TruthInfoContainer>(dstNode, "G4TruthInfo");
102  if (!m_g4truthinfo)
103  {
104  std::cout << "Fun4AllDstPileupMerger::load_nodes - creating node G4TruthInfo" << std::endl;
106  dstNode->addNode(new PHIODataNode<PHObject>(m_g4truthinfo, "G4TruthInfo", "PHObject"));
107  }
108 }
109 
110 //_____________________________________________________________________________
112 {
113  // copy PHHepMCGenEventMap
114  const auto map = findNode::getClass<PHHepMCGenEventMap>(dstNode, "PHHepMCGenEventMap");
115 
116  // keep track of new embed id, after insertion as background event
117  int new_embed_id = -1;
118 
119  if (map && m_geneventmap)
120  {
121  if (map->size() != 1)
122  {
123  std::cout << "Fun4AllDstPileupMerger::copy_background_event - cannot merge events that contain more than one PHHepMCGenEventMap" << std::endl;
124  return;
125  }
126 
127  // get event and insert in new map
128  auto genevent = map->get_map().begin()->second;
130 
131  /*
132  * this hack prevents a crash when writting out
133  * it boils down to root trying to write deleted items from the HepMC::GenEvent copy if the source has been deleted
134  * it does not happen if the source gets written while the copy is deleted
135  */
136  newevent->getEvent()->swap(*genevent->getEvent());
137 
138  // shift vertex time and store new embed id
139  newevent->moveVertex(0, 0, 0, delta_t);
140  new_embed_id = newevent->get_embedding_id();
141  }
142 
143  // copy truth container
144  // keep track of the correspondance between source index and destination index for vertices, tracks and showers
145  using ConversionMap = std::map<int, int>;
146  ConversionMap vtxid_map;
147  ConversionMap trkid_map;
148 
149  const auto container_truth = findNode::getClass<PHG4TruthInfoContainer>(dstNode, "G4TruthInfo");
150  if (container_truth && m_g4truthinfo)
151  {
152  {
153  // primary vertices
154  auto key = m_g4truthinfo->maxvtxindex();
155  const auto range = container_truth->GetPrimaryVtxRange();
156  for (auto iter = range.first; iter != range.second; ++iter)
157  {
158  // clone vertex, insert in map, and add index conversion
159  const auto &sourceVertex = iter->second;
160  auto newVertex = new PHG4VtxPoint_t(sourceVertex);
161  newVertex->set_t(sourceVertex->get_t() + delta_t);
162  m_g4truthinfo->AddVertex(++key, newVertex);
163  vtxid_map.insert(std::make_pair(sourceVertex->get_id(), key));
164  }
165  }
166 
167  {
168  // secondary vertices
169  auto key = m_g4truthinfo->minvtxindex();
170  const auto range = container_truth->GetSecondaryVtxRange();
171 
172  // loop from last to first to preserve order with respect to the original event
173  for (
174  auto iter = std::reverse_iterator<PHG4TruthInfoContainer::ConstVtxIterator>(range.second);
175  iter != std::reverse_iterator<PHG4TruthInfoContainer::ConstVtxIterator>(range.first);
176  ++iter)
177  {
178  // clone vertex, shift time, insert in map, and add index conversion
179  const auto &sourceVertex = iter->second;
180  auto newVertex = new PHG4VtxPoint_t(sourceVertex);
181  newVertex->set_t(sourceVertex->get_t() + delta_t);
182  m_g4truthinfo->AddVertex(--key, newVertex);
183  vtxid_map.insert(std::make_pair(sourceVertex->get_id(), key));
184  }
185  }
186 
187  {
188  // primary particles
189  auto key = m_g4truthinfo->maxtrkindex();
190  const auto range = container_truth->GetPrimaryParticleRange();
191  for (auto iter = range.first; iter != range.second; ++iter)
192  {
193  const auto &source = iter->second;
194  auto dest = new PHG4Particle_t(source);
195  m_g4truthinfo->AddParticle(++key, dest);
196  dest->set_track_id(key);
197 
198  // set parent to zero
199  dest->set_parent_id(0);
200 
201  // set primary to itself
202  dest->set_primary_id(dest->get_track_id());
203 
204  // update vertex
205  const auto keyiter = vtxid_map.find(source->get_vtx_id());
206  if (keyiter != vtxid_map.end())
207  dest->set_vtx_id(keyiter->second);
208  else
209  std::cout << "Fun4AllDstPileupMerger::copy_background_event - vertex id " << source->get_vtx_id() << " not found in map" << std::endl;
210 
211  // insert in map
212  trkid_map.insert(std::make_pair(source->get_track_id(), dest->get_track_id()));
213  }
214  }
215 
216  {
217  // secondary particles
218  auto key = m_g4truthinfo->mintrkindex();
219  const auto range = container_truth->GetSecondaryParticleRange();
220 
221  /*
222  * loop from last to first to preserve order with respect to the original event
223  * also this ensures that for a given particle its parent has already been converted and thus found in the map
224  */
225  for (
226  auto iter = std::reverse_iterator<PHG4TruthInfoContainer::ConstIterator>(range.second);
227  iter != std::reverse_iterator<PHG4TruthInfoContainer::ConstIterator>(range.first);
228  ++iter)
229  {
230  const auto &source = iter->second;
231  auto dest = new PHG4Particle_t(source);
232  m_g4truthinfo->AddParticle(--key, dest);
233  dest->set_track_id(key);
234 
235  // update parent id
236  auto keyiter = trkid_map.find(source->get_parent_id());
237  if (keyiter != trkid_map.end())
238  dest->set_parent_id(keyiter->second);
239  else
240  std::cout << "Fun4AllDstPileupMerger::copy_background_event - track id " << source->get_parent_id() << " not found in map" << std::endl;
241 
242  // update primary id
243  keyiter = trkid_map.find(source->get_primary_id());
244  if (keyiter != trkid_map.end())
245  dest->set_primary_id(keyiter->second);
246  else
247  std::cout << "Fun4AllDstPileupMerger::copy_background_event - track id " << source->get_primary_id() << " not found in map" << std::endl;
248 
249  // update vertex
250  keyiter = vtxid_map.find(source->get_vtx_id());
251  if (keyiter != vtxid_map.end())
252  dest->set_vtx_id(keyiter->second);
253  else
254  std::cout << "Fun4AllDstPileupMerger::copy_background_event - vertex id " << source->get_vtx_id() << " not found in map" << std::endl;
255 
256  // insert in map
257  trkid_map.insert(std::make_pair(source->get_track_id(), dest->get_track_id()));
258  }
259  }
260 
261  // vertex embed flags
262  /* embed flag is stored only for primary vertices, consistently with PHG4TruthEventAction */
263  for (const auto &pair : vtxid_map)
264  {
265  if (pair.first > 0) m_g4truthinfo->AddEmbededVtxId(pair.second, new_embed_id);
266  }
267 
268  // track embed flags
269  /* embed flag is stored only for primary tracks, consistently with PHG4TruthEventAction */
270  for (const auto &pair : trkid_map)
271  {
272  if (pair.first > 0) m_g4truthinfo->AddEmbededTrkId(pair.second, new_embed_id);
273  }
274  }
275 
276  // copy g4hits
277  // loop over registered maps
278  for (const auto &pair : m_g4hitscontainers)
279  {
280  // check destination node
281  if (!pair.second)
282  {
283  std::cout << "Fun4AllDstPileupMerger::copy_background_event - invalid destination container " << pair.first << std::endl;
284  continue;
285  }
286 
287  // find source node
288  auto container_hit = findNode::getClass<PHG4HitContainer>(dstNode, pair.first);
289  if (!container_hit)
290  {
291  std::cout << "Fun4AllDstPileupMerger::copy_background_event - invalid source container " << pair.first << std::endl;
292  continue;
293  }
294  auto detiter = m_DetectorTiming.find(pair.first);
295 // apply special cuts for selected detectors
296  if (detiter != m_DetectorTiming.end())
297  {
298  if (delta_t < detiter->second.first || delta_t > detiter->second.second)
299  {
300  continue;
301  }
302  }
303  {
304  // hits
305  const auto range = container_hit->getHits();
306  for (auto iter = range.first; iter != range.second; ++iter)
307  {
308  // clone hit
309  const auto &sourceHit = iter->second;
310  auto newHit = new PHG4Hit_t(sourceHit);
311 
312  // shift time
313  newHit->set_t(0, sourceHit->get_t(0) + delta_t);
314  newHit->set_t(1, sourceHit->get_t(1) + delta_t);
315 
316  // update track id
317  const auto keyiter = trkid_map.find(sourceHit->get_trkid());
318  if (keyiter != trkid_map.end())
319  newHit->set_trkid(keyiter->second);
320  else
321  std::cout << "Fun4AllDstPileupMerger::copy_background_event - track id " << sourceHit->get_trkid() << " not found in map" << std::endl;
322 
323  /*
324  * reset shower ids
325  * it was decided that showers from the background events will not be copied to the merged event
326  * as such we just reset the hits shower id
327  */
328  newHit->set_shower_id(INT_MIN);
329 
330  /*
331  * this will generate a new key for the hit and assign it to the hit
332  * this ensures that there is no conflict with the hits from the 'main' event
333  */
334  pair.second->AddHit(newHit->get_detid(), newHit);
335  }
336  }
337 
338  {
339  // layers
340  const auto range = container_hit->getLayers();
341  for (auto iter = range.first; iter != range.second; ++iter)
342  {
343  pair.second->AddLayer(*iter);
344  }
345  }
346  }
347 }