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/trackingUtilities/geometry/VectorUtil.h>
12#include <tracking/trackFindingCDC/eventdata/utils/FlightTimeEstimator.h>
13
14#include <tracking/trackFindingCDC/findlets/minimal/EPreferredDirection.h>
15
16#include <cdc/topology/CDCWireTopology.h>
17
18#include <tracking/trackingUtilities/utilities/StringManipulation.h>
19
20#include <cdc/translators/RealisticTDCCountTranslator.h>
21#include <cdc/translators/LinearGlobalADCCountTranslator.h>
22#include <cdc/geometry/CDCGeometryPar.h>
23
24#include <cdc/dataobjects/CDCHit.h>
25
26#include <framework/datastore/StoreArray.h>
27#include <framework/core/ModuleParamList.templateDetails.h>
28
29#include <mdst/dataobjects/MCParticle.h>
30
31#include <Math/Vector3D.h>
32#include <Math/Vector2D.h>
33
34using namespace Belle2;
35using namespace CDC;
36using namespace TrackFindingCDC;
37using namespace TrackingUtilities;
38
41
43{
44 return "Combines the geometrical information and the raw hit information into wire hits, "
45 "which can be used from all modules after that";
46}
47
48void WireHitCreator::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
49{
50 moduleParamList->addParameter(prefixed(prefix, "wirePosition"),
52 "Set of geometry parameters to be used in the track finding. "
53 "Either 'base', 'misaligned' or 'aligned'.",
55
56 moduleParamList->addParameter(prefixed(prefix, "ignoreWireSag"),
58 "Assume a wire sag coefficient of zero "
59 "such that the wires appear to be straight for "
60 "the track finders",
62
63 moduleParamList->addParameter(prefixed(prefix, "flightTimeEstimation"),
65 "Option which flight direction should be assumed for "
66 "an initial time of flight estimation. Options are: "
67 "'none' (no TOF correction), "
68 "'outwards', "
69 "'downwards'.",
71
72 moduleParamList->addParameter(prefixed(prefix, "triggerPoint"),
74 "Point relative to which the flight times are calculated",
76
77 moduleParamList->addParameter(prefixed(prefix, "useSuperLayers"),
79 "List of super layers to be used.",
81
82 moduleParamList->addParameter(prefixed(prefix, "maxDriftTimes"),
84 "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",
86
87 moduleParamList->addParameter(prefixed(prefix, "useLayers"),
89 "List of layers to be used. "
90 "If a layer number is given in 'ignoreLayers', too, this will result on a B2FATAL. "
91 "Either use 'useLayers' and provide a set of layers to be used, "
92 "or use 'ignoreLayers' and provide a list of layers to be ignored, but not both at the same time.",
94
95 moduleParamList->addParameter(prefixed(prefix, "ignoreLayers"),
97 "List of layers to be ignored. "
98 "If a layer number is given in 'useLayers', too, this will result on a B2FATAL. "
99 "Either use 'useLayers' and provide a set of layers to be used, "
100 "or use 'ignoreLayers' and provide a list of layers to be ignored, but not both at the same time.",
102
103 moduleParamList->addParameter(prefixed(prefix, "useSecondHits"),
105 "Use the second hit information in the track finding.",
107
108 moduleParamList->addParameter(prefixed(prefix, "useBadWires"),
110 "Also create the hits that are on bad wires.",
112
113 moduleParamList->addParameter(prefixed(prefix, "useDegreeSector"),
115 "To angles in degrees for which hits should be created - mostly for debugging",
117
118 moduleParamList->addParameter(prefixed(prefix, "useMCParticleIds"),
120 "Ids of the MC particles to use. Default does not look at the MCParticles - most for debugging",
122}
123
125{
127 hits.isRequired();
128
129 // Create the wires and layers once during initialisation
131
132 if (m_param_wirePosition == "base") {
133 m_wirePosition = EWirePosition::c_Base;
134 } else if (m_param_wirePosition == "misaligned") {
135 m_wirePosition = EWirePosition::c_Misaligned;
136 } else if (m_param_wirePosition == "aligned") {
137 m_wirePosition = EWirePosition::c_Aligned;
138 } else {
139 B2ERROR("Received unknown wirePosition " << m_param_wirePosition);
140 }
141
144
145 if (m_param_flightTimeEstimation != std::string("")) {
146 try {
148 } catch (std::invalid_argument& e) {
149 B2ERROR("Unexpected 'flightTimeEstimation' parameter : '" << m_param_flightTimeEstimation);
150 }
151 }
152
153 m_triggerPoint = ROOT::Math::XYZVector(std::get<0>(m_param_triggerPoint),
154 std::get<1>(m_param_triggerPoint),
155 std::get<2>(m_param_triggerPoint));
156
157 if (m_flightTimeEstimation == EPreferredDirection::c_Symmetric) {
158 B2ERROR("Unexpected 'flightTimeEstimation' parameter : '" << m_param_flightTimeEstimation);
159 } else if (m_flightTimeEstimation == EPreferredDirection::c_Downwards) {
160 FlightTimeEstimator::instance(std::make_unique<CosmicRayFlightTimeEstimator>(m_triggerPoint));
161 } else if (m_flightTimeEstimation == EPreferredDirection::c_Outwards) {
162 FlightTimeEstimator::instance(std::make_unique<BeamEventFlightTimeEstimator>());
163 }
164
165 int nSL = m_param_maxDriftTimes.size();
166 for (int iSL = 0; iSL < nSL; ++iSL) {
167 m_maxDriftTimes.at(iSL) = m_param_maxDriftTimes.at(iSL);
168 }
169
170 if (not m_param_useSuperLayers.empty()) {
171 for (const ISuperLayer iSL : m_param_useSuperLayers) {
172 m_useSuperLayers.at(iSL) = true;
173 }
174 } else {
175 m_useSuperLayers.fill(true);
176 }
177
178 // Check for common value in the two vectors for using / ignoring layers
179 for (const uint useLayer : m_param_useLayers) {
180 for (const uint ingoreLayer : m_param_ignoreLayers) {
181 if (useLayer == ingoreLayer) {
182 B2FATAL("You chose to use and ignore CDC layer " << useLayer << " at the same time. "
183 "Please decide to either use or to ignore the layer.");
184 }
185 }
186 }
187
188 // fill all layers that should be used
189 if (not m_param_useLayers.empty()) {
190 for (const uint layer : m_param_useLayers) {
191 m_useLayers.at(layer) = true;
192 }
193 } else {
194 m_useLayers.fill(true);
195 }
196 // set layers that should be ignored to false
197 if (not m_param_ignoreLayers.empty()) {
198 for (const uint layer : m_param_ignoreLayers) {
199 m_useLayers.at(layer) = false;
200 }
201 }
202
203 if (std::isfinite(std::get<0>(m_param_useDegreeSector))) {
204 m_useSector[0] = VectorUtil::Phi(std::get<0>(m_param_useDegreeSector) * Unit::deg);
205 m_useSector[1] = VectorUtil::Phi(std::get<1>(m_param_useDegreeSector) * Unit::deg);
206 }
207
209}
210
217
218void WireHitCreator::apply(std::vector<CDCWireHit>& outputWireHits)
219{
220 // Wire hits have been created before
221 if (not outputWireHits.empty()) return;
222
223 const CDCWireTopology& wireTopology = CDCWireTopology::getInstance();
227
228 // Create the wire hits into a vector
230 std::size_t nHits = hits.getEntries();
231 if (nHits == 0) {
232 B2WARNING("Event with no hits");
233 outputWireHits.clear();
234 }
235
236 std::map<int, size_t> nHitsByMCParticleId;
237
238 outputWireHits.reserve(nHits);
239
240 // make sure that DB object for time cut is valid:
241 if (not m_DBCDClayerTimeCut.isValid()) {
242 B2FATAL("CDClayerTimeCut DB object is invalid");
243 }
244
245 for (const CDCHit& hit : hits) {
246
247 if (hit.getICLayer() < geometryPar.getOffsetOfFirstLayer() or
248 hit.getISuperLayer() < geometryPar.getOffsetOfFirstSuperLayer()) {
249 continue;
250 }
251
252 // ignore this hit if it contains the information of a 2nd hit
253 if (!m_param_useSecondHits && hit.is2ndHit()) {
254 continue;
255 }
256
257 // Only use some MCParticles if request - mostly for debug
258 if (not m_param_useMCParticleIds.empty()) {
259 const MCParticle* mcParticle = hit.getRelated<MCParticle>();
260 // hits without a related MCParticle can never be in the requested id list and are skipped below
261 int mcParticleId = mcParticle ? mcParticle->getArrayIndex() : -1;
262 if (mcParticle) {
263 nHitsByMCParticleId[mcParticleId]++;
264 }
265 bool useMCParticleId = std::count(m_param_useMCParticleIds.begin(),
267 mcParticleId);
268 if (not useMCParticleId) continue;
269 }
270
271 WireID wireID(hit.getID());
272 if (not wireTopology.isValidWireID(wireID)) {
273 B2WARNING("Skip invalid wire id " << hit.getID());
274 continue;
275 }
276
277 // ignore hit if it is on a bad wire
278 if (not m_param_useBadWires and geometryPar.isBadWire(wireID)) {
279 continue;
280 }
281
282 // Exclude hit with large drift time
283 // 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.
284 const double approxDriftTime = tdcCountTranslator.getDriftTime(hit.getTDCCount(), wireID, 0, 0, hit.getADCCount());
285 ISuperLayer iSL = wireID.getISuperLayer();
286
287 // If input module parameter is set to positive value, use it. Otherwise use DB
288 if (m_maxDriftTimes.at(iSL) > 0) {
289 if (approxDriftTime > m_maxDriftTimes.at(iSL)) continue;
290 } else {
291 if (m_DBCDClayerTimeCut->getLayerTimeCut(iSL) > 0 && approxDriftTime > m_DBCDClayerTimeCut->getLayerTimeCut(iSL)) continue;
292 }
293
294 if (not m_useSuperLayers[iSL]) continue;
295 unsigned short layer = wireID.getICLayer();
296 if (not m_useLayers[layer]) continue;
297
298 const CDCWire& wire = wireTopology.getWire(wireID);
299
300 const ROOT::Math::XYVector& pos2D = wire.getRefPos2D();
301
302 // Check whether the position is outside the selected sector
303 if (VectorUtil::isBetween(pos2D, m_useSector[1], m_useSector[0])) continue;
304
305 // Only use some MCParticles if request - mostly for debug
306 if (not m_param_useMCParticleIds.empty()) {
307 const MCParticle* mcParticle = hit.getRelated<MCParticle>();
308 // hits without a related MCParticle can never be in the requested id list and are skipped below
309 int mcParticleId = mcParticle ? mcParticle->getArrayIndex() : -1;
310 if (mcParticle) {
311 nHitsByMCParticleId[mcParticleId]++;
312 }
313 bool useMCParticleId = std::count(m_param_useMCParticleIds.begin(),
315 mcParticleId);
316 if (not useMCParticleId) continue;
317 }
318
319
320
321 // Consider the particle as incoming in the top part of the CDC for a downwards flight direction
322 bool isIncoming = m_flightTimeEstimation == EPreferredDirection::c_Downwards and pos2D.y() > 0;
323 const double alpha = isIncoming ? M_PI : 0;
324 const double beta = 1;
325 const double flightTimeEstimate =
327
328 const double driftTime = tdcCountTranslator.getDriftTime(hit.getTDCCount(),
329 wire.getWireID(),
330 flightTimeEstimate,
331 wire.getRefZ(),
332 hit.getADCCount());
333 const bool left = false;
334 const bool right = true;
335 const double theta = M_PI / 2;
336
337 const double leftRefDriftLength =
338 tdcCountTranslator.getDriftLength(hit.getTDCCount(),
339 wire.getWireID(),
340 flightTimeEstimate,
341 left,
342 wire.getRefZ(),
343 alpha,
344 theta);
345
346 const double rightRefDriftLength =
347 tdcCountTranslator.getDriftLength(hit.getTDCCount(),
348 wire.getWireID(),
349 flightTimeEstimate,
350 right,
351 wire.getRefZ(),
352 alpha,
353 theta);
354
355 const double refDriftLength =
356 (leftRefDriftLength + rightRefDriftLength) / 2.0;
357
358 const double leftRefDriftLengthVariance =
359 tdcCountTranslator.getDriftLengthResolution(refDriftLength,
360 wire.getWireID(),
361 left,
362 wire.getRefZ(),
363 alpha,
364 theta);
365
366 const double rightRefDriftLengthVariance =
367 tdcCountTranslator.getDriftLengthResolution(refDriftLength,
368 wire.getWireID(),
369 right,
370 wire.getRefZ(),
371 alpha,
372 theta);
373
374 const double refDriftLengthVariance =
375 (leftRefDriftLengthVariance + rightRefDriftLengthVariance) / 2.0;
376
377 const double leftRefChargeDeposit =
378 adcCountTranslator.getCharge(hit.getADCCount(),
379 wire.getWireID(),
380 left,
381 wire.getRefZ(),
382 theta);
383
384 const double rightRefChargeDeposit =
385 adcCountTranslator.getCharge(hit.getADCCount(),
386 wire.getWireID(),
387 right,
388 wire.getRefZ(),
389 theta);
390
391 const double refChargeDeposit =
392 (leftRefChargeDeposit + rightRefChargeDeposit) / 2.0;
393
394 outputWireHits.emplace_back(&hit, refDriftLength, refDriftLengthVariance, refChargeDeposit, driftTime);
395 }
396
397 std::sort(outputWireHits.begin(), outputWireHits.end());
398
399 if (not m_param_useMCParticleIds.empty()) {
400 for (const std::pair<int, size_t> nHitsForMCParticleId : nHitsByMCParticleId) {
401 B2DEBUG(25,
402 "MC particle " << nHitsForMCParticleId.first << " #hits "
403 << nHitsForMCParticleId.second);
404 }
405 }
406}
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:234
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
static const FlightTimeEstimator & instance(std::unique_ptr< FlightTimeEstimator > replacement=nullptr)
Getter for the instance.
virtual double getFlightTime2D(const ROOT::Math::XYVector &, double, double=1) const
Default estimator for the flight time.
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.
std::tuple< double, double, double > m_param_triggerPoint
Parameter : Location of the flight time zero.
std::array< ROOT::Math::XYVector, 2 > m_useSector
Unit vectors denoting the sector for which hits should be created.
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.
~WireHitCreator() override
Default destructor.
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.
ROOT::Math::XYZVector m_triggerPoint
Central location of the flight time zero position. Usually the location of the trigger.
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.
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.
signed short ISuperLayer
The type of the layer and superlayer ids.
Definition ISuperLayer.h:24
Abstract base class for different kinds of events.