CMS 3D CMS Logo

PPSFastLocalSimulation.cc
Go to the documentation of this file.
1 /****************************************************************************
2 * Authors:
3 * Jan Kašpar (jan.kaspar@gmail.com)
4 ****************************************************************************/
5 
15 
16 #include "CLHEP/Random/RandomEngine.h"
17 #include "CLHEP/Random/RandGauss.h"
18 #include "CLHEP/Random/RandExponential.h"
19 
21 
24 
29 
33 
35 
36 #include "TMath.h"
37 #include "TMatrixD.h"
38 #include "TVectorD.h"
39 
45 public:
47  ~PPSFastLocalSimulation() override;
48 
49 protected:
51  unsigned int verbosity_;
52 
54  bool makeHepMC_;
55 
57  bool makeHits_;
58 
60  std::vector<unsigned int> RPs_;
61 
63  unsigned int particlesPerEvent_;
64 
67 
69  double z0_;
70 
73 
76 
79 
80  struct Distribution {
84 
86 
87  void Generate(CLHEP::HepRandomEngine &rndEng, double &x, double &y);
88  };
89 
92 
95 
96  //---------- internal parameters ----------
97 
100 
102 
103  void GenerateTrack(unsigned int pi,
104  CLHEP::HepRandomEngine &rndEng,
105  HepMC::GenEvent *gEv,
109  const CTPPSGeometry &geometry);
110 
111  //---------- framework methods ----------
112 
113  void produce(edm::Event &, const edm::EventSetup &) override;
114 };
115 
116 //----------------------------------------------------------------------------------------------------
117 
118 using namespace edm;
119 using namespace std;
120 using namespace CLHEP;
121 using namespace HepMC;
122 
123 //----------------------------------------------------------------------------------------------------
124 
126  // get type
127  string typeName = ps.getParameter<string>("type");
128  if (!typeName.compare("box"))
129  type_ = dtBox;
130  else if (!typeName.compare("gauss"))
131  type_ = dtGauss;
132  else if (!typeName.compare("gauss-limit"))
133  type_ = dtGaussLimit;
134  else
135  throw cms::Exception("PPS") << "Unknown distribution type `" << typeName << "'.";
136 
137  x_mean_ = ps.getParameter<double>("x_mean");
138  x_width_ = ps.getParameter<double>("x_width");
139  x_min_ = ps.getParameter<double>("x_min");
140  x_max_ = ps.getParameter<double>("x_max");
141 
142  y_mean_ = ps.getParameter<double>("y_mean");
143  y_width_ = ps.getParameter<double>("y_width");
144  y_min_ = ps.getParameter<double>("y_min");
145  y_max_ = ps.getParameter<double>("y_max");
146 }
147 
148 //----------------------------------------------------------------------------------------------------
149 
150 void PPSFastLocalSimulation::Distribution::Generate(CLHEP::HepRandomEngine &rndEng, double &x, double &y) {
151  switch (type_) {
152  case dtBox:
153  x = x_mean_ + x_width_ * (rndEng.flat() - 0.5);
154  y = y_mean_ + y_width_ * (rndEng.flat() - 0.5);
155  break;
156 
157  case dtGauss:
158  x = x_mean_ + RandGauss::shoot(&rndEng) * x_width_;
159  y = y_mean_ + RandGauss::shoot(&rndEng) * y_width_;
160  break;
161 
162  case dtGaussLimit: {
163  const double u_x = rndEng.flat(), u_y = rndEng.flat();
164 
165  const double cdf_x_min = (1. + TMath::Erf((x_min_ - x_mean_) / x_width_ / sqrt(2.))) / 2.;
166  const double cdf_x_max = (1. + TMath::Erf((x_max_ - x_mean_) / x_width_ / sqrt(2.))) / 2.;
167  const double a_x = cdf_x_max - cdf_x_min, b_x = cdf_x_min;
168 
169  const double cdf_y_min = (1. + TMath::Erf((y_min_ - y_mean_) / y_width_ / sqrt(2.))) / 2.;
170  const double cdf_y_max = (1. + TMath::Erf((y_max_ - y_mean_) / y_width_ / sqrt(2.))) / 2.;
171  const double a_y = cdf_y_max - cdf_y_min, b_y = cdf_y_min;
172 
173  x = x_mean_ + x_width_ * sqrt(2.) * TMath::ErfInverse(2. * (a_x * u_x + b_x) - 1.);
174  y = y_mean_ + y_width_ * sqrt(2.) * TMath::ErfInverse(2. * (a_y * u_y + b_y) - 1.);
175  }
176 
177  break;
178 
179  default:
180  x = y = 0.;
181  }
182 }
183 
184 //----------------------------------------------------------------------------------------------------
185 
187  : verbosity_(ps.getUntrackedParameter<unsigned int>("verbosity", 0)),
188 
189  makeHepMC_(ps.getParameter<bool>("makeHepMC")),
190  makeHits_(ps.getParameter<bool>("makeHits")),
191 
192  RPs_(ps.getParameter<vector<unsigned int>>("RPs")),
193 
194  particlesPerEvent_(ps.getParameter<unsigned int>("particlesPerEvent")),
195  particle_E_(ps.getParameter<double>("particle_E")),
196  particle_p_(ps.getParameter<double>("particle_p")),
197  z0_(ps.getParameter<double>("z0")),
198 
199  roundToPitch_(ps.getParameter<bool>("roundToPitch")),
200  pitchStrips_(ps.getParameter<double>("pitchStrips")),
201  pitchDiamonds_(ps.getParameter<double>("pitchDiamonds")),
202  pitchPixels_(ps.getParameter<double>("pitchPixels")),
203 
204  insensitiveMarginStrips_(ps.getParameter<double>("insensitiveMarginStrips")),
205 
206  position_dist_(ps.getParameterSet("position_distribution")),
207  angular_dist_(ps.getParameterSet("angular_distribution")),
208 
209  esTokenGeometry_(esConsumes()) {
210  // v position of strip 0
213 
214  // register the output
215  if (makeHepMC_)
216  produces<HepMCProduct>();
217 
218  if (makeHits_) {
219  produces<DetSetVector<TotemRPRecHit>>();
220  produces<DetSetVector<CTPPSDiamondRecHit>>();
221  produces<DetSetVector<CTPPSPixelRecHit>>();
222  }
223 }
224 
225 //----------------------------------------------------------------------------------------------------
226 
228 
229 //----------------------------------------------------------------------------------------------------
230 
232  CLHEP::HepRandomEngine &rndEng,
233  HepMC::GenEvent *gEv,
237  const CTPPSGeometry &geometry) {
238  // generate track
239  double bx = 0., by = 0., ax = 0., ay = 0.;
240  position_dist_.Generate(rndEng, bx, by);
241  angular_dist_.Generate(rndEng, ax, ay);
242 
243  if (verbosity_ > 5)
244  printf("\tax = %.3f mrad, bx = %.3f mm, ay = %.3f mrad, by = %.3f mm, z0 = %.3f m\n",
245  ax * 1E3,
246  bx,
247  ay * 1E3,
248  by,
249  z0_ * 1E-3);
250 
251  // add HepMC track description
252  if (makeHepMC_) {
253  GenVertex *gVx = new GenVertex(HepMC::FourVector(bx, by, z0_, 0.));
254  gEv->add_vertex(gVx);
255 
256  GenParticle *gPe;
257  double az = sqrt(1. - ax * ax - ay * ay);
258  gPe = new GenParticle(HepMC::FourVector(particle_p_ * ax, particle_p_ * ay, particle_p_ * az, particle_E_),
259  2212,
260  1); // add a proton in final state
261  gPe->suggest_barcode(idx + 1);
262  gVx->add_particle_out(gPe);
263  }
264 
265  if (makeHits_) {
266  // check all sensors known to geometry
267  for (CTPPSGeometry::mapType::const_iterator it = geometry.beginSensor(); it != geometry.endSensor(); ++it) {
268  // get RP decimal id
269  CTPPSDetId detId(it->first);
270  unsigned int decRPId = detId.arm() * 100 + detId.station() * 10 + detId.rp();
271 
272  // stop if the RP is not selected
273  if (find(RPs_.begin(), RPs_.end(), decRPId) == RPs_.end())
274  continue;
275 
276  // keep only 1 diamond channel to represent 1 plane
277  if (detId.subdetId() == CTPPSDetId::sdTimingDiamond) {
278  CTPPSDiamondDetId channelId(it->first);
279  if (channelId.channel() != 0)
280  continue;
281  }
282 
283  if (verbosity_ > 5) {
284  printf(" ");
285  printId(it->first);
286  printf(": ");
287  }
288 
289  // determine the track impact point (in global coordinates)
290  // !! this assumes that local axes (1, 0, 0) and (0, 1, 0) describe the sensor surface
291  const auto gl_o = geometry.localToGlobal(detId, CTPPSGeometry::Vector(0, 0, 0));
292  const auto gl_a1 = geometry.localToGlobal(detId, CTPPSGeometry::Vector(1, 0, 0)) - gl_o;
293  const auto gl_a2 = geometry.localToGlobal(detId, CTPPSGeometry::Vector(0, 1, 0)) - gl_o;
294 
295  TMatrixD A(3, 3);
296  TVectorD B(3);
297  A(0, 0) = ax;
298  A(0, 1) = -gl_a1.x();
299  A(0, 2) = -gl_a2.x();
300  B(0) = gl_o.x() - bx;
301  A(1, 0) = ay;
302  A(1, 1) = -gl_a1.y();
303  A(1, 2) = -gl_a2.y();
304  B(1) = gl_o.y() - by;
305  A(2, 0) = 1.;
306  A(2, 1) = -gl_a1.z();
307  A(2, 2) = -gl_a2.z();
308  B(2) = gl_o.z() - z0_;
309  TMatrixD Ai(3, 3);
310  Ai = A.Invert();
311  TVectorD P(3);
312  P = Ai * B;
313 
314  double de_z = P(0);
315  CTPPSGeometry::Vector h_glo(ax * de_z + bx, ay * de_z + by, de_z + z0_);
316 
317  // hit in local coordinates
318  CTPPSGeometry::Vector h_loc = geometry.globalToLocal(detId, h_glo);
319 
320  // strips
321  if (detId.subdetId() == CTPPSDetId::sdTrackingStrip) {
322  double u = h_loc.x();
323  double v = h_loc.y();
324 
325  if (verbosity_ > 5)
326  printf(" u=%+8.4f, v=%+8.4f", u, v);
327 
328  // is it within detector?
330  if (verbosity_ > 5)
331  printf(" | no hit\n");
332  continue;
333  }
334 
335  // round the measurement
336  if (roundToPitch_) {
337  double m = stripZeroPosition_ - v;
338  signed int strip = (int)floor(m / pitchStrips_ + 0.5);
339 
341 
342  if (verbosity_ > 5)
343  printf(" | strip=%+4i", strip);
344  }
345 
346  double sigma = pitchStrips_ / sqrt(12.);
347 
348  if (verbosity_ > 5)
349  printf(" | m=%+8.4f, sigma=%+8.4f\n", v, sigma);
350 
351  DetSet<TotemRPRecHit> &hits = stripHitColl->find_or_insert(detId);
352  hits.emplace_back(v, sigma);
353  }
354 
355  // diamonds
356  if (detId.subdetId() == CTPPSDetId::sdTimingDiamond) {
357  if (roundToPitch_) {
358  h_loc.SetX(pitchDiamonds_ * floor(h_loc.x() / pitchDiamonds_ + 0.5));
359  }
360 
361  if (verbosity_ > 5)
362  printf(" m = %.3f\n", h_loc.x());
363 
364  const double width = pitchDiamonds_;
365 
366  DetSet<CTPPSDiamondRecHit> &hits = diamondHitColl->find_or_insert(detId);
367  hits.emplace_back(h_loc.x(), width, 0., 0., 0., 0., 0., 0., 0., 0, HPTDCErrorFlags(), false);
368  }
369 
370  // pixels
371  if (detId.subdetId() == CTPPSDetId::sdTrackingPixel) {
372  if (roundToPitch_) {
373  h_loc.SetX(pitchPixels_ * floor(h_loc.x() / pitchPixels_ + 0.5));
374  h_loc.SetY(pitchPixels_ * floor(h_loc.y() / pitchPixels_ + 0.5));
375  }
376 
377  if (verbosity_ > 5)
378  printf(" m1 = %.3f, m2 = %.3f\n", h_loc.x(), h_loc.y());
379 
380  const double sigma = pitchPixels_ / sqrt(12.);
381 
382  const LocalPoint lp(h_loc.x(), h_loc.y(), h_loc.z());
383  const LocalError le(sigma, 0., sigma);
384 
385  DetSet<CTPPSPixelRecHit> &hits = pixelHitColl->find_or_insert(detId);
386  hits.emplace_back(lp, le);
387  }
388  }
389  }
390 }
391 
392 //----------------------------------------------------------------------------------------------------
393 
395  if (verbosity_ > 2)
396  printf(">> PPSFastLocalSimulation::produce > event %llu\n", event.id().event());
397 
399  HepRandomEngine &rndEng = rng->getEngine(event.streamID());
400 
401  if (verbosity_ > 5)
402  printf("\tseed = %li\n", rndEng.getSeed());
403 
404  // get geometry
405  auto const &geometry = es.getData(esTokenGeometry_);
406 
407  // initialize products
408  GenEvent *gEv = new GenEvent();
409  gEv->set_event_number(event.id().event());
410 
411  unique_ptr<DetSetVector<TotemRPRecHit>> stripHitColl(new DetSetVector<TotemRPRecHit>());
412  unique_ptr<DetSetVector<CTPPSDiamondRecHit>> diamondHitColl(new DetSetVector<CTPPSDiamondRecHit>());
413  unique_ptr<DetSetVector<CTPPSPixelRecHit>> pixelHitColl(new DetSetVector<CTPPSPixelRecHit>());
414 
415  // run particle loop
416  for (unsigned int pi = 0; pi < particlesPerEvent_; pi++) {
417  if (verbosity_ > 5)
418  printf(" generating track %u\n", pi);
419 
420  GenerateTrack(pi, rndEng, gEv, stripHitColl, diamondHitColl, pixelHitColl, geometry);
421  }
422 
423  // save products
424  if (makeHepMC_) {
425  unique_ptr<HepMCProduct> hepMCoutput(new HepMCProduct());
426  hepMCoutput->addHepMCData(gEv);
427  event.put(move(hepMCoutput));
428  }
429 
430  if (makeHits_) {
431  event.put(move(stripHitColl));
432  event.put(move(diamondHitColl));
433  event.put(move(pixelHitColl));
434  }
435 }
436 
437 //----------------------------------------------------------------------------------------------------
438 
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
Definition: APVGainStruct.h:7
void produce(edm::Event &, const edm::EventSetup &) override
uint32_t arm() const
Definition: CTPPSDetId.h:57
unsigned int verbosity_
verbosity level
Distribution position_dist_
position parameters in mm
bool makeHits_
whether the hits of the proton shall be calculated and saved
static bool IsHit(double u, double v, double insensitiveMargin=0)
Definition: RPTopology.cc:29
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
std::unique_ptr< T, impl::DeviceDeleter > unique_ptr
static const unsigned short no_of_strips_
Definition: RPTopology.h:53
virtual CLHEP::HepRandomEngine & getEngine(StreamID const &)=0
Use this engine in event methods.
double z0_
the "origin" of tracks, in mm
DetGeomDesc::Translation Vector
Definition: CTPPSGeometry.h:36
const Double_t pi
Fast (no G4) proton simulation in within one station. Uses misaligned geometry.
static const double y_width_
Definition: RPTopology.h:55
bool makeHepMC_
whether a HepMC description of the proton shall be saved in the event
T sqrt(T t)
Definition: SSEVec.h:19
Distribution angular_dist_
angular parameters in rad
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:48
bool getData(T &iHolder) const
Definition: EventSetup.h:122
void Generate(CLHEP::HepRandomEngine &rndEng, double &x, double &y)
bool roundToPitch_
whether measurement values shall be rounded to the nearest strip
The manager class for TOTEM RP geometry.
Definition: CTPPSGeometry.h:30
void printId(unsigned int id)
Definition: Utilities.cc:26
static const double last_strip_to_border_dist_
Definition: RPTopology.h:57
unsigned int particlesPerEvent_
number of particles to generate per event
uint32_t rp() const
Definition: CTPPSDetId.h:71
void GenerateTrack(unsigned int pi, CLHEP::HepRandomEngine &rndEng, HepMC::GenEvent *gEv, std::unique_ptr< edm::DetSetVector< TotemRPRecHit >> &stripHitColl, std::unique_ptr< edm::DetSetVector< CTPPSDiamondRecHit >> &diamondHitColl, std::unique_ptr< edm::DetSetVector< CTPPSPixelRecHit >> &pixelHitColl, const CTPPSGeometry &geometry)
double particle_E_
particle energy and momentum
uint8_t channelId(const VFATFrame &frame)
retrieve this channel identifier
uint32_t station() const
Definition: CTPPSDetId.h:64
std::vector< unsigned int > RPs_
the list of RPs to simulate
std::pair< OmniClusterRef, TrackingParticleRef > P
Base class for CTPPS detector IDs.
Definition: CTPPSDetId.h:32
ParameterSet const & getParameterSet(ParameterSetID const &id)
double stripZeroPosition_
v position of strip 0, in mm
HLT enums.
static const double pitch_
Definition: RPTopology.h:51
Detector ID class for CTPPS Timing Diamond detectors. Bits [19:31] : Assigend in CTPPSDetId Calss Bit...
float x
Definition: APVGainStruct.h:7
PPSFastLocalSimulation(const edm::ParameterSet &)
double insensitiveMarginStrips_
size of insensitive margin at sensor&#39;s edge facing the beam, in mm
enum PPSFastLocalSimulation::Distribution::Type type_
def move(src, dest)
Definition: eostools.py:511
Definition: event.py:1
edm::ESGetToken< CTPPSGeometry, VeryForwardMisalignedGeometryRecord > esTokenGeometry_