Belle II Software  release-08-01-10
WireHitCreator.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/trackFindingCDC/findlets/minimal/WireHitCreator.h>
9 
10 #include <tracking/trackFindingCDC/eventdata/hits/CDCWireHit.h>
11 #include <tracking/trackFindingCDC/eventdata/utils/FlightTimeEstimator.h>
12 
13 #include <tracking/trackFindingCDC/findlets/minimal/EPreferredDirection.h>
14 
15 #include <tracking/trackFindingCDC/topology/CDCWireTopology.h>
16 
17 #include <tracking/trackFindingCDC/utilities/StringManipulation.h>
18 
19 #include <cdc/translators/RealisticTDCCountTranslator.h>
20 #include <cdc/translators/LinearGlobalADCCountTranslator.h>
21 #include <cdc/geometry/CDCGeometryPar.h>
22 
23 #include <cdc/dataobjects/CDCHit.h>
24 
25 #include <framework/datastore/StoreArray.h>
26 #include <framework/core/ModuleParamList.templateDetails.h>
27 
28 #include <mdst/dataobjects/MCParticle.h>
29 
30 using namespace Belle2;
31 using namespace TrackFindingCDC;
32 
35 
37 {
38  return "Combines the geometrical information and the raw hit information into wire hits, "
39  "which can be used from all modules after that";
40 }
41 
42 void WireHitCreator::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
43 {
44  moduleParamList->addParameter(prefixed(prefix, "wirePosition"),
46  "Set of geometry parameters to be used in the track finding. "
47  "Either 'base', 'misaligned' or 'aligned'.",
49 
50  moduleParamList->addParameter(prefixed(prefix, "ignoreWireSag"),
52  "Assume a wire sag coefficient of zero "
53  "such that the wires appear to be straight for "
54  "the track finders",
56 
57  moduleParamList->addParameter(prefixed(prefix, "flightTimeEstimation"),
59  "Option which flight direction should be assumed for "
60  "an initial time of flight estimation. Options are: "
61  "'none' (no TOF correction), "
62  "'outwards', "
63  "'downwards'.",
65 
66  moduleParamList->addParameter(prefixed(prefix, "triggerPoint"),
68  "Point relative to which the flight times are calculated",
70 
71  moduleParamList->addParameter(prefixed(prefix, "useSuperLayers"),
73  "List of super layers to be used.",
75 
76  moduleParamList->addParameter(prefixed(prefix, "maxDriftTimes"),
78  "Maximum drift time (nsec) allowed per super layer (in order of super layer#0-8). Default payload-based cut is applied if this value is negative",
80 
81  moduleParamList->addParameter(prefixed(prefix, "useLayers"),
83  "List of layers to be used. "
84  "If a layer number is given in 'ignoreLayers', too, this will result on a B2FATAL. "
85  "Either use 'useLayers' and provide a set of layers to be used, "
86  "or use 'ignoreLayers' and provide a list of layers to be ignored, but not both at the same time.",
88 
89  moduleParamList->addParameter(prefixed(prefix, "ignoreLayers"),
91  "List of layers to be ignored. "
92  "If a layer number is given in 'useLayers', too, this will result on a B2FATAL. "
93  "Either use 'useLayers' and provide a set of layers to be used, "
94  "or use 'ignoreLayers' and provide a list of layers to be ignored, but not both at the same time.",
96 
97  moduleParamList->addParameter(prefixed(prefix, "useSecondHits"),
99  "Use the second hit information in the track finding.",
101 
102  moduleParamList->addParameter(prefixed(prefix, "useBadWires"),
104  "Also create the hits that are on bad wires.",
106 
107  moduleParamList->addParameter(prefixed(prefix, "useDegreeSector"),
109  "To angles in degrees for which hits should be created - mostly for debugging",
111 
112  moduleParamList->addParameter(prefixed(prefix, "useMCParticleIds"),
114  "Ids of the MC particles to use. Default does not look at the MCParticles - most for debugging",
116 }
117 
119 {
120  StoreArray<CDCHit> hits;
121  hits.isRequired();
122 
123  // Create the wires and layers once during initialisation
125 
126  if (m_param_wirePosition == "base") {
127  m_wirePosition = EWirePosition::c_Base;
128  } else if (m_param_wirePosition == "misaligned") {
129  m_wirePosition = EWirePosition::c_Misaligned;
130  } else if (m_param_wirePosition == "aligned") {
131  m_wirePosition = EWirePosition::c_Aligned;
132  } else {
133  B2ERROR("Received unknown wirePosition " << m_param_wirePosition);
134  }
135 
138 
139  if (m_param_flightTimeEstimation != std::string("")) {
140  try {
141  m_flightTimeEstimation = getPreferredDirection(m_param_flightTimeEstimation);
142  } catch (std::invalid_argument& e) {
143  B2ERROR("Unexpected 'flightTimeEstimation' parameter : '" << m_param_flightTimeEstimation);
144  }
145  }
146 
148  std::get<1>(m_param_triggerPoint),
149  std::get<2>(m_param_triggerPoint));
150 
151  if (m_flightTimeEstimation == EPreferredDirection::c_Symmetric) {
152  B2ERROR("Unexpected 'flightTimeEstimation' parameter : '" << m_param_flightTimeEstimation);
153  } else if (m_flightTimeEstimation == EPreferredDirection::c_Downwards) {
154  FlightTimeEstimator::instance(std::make_unique<CosmicRayFlightTimeEstimator>(m_triggerPoint));
155  } else if (m_flightTimeEstimation == EPreferredDirection::c_Outwards) {
156  FlightTimeEstimator::instance(std::make_unique<BeamEventFlightTimeEstimator>());
157  }
158 
159  int nSL = m_param_maxDriftTimes.size();
160  for (int iSL = 0; iSL < nSL; ++iSL) {
161  m_maxDriftTimes.at(iSL) = m_param_maxDriftTimes.at(iSL);
162  }
163 
164  if (not m_param_useSuperLayers.empty()) {
165  for (const ISuperLayer iSL : m_param_useSuperLayers) {
166  m_useSuperLayers.at(iSL) = true;
167  }
168  } else {
169  m_useSuperLayers.fill(true);
170  }
171 
172  // Check for common value in the two vectors for using / ignoring layers
173  for (const uint useLayer : m_param_useLayers) {
174  for (const uint ingoreLayer : m_param_ignoreLayers) {
175  if (useLayer == ingoreLayer) {
176  B2FATAL("You chose to use and ignore CDC layer " << useLayer << " at the same time. "
177  "Please decide to either use or to ignore the layer.");
178  }
179  }
180  }
181 
182  // fill all layers that should be used
183  if (not m_param_useLayers.empty()) {
184  for (const uint layer : m_param_useLayers) {
185  m_useLayers.at(layer) = true;
186  }
187  } else {
188  m_useLayers.fill(true);
189  }
190  // set layers that should be ignored to false
191  if (not m_param_ignoreLayers.empty()) {
192  for (const uint layer : m_param_ignoreLayers) {
193  m_useLayers.at(layer) = false;
194  }
195  }
196 
197  if (std::isfinite(std::get<0>(m_param_useDegreeSector))) {
200  }
201 
203 }
204 
206 {
207  Super::beginRun();
210 }
211 
212 void WireHitCreator::apply(std::vector<CDCWireHit>& outputWireHits)
213 {
214  // Wire hits have been created before
215  if (not outputWireHits.empty()) return;
216 
217  const CDCWireTopology& wireTopology = CDCWireTopology::getInstance();
218  CDC::TDCCountTranslatorBase& tdcCountTranslator = *m_tdcCountTranslator;
219  CDC::ADCCountTranslatorBase& adcCountTranslator = *m_adcCountTranslator;
221 
222  // Create the wire hits into a vector
223  StoreArray<CDCHit> hits;
224  std::size_t nHits = hits.getEntries();
225  if (nHits == 0) {
226  B2WARNING("Event with no hits");
227  outputWireHits.clear();
228  }
229 
230  std::map<int, size_t> nHitsByMCParticleId;
231 
232  outputWireHits.reserve(nHits);
233 
234  // make sure that DB object for time cut is valid:
235  if (not m_DBCDClayerTimeCut.isValid()) {
236  B2FATAL("CDClayerTimeCut DB object is invalid");
237  }
238 
239  for (const CDCHit& hit : hits) {
240 
241  if (hit.getICLayer() < geometryPar.getOffsetOfFirstLayer() or
242  hit.getISuperLayer() < geometryPar.getOffsetOfFirstSuperLayer()) {
243  continue;
244  }
245 
246  // ignore this hit if it contains the information of a 2nd hit
247  if (!m_param_useSecondHits && hit.is2ndHit()) {
248  continue;
249  }
250 
251  // Only use some MCParticles if request - mostly for debug
252  if (not m_param_useMCParticleIds.empty()) {
253  MCParticle* mcParticle = hit.getRelated<MCParticle>();
254  int mcParticleId = mcParticle->getArrayIndex();
255  if (mcParticle) {
256  nHitsByMCParticleId[mcParticleId]++;
257  }
258  bool useMCParticleId = std::count(m_param_useMCParticleIds.begin(),
260  mcParticleId);
261  if (not useMCParticleId) continue;
262  }
263 
264  WireID wireID(hit.getID());
265  if (not wireTopology.isValidWireID(wireID)) {
266  B2WARNING("Skip invalid wire id " << hit.getID());
267  continue;
268  }
269 
270  // ignore hit if it is on a bad wire
271  if (not m_param_useBadWires and geometryPar.isBadWire(wireID)) {
272  continue;
273  }
274 
275  // Exclude hit with large drift time
276  // In the following, the tof correction is off; the propagation-delay corr. is off (default of the translator); the event time corr. is on when it is available.
277  const double approxDriftTime = tdcCountTranslator.getDriftTime(hit.getTDCCount(), wireID, 0, 0, hit.getADCCount());
278  ISuperLayer iSL = wireID.getISuperLayer();
279 
280  // If input module parameter is set to positive value, use it. Otherwise use DB
281  if (m_maxDriftTimes.at(iSL) > 0) {
282  if (approxDriftTime > m_maxDriftTimes.at(iSL)) continue;
283  } else {
284  if (m_DBCDClayerTimeCut->getLayerTimeCut(iSL) > 0 && approxDriftTime > m_DBCDClayerTimeCut->getLayerTimeCut(iSL)) continue;
285  }
286 
287  if (not m_useSuperLayers[iSL]) continue;
288  unsigned short layer = wireID.getICLayer();
289  if (not m_useLayers[layer]) continue;
290 
291  const CDCWire& wire = wireTopology.getWire(wireID);
292 
293  const Vector2D& pos2D = wire.getRefPos2D();
294 
295  // Check whether the position is outside the selected sector
296  if (pos2D.isBetween(m_useSector[1], m_useSector[0])) continue;
297 
298  // Only use some MCParticles if request - mostly for debug
299  if (not m_param_useMCParticleIds.empty()) {
300  MCParticle* mcParticle = hit.getRelated<MCParticle>();
301  int mcParticleId = mcParticle->getArrayIndex();
302  if (mcParticle) {
303  nHitsByMCParticleId[mcParticleId]++;
304  }
305  bool useMCParticleId = std::count(m_param_useMCParticleIds.begin(),
307  mcParticleId);
308  if (not useMCParticleId) continue;
309  }
310 
311 
312 
313  // Consider the particle as incoming in the top part of the CDC for a downwards flight direction
314  bool isIncoming = m_flightTimeEstimation == EPreferredDirection::c_Downwards and pos2D.y() > 0;
315  const double alpha = isIncoming ? M_PI : 0;
316  const double beta = 1;
317  const double flightTimeEstimate =
318  FlightTimeEstimator::instance().getFlightTime2D(pos2D, alpha, beta);
319 
320  const double driftTime = tdcCountTranslator.getDriftTime(hit.getTDCCount(),
321  wire.getWireID(),
322  flightTimeEstimate,
323  wire.getRefZ(),
324  hit.getADCCount());
325  const bool left = false;
326  const bool right = true;
327  const double theta = M_PI / 2;
328 
329  const double leftRefDriftLength =
330  tdcCountTranslator.getDriftLength(hit.getTDCCount(),
331  wire.getWireID(),
332  flightTimeEstimate,
333  left,
334  wire.getRefZ(),
335  alpha,
336  theta);
337 
338  const double rightRefDriftLength =
339  tdcCountTranslator.getDriftLength(hit.getTDCCount(),
340  wire.getWireID(),
341  flightTimeEstimate,
342  right,
343  wire.getRefZ(),
344  alpha,
345  theta);
346 
347  const double refDriftLength =
348  (leftRefDriftLength + rightRefDriftLength) / 2.0;
349 
350  const double leftRefDriftLengthVariance =
351  tdcCountTranslator.getDriftLengthResolution(refDriftLength,
352  wire.getWireID(),
353  left,
354  wire.getRefZ(),
355  alpha,
356  theta);
357 
358  const double rightRefDriftLengthVariance =
359  tdcCountTranslator.getDriftLengthResolution(refDriftLength,
360  wire.getWireID(),
361  right,
362  wire.getRefZ(),
363  alpha,
364  theta);
365 
366  const double refDriftLengthVariance =
367  (leftRefDriftLengthVariance + rightRefDriftLengthVariance) / 2.0;
368 
369  const double leftRefChargeDeposit =
370  adcCountTranslator.getCharge(hit.getADCCount(),
371  wire.getWireID(),
372  left,
373  wire.getRefZ(),
374  theta);
375 
376  const double rightRefChargeDeposit =
377  adcCountTranslator.getCharge(hit.getADCCount(),
378  wire.getWireID(),
379  right,
380  wire.getRefZ(),
381  theta);
382 
383  const double refChargeDeposit =
384  (leftRefChargeDeposit + rightRefChargeDeposit) / 2.0;
385 
386  outputWireHits.emplace_back(&hit, refDriftLength, refDriftLengthVariance, refChargeDeposit, driftTime);
387  }
388 
389  std::sort(outputWireHits.begin(), outputWireHits.end());
390 
391  if (not m_param_useMCParticleIds.empty()) {
392  for (const std::pair<int, size_t> nHitsForMCParticleId : nHitsByMCParticleId) {
393  B2DEBUG(25,
394  "MC particle " << nHitsForMCParticleId.first << " #hits "
395  << nHitsForMCParticleId.second);
396  }
397  }
398 }
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition: CDCHit.h:40
Abstract Base class for the ADC count translator.
virtual float getCharge(unsigned short adcCount=0, const WireID &wireID=WireID(), bool ambiguityDiscriminator=false, float z=0, float theta=static_cast< float >(TMath::Pi()/2.))=0
Function, for which this actually was meant.
The Class for CDC Geometry Parameters.
ushort getOffsetOfFirstLayer() const
Get the offset of the first layer.
bool isBadWire(const WireID &wid)
Inquire if the wire is totally-dead.
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
ushort getOffsetOfFirstSuperLayer() const
Get the offset of the first super layer.
This class simply assumes a linear translation through (0,0)
Translator mirroring the realistic Digitization.
Base class for translation of Drift Time into Drift Length.
virtual double getDriftLength(unsigned short tdcCount=0, const WireID &wireID=WireID(), double timeOfFlightEstimator=0., bool ambiguityDiscriminator=false, double z=0, double alpha=0, double theta=static_cast< double >(TMath::Pi()/2.), unsigned short adcCount=0)=0
Function for getting a drift length estimation.
virtual double getDriftLengthResolution(double driftLength=0., const WireID &wireID=WireID(), bool ambiguityDiscriminator=false, double z=0, double alpha=0, double theta=static_cast< double >(TMath::Pi()/2.))=0
Uncertainty corresponding to drift length from getDriftLength of this class.
virtual double getDriftTime(unsigned short tdcCount, const WireID &wireID, double timeOfFlightEstimator, double z, unsigned short adcCount)=0
Get Drift time.
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
int getArrayIndex() const
Get 0-based index of the particle in the corresponding MCParticle list.
Definition: MCParticle.h:244
The Module parameter list class.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
Class representating the sense wire arrangement in the whole of the central drift chamber.
void reinitialize(EWirePosition wirePosition, bool ignoreWireSag)
Reload all geometry parameters form the CDCGeometryPar to adjust to changes in geometry.
static CDCWireTopology & getInstance()
Getter for the singleton instance of the wire topology.
bool isValidWireID(const WireID &wireID) const
Checks the validity of a wireID convinience object.
const CDCWire & getWire(const WireID &wireId) const
Getter for wire getter by wireID object.
Class representing a sense wire in the central drift chamber.
Definition: CDCWire.h:58
const Vector2D & getRefPos2D() const
Getter for the wire reference position for 2D tracking Gives the wire's reference position projected ...
Definition: CDCWire.h:229
const WireID & getWireID() const
Getter for the wire id.
Definition: CDCWire.h:122
double getRefZ() const
Getter for the wire reference z coordinate Gives the wire's reference z coordinate.
Definition: CDCWire.h:236
void initialize() override
Receive and dispatch signal before the start of the event processing.
void beginRun() override
Receive and dispatch signal for the beginning of a new run.
static const FlightTimeEstimator & instance(std::unique_ptr< FlightTimeEstimator > replacement=nullptr)
Getter for the instance.
virtual double getFlightTime2D(const Vector2D &, double, double=1) const
Default estimator for the flight time.
A two dimensional vector which is equipped with functions for correct handeling of orientation relat...
Definition: Vector2D.h:35
bool isBetween(const Vector2D &lower, const Vector2D &upper) const
Checks if this vector is between two other vectors Between means here that when rotating the lower ve...
Definition: Vector2D.h:537
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:617
static Vector2D Phi(const double phi)
Constucts a unit vector with azimuth angle equal to phi.
Definition: Vector2D.h:71
std::string m_param_wirePosition
Parameter : Geometry set to be used. Either "base", "misalign" or " aligned".
EPreferredDirection m_flightTimeEstimation
Method for the initial time of flight estimation.
std::array< bool, ISuperLayerUtil::c_N > m_useSuperLayers
Bits for the used super layers.
void initialize() final
Signals the beginning of the event processing.
void beginRun() final
Signal the beginning of a new run.
EWirePosition m_wirePosition
Geometry set to be used.
std::vector< int > m_param_useMCParticleIds
Parameter : Indices of the Monte Carlo particles for which hits should be used.
std::tuple< double, double, double > m_param_triggerPoint
Parameter : Location of the flight time zero.
std::unique_ptr< CDC::TDCCountTranslatorBase > m_tdcCountTranslator
TDC Count translator to be used to calculate the initial dirft length estiamtes.
std::string getDescription() final
Short description of the findlet.
std::string m_param_flightTimeEstimation
Parameter : Method for the initial time of flight estimation as string.
std::vector< uint > m_param_useLayers
Parameter : List of layers to be used.
DBObjPtr< CDClayerTimeCut > m_DBCDClayerTimeCut
Cut for approximate drift time (super-layer dependent)
std::vector< uint > m_param_ignoreLayers
Parameter : List of layers to be ignored in tracking e.g. for simulating too high occupancy.
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix) final
Expose the parameters to a module.
std::tuple< double, double > m_param_useDegreeSector
Parameter : Angular range in degrees for which hits should be unpacked.
std::array< bool, c_maxNSenseLayers > m_useLayers
Bits for the used layers.
std::unique_ptr< CDC::ADCCountTranslatorBase > m_adcCountTranslator
ADC Count translator to be used to calculate the charge deposit in the drift cell.
std::vector< int > m_param_useSuperLayers
Parameter : List of super layers to be used - mostly for debugging.
bool m_param_ignoreWireSag
Parameter : Switch to deactivate the sag of the wires for the concerns of the track finders.
void apply(std::vector< CDCWireHit > &outputWireHits) final
Main algorithm creating the wire hits.
std::array< Vector2D, 2 > m_useSector
Unit vectors denoting the sector for which hits should be created.
std::array< float, ISuperLayerUtil::c_N > m_maxDriftTimes
Cut for approximate drift time (super-layer dependent)
bool m_param_useBadWires
Parameter : If true, the hits on bad wires are not ignored.
std::vector< float > m_param_maxDriftTimes
Parameter : Cut for approximate drift time (super-layer dependent)
bool m_param_useSecondHits
Parameter : If true, the second hit information will be used to create Wire Hits.
Vector3D m_triggerPoint
Central location of the flight time zero position. Usually the location of the trigger.
static const double deg
degree to radians
Definition: Unit.h:109
Class to identify a wire inside the CDC.
Definition: WireID.h:34
unsigned short getICLayer() const
Getter for continuous layer numbering.
Definition: WireID.cc:24
unsigned short getISuperLayer() const
Getter for Super-Layer.
Definition: WireID.h:130
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
HepGeom::Vector3D< double > Vector3D
3D Vector
Definition: Cell.h:34
Abstract base class for different kinds of events.