2525#include " Common/DataModel/PIDResponseTOF.h"
2626
2727#include < CCDB/BasicCCDBManager.h>
28+ #include < DataFormatsFIT/Triggers.h>
2829#include < DataFormatsParameters/GRPLHCIFData.h>
2930#include < DataFormatsTOF/ParameterContainers.h>
3031#include < Framework/ASoA.h>
5556#include < map>
5657#include < memory>
5758#include < string>
59+ #include < utility>
5860#include < vector>
5961
6062using namespace o2 ;
@@ -72,7 +74,12 @@ using Run3TrksWtof = soa::Join<Run3Trks, aod::TOFSignal>;
7274using Run3TrksWtofWevTime = soa::Join<Run3TrksWtof, aod::TOFEvTime, aod::pidEvTimeFlags>;
7375
7476using EvTimeCollisions = soa::Join<Run3Cols, aod::EvSels>;
77+ // #define MERGEWITHFT0
78+ #ifndef MERGEWITHFT0
7579using EvTimeCollisionsFT0 = soa::Join<EvTimeCollisions, aod::FT0sCorrected>;
80+ #else
81+ using EvTimeCollisionsFT0 = EvTimeCollisions;
82+ #endif
7683
7784using Run2Trks = o2::soa::Join<aod::Tracks, aod::TracksExtra>;
7885using Run2TrksWtofWevTime = soa::Join<Run2Trks, aod::TOFSignal, aod::TOFEvTime, aod::pidEvTimeFlags>;
@@ -536,6 +543,9 @@ struct tofEventTime {
536543 Produces<o2::aod::TOFEvTime> tableEvTime;
537544 Produces<o2::aod::EvTimeTOFOnly> tableEvTimeTOFOnly;
538545 Produces<o2::aod::pidEvTimeFlags> tableFlags;
546+ #ifdef MERGEWITHFT0
547+ Produces<o2::aod::FT0sCorrected> tableFt0;
548+ #endif
539549 static constexpr bool kRemoveTOFEvTimeBias = true ; // Flag to subtract the Ev. Time bias for low multiplicity events with TOF
540550 static constexpr float kDiamond = 6.0 ; // Collision diamond used in the estimation of the TOF event time
541551 static constexpr float kErrDiamond = kDiamond * 33 .356409f ;
@@ -658,14 +668,48 @@ struct tofEventTime {
658668 using ResponseImplementationEvTime = o2::pid::tof::ExpTimes<Run3TrksWtof::iterator, pid>;
659669 void processRun3 (Run3TrksWtof const & tracks,
660670 aod::FT0s const &,
671+ #ifdef MERGEWITHFT0
672+ EvTimeCollisions const & collisions,
673+ #else
661674 EvTimeCollisionsFT0 const &,
675+ #endif
662676 aod::BCsWithTimestamps const & bcs)
663677 {
664678 if (!enableTableTOFEvTime) {
665679 return ;
666680 }
667681 LOG (debug) << " Processing Run3 data for TOF event time" ;
668-
682+ #ifdef MERGEWITHFT0
683+
684+ std::map<uint64_t , std::pair<float , float >> collisionFt0Map;
685+ tableFt0.reserve (collisions.size ());
686+ for (const auto & collision : collisions) {
687+ static constexpr float DefaultValue = 1e10f;
688+ float t0A = DefaultValue;
689+ float t0C = DefaultValue;
690+ const float vertexPV = collision.posZ ();
691+ static constexpr float kInvLightSpeedCm2NS = 1 .f / o2::constants::physics::LightSpeedCm2NS;
692+ const float vertexCorr = vertexPV * kInvLightSpeedCm2NS ;
693+ constexpr float DummyTime = 30 .f ; // Due to HW limitations time can be only within range (-25,25) ns, dummy time is around 32 ns
694+ if (collision.has_foundFT0 ()) {
695+ const auto & ft0 = collision.foundFT0 ();
696+ const std::bitset<8 >& triggers = ft0.triggerMask ();
697+ const bool ora = triggers[o2::fit::Triggers::bitA];
698+ const bool orc = triggers[o2::fit::Triggers::bitC];
699+ LOGF (debug, " triggers OrA %i OrC %i " , ora, orc);
700+ LOGF (debug, " T0A = %f, T0C %f, vertexCorr %f" , ft0.timeA (), ft0.timeC (), vertexCorr);
701+ if (ora && ft0.timeA () < DummyTime) {
702+ t0A = ft0.timeA () + vertexCorr;
703+ }
704+ if (orc && ft0.timeC () < DummyTime) {
705+ t0C = ft0.timeC () - vertexCorr;
706+ }
707+ }
708+ LOGF (debug, " T0 collision time T0A = %f, T0C = %f" , t0A, t0C);
709+ tableFt0 (t0A, t0C);
710+ collisionFt0Map[collision.globalIndex ()] = std::make_pair (t0A, t0C); // Store the T0A and T0C for the collision
711+ }
712+ #endif
669713 tableEvTime.reserve (tracks.size ());
670714 tableFlags.reserve (tracks.size ());
671715 if (enableTableEvTimeTOFOnly) {
@@ -692,7 +736,8 @@ struct tofEventTime {
692736 }
693737 LOG (debug) << " Running on " << CollisionSystemType::getCollisionSystemName (mTOFCalibConfig .collisionSystem ()) << " mComputeEvTimeWithTOF " << mComputeEvTimeWithTOF .value << " mComputeEvTimeWithFT0 " << mComputeEvTimeWithFT0 .value ;
694738
695- if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 1 ) {
739+ if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 1 ) { // Use both FT0 and TOF event times
740+
696741 int lastCollisionId = -1 ; // Last collision ID analysed
697742 for (auto const & t : tracks) { // Loop on collisions
698743 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
@@ -710,8 +755,9 @@ struct tofEventTime {
710755 lastCollisionId = t.collisionId (); // / Cache last collision ID
711756
712757 const auto & tracksInCollision = tracks.sliceBy (perCollision, lastCollisionId);
758+ #ifndef MERGEWITHFT0
713759 const auto & collision = t.collision_as <EvTimeCollisionsFT0>();
714-
760+ # endif
715761 // Compute the TOF event time
716762 const auto evTimeMakerTOF = evTimeMakerForTracks<Run3TrksWtof::iterator, filterForTOFEventTime, o2::pid::tof::ExpTimes>(tracksInCollision, mRespParamsV3 , kDiamond );
717763
@@ -743,14 +789,25 @@ struct tofEventTime {
743789 sumOfWeights += weight;
744790 }
745791
792+ #ifdef MERGEWITHFT0
793+ float t0A = collisionFt0Map[t.collisionId ()].first ; // T0A for the collision
794+ float t0C = collisionFt0Map[t.collisionId ()].second ; // T0C for the collision
795+
796+ static constexpr float ThresholdValue = 1e9f; // I the value of the FT0s are defined, the values are lower than 10e9
797+ if ((t0A < ThresholdValue) && (t0C < ThresholdValue)) {
798+ t0AC[0 ] = 0.5 * (t0A + t0C) * 1000 .f ;
799+ t0AC[1 ] = 0.5 * std::abs (t0A - t0C) * 1000 .f ;
800+ flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC;
801+
802+ #else
746803 if (collision.has_foundFT0 ()) { // T0 measurement is available
747804 // const auto& ft0 = collision.foundFT0();
748805 if (collision.t0ACValid ()) {
749806 t0AC[0 ] = collision.t0AC () * 1000 .f ;
750807 t0AC[1 ] = collision.t0resolution () * 1000 .f ;
751808 flags |= o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC;
752809 }
753-
810+ #endif
754811 weight = 1 .f / (t0AC[1 ] * t0AC[1 ]);
755812 eventTime += t0AC[0 ] * weight;
756813 sumOfWeights += weight;
@@ -769,7 +826,8 @@ struct tofEventTime {
769826 }
770827 }
771828 }
772- } else if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 0 ) {
829+ } else if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 0 ) { // Use TOF event time only
830+
773831 int lastCollisionId = -1 ; // Last collision ID analysed
774832 for (auto const & t : tracks) { // Loop on collisions
775833 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
@@ -812,7 +870,8 @@ struct tofEventTime {
812870 }
813871 }
814872 }
815- } else if (mComputeEvTimeWithTOF == 0 && mComputeEvTimeWithFT0 == 1 ) {
873+ } else if (mComputeEvTimeWithTOF == 0 && mComputeEvTimeWithFT0 == 1 ) { // Use FT0 event time only
874+
816875 for (auto const & t : tracks) { // Loop on collisions
817876 if (enableTableEvTimeTOFOnly) {
818877 tableEvTimeTOFOnly ((uint8_t )0 , 0 .f , 0 .f , -1 );
@@ -822,6 +881,22 @@ struct tofEventTime {
822881 tableEvTime (0 .f , 999 .f );
823882 continue ;
824883 }
884+ #ifdef MERGEWITHFT0
885+
886+ float t0A = collisionFt0Map[t.collisionId ()].first ; // T0A for the collision
887+ float t0C = collisionFt0Map[t.collisionId ()].second ; // T0C for the collision
888+
889+ static constexpr float ThresholdValue = 1e9f; // I the value of the FT0s are defined, the values are lower than 10e9
890+ float t0AC[2 ] = {.0f , 999 .f };
891+ uint8_t flags = 0 ;
892+ if ((t0A < ThresholdValue) && (t0C < ThresholdValue)) {
893+ t0AC[0 ] = 0.5 * (t0A + t0C) * 1000 .f ;
894+ t0AC[1 ] = 0.5 * std::abs (t0A - t0C) * 1000 .f ;
895+ flags = o2::aod::pidflags::enums::PIDFlags::EvTimeT0AC;
896+ }
897+ tableFlags (flags);
898+ tableEvTime (t0AC[0 ], t0AC[1 ]);
899+ #else
825900 const auto & collision = t.collision_as <EvTimeCollisionsFT0>();
826901
827902 if (collision.has_foundFT0 ()) { // T0 measurement is available
@@ -834,8 +909,9 @@ struct tofEventTime {
834909 }
835910 tableFlags (0 );
836911 tableEvTime (0 .f , 999 .f );
912+ #endif
837913 }
838- } else {
914+ } else { // Error
839915 LOG (fatal) << " Invalid configuration for TOF event time computation" ;
840916 }
841917 }
@@ -942,7 +1018,7 @@ struct tofPidMerge {
9421018 doprocessRun2.value = false ;
9431019 } else {
9441020 if (mTOFCalibConfig .autoSetProcessFunctions ()) {
945- LOG (info) << " Autodetecting process functions" ;
1021+ LOG (info) << " Autodetecting process functions for mass and beta " ;
9461022 if (metadataInfo.isFullyDefined ()) {
9471023 if (metadataInfo.isRun3 ()) {
9481024 doprocessRun3.value = true ;
0 commit comments