CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
SubsystemNeutronWriter.cc
Go to the documentation of this file.
10 #include "CLHEP/Random/RandomEngine.h"
13 
14 #include <algorithm>
15 
16 using namespace std;
17 
18 class SortByTime {
19 public:
20  bool operator()(const PSimHit & h1, const PSimHit & h2) {
21  return (h1.tof() < h2.tof());
22  }
23 };
24 
25 
27 : theHitWriter(0),
28  theRandFlat(0),
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  CLHEP::HepRandomEngine& engine = rng->getEngine();
62  theRandFlat = new CLHEP::RandFlat(engine);
63  }
64  else
65  {
66  throw cms::Exception("NeutronWriter") << "Bad writer: "
67  << writer;
68  }
69 }
70 
71 
73 {
74  printStats();
75  delete theHitWriter;
76  delete theRandFlat;
77 }
78 
79 
80 
82  edm::LogInfo("SubsystemNeutronWriter") << "SubsystemNeutronWriter Statistics:\n";
83  for(map<int,int>::iterator mapItr = theCountPerChamberType.begin();
84  mapItr != theCountPerChamberType.end(); ++mapItr) {
85  edm::LogInfo("SubsystemNeutronWriter") << " theEventOccupancy[" << mapItr->first << "] = "
86  << mapItr->second << " / " << theNEvents << " / NCT \n";
87  }
88 }
89 
90 
92 {
94  ++theNEvents;
96  e.getByLabel(theInputTag, hits);
97 
98  // sort hits by chamber
99  map<int, edm::PSimHitContainer> hitsByChamber;
100  for(edm::PSimHitContainer::const_iterator hitItr = hits->begin();
101  hitItr != hits->end(); ++hitItr)
102  {
103  int chamberIndex = chamberId(hitItr->detUnitId());
104  hitsByChamber[chamberIndex].push_back(*hitItr);
105  }
106 
107  // now write out each chamber's contents
108  for(map<int, edm::PSimHitContainer>::iterator hitsByChamberItr = hitsByChamber.begin();
109  hitsByChamberItr != hitsByChamber.end(); ++hitsByChamberItr)
110  {
111  int chambertype = chamberType(hitsByChamberItr->first);
112  writeHits(chambertype, hitsByChamberItr->second);
113  }
115 }
116 
117 
119 {
120  // should instantiate one of every chamber type, just so
121  // ROOT knows what file to associate them with
122  theHitWriter->initialize(chamberType);
123 }
124 
125 
126 void SubsystemNeutronWriter::writeHits(int chamberType, edm::PSimHitContainer & chamberHits)
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(theRandFlat) {
146  smearing += theRandFlat->fire(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 
167 void SubsystemNeutronWriter::writeCluster(int chamberType, const edm::PSimHitContainer & cluster)
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 
192 void SubsystemNeutronWriter::updateCount(int chamberType) {
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
int i
Definition: DBlmapReader.cc:9
float tof() const
deprecated name for timeOfFlight()
Definition: PSimHit.h:72
virtual int chamberType(int globalDetId) const =0
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
virtual bool accept(const edm::PSimHitContainer &cluster) const =0
decides whether this cluster is good enough to be included
Geom::Phi< T > phi() const
Definition: PV3DBase.h:63
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
Geom::Theta< T > theta() const
Definition: PV3DBase.h:69
virtual int localDetId(int globalDetId) const =0
Local3DPoint exitPoint() const
Exit point in the local Det frame.
Definition: PSimHit.h:38
virtual int chamberId(int globalDetId) const =0
float timeOfFlight() const
Definition: PSimHit.h:69
virtual void endEvent()
Definition: NeutronWriter.h:21
std::pair< std::string, MonitorElement * > entry
Definition: ME_MAP.h:8
bool operator()(const PSimHit &h1, const PSimHit &h2)
bool isAvailable() const
Definition: Service.h:47
std::map< int, int > theCountPerChamberType
tuple pset
Definition: CrabTask.py:85
virtual CLHEP::HepRandomEngine & getEngine() const =0
Use this to get the random number engine, this is the only function most users should call...
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:359
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)
float energyLoss() const
The energy deposit in the PSimHit, in ???.
Definition: PSimHit.h:75
int particleType() const
Definition: PSimHit.h:85
virtual void writeHits(int chamberType, edm::PSimHitContainer &chamberHits)
unsigned int trackId() const
Definition: PSimHit.h:102
virtual void produce(edm::Event &e, edm::EventSetup const &c)
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
Local3DPoint entryPoint() const
Entry point in the local Det frame.
Definition: PSimHit.h:35
unsigned int detUnitId() const
Definition: PSimHit.h:93