Belle II Software development
PXDDQMEfficiencyNtupleModule.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <pxd/modules/pxdDQM/PXDDQMEfficiencyNtupleModule.h>
10#include <pxd/dataobjects/PXDCluster.h>
11#include <tracking/dataobjects/ROIid.h>
12#include <tracking/dataobjects/RecoTrack.h>
13#include <tracking/dataobjects/PXDIntercept.h>
14
15#include <pxd/reconstruction/PXDPixelMasker.h>
16#include <mdst/dataobjects/Track.h>
17#include <framework/gearbox/Const.h>
18
19#include "TMatrixDSym.h"
20#include <Math/Vector3D.h>
21
22using namespace Belle2;
23
24//-----------------------------------------------------------------
25// Register the Module
26//-----------------------------------------------------------------
27REG_MODULE(PXDDQMEfficiencyNtuple);
28
29//-----------------------------------------------------------------
30// Implementation
31//-----------------------------------------------------------------
32
34{
35 // Set module properties
36 setDescription("Create basic histograms for PXD efficiency");
37
38 // setPropertyFlags(c_ParallelProcessingCertified);// for ntuple not certified!!!
39
40 // Parameter definitions
41 addParam("ntupleName", m_ntupleName, "name of ntuple file", std::string("test.root"));
42 addParam("pxdClustersName", m_pxdClustersName, "name of StoreArray with PXD cluster", std::string(""));
43 addParam("recoTracksName", m_recoTracksName, "name of StoreArray with RecoTracks", std::string(""));
44 addParam("tracksName", m_tracksName, "name of StoreArray with Tracks", std::string(""));
45 addParam("ROIsName", m_ROIsName, "name of the list of HLT ROIs, if available in output", std::string(""));
46 addParam("PXDInterceptListName", m_PXDInterceptListName, "name of the list of interceptions", std::string(""));
47 addParam("useAlignment", m_useAlignment, "if true the alignment will be used", true);
48 addParam("pCut", m_pcut, "Set a cut on the track fit p-value (0=no cut)", double(0));
49 addParam("minSVDHits", m_minSVDHits, "Number of SVD hits required in a track to be considered", 0u);
50 addParam("momCut", m_momCut, "Set a cut on the track momentum in GeV/c, 0 disables", double(0));
51 addParam("pTCut", m_pTCut, "Set a cut on the track pT in GeV/c, 0 disables", double(0));
52 addParam("maskedDistance", m_maskedDistance, "Distance inside which no masked pixel or sensor border is allowed", int(10));
53}
54
55
57{
58 auto dir = gDirectory;
59 if (m_tuple) {
60 if (m_file) { // no file -> no write to file
61 m_file->cd();
62 }
63 m_tuple->Write();
64 delete m_tuple;
65 m_tuple = nullptr;
66 }
67 if (m_file) {
68 m_file->Write();
69 m_file->Close();
70 delete m_file;
71 m_file = nullptr;
72 }
73 dir->cd();
74}
75
76
78{
79 m_file = new TFile(m_ntupleName.data(), "recreate");
80 if (m_file) m_file->cd();
81 m_tuple = new TNtuple("effcontrol", "effcontrol",
82 "vxdid:u:v:p:pt:distu:distv:sigu:sigv:dist:inroi:clborder:cldead:matched:z0:d0:svdhits:charge:phi:costheta");
83
84 //register the required arrays
85 //Register as optional so validation for cases where they are not available still succeeds, but module will not do any meaningful work without them
88 m_tracks.isOptional(m_tracksName);
89 m_ROIs.isOptional(m_ROIsName);
91}
92
93
95{
96 if (!m_pxdclusters.isValid()) {
97 B2INFO("PXDClusters array is missing, no efficiencies");
98 return;
99 }
100 if (!m_recoTracks.isValid()) {
101 B2INFO("RecoTrack array is missing, no efficiencies");
102 return;
103 }
104 if (!m_tracks.isValid()) {
105 B2INFO("Track array is missing, no efficiencies");
106 return;
107 }
108 if (!m_intercepts.isValid()) {
109 B2INFO("Intercept array is missing, no efficiencies");
110 return;
111 }
112
113 for (auto& track : m_tracks) {
114 RelationVector<RecoTrack> recoTrack = track.getRelationsTo<RecoTrack>(m_recoTracksName);
115 if (!recoTrack.size()) continue;
116
117 auto a_track = recoTrack[0];
118 //If fit failed assume position pointed to is useless anyway
119 if (!a_track->wasFitSuccessful()) continue;
120
121 if (a_track->getNumberOfSVDHits() < m_minSVDHits) continue;
122
123 RelationVector<PXDIntercept> interceptList = a_track->getRelationsTo<PXDIntercept>(m_PXDInterceptListName);
124 if (!interceptList.size()) continue;
125
126 const genfit::FitStatus* fitstatus = a_track->getTrackFitStatus();
127 if (fitstatus->getPVal() < m_pcut) continue;
128
129 genfit::MeasuredStateOnPlane trackstate;
130 trackstate = a_track->getMeasuredStateOnPlaneFromFirstHit();
131 if (trackstate.getMom().Mag() < m_momCut) continue;
132 if (trackstate.getMom().Pt() < m_pTCut) continue;
133
134 const TrackFitResult* ptr2 = track.getTrackFitResultWithClosestMass(Const::pion);
135 if (!ptr2) {
136 B2ERROR("expect a track fit result for mass");
137 continue;
138 }
139
140 //loop over all PXD sensors to get the intersections
141 std::vector<VxdID> sensors = m_vxdGeometry.getListOfSensors();
142 for (auto intercept : interceptList) {
143 auto aVxdID = intercept.getSensorID();
144 auto& info = m_vxdGeometry.getSensorInfo(aVxdID);
145 //Search for intersections of the track with all PXD layers
146 //Traditional (aka the person before did it like this) method
147 //If there is a way to find out sensors crossed by a track directly, that would most likely be faster
148
149 double sigu = intercept.getSigmaU();
150 double sigv = intercept.getSigmaV();
151
152 double u_fit = intercept.getCoorU();
153 double v_fit = intercept.getCoorV();
154
155 int ucell_fit = info.getUCellID(u_fit); // check wie overflow!!!
156 int vcell_fit = info.getVCellID(v_fit); // Check wie overflow
157
158 bool closeToBoarder = false;
159 if (isCloseToBorder(ucell_fit, vcell_fit, m_maskedDistance)) {
160 closeToBoarder = true;
161 }
162
163 bool closeToDead = false;
164 if (isDeadPixelClose(ucell_fit, vcell_fit, m_maskedDistance, aVxdID)) {
165 closeToDead = true;
166 }
167
168 bool fitInsideROI = false;
169 if (m_ROIs.isValid()) {
170 //Check if the intersection is inside a ROI
171 //If not, even if measured the cluster was thrown away->Not PXD's fault
172 for (auto& roit : m_ROIs) {
173 if (aVxdID != (roit.getSensorID()).getID()) {
174 continue; //ROI on other sensor
175 }
176
177 if (ucell_fit < roit.getMaxUid()
178 && ucell_fit > roit.getMinUid()
179 && vcell_fit < roit.getMaxVid()
180 && vcell_fit > roit.getMinVid()) {
181 fitInsideROI = true;
182 }
183 }
184 }
185
186 //Now check if the sensor measured a hit here
187
188 int bestcluster = findClosestCluster(aVxdID, ROOT::Math::XYZVector(u_fit, v_fit, 0));
189 double du_clus = 0;
190 double dv_clus = 0;
191 double d_clus = 0;
192 float charge = 0;
193 bool matched = false;
194 if (bestcluster >= 0) {
195 double u_clus = m_pxdclusters[bestcluster]->getU();
196 double v_clus = m_pxdclusters[bestcluster]->getV();
197
198 //is the closest cluster close enough to the track to count as measured?
199 ROOT::Math::XYZVector dist_clus(u_fit - u_clus, v_fit - v_clus, 0);
200 du_clus = u_fit - u_clus;
201 dv_clus = v_fit - v_clus;
202 d_clus = dist_clus.R();
203 charge = m_pxdclusters[bestcluster]->getCharge();
204 matched = true;
205 }
206 float fill[22] = {float((int)aVxdID), float(u_fit), float(v_fit), float(trackstate.getMom().Mag()), float(trackstate.getMom().Pt()),
207 float(du_clus), float(dv_clus), float(sigu), float(sigv), float(d_clus),
208 float(fitInsideROI), float(closeToBoarder), float(closeToDead), float(matched),
209 float(ptr2->getZ0()), float(ptr2->getD0()), float(a_track->getNumberOfSVDHits()),
210 charge, float(trackstate.getMom().Phi()), float(trackstate.getMom().CosTheta())
211 };
212 m_tuple->Fill(fill);
213 }
214 }
215}
216
217int
218PXDDQMEfficiencyNtupleModule::findClosestCluster(const VxdID& avxdid, ROOT::Math::XYZVector intersection)
219{
220 int closest = -1;
221 double mindist = 999999999999; //definitely outside of the sensor
222
223 VXD::SensorInfoBase info = m_vxdGeometry.getSensorInfo(avxdid);
224
225 //loop the clusters
226 for (int iclus = 0; iclus < m_pxdclusters.getEntries(); iclus++) {
227 //Do not consider as different if only segment differs!
228 //As of this writing segment is never filled for clusters, but just to be sure
229 VxdID clusterID = m_pxdclusters[iclus]->getSensorID();
230 if (avxdid.getLayerNumber() != clusterID.getLayerNumber() ||
231 avxdid.getLadderNumber() != clusterID.getLadderNumber() ||
232 avxdid.getSensorNumber() != clusterID.getSensorNumber()) {
233 continue;
234 }
235 //only cluster on the correct sensor and direction should survive
236
237 double u = m_pxdclusters[iclus]->getU();
238 double v = m_pxdclusters[iclus]->getV();
239 ROOT::Math::XYZVector current(u, v, 0);
240
241 //2D dist squared
242 double dist = (intersection - current).R();
243 if (dist < mindist) {
244 closest = iclus;
245 mindist = dist;
246 }
247 }
248
249 return closest;
250
251}
252
253bool PXDDQMEfficiencyNtupleModule::isCloseToBorder(int u, int v, int checkDistance)
254{
255
256 if (u - checkDistance < 0 || u + checkDistance >= 250 ||
257 v - checkDistance < 0 || v + checkDistance >= 768) {
258 return true;
259 }
260 return false;
261}
262
263bool PXDDQMEfficiencyNtupleModule::isDeadPixelClose(int u, int v, int checkDistance, const VxdID& moduleID)
264{
265
266 //Iterate over square around the intersection to see if any close pixel is dead
267 for (int u_iter = u - checkDistance; u_iter <= u + checkDistance ; ++u_iter) {
268 for (int v_iter = v - checkDistance; v_iter <= v + checkDistance ; ++v_iter) {
269 if (PXD::PXDPixelMasker::getInstance().pixelDead(moduleID, u_iter, v_iter)
270 || !PXD::PXDPixelMasker::getInstance().pixelOK(moduleID, u_iter, v_iter)) {
271 return true;
272 }
273 }
274 }
275 return false;
276}
double R
typedef autogenerated by FFTW
static const ChargedStable pion
charged pion particle
Definition Const.h:661
void setDescription(const std::string &description)
Sets the description of the module.
Definition Module.cc:214
Module()
Constructor.
Definition Module.cc:30
void initialize() override final
initializes the need store arrays, trees and histograms
bool isCloseToBorder(int u, int v, int checkDistance)
is it close to the border
unsigned int m_minSVDHits
Required hits in SVD strips for tracks.
StoreArray< PXDCluster > m_pxdclusters
store array of pxd clusters
std::string m_PXDInterceptListName
intercept list name
double m_momCut
Cut on fitted track momentum.
int findClosestCluster(const VxdID &vxdid, ROOT::Math::XYZVector intersection)
find the closest cluster
bool isDeadPixelClose(int u, int v, int checkDistance, const VxdID &moduleID)
is a dead pixel close
void terminate() override final
terminate , save tuple to file if needed
void event() override final
main function which fills trees and histograms
std::string m_pxdClustersName
name of the store array of pxd clusters
StoreArray< Track > m_tracks
store array of tracks
std::string m_recoTracksName
name of the store array of recotracks
int m_maskedDistance
Distance inside which no dead pixel or module border is allowed.
StoreArray< PXDIntercept > m_intercepts
store array of PXD Intercepts
std::string m_ROIsName
name of the store array of ROIs
StoreArray< RecoTrack > m_recoTracks
store array of reco tracks
bool m_useAlignment
if true alignment will be used!
PXDDQMEfficiencyNtupleModule()
Constructor: Sets the description, the properties and the parameters of the module.
std::string m_tracksName
name of the store array of tracks
StoreArray< ROIid > m_ROIs
store array of ROIs
PXDIntercept stores the U,V coordinates and uncertainties of the intersection of a track with an PXD ...
static PXDPixelMasker & getInstance()
Main (and only) way to access the PXDPixelMasker.
This is the Reconstruction Event-Data Model Track.
Definition RecoTrack.h:79
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
Values of the result of a track fit with a given particle hypothesis.
double getD0() const
Getter for d0.
double getZ0() const
Getter for z0.
Base class to provide Sensor Information for PXD and SVD.
Class to uniquely identify a any structure of the PXD and SVD.
Definition VxdID.h:32
baseType getSensorNumber() const
Get the sensor id.
Definition VxdID.h:99
baseType getLadderNumber() const
Get the ladder id.
Definition VxdID.h:97
baseType getLayerNumber() const
Get the layer id.
Definition VxdID.h:95
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition Module.h:559
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
Namespace to provide code needed by both Vertex Detectors, PXD and SVD, and also testbeam telescopes.
Definition GeoCache.h:33
Abstract base class for different kinds of events.