CMS 3D CMS Logo

SiStripCPEAnalyzer.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: CalibTracker/SiStripHitResolution
4 // Class: SiStripCPEAnalyzer
5 //
13 //
14 // Original Author: Christophe Delaere
15 // Created: Thu, 12 Sep 2019 13:51:00 GMT
16 //
17 //
18 
19 // system include files
20 #include <memory>
21 #include <iostream>
22 #include <algorithm>
23 
24 // user include files
47 
48 #include "TH1.h"
49 #include "TTree.h"
50 
51 //
52 // class declaration
53 //
54 
56 typedef std::vector<Trajectory> TrajectoryCollection;
57 
58 struct CPEBranch {
59  float x, y, z;
61  float x1r, x2r, x1m, x2m, y1m, y2m;
62 };
63 
64 struct TrackBranch {
65  float px, py, pz, pt, eta, phi, charge;
66 };
67 
70  float pitch;
71  int detid;
72 };
73 
74 struct ClusterBranch {
75  int strips[11];
77  float barycenter;
78 };
79 
80 class SiStripCPEAnalyzer : public edm::one::EDAnalyzer<edm::one::SharedResources> {
81 public:
82  explicit SiStripCPEAnalyzer(const edm::ParameterSet&);
83  ~SiStripCPEAnalyzer() override = default;
84 
85  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
86 
87 private:
88  void analyze(const edm::Event&, const edm::EventSetup&) override;
89  static bool goodMeasurement(TrajectoryMeasurement const& m);
90 
91  // ----------member data ---------------------------
92 
93  // tokens for event data
94  const edm::EDGetTokenT<TrackCollection> tracksToken_; //used to select what tracks to read from configuration file
96  trajsToken_; //used to select what trajectories to read from configuration file
97  const edm::EDGetTokenT<TrajTrackAssociationCollection> tjTagToken_; //association map between tracks and trajectories
99 
100  // tokens for ES data
105 
107 
108  // to fill the tree
109  TTree* tree_;
116 };
117 
118 //
119 // constructors and destructor
120 //
122  : tracksToken_(consumes<TrackCollection>(iConfig.getUntrackedParameter<edm::InputTag>("tracks"))),
123  trajsToken_(consumes<TrajectoryCollection>(iConfig.getUntrackedParameter<edm::InputTag>("trajectories"))),
124  tjTagToken_(
125  consumes<TrajTrackAssociationCollection>(iConfig.getUntrackedParameter<edm::InputTag>("association"))),
126  clusToken_(
127  consumes<edmNew::DetSetVector<SiStripCluster> >(iConfig.getUntrackedParameter<edm::InputTag>("clusters"))),
128  cpeTag_(iConfig.getParameter<edm::ESInputTag>("StripCPE")),
129  cpeToken_(esConsumes(cpeTag_)),
130  topoToken_(esConsumes()),
131  geomToken_(esConsumes()) {
132  //now do what ever initialization is needed
133  usesResource("TFileService");
135  //histo = fs->make<TH1I>("charge" , "Charges" , 3 , -1 , 2 );
136  tree_ = fs->make<TTree>("CPEanalysis", "CPE analysis tree");
137  tree_->Branch(
138  "Overlaps", &treeBranches_, "x:y:z:distance:mdistance:shift:offsetA:offsetB:angle:x1r:x2r:x1m:x2m:y1m:y2m");
139  tree_->Branch("Tracks", &trackBranches_, "px:py:pz:pt:eta:phi:charge");
140  tree_->Branch("Cluster1", &cluster1Branches_, "strips[11]/I:size/I:firstStrip/I:barycenter/F");
141  tree_->Branch("Cluster2", &cluster2Branches_, "strips[11]/I:size/I:firstStrip/I:barycenter/F");
142  tree_->Branch("Geom1", &geom1Branches_, "subdet/I:moduleGeometry/I:stereo/I:layer/I:side/I:ring/I:pitch/F:detid/I");
143  tree_->Branch("Geom2", &geom2Branches_, "subdet/I:moduleGeometry/I:stereo/I:layer/I:side/I:ring/I:pitch/F:detid/I");
144 }
145 
146 //
147 // member functions
148 //
149 // ------------ method called for each event ------------
151  using namespace edm;
152 
153  // load the CPE, geometry and topology
154  parameterestimator_ = &iSetup.getData(cpeToken_); //CPE
155  const TrackerGeometry* tracker = &iSetup.getData(geomToken_);
156  const TrackerTopology* const tTopo = &iSetup.getData(topoToken_);
157 
158  // prepare the output
159  std::vector<SiStripOverlapHit> hitpairs;
160 
161  // loop on trajectories and tracks
162  //for(const auto& tt : iEvent.get(tjTagToken_) ) {
163  edm::Handle<TrajTrackAssociationCollection> trajTrackAssociations;
164  iEvent.getByToken(tjTagToken_, trajTrackAssociations);
165  for (const auto& tt : *trajTrackAssociations) {
166  auto& traj = *(tt.key);
167  auto& track = *(tt.val);
168  // track quantities
169  trackBranches_.px = track.px();
170  trackBranches_.py = track.py();
171  trackBranches_.pz = track.pz();
172  trackBranches_.pt = track.pt();
173  trackBranches_.eta = track.eta();
174  trackBranches_.phi = track.phi();
175  trackBranches_.charge = track.charge();
176  // loop on measurements
177  for (auto it = traj.measurements().begin(); it != traj.measurements().end(); ++it) {
178  auto& meas = *it;
179 
180  // only OT measurements on valid hits (not glued det)
181  if (!goodMeasurement(meas))
182  continue;
183 
184  // restrict the search for compatible hits in the same layer (measurements are sorted by layer)
185  auto layerRangeEnd = it + 1;
186  for (; layerRangeEnd < traj.measurements().end(); ++layerRangeEnd) {
187  if (layerRangeEnd->layer()->seqNum() != meas.layer()->seqNum())
188  break;
189  }
190 
191  // now look for a matching hit in that range.
192  auto meas2it = std::find_if(it + 1, layerRangeEnd, [meas](const TrajectoryMeasurement& m) -> bool {
193  return goodMeasurement(m) && (m.recHit()->rawId() & 0x3) == (meas.recHit()->rawId() & 0x3);
194  });
195 
196  // check if we found something, build a pair object and add to vector
197  if (meas2it != layerRangeEnd) {
198  auto& meas2 = *meas2it;
199  hitpairs.push_back(SiStripOverlapHit(meas, meas2));
200  }
201  }
202  }
203 
204  // load clusters
206  iEvent.getByToken(clusToken_, clusters);
207 
208  // At this stage we will have a vector of pairs of measurement. Fill a ntuple and some histograms.
209  for (const auto& pair : hitpairs) {
210  //TODO basically everything below is done twice. -> can be factorized.
211 
212  // store generic information about the pair
213  treeBranches_.x = pair.position().x();
214  treeBranches_.y = pair.position().y();
215  treeBranches_.z = pair.position().z();
216  treeBranches_.distance = pair.distance(false);
217  treeBranches_.mdistance = pair.distance(true);
218  treeBranches_.shift = pair.shift();
219  treeBranches_.offsetA = pair.offset(0);
220  treeBranches_.offsetB = pair.offset(1);
221  treeBranches_.angle = pair.getTrackLocalAngle(0);
222  treeBranches_.x1r = pair.hitA()->localPosition().x();
223  treeBranches_.x1m = pair.trajectoryStateOnSurface(0, false).localPosition().x();
224  treeBranches_.y1m = pair.trajectoryStateOnSurface(0, false).localPosition().y();
225  treeBranches_.x2r = pair.hitB()->localPosition().x();
226  treeBranches_.x2m = pair.trajectoryStateOnSurface(1, false).localPosition().x();
227  treeBranches_.y2m = pair.trajectoryStateOnSurface(1, false).localPosition().y();
228 
229  // load the clusters for the detectors
230  auto detset1 = (*clusters)[pair.hitA()->rawId()];
231  auto detset2 = (*clusters)[pair.hitB()->rawId()];
232 
233  // look for the proper cluster
234  const GeomDetUnit* du;
235  du = tracker->idToDetUnit(pair.hitA()->rawId());
236  auto cluster1 = std::min_element(
237  detset1.begin(), detset1.end(), [du, this](SiStripCluster const& cl1, SiStripCluster const& cl2) {
238  return (fabs(parameterestimator_->localParameters(cl1, *du).first.x() - treeBranches_.x1r) <
239  fabs(parameterestimator_->localParameters(cl2, *du).first.x() - treeBranches_.x1r));
240  });
241  du = tracker->idToDetUnit(pair.hitB()->rawId());
242  auto cluster2 = std::min_element(
243  detset2.begin(), detset2.end(), [du, this](SiStripCluster const& cl1, SiStripCluster const& cl2) {
244  return (fabs(parameterestimator_->localParameters(cl1, *du).first.x() - treeBranches_.x2r) <
245  fabs(parameterestimator_->localParameters(cl2, *du).first.x() - treeBranches_.x2r));
246  });
247 
248  // store the amplitudes centered around the maximum
249  auto amplitudes1 = cluster1->amplitudes();
250  auto amplitudes2 = cluster2->amplitudes();
251  auto max1 = std::max_element(amplitudes1.begin(), amplitudes1.end());
252  auto max2 = std::max_element(amplitudes2.begin(), amplitudes2.end());
253  for (unsigned int i = 0; i < 11; ++i) {
254  cluster1Branches_.strips[i] = 0.;
255  cluster2Branches_.strips[i] = 0.;
256  }
257  cluster1Branches_.size = amplitudes1.size();
258  cluster2Branches_.size = amplitudes2.size();
259  cluster1Branches_.firstStrip = cluster1->firstStrip();
260  cluster1Branches_.barycenter = cluster1->barycenter();
261  cluster2Branches_.firstStrip = cluster2->firstStrip();
262  cluster2Branches_.barycenter = cluster2->barycenter();
263 
264  int cnt = 0;
265  int offset = 5 - (max1 - amplitudes1.begin());
266  for (auto& s : amplitudes1) {
267  if ((offset + cnt) >= 0 && (offset + cnt) < 11) {
268  cluster1Branches_.strips[offset + cnt] = s;
269  }
270  cnt++;
271  }
272  cnt = 0;
273  offset = 5 - (max2 - amplitudes2.begin());
274  for (auto& s : amplitudes2) {
275  if ((offset + cnt) >= 0 && (offset + cnt) < 11) {
276  cluster2Branches_.strips[offset + cnt] = s;
277  }
278  cnt++;
279  }
280 
281  // store information about the geometry (for both sensors)
282  DetId detid1 = pair.hitA()->geographicalId();
283  DetId detid2 = pair.hitB()->geographicalId();
284  geom1Branches_.detid = detid1.rawId();
285  geom2Branches_.detid = detid2.rawId();
286  geom1Branches_.subdet = detid1.subdetId();
287  geom2Branches_.subdet = detid2.subdetId();
288  //geom1Branches_.moduleGeometry = tTopo->moduleGeometry(detid1);
289  //geom2Branches_.moduleGeometry = tTopo->moduleGeometry(detid2);
290  geom1Branches_.stereo = tTopo->isStereo(detid1);
291  geom2Branches_.stereo = tTopo->isStereo(detid2);
292  geom1Branches_.layer = tTopo->layer(detid1);
293  geom2Branches_.layer = tTopo->layer(detid2);
294  geom1Branches_.side = tTopo->side(detid1);
295  geom2Branches_.side = tTopo->side(detid2);
297  geom1Branches_.ring = tTopo->tidRing(detid1);
299  geom1Branches_.ring = tTopo->tecRing(detid1);
300  } else {
301  geom1Branches_.ring = 0;
302  }
304  geom2Branches_.ring = tTopo->tidRing(detid2);
306  geom2Branches_.ring = tTopo->tecRing(detid2);
307  } else {
308  geom2Branches_.ring = 0;
309  }
310 
311  const StripGeomDetUnit* theStripDet;
312  theStripDet = dynamic_cast<const StripGeomDetUnit*>(tracker->idToDetUnit(pair.hitA()->rawId()));
314  theStripDet->specificTopology().localPitch(pair.trajectoryStateOnSurface(0, false).localPosition());
315  theStripDet = dynamic_cast<const StripGeomDetUnit*>(tracker->idToDetUnit(pair.hitB()->rawId()));
317  theStripDet->specificTopology().localPitch(pair.trajectoryStateOnSurface(1, false).localPosition());
318 
319  //fill the tree.
320  tree_->Fill(); // we fill one entry per overlap, to track info is multiplicated
321  }
322 }
323 
324 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
327  desc.addUntracked<edm::InputTag>("tracks", edm::InputTag("generalTracks"));
328  desc.addUntracked<edm::InputTag>("trajectories", edm::InputTag("generalTracks"));
329  desc.addUntracked<edm::InputTag>("association", edm::InputTag("generalTracks"));
330  desc.addUntracked<edm::InputTag>("clusters", edm::InputTag("siStripClusters"));
331  desc.add<edm::ESInputTag>("StripCPE", edm::ESInputTag("StripCPEfromTrackAngleESProducer", "StripCPEfromTrackAngle"));
332  descriptions.addWithDefaultLabel(desc);
333 }
334 
336  return m.recHit()->isValid() && // valid
337  m.recHit()->geographicalId().subdetId() > 2 && // not IT
338  (m.recHit()->rawId() & 0x3) != 0 && // not glued DetLayer
339  m.recHit()->getType() == 0; // only valid hits (redundant?)
340 }
341 
342 //define this as a plug-in
static constexpr auto TEC
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
const edm::ESGetToken< TrackerTopology, TrackerTopologyRcd > topoToken_
virtual void localParameters(AClusters const &clusters, ALocalValues &retValues, const GeomDetUnit &gd, const LocalTrajectoryParameters &ltp) const
ClusterBranch cluster2Branches_
std::vector< Track > TrackCollection
collection of Tracks
Definition: TrackFwd.h:14
SiStripCPEAnalyzer(const edm::ParameterSet &)
void analyze(const edm::Event &, const edm::EventSetup &) override
bool isStereo(const DetId &id) const
const edm::EDGetTokenT< TrajectoryCollection > trajsToken_
unsigned int side(const DetId &id) const
const edm::ESGetToken< TrackerGeometry, TrackerDigiGeometryRecord > geomToken_
unsigned int tecRing(const DetId &id) const
ring id
unsigned int layer(const DetId &id) const
virtual float localPitch(const LocalPoint &) const =0
const edm::ESGetToken< StripClusterParameterEstimator, TkStripCPERecord > cpeToken_
int iEvent
Definition: GenABIO.cc:224
Definition: TTTypes.h:54
~SiStripCPEAnalyzer() override=default
virtual const StripTopology & specificTopology() const
Returns a reference to the strip proxy topology.
static bool goodMeasurement(TrajectoryMeasurement const &m)
#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
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const edm::EDGetTokenT< TrajTrackAssociationCollection > tjTagToken_
Definition: DetId.h:17
const edm::EDGetTokenT< edmNew::DetSetVector< SiStripCluster > > clusToken_
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
GeometryBranch geom2Branches_
const edm::ESInputTag cpeTag_
GeometryBranch geom1Branches_
HLT enums.
std::vector< Trajectory > TrajectoryCollection
unsigned int tidRing(const DetId &id) const
const edm::EDGetTokenT< TrackCollection > tracksToken_
static constexpr auto TID
const StripClusterParameterEstimator * parameterestimator_
ClusterBranch cluster1Branches_