2828#include < Acts/Seeding/detail/CylindricalSpacePointGrid.hpp>
2929#include < Acts/Utilities/GridBinFinder.hpp>
3030#include < Acts/Utilities/RangeXD.hpp>
31+ #include < Acts/Definitions/TrackParametrization.hpp>
32+ #include < Acts/Seeding/EstimateTrackParamsFromSeed.hpp>
3133
3234namespace o2 ::trk
3335{
@@ -238,17 +240,128 @@ void TrackerACTS<nLayers>::createSeeds()
238240template <int nLayers>
239241bool TrackerACTS<nLayers>::estimateTrackParams(const SeedACTS& seed, o2::its::TrackITSExt& track) const
240242{
243+ const SpacePoint* sp0 = seed.bottom ;
244+ const SpacePoint* sp1 = seed.middle ;
245+ const SpacePoint* sp2 = seed.top ;
246+
247+ // Use ACTS parameter estimation
248+ Acts::Vector3 pos0{sp0->x , sp0->y , sp0->z };
249+ Acts::Vector3 pos1{sp1->x , sp1->y , sp1->z };
250+ Acts::Vector3 pos2{sp2->x , sp2->y , sp2->z };
251+
252+ // Magnetic field vector (along z-axis)
253+ Acts::Vector3 bField{0 ., 0 ., mBz * Acts::UnitConstants::T};
254+
255+ // Use the ACTS function with time parameter (t0 = 0)
256+ LOG (info) << " Calling ACTS estimateTrackParamsFromSeed with mag field " << mBz << " T" ;
257+ LOG (info) << " Seed space points: (" << pos0.transpose () << " ), (" << pos1.transpose () << " ), (" << pos2.transpose () << " )" ;
258+
259+ Acts::FreeVector params;
260+ try {
261+ params = Acts::estimateTrackParamsFromSeed (pos0, 0.0 , pos1, pos2, bField);
262+ } catch (const std::exception& e) {
263+ LOG (fatal) << " ACTS parameter estimation failed: " << e.what ();
264+ return false ;
265+ }
266+ LOG (info) << " ACTS parameter estimation successful: x=" << params[Acts::eFreePos0] << " y=" << params[Acts::eFreePos1]
267+ << " z=" << params[Acts::eFreePos2] << " q/p=" << params[Acts::eFreeQOverP];
268+
269+ // Extract parameters from ACTS format
270+ const auto & p = params;
271+ // ACTS FreeVector: x, y, z, t, dir_x, dir_y, dir_z, q/|p|
272+ // Direction components are normalized (unit vector)
273+ const float x = p[Acts::eFreePos0];
274+ const float y = p[Acts::eFreePos1];
275+ const float z = p[Acts::eFreePos2];
276+ const float px = p[Acts::eFreeDir0] * pMag;
277+ const float py = p[Acts::eFreeDir1] * pMag;
278+ const float pz = p[Acts::eFreeDir2] * pMag;
279+ const int charge = (p[Acts::eFreeQOverP] >= 0 ) ? 1 : -1 ;
280+
281+ // Set cluster indices from seed
282+ const int charge = std::sgn (p[Acts::eFreeQOverP]);
283+ track.set ({x, y, z}, {px, py, pz}, charge, false , PID ::Pion);
284+ track.setPxPyPz (px, py, pz);
285+ track.setPosition (x, y, z);
286+
287+ // q/pT = q/|p| * |p|/pT = qOverP * |p| / pT = qOverP / (pT / |p|) = qOverP / sin(theta)
288+ // Or simply: charge / pT where charge = sign(qOverP)
289+ track.setAbsCharge (charge);
290+
291+ LOG (info) << " Estimated track parameters" ;
241292 return true ;
242293}
243294
244295template <int nLayers>
245296void TrackerACTS<nLayers>::findTracks()
246297{
298+ return ; // For now we only create seeds, track finding and fitting will be implemented in the next iterations
299+ int nTracks = 0 ;
300+
301+ for (const auto & seed : mSeeds ) {
302+ o2::its::TrackITSExt track;
303+
304+ LOG (info) << " Estimating track parameters for seed with quality (pT) = " << seed.quality ;
305+ if (!estimateTrackParams (seed, track)) {
306+ continue ;
307+ }
308+
309+ // Add track to TimeFrame
310+ const int rof = seed.middle ->rof ;
311+ if (mTimeFrame && rof >= 0 && rof < mTimeFrame ->getNrof (0 )) {
312+ LOG (info) << " Adding track to ROF " << rof;
313+ auto & tracks = mTimeFrame ->getTracks ();
314+ // tracks.emplace_back(track);
315+ ++nTracks;
316+ }
317+ }
318+ LOG (info) << " Created " << nTracks << " tracks from " << mSeeds .size () << " seeds" ;
247319}
248320
249321template <int nLayers>
250322void TrackerACTS<nLayers>::computeTracksMClabels()
251323{
324+ return ; // For now we skip MC labeling, will be implemented in the next iterations once we have track candidates to label
325+ if (!mTimeFrame || !mTimeFrame ->hasMCinformation ()) {
326+ return ;
327+ }
328+
329+ // MC labeling using majority voting on cluster labels
330+ for (int iROF = 0 ; iROF < mTimeFrame ->getNrof (0 ); ++iROF) {
331+ for (auto & track : mTimeFrame ->getTracks ()) {
332+ std::vector<std::pair<MCCompLabel, size_t >> labelCounts;
333+
334+ for (int iCluster = 0 ; iCluster < o2::its::TrackITSExt::MaxClusters; ++iCluster) {
335+ const int clusterIdx = track.getClusterIndex (iCluster);
336+ if (clusterIdx == o2::its::constants::UnusedIndex) {
337+ continue ;
338+ }
339+
340+ auto clusterLabels = mTimeFrame ->getClusterLabels (iCluster, clusterIdx);
341+ for (const auto & label : clusterLabels) {
342+ auto it = std::find_if (labelCounts.begin (), labelCounts.end (),
343+ [&label](const auto & p) { return p.first == label; });
344+ if (it != labelCounts.end ()) {
345+ ++(it->second );
346+ } else {
347+ labelCounts.emplace_back (label, 1 );
348+ }
349+ }
350+ }
351+
352+ if (!labelCounts.empty ()) {
353+ // Find label with most occurrences
354+ auto maxIt = std::max_element (labelCounts.begin (), labelCounts.end (),
355+ [](const auto & a, const auto & b) { return a.second < b.second ; });
356+
357+ MCCompLabel trackLabel = maxIt->first ;
358+ if (maxIt->second < static_cast <size_t >(track.getNumberOfClusters ())) {
359+ trackLabel.setFakeFlag ();
360+ }
361+ mTimeFrame ->getTracksLabel ().emplace_back (trackLabel);
362+ }
363+ }
364+ }
252365}
253366
254367template <int nLayers>
@@ -261,26 +374,26 @@ void TrackerACTS<nLayers>::clustersToTracks()
261374
262375 double totalTime = 0 .;
263376 LOG (info) << " ==== TRK ACTS Tracking ====" ;
264- LOG (info) << " Processing " << mTimeFrame ->getNrof () << " ROFs with B = " << mBz << " T" ;
377+ // LOG(info) << "Processing " << mTimeFrame->getNrof() << " ROFs with B = " << mBz << " T";
265378
266379 // Process each ROF
267- for (int iROF = 0 ; iROF < mTimeFrame ->getNrof (); ++iROF) {
268- LOG (info) << " Processing ROF " << iROF;
269- // Build space points
270- mCurState = SpacePointBuilding;
271- totalTime += evaluateTask ([this , iROF]() { buildSpacePoints (iROF); },
272- StateNames[mCurState ]);
273-
274- // Run seeding
275- mCurState = Seeding;
276- totalTime += evaluateTask ([this ]() { createSeeds (); },
277- StateNames[mCurState ]);
278-
279- // Find tracks
280- mCurState = TrackFinding;
281- totalTime += evaluateTask ([this ]() { findTracks (); },
282- StateNames[mCurState ]);
283- }
380+ // for (int iROF = 0; iROF < mTimeFrame->getNrof(); ++iROF) {
381+ // LOG(info) << "Processing ROF " << iROF;
382+ // // Build space points
383+ // mCurState = SpacePointBuilding;
384+ // totalTime += evaluateTask([this, iROF]() { buildSpacePoints(iROF); },
385+ // StateNames[mCurState]);
386+
387+ // // Run seeding
388+ // mCurState = Seeding;
389+ // totalTime += evaluateTask([this]() { createSeeds(); },
390+ // StateNames[mCurState]);
391+
392+ // // Find tracks
393+ // mCurState = TrackFinding;
394+ // totalTime += evaluateTask([this]() { findTracks(); },
395+ // StateNames[mCurState]);
396+ // }
284397
285398 // MC labeling
286399 if (mTimeFrame ->hasMCinformation ()) {
0 commit comments