Belle II Software development
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/trackingUtilities/eventdata/hits/CDCWireHit.h>
11#include <tracking/trackFindingCDC/eventdata/utils/FlightTimeEstimator.h>
12
13#include <tracking/trackFindingCDC/findlets/minimal/EPreferredDirection.h>
14
15#include <cdc/topology/CDCWireTopology.h>
16
17#include <tracking/trackingUtilities/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
30using namespace Belle2;
31using namespace CDC;
32using namespace TrackFindingCDC;
33using namespace TrackingUtilities;
34
37
39{
40 return "Combines the geometrical information and the raw hit information into wire hits, "
41 "which can be used from all modules after that";
42}
43
44void WireHitCreator::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
45{
46 moduleParamList->addParameter(prefixed(prefix, "wirePosition"),
48 "Set of geometry parameters to be used in the track finding. "
49 "Either 'base', 'misaligned' or 'aligned'.",
51
52 moduleParamList->addParameter(prefixed(prefix, "ignoreWireSag"),
54 "Assume a wire sag coefficient of zero "
55 "such that the wires appear to be straight for "
56 "the track finders",
58
59 moduleParamList->addParameter(prefixed(prefix, "flightTimeEstimation"),
61 "Option which flight direction should be assumed for "
62 "an initial time of flight estimation. Options are: "
63 "'none' (no TOF correction), "
64 "'outwards', "
65 "'downwards'.",
67
68 moduleParamList->addParameter(prefixed(prefix, "triggerPoint"),
70 "Point relative to which the flight times are calculated",
72
73 moduleParamList->addParameter(prefixed(prefix, "useSuperLayers"),
75 "List of super layers to be used.",
77
78 moduleParamList->addParameter(prefixed(prefix, "maxDriftTimes"),
80 "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",
82
83 moduleParamList->addParameter(prefixed(prefix, "useLayers"),
85 "List of layers to be used. "
86 "If a layer number is given in 'ignoreLayers', too, this will result on a B2FATAL. "
87 "Either use 'useLayers' and provide a set of layers to be used, "
88 "or use 'ignoreLayers' and provide a list of layers to be ignored, but not both at the same time.",
90
91 moduleParamList->addParameter(prefixed(prefix, "ignoreLayers"),
93 "List of layers to be ignored. "
94 "If a layer number is given in 'useLayers', too, this will result on a B2FATAL. "
95 "Either use 'useLayers' and provide a set of layers to be used, "
96 "or use 'ignoreLayers' and provide a list of layers to be ignored, but not both at the same time.",
98
99 moduleParamList->addParameter(prefixed(prefix, "useSecondHits"),
101 "Use the second hit information in the track finding.",
103
104 moduleParamList->addParameter(prefixed(prefix, "useBadWires"),
106 "Also create the hits that are on bad wires.",
108
109 moduleParamList->addParameter(prefixed(prefix, "useDegreeSector"),
111 "To angles in degrees for which hits should be created - mostly for debugging",
113
114 moduleParamList->addParameter(prefixed(prefix, "useMCParticleIds"),
116 "Ids of the MC particles to use. Default does not look at the MCParticles - most for debugging",
118}
119
121{
123 hits.isRequired();
124
125 // Create the wires and layers once during initialisation
127
128 if (m_param_wirePosition == "base") {
129 m_wirePosition = EWirePosition::c_Base;
130 } else if (m_param_wirePosition == "misaligned") {
131 m_wirePosition = EWirePosition::c_Misaligned;
132 } else if (m_param_wirePosition == "aligned") {
133 m_wirePosition = EWirePosition::c_Aligned;
134 } else {
135 B2ERROR("Received unknown wirePosition " << m_param_wirePosition);
136 }
137
140
141 if (m_param_flightTimeEstimation != std::string("")) {
142 try {
144 } catch (std::invalid_argument& e) {
145 B2ERROR("Unexpected 'flightTimeEstimation' parameter : '" << m_param_flightTimeEstimation);
146 }
147 }
148
150 std::get<1>(m_param_triggerPoint),
151 std::get<2>(m_param_triggerPoint));
152
153 if (m_flightTimeEstimation == EPreferredDirection::c_Symmetric) {
154 B2ERROR("Unexpected 'flightTimeEstimation' parameter : '" << m_param_flightTimeEstimation);
155 } else if (m_flightTimeEstimation == EPreferredDirection::c_Downwards) {
156 FlightTimeEstimator::instance(std::make_unique<CosmicRayFlightTimeEstimator>(m_triggerPoint));
157 } else if (m_flightTimeEstimation == EPreferredDirection::c_Outwards) {
158 FlightTimeEstimator::instance(std::make_unique<BeamEventFlightTimeEstimator>());
159 }
160
161 int nSL = m_param_maxDriftTimes.size();
162 for (int iSL = 0; iSL < nSL; ++iSL) {
163 m_maxDriftTimes.at(iSL) = m_param_maxDriftTimes.at(iSL);
164 }
165
166 if (not m_param_useSuperLayers.empty()) {
167 for (const ISuperLayer iSL : m_param_useSuperLayers) {
168 m_useSuperLayers.at(iSL) = true;
169 }
170 } else {
171 m_useSuperLayers.fill(true);
172 }
173
174 // Check for common value in the two vectors for using / ignoring layers
175 for (const uint useLayer : m_param_useLayers) {
176 for (const uint ingoreLayer : m_param_ignoreLayers) {
177 if (useLayer == ingoreLayer) {
178 B2FATAL("You chose to use and ignore CDC layer " << useLayer << " at the same time. "
179 "Please decide to either use or to ignore the layer.");
180 }
181 }
182 }
183
184 // fill all layers that should be used
185 if (not m_param_useLayers.empty()) {
186 for (const uint layer : m_param_useLayers) {
187 m_useLayers.at(layer) = true;
188 }
189 } else {
190 m_useLayers.fill(true);
191 }
192 // set layers that should be ignored to false
193 if (not m_param_ignoreLayers.empty()) {
194 for (const uint layer : m_param_ignoreLayers) {
195 m_useLayers.at(layer) = false;
196 }
197 }
198
199 if (std::isfinite(std::get<0>(m_param_useDegreeSector))) {
202 }
203
205}
206
213
214void WireHitCreator::apply(std::vector<CDCWireHit>& outputWireHits)
215{
216 // Wire hits have been created before
217 if (not outputWireHits.empty()) return;
218
219 const CDCWireTopology& wireTopology = CDCWireTopology::getInstance();
223
224 // Create the wire hits into a vector
226 std::size_t nHits = hits.getEntries();
227 if (nHits == 0) {
228 B2WARNING("Event with no hits");
229 outputWireHits.clear();
230 }
231
232 std::map<int, size_t> nHitsByMCParticleId;
233
234 outputWireHits.reserve(nHits);
235
236 // make sure that DB object for time cut is valid:
237 if (not m_DBCDClayerTimeCut.isValid()) {
238 B2FATAL("CDClayerTimeCut DB object is invalid");
239 }
240
241 for (const CDCHit& hit : hits) {
242
243 if (hit.getICLayer() < geometryPar.getOffsetOfFirstLayer() or
244 hit.getISuperLayer() < geometryPar.getOffsetOfFirstSuperLayer()) {
245 continue;
246 }
247
248 // ignore this hit if it contains the information of a 2nd hit
249 if (!m_param_useSecondHits && hit.is2ndHit()) {
250 continue;
251 }
252
253 // Only use some MCParticles if request - mostly for debug
254 if (not m_param_useMCParticleIds.empty()) {
255 MCParticle* mcParticle = hit.getRelated<MCParticle>();
256 int mcParticleId = mcParticle->getArrayIndex();
257 if (mcParticle) {
258 nHitsByMCParticleId[mcParticleId]++;
259 }
260 bool useMCParticleId = std::count(m_param_useMCParticleIds.begin(),
262 mcParticleId);
263 if (not useMCParticleId) continue;
264 }
265
266 WireID wireID(hit.getID());
267 if (not wireTopology.isValidWireID(wireID)) {
268 B2WARNING("Skip invalid wire id " << hit.getID());
269 continue;
270 }
271
272 // ignore hit if it is on a bad wire
273 if (not m_param_useBadWires and geometryPar.isBadWire(wireID)) {
274 continue;
275 }
276
277 // Exclude hit with large drift time
278 // 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.
279 const double approxDriftTime = tdcCountTranslator.getDriftTime(hit.getTDCCount(), wireID, 0, 0, hit.getADCCount());
280 ISuperLayer iSL = wireID.getISuperLayer();
281
282 // If input module parameter is set to positive value, use it. Otherwise use DB
283 if (m_maxDriftTimes.at(iSL) > 0) {
284 if (approxDriftTime > m_maxDriftTimes.at(iSL)) continue;
285 } else {
286 if (m_DBCDClayerTimeCut->getLayerTimeCut(iSL) > 0 && approxDriftTime > m_DBCDClayerTimeCut->getLayerTimeCut(iSL)) continue;
287 }
288
289 if (not m_useSuperLayers[iSL]) continue;
290 unsigned short layer = wireID.getICLayer();
291 if (not m_useLayers[layer]) continue;
292
293 const CDCWire& wire = wireTopology.getWire(wireID);
294
295 const Vector2D& pos2D = wire.getRefPos2D();
296
297 // Check whether the position is outside the selected sector
298 if (pos2D.isBetween(m_useSector[1], m_useSector[0])) continue;
299
300 // Only use some MCParticles if request - mostly for debug
301 if (not m_param_useMCParticleIds.empty()) {
302 MCParticle* mcParticle = hit.getRelated<MCParticle>();
303 int mcParticleId = mcParticle->getArrayIndex();
304 if (mcParticle) {
305 nHitsByMCParticleId[mcParticleId]++;
306 }
307 bool useMCParticleId = std::count(m_param_useMCParticleIds.begin(),
309 mcParticleId);
310 if (not useMCParticleId) continue;
311 }
312
313
314
315 // Consider the particle as incoming in the top part of the CDC for a downwards flight direction
316 bool isIncoming = m_flightTimeEstimation == EPreferredDirection::c_Downwards and pos2D.y() > 0;
317 const double alpha = isIncoming ? M_PI : 0;
318 const double beta = 1;
319 const double flightTimeEstimate =
321
322 const double driftTime = tdcCountTranslator.getDriftTime(hit.getTDCCount(),
323 wire.getWireID(),
324 flightTimeEstimate,
325 wire.getRefZ(),
326 hit.getADCCount());
327 const bool left = false;
328 const bool right = true;
329 const double theta = M_PI / 2;
330
331 const double leftRefDriftLength =
332 tdcCountTranslator.getDriftLength(hit.getTDCCount(),
333 wire.getWireID(),
334 flightTimeEstimate,
335 left,
336 wire.getRefZ(),
337 alpha,
338 theta);
339
340 const double rightRefDriftLength =
341 tdcCountTranslator.getDriftLength(hit.getTDCCount(),
342 wire.getWireID(),
343 flightTimeEstimate,
344 right,
345 wire.getRefZ(),
346 alpha,
347 theta);
348
349 const double refDriftLength =
350 (leftRefDriftLength + rightRefDriftLength) / 2.0;
351
352 const double leftRefDriftLengthVariance =
353 tdcCountTranslator.getDriftLengthResolution(refDriftLength,
354 wire.getWireID(),
355 left,
356 wire.getRefZ(),
357 alpha,
358 theta);
359
360 const double rightRefDriftLengthVariance =
361 tdcCountTranslator.getDriftLengthResolution(refDriftLength,
362 wire.getWireID(),
363 right,
364 wire.getRefZ(),
365 alpha,
366 theta);
367
368 const double refDriftLengthVariance =
369 (leftRefDriftLengthVariance + rightRefDriftLengthVariance) / 2.0;
370
371 const double leftRefChargeDeposit =
372 adcCountTranslator.getCharge(hit.getADCCount(),
373 wire.getWireID(),
374 left,
375 wire.getRefZ(),
376 theta);
377
378 const double rightRefChargeDeposit =
379 adcCountTranslator.getCharge(hit.getADCCount(),
380 wire.getWireID(),
381 right,
382 wire.getRefZ(),
383 theta);
384
385 const double refChargeDeposit =
386 (leftRefChargeDeposit + rightRefChargeDeposit) / 2.0;
387
388 outputWireHits.emplace_back(&hit, refDriftLength, refDriftLengthVariance, refChargeDeposit, driftTime);
389 }
390
391 std::sort(outputWireHits.begin(), outputWireHits.end());
392
393 if (not m_param_useMCParticleIds.empty()) {
394 for (const std::pair<int, size_t> nHitsForMCParticleId : nHitsByMCParticleId) {
395 B2DEBUG(25,
396 "MC particle " << nHitsForMCParticleId.first << " #hits "
397 << nHitsForMCParticleId.second);
398 }
399 }
400}
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.
Class representing the sense wire arrangement in the whole of the central drift chamber.
const CDCWire & getWire(const WireID &wireId) const
Getter for wire getter by wireID object.
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 convenience object.
Class representing a sense wire in the central drift chamber.
Definition CDCWire.h:50
const ROOT::Math::XYVector & getRefPos2D() const
Getter for the wire reference position for 2D tracking Gives the wire's reference position projected ...
Definition CDCWire.h:221
const WireID & getWireID() const
Getter for the wire id.
Definition CDCWire.h:114
double getRefZ() const
Getter for the wire reference z coordinate Gives the wire's reference z coordinate.
Definition CDCWire.h:228
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:233
The Module parameter list class.
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
Accessor to arrays stored in the data store.
Definition StoreArray.h:113
int getEntries() const
Get the number of objects in the array.
Definition StoreArray.h:216
virtual double getFlightTime2D(const TrackingUtilities::Vector2D &, double, double=1) const
Default estimator for the flight time.
static const FlightTimeEstimator & instance(std::unique_ptr< FlightTimeEstimator > replacement=nullptr)
Getter for the instance.
void apply(std::vector< TrackingUtilities::CDCWireHit > &outputWireHits) final
Main algorithm creating the wire hits.
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.
void initialize() final
Signals the beginning of the event processing.
void beginRun() final
Signal the beginning of a new run.
std::vector< int > m_param_useMCParticleIds
Parameter : Indices of the Monte Carlo particles for which hits should be used.
TrackingUtilities::Vector3D m_triggerPoint
Central location of the flight time zero position. Usually the location of the trigger.
std::tuple< double, double, double > m_param_triggerPoint
Parameter : Location of the flight time zero.
std::array< float, CDC::ISuperLayerUtil::c_N > m_maxDriftTimes
Cut for approximate drift time (super-layer dependent)
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.
std::array< TrackingUtilities::Vector2D, 2 > m_useSector
Unit vectors denoting the sector for which hits should be created.
bool m_param_ignoreWireSag
Parameter : Switch to deactivate the sag of the wires for the concerns of the track finders.
bool m_param_useBadWires
Parameter : If true, the hits on bad wires are not ignored.
std::array< bool, CDC::ISuperLayerUtil::c_N > m_useSuperLayers
Bits for the used super layers.
CDC::EWirePosition m_wirePosition
Geometry set to be used.
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.
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Definition Vector2D.h:36
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:556
double y() const
Getter for the y coordinate.
Definition Vector2D.h:641
static Vector2D Phi(const double phi)
Constructs a unit vector with azimuth angle equal to phi.
Definition Vector2D.h:82
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
signed short ISuperLayer
The type of the layer and superlayer ids.
Definition ISuperLayer.h:24
Abstract base class for different kinds of events.