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(0),
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
virtual ~SubsystemNeutronWriter()
destructor prints statistics on number of events written
void initialize(int chamberType)
good practice to do once for each chamber type
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
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:413
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
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:81
unsigned int trackId() const
Definition: PSimHit.h:102
virtual void produce(edm::Event &e, edm::EventSetup const &c)
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