8#include <tracking/trackFindingCDC/processing/AxialTrackUtil.h>
10#include <tracking/trackFindingCDC/fitting/CDCRiemannFitter.h>
11#include <tracking/trackFindingCDC/fitting/CDCKarimakiFitter.h>
12#include <tracking/trackFindingCDC/fitting/CDCObservations2D.h>
14#include <tracking/trackingUtilities/eventdata/tracks/CDCTrack.h>
15#include <tracking/trackingUtilities/eventdata/hits/CDCWireHit.h>
16#include <tracking/trackingUtilities/eventdata/trajectories/CDCTrajectorySZ.h>
17#include <tracking/trackingUtilities/eventdata/trajectories/CDCTrajectory2D.h>
19#include <tracking/trackingUtilities/utilities/Algorithms.h>
23using namespace TrackFindingCDC;
24using namespace TrackingUtilities;
27 const std::vector<const CDCWireHit*>& allAxialWireHits,
28 std::vector<CDCTrack>& axialTracks,
29 bool withPostprocessing)
31 if (foundAxialWireHits.empty())
return;
42 for (
const CDCWireHit* wireHit : foundAxialWireHits) {
46 track.push_back(std::move(recoHit3D));
50 track.sortByArcLength2D();
53 bool success = withPostprocessing ?
postprocessTrack(track, allAxialWireHits) :
true;
57 recoHit3D.getWireHit().getAutomatonCell().setTakenFlag(
true);
59 axialTracks.emplace_back(std::move(track));
63 recoHit3D.getWireHit().getAutomatonCell().setMaskedFlag(
true);
64 recoHit3D.getWireHit().getAutomatonCell().setTakenFlag(
false);
92 return not(track.size() < 5);
98 if (track.size() < 5)
return;
102 observations2D.
append(item);
120 track.sortByArcLength2D();
123 track.setStartTrajectory3D(trajectory3D);
125 Vector3D backPosition = track.back().getRecoPos3D();
127 track.setEndTrajectory3D(trajectory3D);
144 const CDCTrajectory2D& trajectory2D = track.getStartTrajectory3D().getTrajectory2D();
145 auto farFromTrajectory = [&trajectory2D, &maximumDistance](
CDCRecoHit3D & recoHit3D) {
146 Vector2D refPos2D = recoHit3D.getRefPos2D();
147 double distance = trajectory2D.
getDist2D(refPos2D) - recoHit3D.getSignedRecoDriftLength();
148 if (std::fabs(distance) > maximumDistance) {
149 recoHit3D.getWireHit().getAutomatonCell().setTakenFlag(
false);
151 recoHit3D.getWireHit().getAutomatonCell().setMaskedFlag(
true);
156 erase_remove_if(track, farFromTrajectory);
160 double minimal_probability_for_good_fit)
163 const auto lowPValue = [&](
const CDCTrack & track) {
167 if (not(fittedTrajectory.
getPValue() >= minimal_probability_for_good_fit)) {
169 track.forwardTakenFlag(
false);
174 erase_remove_if(axialTracks, lowPValue);
178 const std::vector<const CDCWireHit*>& allAxialWireHits,
179 double minimalDistance)
181 if (track.size() < 10)
return;
183 const CDCTrajectory2D& trackTrajectory2D = track.getStartTrajectory3D().getTrajectory2D();
185 for (
const CDCWireHit* wireHit : allAxialWireHits) {
186 if (wireHit->getAutomatonCell().hasTakenFlag())
continue;
191 if (fabs(trackTrajectory2D.
getDist2D(recoPos2D)) < minimalDistance) {
192 track.push_back(std::move(recoHit3D));
200 const auto isShort = [&](
const CDCTrack & track) {
201 if (track.size() < minimal_size) {
203 track.forwardTakenFlag(
false);
208 erase_remove_if(axialTracks, isShort);
213 std::vector<CDCRecoHit3D> removedHits;
215 if (track.size() < 5)
return removedHits;
218 Vector2D center = track.getStartTrajectory3D().getGlobalCenter();
221 auto isOnMajorArm = [¢er, &majorArmSign](
const CDCRecoHit3D & hit) {
222 return getArmSign(hit, center) == majorArmSign;
225 auto itFirstMinorArmHit = std::stable_partition(track.begin(),
229 for (
const CDCRecoHit3D& recoHit3D : asRange(itFirstMinorArmHit, track.end())) {
230 recoHit3D.getWireHit().getAutomatonCell().setTakenFlag(
false);
231 removedHits.push_back(recoHit3D);
233 track.erase(itFirstMinorArmHit, track.end());
240 Vector2D center = track.getStartTrajectory3D().getGlobalCenter();
242 if (std::abs(armSignVote) <
int(track.size()) and std::fabs(center.
cylindricalR()) > 60.) {
251 if (armSignVote > 0) {
252 return ESign::c_Plus;
254 return ESign::c_Minus;
264 B2WARNING(
"Trajectory is not set or wrong!");
271 if (armSign == ESign::c_Plus) {
273 }
else if (armSign == ESign::c_Minus) {
276 B2ERROR(
"Strange behaviour of getArmSignVote");
279 int armSignVote = votePos - voteNeg;
290 double apogeeArcLength = fabs(track.getStartTrajectory3D().getGlobalCircle().perimeter()) / 2.;
292 std::array<int, ISuperLayerUtil::c_N> nForwardArmHitsBySLayer = {0};
293 std::array<int, ISuperLayerUtil::c_N> nBackwardArmHitsBySLayer = {0};
297 if ((hit.getArcLength2D() <= apogeeArcLength) and (hit.getArcLength2D() > 0)) {
298 nForwardArmHitsBySLayer[hit.getISuperLayer()]++;
300 nBackwardArmHitsBySLayer[hit.getISuperLayer()]++;
304 std::vector<ISuperLayer> forwardSLayerHoles =
getSLayerHoles(nForwardArmHitsBySLayer);
305 std::vector<ISuperLayer> backwardSLayerHoles =
getSLayerHoles(nBackwardArmHitsBySLayer);
308 if (forwardSLayerHoles.empty() and backwardSLayerHoles.empty())
return;
312 assert(std::is_sorted(forwardSLayerHoles.begin(), forwardSLayerHoles.end()));
313 if (forwardSLayerHoles.empty())
return;
315 const ISuperLayer breakSLayer = forwardSLayerHoles.front();
317 auto isInBackwardArm = [apogeeArcLength](
const CDCRecoHit3D & recoHit3D) {
318 if ((recoHit3D.getArcLength2D() >= apogeeArcLength) or (recoHit3D.getArcLength2D() < 0)) {
319 recoHit3D.getWireHit().getAutomatonCell().unsetTakenFlag();
325 erase_remove_if(track, isInBackwardArm);
327 auto isAfterSLayerBreak = [breakSLayer](
const CDCRecoHit3D & recoHit3D) {
328 recoHit3D.getWireHit().getAutomatonCell().unsetTakenFlag();
329 if (recoHit3D.getISuperLayer() >= breakSLayer) {
330 recoHit3D.getWireHit().getAutomatonCell().unsetTakenFlag();
336 erase_remove_if(track, isAfterSLayerBreak);
341 std::vector<ISuperLayer> sLayerHoles;
351 for (
ISuperLayer iSLayer = firstSlayer; iSLayer <= lastSlayer; iSLayer += 2) {
352 if (nHitsBySLayer[iSLayer] == 0) {
353 sLayerHoles.push_back(iSLayer);
362 if (nHitsBySLayer[iSLayer] > 0)
return iSLayer;
370 if (nHitsBySLayer[iSLayer] > 0)
return iSLayer;
TrackingUtilities::CDCTrajectory2D fit(const CDCObservations2D &observations2D) const
Fits a collection of observation drift circles.
Class implementing the fitter using Karimakis method.
static const CDCKarimakiFitter & getNoDriftVarianceFitter()
Static getter for a general fitter that does not use the drift length variances.
Class serving as a storage of observed drift circles to present to the Riemann fitter.
std::size_t append(const TrackingUtilities::CDCWireHit &wireHit, TrackingUtilities::ERightLeft rlInfo=TrackingUtilities::ERightLeft::c_Unknown)
Appends the hit circle at wire reference position without a right left passage hypotheses.
Class implementing the Riemann fit for two dimensional trajectory circle.
static const CDCRiemannFitter & getFitter()
Static getter for a general Riemann fitter.
Cell used by the cellular automata.
void setTakenFlag(bool setTo=true)
Sets the taken flag to the given value. Default value true.
bool hasTakenFlag() const
Gets the current state of the taken marker flag.
Class representing a three dimensional reconstructed hit.
const CDCWireHit & getWireHit() const
Getter for the wire hit.
const Vector2D & getRecoPos2D() const
Getter for the 2d position of the hit.
double getArcLength2D() const
Getter for the travel distance in the xy projection.
void setArcLength2D(const double arcLength2D)
Setter for the travel distance in the xy projection.
static CDCRecoHit3D reconstructNearest(const CDCWireHit *axialWireHit, const CDCTrajectory2D &trajectory2D)
Reconstruct a three dimensional hit from a wire hit (as in reconstruct(rlWireHit, trajectory2D)),...
Class representing a sequence of three dimensional reconstructed hits.
Particle trajectory as it is seen in xy projection represented as a circle.
void reverse()
Reverses the trajectory in place.
double setLocalOrigin(const Vector2D &localOrigin)
Setter for the origin of the local coordinate system.
ESign getChargeSign() const
Gets the charge sign of the trajectory.
double getPValue() const
Getter for p-value.
double getArcLength2DPeriod() const
Getter for the arc length for one round trip around the trajectory.
Vector2D getGlobalCenter() const
Getter for the center of the trajectory in global coordinates.
Vector2D getGlobalPerigee() const
Getter for the closest approach on the trajectory to the global origin.
double getDist2D(const Vector2D &point) const
Calculates the distance from the point to the trajectory as seen from the xy projection.
Particle full three dimensional trajectory.
double setLocalOrigin(const Vector3D &localOrigin)
Setter for the origin of the local coordinate system.
static CDCTrajectorySZ basicAssumption()
Constructs a basic assumption, what the z0 start position and the sz slope are, including some broad ...
Class representing a hit wire in the central drift chamber.
AutomatonCell & getAutomatonCell() const
Mutable getter for the automaton cell.
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
double cylindricalR() const
Gives the cylindrical radius of the vector. Same as norm()
ERightLeft isRightOrLeftOf(const Vector2D &rhs) const
Indicates if the given vector is more left or more right if you looked in the direction of this vecto...
bool hasNAN() const
Checks if one of the coordinates is NAN.
HepGeom::Vector3D< double > Vector3D
3D Vector
signed short ISuperLayer
The type of the layer and superlayer ids.
Abstract base class for different kinds of events.
static const ISuperLayer c_Invalid
Constant making an invalid superlayer id.
static const ISuperLayer c_N
Constant representing the total number of cdc superlayers.
static bool isInvalid(ISuperLayer iSuperLayer)
Indicates if the given number corresponds to a true cdc superlayer - excludes the logic ids for inner...
static void normalizeTrack(TrackingUtilities::CDCTrack &track)
Refit and resort the track. Unmask all hits.
static void deleteShortTracks(std::vector< TrackingUtilities::CDCTrack > &axialTracks, double minimal_size=5)
Remove tracks that are shorter than the given number of hits.
static void updateRecoHit3D(const TrackingUtilities::CDCTrajectory2D &trajectory2D, TrackingUtilities::CDCRecoHit3D &hit)
update given CDCRecoHit3D with given trajectory
static void addCandidateFromHits(const std::vector< const TrackingUtilities::CDCWireHit * > &foundAxialWireHits, const std::vector< const TrackingUtilities::CDCWireHit * > &allAxialWireHits, std::vector< TrackingUtilities::CDCTrack > &axialTracks, bool withPostprocessing=true)
Create CDCTrack using CDCWireHit hits and store it in the list. Then call the postprocessing on it.
static void deleteTracksWithLowFitProbability(std::vector< TrackingUtilities::CDCTrack > &axialTracks, double minimal_probability_for_good_fit=0.4)
Check an (improper) p-values of the tracks. If they are below the given value, delete the track from ...
static TrackingUtilities::ESign getMajorArmSign(const TrackingUtilities::CDCTrack &track, const TrackingUtilities::Vector2D ¢er)
Calculate whether the majority of hits is to the right or to the left relative to the line from origi...
static void removeHitsAfterSuperLayerBreak(TrackingUtilities::CDCTrack &track)
Searches for a break in the super layer chain and remove all hits that come after that.
static int getArmSignVote(const TrackingUtilities::CDCTrack &track, const TrackingUtilities::Vector2D ¢er)
Calculate the sum of right and left votes for the hits relative to the center.
static std::vector< CDC::ISuperLayer > getSLayerHoles(const std::array< int, CDC::ISuperLayerUtil::c_N > &nHitsBySLayer)
Helper function getting the empty axial!
static std::vector< TrackingUtilities::CDCRecoHit3D > splitBack2BackTrack(TrackingUtilities::CDCTrack &track)
Tries to split back-to-back tracks into two different tracks.
static void assignNewHitsToTrack(TrackingUtilities::CDCTrack &track, const std::vector< const TrackingUtilities::CDCWireHit * > &allAxialWireHits, double minimalDistance=0.2)
Assign new hits to the track basing on the distance from the hit to the track.
static bool postprocessTrack(TrackingUtilities::CDCTrack &track, const std::vector< const TrackingUtilities::CDCWireHit * > &allAxialWireHits)
Perform all track postprocessing - return whether the track is considered good after the postprocessi...
static void deleteHitsFarAwayFromTrajectory(TrackingUtilities::CDCTrack &track, double maximumDistance=0.2)
Postprocessing: Delete axial hits that do not "match" to the given track.
static TrackingUtilities::ESign getArmSign(const TrackingUtilities::CDCRecoHit3D &hit, const TrackingUtilities::Vector2D ¢er)
Calculate whether the hits is to the right or to the left relative to the line from origin to the giv...
static bool isBack2BackTrack(TrackingUtilities::CDCTrack &track)
Checks whether the track has hits on both arms as seen from the origin.
static CDC::ISuperLayer getLastOccupiedISuperLayer(const std::array< int, CDC::ISuperLayerUtil::c_N > &nHitsBySLayer)
Helper function to extract the last filled entry in the array of super layers ( = the final superlaye...
static bool checkTrackQuality(const TrackingUtilities::CDCTrack &track)
Check track quality – currently based on number of hits only.
static CDC::ISuperLayer getFirstOccupiedISuperLayer(const std::array< int, CDC::ISuperLayerUtil::c_N > &nHitsBySLayer)
Helper function to extract the first filled entry in the array of super layers ( = the start superlay...