CMS 3D CMS Logo

SubsystemNeutronWriter.cc
Go to the documentation of this file.
12 
13 #include "CLHEP/Random/RandFlat.h"
14 
15 #include <algorithm>
16 
17 using namespace std;
18 
19 class SortByTime {
20 public:
21  bool operator()(const PSimHit& h1, const PSimHit& h2) { return (h1.tof() < h2.tof()); }
22 };
23 
25  : theHitWriter(nullptr),
26  useRandFlat(false),
27  theInputTag(pset.getParameter<edm::InputTag>("input")),
28  theNeutronTimeCut(pset.getParameter<double>("neutronTimeCut")),
29  theTimeWindow(pset.getParameter<double>("timeWindow")),
30  theT0(pset.getParameter<double>("t0")),
31  hitToken_(consumes<edm::PSimHitContainer>(theInputTag)),
32  theNEvents(0),
33  initialized(false),
34  useLocalDetId_(true) {
35  string writer = pset.getParameter<string>("writer");
36  string output = pset.getParameter<string>("output");
37  if (writer == "ASCII") {
39  } else if (writer == "ROOT") {
41  } else if (writer == "EDM") {
42  produces<edm::PSimHitContainer>();
44  // write out the real DetId, not the local one
45  useLocalDetId_ = false;
46  // smear the times
48  if (!rng.isAvailable()) {
49  throw cms::Exception("Configuration")
50  << "SubsystemNeutronWriter requires the RandomNumberGeneratorService\n"
51  "which is not present in the configuration file. You must add the service\n"
52  "in the configuration file or remove the modules that require it.";
53  }
54  useRandFlat = true;
55  } else {
56  throw cms::Exception("NeutronWriter") << "Bad writer: " << writer;
57  }
58 }
59 
61  printStats();
62  delete theHitWriter;
63 }
64 
66  edm::LogInfo("SubsystemNeutronWriter") << "SubsystemNeutronWriter Statistics:\n";
67  for (map<int, int>::iterator mapItr = theCountPerChamberType.begin(); mapItr != theCountPerChamberType.end();
68  ++mapItr) {
69  edm::LogInfo("SubsystemNeutronWriter")
70  << " theEventOccupancy[" << mapItr->first << "] = " << mapItr->second << " / " << theNEvents << " / NCT \n";
71  }
72 }
73 
75  CLHEP::HepRandomEngine* engine = nullptr;
76  if (useRandFlat) {
78  engine = &rng->getEngine(e.streamID());
79  }
81  ++theNEvents;
83 
84  // sort hits by chamber
85  std::map<int, edm::PSimHitContainer> hitsByChamber;
86  for (edm::PSimHitContainer::const_iterator hitItr = hits->begin(); hitItr != hits->end(); ++hitItr) {
87  int chamberIndex = chamberId(hitItr->detUnitId());
88  hitsByChamber[chamberIndex].push_back(*hitItr);
89  }
90 
91  // now write out each chamber's contents
92  for (std::map<int, edm::PSimHitContainer>::iterator hitsByChamberItr = hitsByChamber.begin();
93  hitsByChamberItr != hitsByChamber.end();
94  ++hitsByChamberItr) {
95  int chambertype = chamberType(hitsByChamberItr->first);
96  writeHits(chambertype, hitsByChamberItr->second, engine);
97  }
99 }
100 
102  // should instantiate one of every chamber type, just so
103  // ROOT knows what file to associate them with
105 }
106 
108  edm::PSimHitContainer& chamberHits,
109  CLHEP::HepRandomEngine* engine) {
110  sort(chamberHits.begin(), chamberHits.end(), SortByTime());
111  edm::PSimHitContainer cluster;
112  float startTime = -1000.;
113  float smearing = 0.;
114  for (size_t i = 0; i < chamberHits.size(); ++i) {
115  PSimHit hit = chamberHits[i];
116  float tof = hit.tof();
117  LogDebug("SubsystemNeutronWriter") << "found hit from part type " << hit.particleType() << " at tof " << tof
118  << " p " << hit.pabs() << " on det " << hit.detUnitId() << " chamber type "
119  << chamberType;
120  if (tof > theNeutronTimeCut) {
121  if (tof > (startTime + theTimeWindow)) { // 1st in cluster
122  startTime = tof;
123  // set the time to be [t0, t0+25] at start of event
124  smearing = theT0;
125  if (useRandFlat) {
126  smearing += CLHEP::RandFlat::shoot(engine, 25.);
127  }
128  if (!cluster.empty()) {
129  LogDebug("SubsystemNeutronWriter") << "filling old cluster";
130  writeCluster(chamberType, cluster);
131  cluster.clear();
132  }
133  LogDebug("SubsystemNeutronWriter")
134  << "starting neutron cluster at time " << startTime << " on detType " << chamberType;
135  }
136  adjust(hit, -1. * startTime, smearing);
137  cluster.push_back(hit);
138  }
139  }
140  // get any leftover cluster
141  if (!cluster.empty()) {
142  writeCluster(chamberType, cluster);
143  }
144 }
145 
147  if (accept(cluster)) {
150  }
151 }
152 
153 void SubsystemNeutronWriter::adjust(PSimHit& h, float timeOffset, float smearing) {
154  unsigned int detId = useLocalDetId_ ? localDetId(h.detUnitId()) : h.detUnitId();
155  float htime = h.timeOfFlight() + timeOffset + smearing;
156  // prevent float precision loss
157  if (h.timeOfFlight() > 1.E+6) {
158  htime = smearing;
159  }
160  h = PSimHit(h.entryPoint(),
161  h.exitPoint(),
162  h.pabs(),
163  htime,
164  h.energyLoss(),
165  h.particleType(),
166  detId,
167  h.trackId(),
168  h.momentumAtEntry().theta(),
169  h.momentumAtEntry().phi());
170 }
171 
173  map<int, int>::iterator entry = theCountPerChamberType.find(chamberType);
174  if (entry == theCountPerChamberType.end()) {
175  theCountPerChamberType.insert(pair<int, int>(chamberType, 1));
176  } else {
177  ++(entry->second);
178  }
179 }
virtual int chamberType(int globalDetId) const =0
void initialize(int chamberType)
good practice to do once for each chamber type
~SubsystemNeutronWriter() override
destructor prints statistics on number of events written
virtual bool accept(const edm::PSimHitContainer &cluster) const =0
decides whether this cluster is good enough to be included
virtual CLHEP::HepRandomEngine & getEngine(StreamID const &)=0
Use this engine in event methods.
virtual void beginEvent(edm::Event &e, const edm::EventSetup &es)
Definition: NeutronWriter.h:20
void adjust(PSimHit &h, float timeOffset, float smearing)
helper to add time offsets and local det ID
virtual int localDetId(int globalDetId) const =0
virtual int chamberId(int globalDetId) const =0
virtual void endEvent()
Definition: NeutronWriter.h:21
virtual void writeHits(int chamberType, edm::PSimHitContainer &chamberHits, CLHEP::HepRandomEngine *)
const edm::EDGetTokenT< edm::PSimHitContainer > hitToken_
bool operator()(const PSimHit &h1, const PSimHit &h2)
std::map< int, int > theCountPerChamberType
virtual void writeCluster(int detType, const edm::PSimHitContainer &simHits)=0
writes out a list of SimHits.
virtual void initialize(int detType)
Definition: NeutronWriter.h:19
Log< level::Info, false > LogInfo
SubsystemNeutronWriter(edm::ParameterSet const &pset)
void updateCount(int chamberType)
updates the counter
float tof() const
deprecated name for timeOfFlight()
Definition: PSimHit.h:76
void writeCluster(int chamberType, const edm::PSimHitContainer &cluster)
void produce(edm::Event &e, edm::EventSetup const &c) override
HLT enums.
bool isAvailable() const
Definition: Service.h:40
std::vector< PSimHit > PSimHitContainer
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
#define LogDebug(id)