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) {
22  return (h1.tof() < h2.tof());
23  }
24 };
25 
27 : theHitWriter(nullptr),
28  useRandFlat(false),
29  theInputTag(pset.getParameter<edm::InputTag>("input")),
30  theNeutronTimeCut(pset.getParameter<double>("neutronTimeCut")),
31  theTimeWindow(pset.getParameter<double>("timeWindow")),
32  theT0(pset.getParameter<double>("t0")),
33  theNEvents(0),
34  initialized(false),
35  useLocalDetId_(true)
36 {
37  string writer = pset.getParameter<string>("writer");
38  string output = pset.getParameter<string>("output");
39  if(writer == "ASCII")
40  {
41  theHitWriter = new AsciiNeutronWriter(output);
42  }
43  else if (writer == "ROOT")
44  {
45  theHitWriter = new RootNeutronWriter(output);
46  }
47  else if (writer == "EDM")
48  {
49  produces<edm::PSimHitContainer>();
51  // write out the real DetId, not the local one
52  useLocalDetId_ = false;
53  // smear the times
55  if ( ! rng.isAvailable()) {
56  throw cms::Exception("Configuration")
57  << "SubsystemNeutronWriter requires the RandomNumberGeneratorService\n"
58  "which is not present in the configuration file. You must add the service\n"
59  "in the configuration file or remove the modules that require it.";
60  }
61  useRandFlat = true;
62  }
63  else
64  {
65  throw cms::Exception("NeutronWriter") << "Bad writer: "
66  << writer;
67  }
68 }
69 
71 {
72  printStats();
73  delete theHitWriter;
74 }
75 
77  edm::LogInfo("SubsystemNeutronWriter") << "SubsystemNeutronWriter Statistics:\n";
78  for(map<int,int>::iterator mapItr = theCountPerChamberType.begin();
79  mapItr != theCountPerChamberType.end(); ++mapItr) {
80  edm::LogInfo("SubsystemNeutronWriter") << " theEventOccupancy[" << mapItr->first << "] = "
81  << mapItr->second << " / " << theNEvents << " / NCT \n";
82  }
83 }
84 
86 {
87  CLHEP::HepRandomEngine* engine = nullptr;
88  if(useRandFlat) {
90  engine = &rng->getEngine(e.streamID());
91  }
93  ++theNEvents;
95  e.getByLabel(theInputTag, hits);
96 
97  // sort hits by chamber
98  map<int, edm::PSimHitContainer> hitsByChamber;
99  for(edm::PSimHitContainer::const_iterator hitItr = hits->begin();
100  hitItr != hits->end(); ++hitItr)
101  {
102  int chamberIndex = chamberId(hitItr->detUnitId());
103  hitsByChamber[chamberIndex].push_back(*hitItr);
104  }
105 
106  // now write out each chamber's contents
107  for(map<int, edm::PSimHitContainer>::iterator hitsByChamberItr = hitsByChamber.begin();
108  hitsByChamberItr != hitsByChamber.end(); ++hitsByChamberItr)
109  {
110  int chambertype = chamberType(hitsByChamberItr->first);
111  writeHits(chambertype, hitsByChamberItr->second, engine);
112  }
114 }
115 
116 
118 {
119  // should instantiate one of every chamber type, just so
120  // ROOT knows what file to associate them with
121  theHitWriter->initialize(chamberType);
122 }
123 
124 
126  CLHEP::HepRandomEngine* engine)
127 {
128 
129  sort(chamberHits.begin(), chamberHits.end(), SortByTime());
130  edm::PSimHitContainer cluster;
131  float startTime = -1000.;
132  float smearing = 0.;
133  for(size_t i = 0; i < chamberHits.size(); ++i) {
134  PSimHit hit = chamberHits[i];
135  float tof = hit.tof();
136  LogDebug("SubsystemNeutronWriter") << "found hit from part type " << hit.particleType()
137  << " at tof " << tof << " p " << hit.pabs()
138  << " on det " << hit.detUnitId()
139  << " chamber type " << chamberType;
140  if(tof > theNeutronTimeCut) {
141  if(tof > (startTime + theTimeWindow) ) { // 1st in cluster
142  startTime = tof;
143  // set the time to be [t0, t0+25] at start of event
144  smearing = theT0;
145  if(useRandFlat) {
146  smearing += CLHEP::RandFlat::shoot(engine, 25.);
147  }
148  if(!cluster.empty()) {
149  LogDebug("SubsystemNeutronWriter") << "filling old cluster";
150  writeCluster(chamberType, cluster);
151  cluster.clear();
152  }
153  LogDebug("SubsystemNeutronWriter") << "starting neutron cluster at time " << startTime
154  << " on detType " << chamberType;
155  }
156  adjust(hit, -1.*startTime, smearing);
157  cluster.push_back( hit );
158  }
159  }
160  // get any leftover cluster
161  if(!cluster.empty()) {
162  writeCluster(chamberType, cluster);
163  }
164 }
165 
166 
168 {
169  if(accept(cluster))
170  {
171  theHitWriter->writeCluster(chamberType, cluster);
172  updateCount(chamberType);
173  }
174 }
175 
176 
177 void SubsystemNeutronWriter::adjust(PSimHit & h, float timeOffset, float smearing) {
178  unsigned int detId = useLocalDetId_ ? localDetId(h.detUnitId()) : h.detUnitId();
179  float htime = h.timeOfFlight() + timeOffset + smearing;
180  // prevent float precision loss
181  if (h.timeOfFlight() > 1.E+6) {
182  htime = smearing;
183  }
184  h = PSimHit( h.entryPoint(), h.exitPoint(), h.pabs(), htime,
185  h.energyLoss(), h.particleType(),
186  detId, h.trackId(),
187  h.momentumAtEntry().theta(),
188  h.momentumAtEntry().phi() );
189 }
190 
191 
193  map<int,int>::iterator entry = theCountPerChamberType.find(chamberType);
194  if(entry == theCountPerChamberType.end()) {
195  theCountPerChamberType.insert( pair<int,int>(chamberType, 1) );
196  } else {
197  ++(entry->second);
198  }
199 }
200 
201 
#define LogDebug(id)
T getParameter(std::string const &) const
float tof() const
deprecated name for timeOfFlight()
Definition: PSimHit.h:72
void initialize(int chamberType)
good practice to do once for each chamber type
~SubsystemNeutronWriter() override
destructor prints statistics on number of events written
LocalVector momentumAtEntry() const
The momentum of the track that produced the hit, at entry point.
Definition: PSimHit.h:47
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
#define nullptr
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
virtual bool accept(const edm::PSimHitContainer &cluster) const =0
decides whether this cluster is good enough to be included
void adjust(PSimHit &h, float timeOffset, float smearing)
helper to add time offsets and local det ID
Geom::Theta< T > theta() const
Definition: PV3DBase.h:75
Local3DPoint exitPoint() const
Exit point in the local Det frame.
Definition: PSimHit.h:38
float timeOfFlight() const
Definition: PSimHit.h:69
virtual void endEvent()
Definition: NeutronWriter.h:21
virtual void writeHits(int chamberType, edm::PSimHitContainer &chamberHits, CLHEP::HepRandomEngine *)
bool operator()(const PSimHit &h1, const PSimHit &h2)
bool isAvailable() const
Definition: Service.h:46
std::map< int, int > theCountPerChamberType
virtual void writeCluster(int detType, const edm::PSimHitContainer &simHits)=0
writes out a list of SimHits.
float pabs() const
fast and more accurate access to momentumAtEntry().mag()
Definition: PSimHit.h:63
bool getByLabel(InputTag const &tag, Handle< PROD > &result) const
Definition: Event.h:464
virtual void initialize(int detType)
Definition: NeutronWriter.h:19
SubsystemNeutronWriter(edm::ParameterSet const &pset)
void updateCount(int chamberType)
updates the counter
void writeCluster(int chamberType, const edm::PSimHitContainer &cluster)
virtual int chamberId(int globalDetId) const =0
void produce(edm::Event &e, edm::EventSetup const &c) override
float energyLoss() const
The energy deposit in the PSimHit, in ???.
Definition: PSimHit.h:75
HLT enums.
int particleType() const
Definition: PSimHit.h:85
StreamID streamID() const
Definition: Event.h:86
unsigned int trackId() const
Definition: PSimHit.h:102
std::vector< PSimHit > PSimHitContainer
virtual int chamberType(int globalDetId) const =0
Local3DPoint entryPoint() const
Entry point in the local Det frame.
Definition: PSimHit.h:35
virtual int localDetId(int globalDetId) const =0
unsigned int detUnitId() const
Definition: PSimHit.h:93