CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
CTPPSProtonProducer.cc
Go to the documentation of this file.
1 /****************************************************************************
2  * Authors:
3  * Jan Kašpar
4  * Laurent Forthomme
5  ****************************************************************************/
6 
14 
16 
20 
23 
25 
28 
31 
34 
37 
38 //----------------------------------------------------------------------------------------------------
39 
41 public:
42  explicit CTPPSProtonProducer(const edm::ParameterSet &);
43  ~CTPPSProtonProducer() override = default;
44 
45  static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
46 
47 private:
48  void produce(edm::Event &, const edm::EventSetup &) override;
49 
51 
53 
57 
58  unsigned int verbosity_;
59 
62 
65 
67 
68  unsigned int max_n_timing_tracks_;
69  double default_time_;
70 
72 
75 
80 };
81 
82 //----------------------------------------------------------------------------------------------------
83 
85  : tracksToken_(consumes<CTPPSLocalTrackLiteCollection>(iConfig.getParameter<edm::InputTag>("tagLocalTrackLite"))),
86 
87  pixelDiscardBXShiftedTracks_(iConfig.getParameter<bool>("pixelDiscardBXShiftedTracks")),
88 
89  lhcInfoLabel_(iConfig.getParameter<std::string>("lhcInfoLabel")),
90  opticsLabel_(iConfig.getParameter<std::string>("opticsLabel")),
91  ppsAssociationCutsLabel_(iConfig.getParameter<std::string>("ppsAssociationCutsLabel")),
92  verbosity_(iConfig.getUntrackedParameter<unsigned int>("verbosity", 0)),
93  doSingleRPReconstruction_(iConfig.getParameter<bool>("doSingleRPReconstruction")),
94  doMultiRPReconstruction_(iConfig.getParameter<bool>("doMultiRPReconstruction")),
95  singleRPReconstructionLabel_(iConfig.getParameter<std::string>("singleRPReconstructionLabel")),
96  multiRPReconstructionLabel_(iConfig.getParameter<std::string>("multiRPReconstructionLabel")),
97 
98  localAngleXMin_(iConfig.getParameter<double>("localAngleXMin")),
99  localAngleXMax_(iConfig.getParameter<double>("localAngleXMax")),
100  localAngleYMin_(iConfig.getParameter<double>("localAngleYMin")),
101  localAngleYMax_(iConfig.getParameter<double>("localAngleYMax")),
102 
103  max_n_timing_tracks_(iConfig.getParameter<unsigned int>("max_n_timing_tracks")),
104  default_time_(iConfig.getParameter<double>("default_time")),
105 
106  algorithm_(iConfig.getParameter<bool>("fitVtxY"),
107  iConfig.getParameter<bool>("useImprovedInitialEstimate"),
108  iConfig.getParameter<std::string>("multiRPAlgorithm"),
109  verbosity_),
110  opticsValid_(false),
111  lhcInfoToken_(esConsumes<LHCInfo, LHCInfoRcd>(edm::ESInputTag("", lhcInfoLabel_))),
113  edm::ESInputTag("", opticsLabel_))),
115  ppsAssociationCutsToken_(
116  esConsumes<PPSAssociationCuts, PPSAssociationCutsRcd>(edm::ESInputTag("", ppsAssociationCutsLabel_))) {
118  produces<reco::ForwardProtonCollection>(singleRPReconstructionLabel_);
119 
121  produces<reco::ForwardProtonCollection>(multiRPReconstructionLabel_);
122 }
123 
124 //----------------------------------------------------------------------------------------------------
125 
128 
129  desc.add<edm::InputTag>("tagLocalTrackLite", edm::InputTag("ctppsLocalTrackLiteProducer"))
130  ->setComment("specification of the input lite-track collection");
131 
132  desc.add<bool>("pixelDiscardBXShiftedTracks", false)
133  ->setComment("whether to discard pixel tracks built from BX-shifted planes");
134 
135  desc.add<std::string>("lhcInfoLabel", "")->setComment("label of the LHCInfo record");
136  desc.add<std::string>("opticsLabel", "")->setComment("label of the optics record");
137  desc.add<std::string>("ppsAssociationCutsLabel", "")->setComment("label of the association cuts record");
138 
139  desc.addUntracked<unsigned int>("verbosity", 0)->setComment("verbosity level");
140 
141  desc.add<bool>("doSingleRPReconstruction", true)
142  ->setComment("flag whether to apply single-RP reconstruction strategy");
143 
144  desc.add<bool>("doMultiRPReconstruction", true)->setComment("flag whether to apply multi-RP reconstruction strategy");
145 
146  desc.add<std::string>("singleRPReconstructionLabel", "singleRP")
147  ->setComment("output label for single-RP reconstruction products");
148 
149  desc.add<std::string>("multiRPReconstructionLabel", "multiRP")
150  ->setComment("output label for multi-RP reconstruction products");
151 
152  desc.add<double>("localAngleXMin", -0.03)->setComment("minimal accepted value of local horizontal angle (rad)");
153  desc.add<double>("localAngleXMax", +0.03)->setComment("maximal accepted value of local horizontal angle (rad)");
154  desc.add<double>("localAngleYMin", -0.04)->setComment("minimal accepted value of local vertical angle (rad)");
155  desc.add<double>("localAngleYMax", +0.04)->setComment("maximal accepted value of local vertical angle (rad)");
156 
157  std::vector<edm::ParameterSet> config;
158 
159  desc.add<unsigned int>("max_n_timing_tracks", 5)->setComment("maximum number of timing tracks per RP");
160 
161  desc.add<double>("default_time", 0.)->setComment("proton time to be used when no timing information available");
162 
163  desc.add<bool>("fitVtxY", true)
164  ->setComment("for multi-RP reconstruction, flag whether y* should be free fit parameter");
165 
166  desc.add<bool>("useImprovedInitialEstimate", true)
167  ->setComment(
168  "for multi-RP reconstruction, flag whether a quadratic estimate of the initial point should be used");
169 
170  desc.add<std::string>("multiRPAlgorithm", "chi2")
171  ->setComment("algorithm for multi-RP reco, options include chi2, newton, anal-iter");
172 
173  descriptions.add("ctppsProtons", desc);
174 }
175 
176 //----------------------------------------------------------------------------------------------------
177 
179  // get input
181  iEvent.getByToken(tracksToken_, hTracks);
182 
183  // book output
184  std::unique_ptr<reco::ForwardProtonCollection> pOutSingleRP(new reco::ForwardProtonCollection);
185  std::unique_ptr<reco::ForwardProtonCollection> pOutMultiRP(new reco::ForwardProtonCollection);
186 
187  // continue only if there is something to process
188  // NB: this avoids loading (possibly non-existing) conditions in workflows without proton data
189  if (!hTracks->empty()) {
190  // get conditions
192 
195 
197 
199 
200  // re-initialise algorithm upon crossing-angle change
201  if (opticsWatcher_.check(iSetup)) {
202  if (hOpticalFunctions->empty()) {
203  edm::LogInfo("CTPPSProtonProducer") << "No optical functions available, reconstruction disabled.";
205  opticsValid_ = false;
206  } else {
207  algorithm_.init(*hOpticalFunctions);
208  opticsValid_ = true;
209  }
210  }
211 
212  // do reconstruction only if optics is valid
213  if (opticsValid_) {
214  // prepare log
215  std::ostringstream ssLog;
216  if (verbosity_)
217  ssLog << "* input tracks:" << std::endl;
218 
219  // select tracks with small local angles, split them by LHC sector and tracker/timing RPs
220  std::map<unsigned int, std::vector<unsigned int>> trackingSelection, timingSelection;
221 
222  for (unsigned int idx = 0; idx < hTracks->size(); ++idx) {
223  const auto &tr = hTracks->at(idx);
224 
225  if (tr.tx() < localAngleXMin_ || tr.tx() > localAngleXMax_ || tr.ty() < localAngleYMin_ ||
226  tr.ty() > localAngleYMax_)
227  continue;
228 
230  if (tr.pixelTrackRecoInfo() == CTPPSpixelLocalTrackReconstructionInfo::allShiftedPlanes ||
231  tr.pixelTrackRecoInfo() == CTPPSpixelLocalTrackReconstructionInfo::mixedPlanes)
232  continue;
233  }
234 
235  const CTPPSDetId rpId(tr.rpId());
236 
237  if (verbosity_)
238  ssLog << "\t"
239  << "[" << idx << "] " << tr.rpId() << " (" << (rpId.arm() * 100 + rpId.station() * 10 + rpId.rp())
240  << "): "
241  << "x=" << tr.x() << " +- " << tr.xUnc() << " mm, "
242  << "y=" << tr.y() << " +- " << tr.yUnc() << " mm" << std::endl;
243 
244  const bool trackerRP =
245  (rpId.subdetId() == CTPPSDetId::sdTrackingStrip || rpId.subdetId() == CTPPSDetId::sdTrackingPixel);
246 
247  if (trackerRP)
248  trackingSelection[rpId.arm()].push_back(idx);
249  else
250  timingSelection[rpId.arm()].push_back(idx);
251  }
252 
253  // process each arm
254  for (const auto &arm_it : trackingSelection) {
255  const auto &indices = arm_it.second;
256 
257  const auto &ac = ppsAssociationCuts->getAssociationCuts(arm_it.first);
258 
259  // do single-RP reco if needed
260  std::map<unsigned int, reco::ForwardProton> singleRPResultsIndexed;
261  if (doSingleRPReconstruction_ || ac.isApplied(ac.qXi) || ac.isApplied(ac.qThetaY)) {
262  for (const auto &idx : indices) {
263  if (verbosity_)
264  ssLog << std::endl << "* reconstruction from track " << idx << std::endl;
265 
266  singleRPResultsIndexed[idx] =
267  algorithm_.reconstructFromSingleRP(CTPPSLocalTrackLiteRef(hTracks, idx), *hLHCInfo, ssLog);
268  }
269  }
270 
271  // check that exactly two tracking RPs are involved
272  // - 1 is insufficient for multi-RP reconstruction
273  // - PPS did not use more than 2 tracking RPs per arm -> algorithms are tuned to this
274  std::set<unsigned int> rpIds;
275  for (const auto &idx : indices)
276  rpIds.insert(hTracks->at(idx).rpId());
277 
278  // do multi-RP reco if chosen
279  if (doMultiRPReconstruction_ && rpIds.size() == 2) {
280  // find matching track pairs from different tracking RPs, ordered: i=near, j=far RP
281  std::vector<std::pair<unsigned int, unsigned int>> idx_pairs;
282  std::map<unsigned int, unsigned int> idx_pair_multiplicity;
283  for (const auto &i : indices) {
284  for (const auto &j : indices) {
285  const auto &tr_i = hTracks->at(i);
286  const auto &tr_j = hTracks->at(j);
287 
288  const double z_i = hGeometry->rpTranslation(tr_i.rpId()).z();
289  const double z_j = hGeometry->rpTranslation(tr_j.rpId()).z();
290 
291  const auto &pr_i = singleRPResultsIndexed[i];
292  const auto &pr_j = singleRPResultsIndexed[j];
293 
294  if (tr_i.rpId() == tr_j.rpId())
295  continue;
296 
297  if (std::abs(z_i) >= std::abs(z_j))
298  continue;
299 
300  bool matching = true;
301 
302  if (!ac.isSatisfied(ac.qX, tr_i.x(), tr_i.y(), hLHCInfo->crossingAngle(), tr_i.x() - tr_j.x()))
303  matching = false;
304  else if (!ac.isSatisfied(ac.qY, tr_i.x(), tr_i.y(), hLHCInfo->crossingAngle(), tr_i.y() - tr_j.y()))
305  matching = false;
306  else if (!ac.isSatisfied(ac.qXi, tr_i.x(), tr_i.y(), hLHCInfo->crossingAngle(), pr_i.xi() - pr_j.xi()))
307  matching = false;
308  else if (!ac.isSatisfied(
309  ac.qThetaY, tr_i.x(), tr_i.y(), hLHCInfo->crossingAngle(), pr_i.thetaY() - pr_j.thetaY()))
310  matching = false;
311 
312  if (!matching)
313  continue;
314 
315  idx_pairs.emplace_back(i, j);
316  idx_pair_multiplicity[i]++;
317  idx_pair_multiplicity[j]++;
318  }
319  }
320 
321  // evaluate track multiplicity in each timing RP
322  std::map<unsigned int, unsigned int> timing_RP_track_multiplicity;
323  for (const auto &ti : timingSelection[arm_it.first]) {
324  const auto &tr = hTracks->at(ti);
325  timing_RP_track_multiplicity[tr.rpId()]++;
326  }
327 
328  // associate tracking-RP pairs with timing-RP tracks
329  std::map<unsigned int, std::vector<unsigned int>> matched_timing_track_indices;
330  std::map<unsigned int, unsigned int> matched_timing_track_multiplicity;
331  for (unsigned int pr_idx = 0; pr_idx < idx_pairs.size(); ++pr_idx) {
332  const auto &i = idx_pairs[pr_idx].first;
333  const auto &j = idx_pairs[pr_idx].second;
334 
335  // skip non-unique associations
336  if (idx_pair_multiplicity[i] > 1 || idx_pair_multiplicity[j] > 1)
337  continue;
338 
339  const auto &tr_i = hTracks->at(i);
340  const auto &tr_j = hTracks->at(j);
341 
342  const double z_i = hGeometry->rpTranslation(tr_i.rpId()).z();
343  const double z_j = hGeometry->rpTranslation(tr_j.rpId()).z();
344 
345  for (const auto &ti : timingSelection[arm_it.first]) {
346  const auto &tr_ti = hTracks->at(ti);
347 
348  // skip if timing RP saturated (high track multiplicity)
349  if (timing_RP_track_multiplicity[tr_ti.rpId()] > max_n_timing_tracks_)
350  continue;
351 
352  // interpolation from tracking RPs
353  const double z_ti = hGeometry->rpTranslation(tr_ti.rpId()).z();
354  const double f_i = (z_ti - z_j) / (z_i - z_j), f_j = (z_i - z_ti) / (z_i - z_j);
355  const double x_inter = f_i * tr_i.x() + f_j * tr_j.x();
356  const double x_inter_unc_sq =
357  f_i * f_i * tr_i.xUnc() * tr_i.xUnc() + f_j * f_j * tr_j.xUnc() * tr_j.xUnc();
358 
359  const double de_x = tr_ti.x() - x_inter;
360  const double de_x_unc = sqrt(tr_ti.xUnc() * tr_ti.xUnc() + x_inter_unc_sq);
361  const double r = (de_x_unc > 0.) ? de_x / de_x_unc : 1E100;
362 
363  const bool matching = (ac.getTiTrMin() < r && r < ac.getTiTrMax());
364 
365  if (verbosity_)
366  ssLog << "ti=" << ti << ", i=" << i << ", j=" << j << " | z_ti=" << z_ti << ", z_i=" << z_i
367  << ", z_j=" << z_j << " | x_ti=" << tr_ti.x() << ", x_inter=" << x_inter << ", de_x=" << de_x
368  << ", de_x_unc=" << de_x_unc << ", matching=" << matching << std::endl;
369 
370  if (!matching)
371  continue;
372 
373  matched_timing_track_indices[pr_idx].push_back(ti);
374  matched_timing_track_multiplicity[ti]++;
375  }
376  }
377 
378  // process associated tracks
379  for (unsigned int pr_idx = 0; pr_idx < idx_pairs.size(); ++pr_idx) {
380  const auto &i = idx_pairs[pr_idx].first;
381  const auto &j = idx_pairs[pr_idx].second;
382 
383  // skip non-unique associations of tracking-RP tracks
384  if (idx_pair_multiplicity[i] > 1 || idx_pair_multiplicity[j] > 1)
385  continue;
386 
387  if (verbosity_)
388  ssLog << std::endl
389  << "* reconstruction from tracking-RP tracks: " << i << ", " << j << " and timing-RP tracks: ";
390 
391  // buffer contributing tracks
392  CTPPSLocalTrackLiteRefVector sel_tracks;
393  sel_tracks.push_back(CTPPSLocalTrackLiteRef(hTracks, i));
394  sel_tracks.push_back(CTPPSLocalTrackLiteRef(hTracks, j));
395 
396  CTPPSLocalTrackLiteRefVector sel_track_for_kin_reco = sel_tracks;
397 
398  // process timing-RP data
399  double sw = 0., swt = 0.;
400  for (const auto &ti : matched_timing_track_indices[pr_idx]) {
401  // skip non-unique associations of timing-RP tracks
402  if (matched_timing_track_multiplicity[ti] > 1)
403  continue;
404 
405  sel_tracks.push_back(CTPPSLocalTrackLiteRef(hTracks, ti));
406 
407  if (verbosity_)
408  ssLog << ti << ", ";
409 
410  const auto &tr = hTracks->at(ti);
411  const double t_unc = tr.timeUnc();
412  const double w = (t_unc > 0.) ? 1. / t_unc / t_unc : 1.;
413  sw += w;
414  swt += w * tr.time();
415  }
416 
417  float time = default_time_, time_unc = 0.;
418  if (sw > 0.) {
419  time = swt / sw;
420  time_unc = 1. / sqrt(sw);
421  }
422 
423  if (verbosity_)
424  ssLog << std::endl << " time = " << time << " +- " << time_unc << std::endl;
425 
426  // process tracking-RP data
427  reco::ForwardProton proton = algorithm_.reconstructFromMultiRP(sel_track_for_kin_reco, *hLHCInfo, ssLog);
428 
429  // save combined output
430  proton.setContributingLocalTracks(sel_tracks);
431  proton.setTime(time);
432  proton.setTimeError(time_unc);
433 
434  pOutMultiRP->emplace_back(proton);
435  }
436  }
437 
438  // save single-RP results (un-indexed)
439  for (const auto &p : singleRPResultsIndexed)
440  pOutSingleRP->emplace_back(p.second);
441  }
442 
443  // dump log
444  if (verbosity_)
445  edm::LogInfo("CTPPSProtonProducer") << ssLog.str();
446  }
447  }
448 
449  // save output
451  iEvent.put(std::move(pOutSingleRP), singleRPReconstructionLabel_);
452 
454  iEvent.put(std::move(pOutMultiRP), multiRPReconstructionLabel_);
455 }
456 
457 //----------------------------------------------------------------------------------------------------
458 
void setComment(std::string const &value)
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:133
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
const double w
Definition: UKUtility.cc:23
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:539
reco::ForwardProton reconstructFromSingleRP(const CTPPSLocalTrackLiteRef &track, const LHCInfo &lhcInfo, std::ostream &os) const
run proton reconstruction using single-RP strategy
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
edm::ESGetToken< CTPPSGeometry, VeryForwardRealGeometryRecord > geometryToken_
~CTPPSProtonProducer() override=default
unsigned int max_n_timing_tracks_
Event setup record containing the real (actual) geometry information.
void init(const LHCInterpolatedOpticalFunctionsSetCollection &opticalFunctions)
CTPPSDetId rpId() const
Definition: CTPPSDetId.h:78
std::string ppsAssociationCutsLabel_
int iEvent
Definition: GenABIO.cc:224
void setTimeError(float time_err)
T sqrt(T t)
Definition: SSEVec.h:19
reco::ForwardProton reconstructFromMultiRP(const CTPPSLocalTrackLiteRefVector &tracks, const LHCInfo &lhcInfo, std::ostream &os) const
run proton reconstruction using multiple-RP strategy
def move
Definition: eostools.py:511
CTPPSProtonProducer(const edm::ParameterSet &)
edm::ESWatcher< CTPPSInterpolatedOpticsRcd > opticsWatcher_
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
edm::Ref< CTPPSLocalTrackLiteCollection > CTPPSLocalTrackLiteRef
Persistent reference to a CTPPSLocalTrackLite.
void setTime(float time)
ParameterDescriptionBase * add(U const &iLabel, T const &value)
The manager class for TOTEM RP geometry.
Definition: CTPPSGeometry.h:30
Log< level::Info, false > LogInfo
std::vector< CTPPSLocalTrackLite > CTPPSLocalTrackLiteCollection
Collection of CTPPSLocalTrackLite objects.
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void produce(edm::Event &, const edm::EventSetup &) override
bool check(const edm::EventSetup &iSetup)
Definition: ESWatcher.h:57
Base class for CTPPS detector IDs.
Definition: CTPPSDetId.h:32
tuple config
parse the configuration file
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
ProtonReconstructionAlgorithm algorithm_
edm::ESGetToken< PPSAssociationCuts, PPSAssociationCutsRcd > ppsAssociationCutsToken_
void push_back(value_type const &ref)
Add a Ref&lt;C, T&gt; to the RefVector.
Definition: RefVector.h:67
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:157
std::vector< ForwardProton > ForwardProtonCollection
Collection of ForwardProton objects.
list indices
Definition: dqmdumpme.py:50
void setContributingLocalTracks(const CTPPSLocalTrackLiteRefVector &v)
store the list of RP tracks that contributed to this global track
ESGetTokenH3DDVariant esConsumes(std::string const &Reccord, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
std::string singleRPReconstructionLabel_
std::string multiRPReconstructionLabel_
edm::EDGetTokenT< CTPPSLocalTrackLiteCollection > tracksToken_
edm::ESGetToken< LHCInfo, LHCInfoRcd > lhcInfoToken_
edm::ESGetToken< LHCInterpolatedOpticalFunctionsSetCollection, CTPPSInterpolatedOpticsRcd > opticalFunctionsToken_