Belle II Software  release-08-01-10
ROIFinder.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 #include <tracking/vxdHoughTracking/findlets/ROIFinder.h>
9 #include <tracking/vxdHoughTracking/findlets/RawTrackCandCleaner.icc.h>
10 #include <tracking/trackFindingCDC/utilities/StringManipulation.h>
11 #include <tracking/trackFindingVXD/trackQualityEstimators/QualityEstimatorCircleFit.h>
12 #include <tracking/trackFindingVXD/trackQualityEstimators/QualityEstimatorRiemannHelixFit.h>
13 #include <tracking/trackFindingVXD/trackQualityEstimators/QualityEstimatorTripletFit.h>
14 #include <framework/logging/Logger.h>
15 #include <framework/core/ModuleParamList.h>
16 #include <framework/geometry/BFieldManager.h>
17 #include <framework/geometry/B2Vector3.h>
18 #include <framework/database/DBObjPtr.h>
19 #include <mdst/dbobjects/BeamSpot.h>
20 #include <pxd/geometry/SensorInfo.h>
21 #include <vxd/geometry/GeoCache.h>
22 
23 using namespace Belle2;
24 using namespace TrackFindingCDC;
25 using namespace vxdHoughTracking;
26 
27 ROIFinder::~ROIFinder() = default;
28 
29 ROIFinder::ROIFinder()
30 {
31 }
32 
33 void ROIFinder::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
34 {
35  Super::exposeParameters(moduleParamList, prefix);
36 
37  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "calculateROI"), m_calculateROI,
38  "Calculate PXDIntercepts and ROIs in this findlet based on a simple circle extrapolation (r-phi) and straigh line extrapolation (z, theta)?",
39  m_calculateROI);
40 
41  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "storePXDInterceptsName"), m_storePXDInterceptsName,
42  "Name of the PXDIntercepts StoreArray produced by SVDHoughTracking using a simple circle extrapolation in r-phi and a straight line extrapolation in theta.",
43  m_storePXDInterceptsName);
44 
45  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "storeROIsName"), m_storeROIsName,
46  "Name of the ROIs StoreArray produced by SVDHoughTracking using a simple circle extrapolation in r-phi and a straight line extrapolation in theta.",
47  m_storeROIsName);
48 
49  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "tolerancePhi"), m_tolerancePhi,
50  "Allowed tolerance in phi (in radians) (for ROI calculation in u direction). If the intercept is within this range of the active region, an intercept is created.",
51  m_tolerancePhi);
52  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "toleranceZ"), m_toleranceZ,
53  "Allowed tolerance in z (in cm) (for ROI calculation in v direction). If the intercept is within this range of the active region of a sensor, an intercept is created.",
54  m_toleranceZ);
55 
56  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "radiusCorrectionFactorL1"), m_radiusCorrectionFactorL1,
57  "Correct charge-dependent bias of the extrapolated hit on L1 with radiusCorrectionFactor * trackCharge / trackRadius.",
58  m_radiusCorrectionFactorL1);
59  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "radiusCorrectionFactorL2"), m_radiusCorrectionFactorL2,
60  "Correct charge-dependent bias of the extrapolated hit on L2 with radiusCorrectionFactor * trackCharge / trackRadius.",
61  m_radiusCorrectionFactorL2);
62  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "sinPhiCorrectionFactor"), m_sinPhiCorrectionFactor,
63  "Correct sin(trackPhi) dependent bias with sinPhiCorrectionFactor * sin(trackPhi).",
64  m_sinPhiCorrectionFactor);
65  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "cosPhiCorrectionFactor"), m_cosPhiCorrectionFactor,
66  "Correct cos(trackPhi) dependent bias with cosPhiCorrectionFactor * cos(trackPhi).",
67  m_cosPhiCorrectionFactor);
68 
69  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "zPositionCorrectionFactor"), m_zPositionCorrectionFactor,
70  "Correction factor for the extrapolated z position.",
71  m_zPositionCorrectionFactor);
72 
73  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "minimumROISizeUL1"), m_minimumROISizeUL1,
74  "Minimum ROI size (in pixel) in u direction on L1.", m_minimumROISizeUL1);
75  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "minimumROISizeVL1"), m_minimumROISizeVL1,
76  "Minimum ROI size (in pixel) in v direction on L1.", m_minimumROISizeVL1);
77  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "minimumROISizeUL2"), m_minimumROISizeUL2,
78  "Minimum ROI size (in pixel) in u direction on L2.", m_minimumROISizeUL2);
79  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "minimumROISizeVL2"), m_minimumROISizeVL2,
80  "Minimum ROI size (in pixel) in v direction on L2.", m_minimumROISizeVL2);
81 
82  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "multiplierUL1"), m_multiplierUL1,
83  "Multiplier term for ROI size estimation for L1 u direction. Usage: multiplierUL1 * 1/R + minimumROISizeUL1, with R in cm.",
84  m_multiplierUL1);
85  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "multiplierUL2"), m_multiplierUL2,
86  "Multiplier term for ROI size estimation for L2 u direction. Usage: multiplierUL2 * 1/R + minimumROISizeUL2, with R in cm.",
87  m_multiplierUL2);
88  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "multiplierVL1"), m_multiplierVL1,
89  "Multiplier term for ROI size estimation for L1 v direction. Usage: (1 + abs(tan(lambda)) * multiplierVL1) + minimumROISizeVL1.",
90  m_multiplierVL1);
91  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "multiplierVL2"), m_multiplierVL2,
92  "Multiplier term for ROI size estimation for L2 v direction. Usage: (1 + abs(tan(lambda)) * multiplierVL2) + minimumROISizeVL2.",
93  m_multiplierVL2);
94 
95  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "maximumROISizeU"), m_maximumROISizeU,
96  "Maximum ROI size in u.", m_maximumROISizeU);
97  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "maximumROISizeV"), m_maximumROISizeV,
98  "Maximum ROI size in v.", m_maximumROISizeV);
99 
100 
101  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "refit"), m_refit,
102  "Refit the track with trackQualityEstimationMethod?", m_refit);
103  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "addVirtualIP"), m_addVirtualIP,
104  "Add virtual IP to fit the tracks again for ROI creation?", m_addVirtualIP);
105  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "ROIFitMethod"), m_ROIFitMethod,
106  "Identifier which fit method to use. Valid identifiers are: [circleFit, tripletFit, helixFit]",
107  m_ROIFitMethod);
108 
109 }
110 
112 void ROIFinder::initialize()
113 {
114  // If no ROIs shall be calculated, return rightaway and don't do anything
115  if (not m_calculateROI) {
116  return;
117  }
118 
119  Super::initialize();
120 
121  m_storePXDIntercepts.registerInDataStore(m_storePXDInterceptsName);
122  m_storeROIs.registerInDataStore(m_storeROIsName);
123 
124  if (m_minimumROISizeUL1 < 0 or m_minimumROISizeUL2 < 0 or
125  m_minimumROISizeVL1 < 0 or m_minimumROISizeVL2 < 0 or
126  m_multiplierUL1 < 0 or m_multiplierUL2 < 0 or
127  m_multiplierVL1 < 0 or m_multiplierVL2 < 0 or
128  m_tolerancePhi < 0 or m_toleranceZ < 0) {
129  B2ERROR("Please check the ROI size parameters. "
130  "None of minimumROISizeUL1, minimumROISizeUL2, minimumROISizeVL1, minimumROISizeVL2, "
131  "multiplierUL1, multiplierUL2, multiplierVL1, multiplierVL2, overlapU, overlapV must be < 0!");
132  }
133 
134  if (m_ROIFitMethod == "tripletFit") {
135  m_estimator = std::make_unique<QualityEstimatorTripletFit>();
136  } else if (m_ROIFitMethod == "circleFit") {
137  m_estimator = std::make_unique<QualityEstimatorCircleFit>();
138  } else if (m_ROIFitMethod == "helixFit") {
139  m_estimator = std::make_unique<QualityEstimatorRiemannHelixFit>();
140  }
141  B2ASSERT("QualityEstimator could not be initialized with method: " << m_ROIFitMethod, m_estimator);
142 
143 };
144 
145 void ROIFinder::beginRun()
146 {
147  // If no ROIs shall be calculated, return rightaway and don't do anything
148  if (not m_calculateROI) {
149  return;
150  }
151 
152  Super::beginRun();
153 
154  m_bFieldZ = BFieldManager::getField(0, 0, 0).Z() / Unit::T;
155  m_estimator->setMagneticFieldStrength(m_bFieldZ);
156 
157  DBObjPtr<BeamSpot> beamSpotDB;
158  if (beamSpotDB.isValid()) {
159  m_BeamSpotPosition = (*beamSpotDB).getIPPosition();
160  const TMatrixDSym posErr = (*beamSpotDB).getIPPositionCovMatrix();
161  m_BeamSpotPositionError.SetXYZ(sqrt(posErr[0][0]), sqrt(posErr[1][1]), sqrt(posErr[2][2]));
162  } else {
163  m_BeamSpotPosition.SetXYZ(0., 0., 0.);
164  m_BeamSpotPositionError.SetXYZ(0., 0., 0.);
165  }
166 }
167 
168 
169 void ROIFinder::beginEvent()
170 {
171  // If no ROIs shall be calculated, return rightaway and don't do anything
172  if (not m_calculateROI) {
173  return;
174  }
175 
176  Super::beginEvent();
177 }
178 
179 void ROIFinder::apply(const std::vector<SpacePointTrackCand>& finalTracks)
180 {
181  // If no ROIs shall be calculated, return rightaway and don't do anything
182  if (not m_calculateROI) {
183  return;
184  }
185 
186  for (auto& track : finalTracks) {
187  // do nothing if the SpacePointTrackCand is not active
188  if (!track.hasRefereeStatus(SpacePointTrackCand::c_isActive)) {
189  continue;
190  }
191 
192  QualityEstimationResults refittedTrackEstimate;
193  if (m_refit) {
194  auto sortedHits = track.getSortedHits();
195 
196  if (m_addVirtualIP) {
197  SpacePoint virtualIPSpacePoint = SpacePoint(m_BeamSpotPosition, m_BeamSpotPositionError, {0.5, 0.5}, {false, false},
199  sortedHits.push_back(&virtualIPSpacePoint);
200  }
201 
202  std::sort(sortedHits.begin(), sortedHits.end(),
203  [](const SpacePoint * a, const SpacePoint * b) {return a->getPosition().Perp() < b->getPosition().Perp(); });
204 
205  refittedTrackEstimate = m_estimator->estimateQualityAndProperties(sortedHits);
206  }
207 
208  std::vector<PXDIntercept> thisTracksIntercepts;
209  thisTracksIntercepts.reserve(8);
210 
211  B2Vector3D momentumEstimate = track.getMomSeed();
212  if (m_refit) {
213  momentumEstimate = *refittedTrackEstimate.p;
214  }
215 
216  const double trackPhi = momentumEstimate.Phi();
217  const double trackTheta = momentumEstimate.Theta();
218  const double tanTrackLambda = tan(M_PI_2 - trackTheta);
219  const double trackRadius = momentumEstimate.Perp() / (0.00299792458 * m_bFieldZ) ;
220  const double trackCharge = track.getChargeSeed();
221 
223  for (int layer = 1; layer <= 2; layer++) {
224  const double sensorPerpRadius = c_layerRadius[layer - 1];
225 
227  for (int ladder = 1; ladder <= (layer == 1 ? 8 : 12); ladder++) {
228  const double sensorPhi = (layer == 1) ? c_ladderPhiL1[ladder - 1] : c_ladderPhiL2[ladder - 1];
229  const double rotatedBeamSpotX = m_BeamSpotPosition.X() * cos(sensorPhi) + m_BeamSpotPosition.Y() * sin(sensorPhi);
230  const double rotatedBeamSpotY = -m_BeamSpotPosition.X() * sin(sensorPhi) + m_BeamSpotPosition.Y() * cos(sensorPhi);
231 
232  // in the rotated coordinate the sensor is perpendicular to the x axis at position sensorLocalX
233  const double sensorLocalX = sensorPerpRadius - rotatedBeamSpotX;
234 
235  double phiDiff = trackPhi - sensorPhi;
236  if (phiDiff < -M_PI) {
237  phiDiff += 2. * M_PI;
238  }
239  if (phiDiff > M_PI) {
240  phiDiff -= 2. * M_PI;
241  }
242 
243  // Don't try to extrapolate if track direction and sensor are too different (in phi)
244  // this should speed up the calculation as wrong combinations are not checked at all.
245  // Two values to check both the outgoing (0.3) and incoming (0.8) arm.
246  if (fabs(phiDiff) > 0.25 * M_PI and fabs(phiDiff) < 0.75 * M_PI) {
247  continue;
248  }
249  if (fabs(phiDiff) > 0.75 * M_PI and fabs(tanTrackLambda) > 0.2 /*and fabs(trackRadius) > 20*/) {
250  continue;
251  }
252 
253 
254  // relative phi value of the track center compared to the rotated
255  // coordinate system defined by the (rotated) line perpendicular
256  // to the sensor (with length sensorPerpRadius)
257  double relTrackCenterPhi = 0;
258  if (trackCharge < 0) {
259  relTrackCenterPhi = trackPhi - M_PI_2 - sensorPhi;
260  } else if (trackCharge > 0) {
261  relTrackCenterPhi = trackPhi + M_PI_2 - sensorPhi;
262  }
263  const double xCenter = trackRadius * cos(relTrackCenterPhi);
264  const double yCenter = trackRadius * sin(relTrackCenterPhi);
265 
266  // continue if radicant of sqrt is negative
267  if ((trackRadius * trackRadius - (sensorLocalX - xCenter) * (sensorLocalX - xCenter)) < 0) {
268  continue;
269  }
270  const double ytmp = sqrt(trackRadius * trackRadius - (sensorLocalX - xCenter) * (sensorLocalX - xCenter));
271  const double yplus = yCenter + ytmp + rotatedBeamSpotY;
272  const double yminus = yCenter - ytmp + rotatedBeamSpotY;
273 
274  const double correctionterm = ((layer == 1 ? m_radiusCorrectionFactorL1 : m_radiusCorrectionFactorL2) * trackCharge /
275  trackRadius) +
276  m_sinPhiCorrectionFactor * sin(trackPhi) +
277  m_cosPhiCorrectionFactor * cos(trackPhi);
278 
279  const double localUPositionPlus = yplus - c_shiftY + correctionterm;
280  const double localUPositionMinus = yminus - c_shiftY + correctionterm;
281  const double toleranceRPhi = m_tolerancePhi * sensorLocalX;
282 
283  // if the hit for sure is out of reach of the current ladder, continue
284  if (not(yplus >= c_sensorMinY - toleranceRPhi and yplus <= c_sensorMaxY + toleranceRPhi) and
285  not(yminus >= c_sensorMinY - toleranceRPhi and yminus <= c_sensorMaxY + toleranceRPhi)) {
286  continue;
287  }
288 
289  // estimate the z coordinate of the extrapolation on this layer
290  const double z = sensorLocalX * tanTrackLambda - m_BeamSpotPosition.Z();
291  const double zPlus = sqrt(sensorLocalX * sensorLocalX + yplus * yplus) * tanTrackLambda * m_zPositionCorrectionFactor -
292  m_BeamSpotPosition.Z();
293  const double zMinus = sqrt(sensorLocalX * sensorLocalX + yminus * yminus) * tanTrackLambda * m_zPositionCorrectionFactor -
294  m_BeamSpotPosition.Z();
295 
297  for (int sensor = 1; sensor <= 2; sensor++) {
298 
299  const double shiftZ = (layer == 1) ? c_centerZShiftLayer1[sensor - 1] : c_centerZShiftLayer2[sensor - 1];
300 
301  double localVPosition = z - shiftZ;
302  double localVPositionPlus = zPlus - shiftZ;
303  double localVPositionMinus = zMinus - shiftZ;
304  // check whether z intersection possibly is on sensor to be checked, only continue with the rest of calculations if that's the case
305  if (localVPosition >= ((-c_activeSensorLength[layer - 1] / 2.0) - m_toleranceZ) and
306  localVPosition <= ((c_activeSensorLength[layer - 1] / 2.0) + m_toleranceZ)) {
307 
308  const VxdID sensorID = VxdID(layer, ladder, sensor);
309 
310  // check for first option of the intersection
311  if (localUPositionPlus >= -c_activeSensorWidth / 2.0 - toleranceRPhi and
312  localUPositionPlus <= c_activeSensorWidth / 2.0 + toleranceRPhi) {
313  PXDIntercept intercept;
314  intercept.setCoorU(localUPositionPlus);
315  intercept.setCoorV(localVPositionPlus);
316  intercept.setVxdID(sensorID);
317  m_storePXDIntercepts.appendNew(intercept);
318  thisTracksIntercepts.push_back(intercept);
319  }
320  // check for second option of the intersection
321  if (localUPositionMinus >= -c_activeSensorWidth / 2.0 - toleranceRPhi and
322  localUPositionMinus <= c_activeSensorWidth / 2.0 + toleranceRPhi) {
323  PXDIntercept intercept;
324  intercept.setCoorU(localUPositionMinus);
325  intercept.setCoorV(localVPositionMinus);
326  intercept.setVxdID(sensorID);
327  m_storePXDIntercepts.appendNew(intercept);
328  thisTracksIntercepts.push_back(intercept);
329  }
330  }
331  }
332  }
333  }
334 
335  const double omega = 1. / trackRadius;
336  unsigned short uSizeL1 = (unsigned short)(m_multiplierUL1 * omega + m_minimumROISizeUL1);
337  unsigned short uSizeL2 = (unsigned short)(m_multiplierUL2 * omega + m_minimumROISizeUL2);
338  unsigned short vSizeL1 = (unsigned short)((1. + fabs(tanTrackLambda) * m_multiplierVL1) * m_minimumROISizeVL1);
339  unsigned short vSizeL2 = (unsigned short)((1. + fabs(tanTrackLambda) * m_multiplierVL2) * m_minimumROISizeVL2);
340  for (auto& intercept : thisTracksIntercepts) {
341  const VxdID& interceptSensorID = intercept.getSensorID();
342 
343  double uCoordinate = intercept.getCoorU();
344  double vCoordinate = intercept.getCoorV();
345 
346  const PXD::SensorInfo* currentSensor = dynamic_cast<const PXD::SensorInfo*>(&VXD::GeoCache::get(interceptSensorID));
347 
348  int interceptUCell = currentSensor->getUCellID(uCoordinate, vCoordinate, false);
349  int interceptVCell = currentSensor->getVCellID(vCoordinate, false);
350  int nUCells = currentSensor->getUCells();
351  int nVCells = currentSensor->getVCells();
352 
353  unsigned short uSize = (interceptSensorID.getLayerNumber() == 1 ? uSizeL1 : uSizeL2);
354  unsigned short vSize = (interceptSensorID.getLayerNumber() == 1 ? vSizeL1 : vSizeL2);
355  if (uSize > m_maximumROISizeU) {
356  uSize = m_maximumROISizeU;
357  }
358  if (vSize > m_maximumROISizeV) {
359  vSize = m_maximumROISizeV;
360  }
361 
363  short uCellDownLeft = interceptUCell - uSize / 2;
364  short vCellDownLeft = interceptVCell - vSize / 2;
365 
367  short uCellUpRight = interceptUCell + uSize / 2;
368  short vCellUpRight = interceptVCell + vSize / 2;
369 
370  if (uCellDownLeft >= nUCells or vCellDownLeft >= nVCells or uCellUpRight < 0 or vCellUpRight < 0) {
371  continue;
372  }
373 
374  if (uCellDownLeft < 0) {
375  uCellDownLeft = 0;
376  }
377  if (vCellDownLeft < 0) {
378  vCellDownLeft = 0;
379  }
380 
381  // minimum cell id is 0, maximum is nCells - 1
382  if (uCellUpRight >= nUCells) {
383  uCellUpRight = nUCells - 1;
384  }
385  if (vCellUpRight >= nVCells) {
386  vCellUpRight = nVCells - 1;
387  }
388 
389  m_storeROIs.appendNew(ROIid(uCellDownLeft, uCellUpRight, vCellDownLeft, vCellUpRight, interceptSensorID));
390  }
391 
392  }
393 }
394 
DataType Phi() const
The azimuth angle.
Definition: B2Vector3.h:151
DataType Theta() const
The polar angle.
Definition: B2Vector3.h:153
DataType Perp() const
The transverse component (R in cylindrical coordinate system).
Definition: B2Vector3.h:200
bool isValid() const
Check whether a valid object was obtained from the database.
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
The Module parameter list class.
PXDIntercept stores the U,V coordinates and uncertainties of the intersection of a track with an PXD ...
Definition: PXDIntercept.h:22
Specific implementation of SensorInfo for PXD Sensors which provides additional pixel specific inform...
Definition: SensorInfo.h:23
ROIid stores the U and V ids and the sensor id of the Region Of Interest.
Definition: ROIid.h:25
@ c_isActive
bit 11: SPTC is active (i.e.
SpacePoint typically is build from 1 PXDCluster or 1-2 SVDClusters.
Definition: SpacePoint.h:42
static const double T
[tesla]
Definition: Unit.h:120
void setVxdID(VxdID::baseType user_vxdID)
set the sensor ID
Definition: VXDIntercept.h:75
void setCoorU(double user_coorU)
set the U coordinate of the intercept
Definition: VXDIntercept.h:68
void setCoorV(double user_coorV)
set the V coordinate of the intercept
Definition: VXDIntercept.h:69
static const SensorInfoBase & get(Belle2::VxdID id)
Return a reference to the SensorInfo of a given SensorID.
Definition: GeoCache.h:139
int getVCells() const
Return number of pixel/strips in v direction.
@ VXD
Any type of VXD Sensor.
int getUCells() const
Return number of pixel/strips in u direction.
int getVCellID(double v, bool clamp=false) const
Return the corresponding pixel/strip ID of a given v coordinate.
int getUCellID(double u, double v=0, bool clamp=false) const
Return the corresponding pixel/strip ID of a given u coordinate.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
baseType getLayerNumber() const
Get the layer id.
Definition: VxdID.h:96
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
static void getField(const double *pos, double *field)
return the magnetic field at a given position.
Definition: BFieldManager.h:91
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
double tan(double a)
tan for double
Definition: beamHelpers.h:31
Abstract base class for different kinds of events.
Container for complete fit/estimation results.
std::optional< B2Vector3D > p
momentum vector estimate from the QE