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/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
30using namespace Belle2;
31using 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
42void 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{
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 {
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{
210}
211
212void 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();
221
222 // Create the wire hits into a vector
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 =
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 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:58
const WireID & getWireID() const
Getter for the wire id.
Definition: CDCWire.h:122
const Vector2D & getRefPos2D() const
Getter for the wire reference position for 2D tracking Gives the wire's reference position projected ...
Definition: CDCWire.h:229
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 handling of orientation relate...
Definition: Vector2D.h:32
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:525
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:605
static Vector2D Phi(const double phi)
Constructs a unit vector with azimuth angle equal to phi.
Definition: Vector2D.h:62
A three dimensional vector.
Definition: Vector3D.h:33
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.
Abstract base class for different kinds of events.