2323
2424// O2 includes
2525#include < CCDB/BasicCCDBManager.h>
26+ #include < DataFormatsFIT/Triggers.h>
2627#include < Framework/AnalysisTask.h>
2728#include < Framework/HistogramRegistry.h>
2829#include < Framework/runDataProcessing.h>
@@ -519,6 +520,7 @@ struct tofEventTime {
519520 Produces<o2::aod::TOFEvTime> tableEvTime;
520521 Produces<o2::aod::EvTimeTOFOnly> tableEvTimeTOFOnly;
521522 Produces<o2::aod::pidEvTimeFlags> tableFlags;
523+ Produces<o2::aod::FT0sCorrected> tableFt0;
522524 static constexpr bool kRemoveTOFEvTimeBias = true ; // Flag to subtract the Ev. Time bias for low multiplicity events with TOF
523525 static constexpr float kDiamond = 6.0 ; // Collision diamond used in the estimation of the TOF event time
524526 static constexpr float kErrDiamond = kDiamond * 33 .356409f ;
@@ -641,14 +643,42 @@ struct tofEventTime {
641643 using ResponseImplementationEvTime = o2::pid::tof::ExpTimes<Run3TrksWtof::iterator, pid>;
642644 void processRun3 (Run3TrksWtof const & tracks,
643645 aod::FT0s const &,
644- EvTimeCollisionsFT0 const &,
646+ EvTimeCollisions const & collisions ,
645647 aod::BCsWithTimestamps const & bcs)
646648 {
647649 if (!enableTableTOFEvTime) {
648650 return ;
649651 }
650652 LOG (debug) << " Processing Run3 data for TOF event time" ;
651653
654+ std::map<uint64_t , std::pair<float , float >> collisionFt0Map;
655+ tableFt0.reserve (collisions.size ());
656+ for (const auto & collision : collisions) {
657+ static constexpr float defaultValue = 1e10f;
658+ float t0A = defaultValue;
659+ float t0C = defaultValue;
660+ const float vertexPV = collision.posZ ();
661+ static constexpr float invLightSpeedCm2NS = 1 .f / o2::constants::physics::LightSpeedCm2NS;
662+ const float vertexCorr = vertexPV * invLightSpeedCm2NS;
663+ constexpr float dummyTime = 30 .f ; // Due to HW limitations time can be only within range (-25,25) ns, dummy time is around 32 ns
664+ if (collision.has_foundFT0 ()) {
665+ const auto & ft0 = collision.foundFT0 ();
666+ const std::bitset<8 >& triggers = ft0.triggerMask ();
667+ const bool ora = triggers[o2::fit::Triggers::bitA];
668+ const bool orc = triggers[o2::fit::Triggers::bitC];
669+ LOGF (debug, " triggers OrA %i OrC %i " , ora, orc);
670+ LOGF (debug, " T0A = %f, T0C %f, vertexCorr %f" , ft0.timeA (), ft0.timeC (), vertexCorr);
671+ if (ora && ft0.timeA () < dummyTime) {
672+ t0A = ft0.timeA () + vertexCorr;
673+ }
674+ if (orc && ft0.timeC () < dummyTime) {
675+ t0C = ft0.timeC () - vertexCorr;
676+ }
677+ }
678+ LOGF (debug, " T0 collision time T0A = %f, T0C = %f" , t0A, t0C);
679+ tableFt0 (t0A, t0C);
680+ collisionFt0Map[collision.globalIndex ()] = std::make_pair (t0A, t0C); // Store the T0A and T0C for the collision
681+ }
652682 tableEvTime.reserve (tracks.size ());
653683 tableFlags.reserve (tracks.size ());
654684 if (enableTableEvTimeTOFOnly) {
@@ -675,7 +705,8 @@ struct tofEventTime {
675705 }
676706 LOG (debug) << " Running on " << CollisionSystemType::getCollisionSystemName (mTOFCalibConfig .collisionSystem ()) << " mComputeEvTimeWithTOF " << mComputeEvTimeWithTOF .value << " mComputeEvTimeWithFT0 " << mComputeEvTimeWithFT0 .value ;
677707
678- if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 1 ) {
708+ if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 1 ) { // Use both FT0 and TOF event times
709+
679710 int lastCollisionId = -1 ; // Last collision ID analysed
680711 for (auto const & t : tracks) { // Loop on collisions
681712 if (!t.has_collision () || ((sel8TOFEvTime.value == true ) && !t.collision_as <EvTimeCollisionsFT0>().sel8 ())) { // Track was not assigned, cannot compute event time or event did not pass the event selection
@@ -693,7 +724,7 @@ struct tofEventTime {
693724 lastCollisionId = t.collisionId (); // / Cache last collision ID
694725
695726 const auto & tracksInCollision = tracks.sliceBy (perCollision, lastCollisionId);
696- const auto & collision = t.collision_as <EvTimeCollisionsFT0 >();
727+ const auto & collision = t.collision_as <EvTimeCollisions >();
697728
698729 // Compute the TOF event time
699730 const auto evTimeMakerTOF = evTimeMakerForTracks<Run3TrksWtof::iterator, filterForTOFEventTime, o2::pid::tof::ExpTimes>(tracksInCollision, mRespParamsV3 , kDiamond );
@@ -726,13 +757,14 @@ struct tofEventTime {
726757 sumOfWeights += weight;
727758 }
728759
729- if (collision.has_foundFT0 ()) { // T0 measurement is available
730- // const auto& ft0 = collision.foundFT0();
731- if (collision.t0ACValid ()) {
732- t0AC[0 ] = collision.t0AC () * 1000 .f ;
733- t0AC[1 ] = collision.t0resolution () * 1000 .f ;
734- flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC;
735- }
760+ float t0A = collisionFt0Map[t.collisionId ()].first ; // T0A for the collision
761+ float t0C = collisionFt0Map[t.collisionId ()].second ; // T0C for the collision
762+
763+ static constexpr float thresholdValue = 1e9f; // I the value of the FT0s are defined, the values are lower than 10e9
764+ if ((t0A < thresholdValue) && (t0C < thresholdValue)) {
765+ t0AC[0 ] = 0.5 * (t0A + t0C) * 1000 .f ;
766+ t0AC[1 ] = 0.5 * std::abs (t0A - t0C) * 1000 .f ;
767+ flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC;
736768
737769 weight = 1 .f / (t0AC[1 ] * t0AC[1 ]);
738770 eventTime += t0AC[0 ] * weight;
@@ -752,7 +784,8 @@ struct tofEventTime {
752784 }
753785 }
754786 }
755- } else if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 0 ) {
787+ } else if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 0 ) { // Use TOF event time only
788+
756789 int lastCollisionId = -1 ; // Last collision ID analysed
757790 for (auto const & t : tracks) { // Loop on collisions
758791 if (!t.has_collision () || ((sel8TOFEvTime.value == true ) && !t.collision_as <EvTimeCollisions>().sel8 ())) { // Track was not assigned, cannot compute event time or event did not pass the event selection
@@ -795,7 +828,8 @@ struct tofEventTime {
795828 }
796829 }
797830 }
798- } else if (mComputeEvTimeWithTOF == 0 && mComputeEvTimeWithFT0 == 1 ) {
831+ } else if (mComputeEvTimeWithTOF == 0 && mComputeEvTimeWithFT0 == 1 ) { // Use FT0 event time only
832+
799833 for (auto const & t : tracks) { // Loop on collisions
800834 if (enableTableEvTimeTOFOnly) {
801835 tableEvTimeTOFOnly ((uint8_t )0 , 0 .f , 0 .f , -1 );
@@ -805,20 +839,22 @@ struct tofEventTime {
805839 tableEvTime (0 .f , 999 .f );
806840 continue ;
807841 }
808- const auto & collision = t.collision_as <EvTimeCollisionsFT0>();
809-
810- if (collision.has_foundFT0 ()) { // T0 measurement is available
811- // const auto& ft0 = collision.foundFT0();
812- if (collision.t0ACValid ()) {
813- tableFlags (o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC);
814- tableEvTime (collision.t0AC () * 1000 .f , collision.t0resolution () * 1000 .f );
815- continue ;
816- }
842+
843+ float t0A = collisionFt0Map[t.collisionId ()].first ; // T0A for the collision
844+ float t0C = collisionFt0Map[t.collisionId ()].second ; // T0C for the collision
845+
846+ static constexpr float thresholdValue = 1e9f; // I the value of the FT0s are defined, the values are lower than 10e9
847+ float t0AC[2 ] = {.0f , 999 .f };
848+ uint8_t flags = 0 ;
849+ if ((t0A < thresholdValue) && (t0C < thresholdValue)) {
850+ t0AC[0 ] = 0.5 * (t0A + t0C) * 1000 .f ;
851+ t0AC[1 ] = 0.5 * std::abs (t0A - t0C) * 1000 .f ;
852+ flags = o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC;
817853 }
818- tableFlags (0 );
819- tableEvTime (0 . f , 999 . f );
854+ tableFlags (flags );
855+ tableEvTime (t0AC[ 0 ], t0AC[ 1 ] );
820856 }
821- } else {
857+ } else { // Error
822858 LOG (fatal) << " Invalid configuration for TOF event time computation" ;
823859 }
824860 }
@@ -925,7 +961,7 @@ struct tofPidMerge {
925961 doprocessRun2.value = false ;
926962 } else {
927963 if (mTOFCalibConfig .autoSetProcessFunctions ()) {
928- LOG (info) << " Autodetecting process functions" ;
964+ LOG (info) << " Autodetecting process functions for mass and beta " ;
929965 if (metadataInfo.isFullyDefined ()) {
930966 if (metadataInfo.isRun3 ()) {
931967 doprocessRun3.value = true ;
0 commit comments