diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/TPCTimeSeriesSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/TPCTimeSeriesSpec.h index d7da0b9acb343..3a61472d4bd8a 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/TPCTimeSeriesSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/TPCTimeSeriesSpec.h @@ -23,7 +23,7 @@ namespace tpc static constexpr header::DataDescription getDataDescriptionTimeSeries() { return header::DataDescription{"TIMESERIES"}; } static constexpr header::DataDescription getDataDescriptionTPCTimeSeriesTFId() { return header::DataDescription{"ITPCTSTFID"}; } -o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, const o2::base::Propagator::MatCorrType matType, const bool enableUnbinnedWriter, o2::dataformats::GlobalTrackID::mask_t src); +o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, const o2::base::Propagator::MatCorrType matType, const bool enableUnbinnedWriter, o2::dataformats::GlobalTrackID::mask_t src, bool useft0 = false); } // end namespace tpc } // end namespace o2 diff --git a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx index c34cc0b7e9863..dbf962d87e135 100644 --- a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx +++ b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx @@ -45,6 +45,7 @@ #include "TROOT.h" #include "ReconstructionDataFormats/MatchInfoTOF.h" #include "DataFormatsTOF/Cluster.h" +#include "DataFormatsFT0/RecPoints.h" using namespace o2::globaltracking; using GTrackID = o2::dataformats::GlobalTrackID; @@ -206,25 +207,74 @@ class TPCTimeSeries : public Task indicesITSTPC[tracksITSTPC[i].getRefTPC().getIndex()] = {i, idxVtx}; } - std::vector> idxTPCTrackToTOFCluster; // store for each tpc track index the index to the TOF cluster + std::vector> idxTPCTrackToTOFCluster; // store for each tpc track index the index to the TOF cluster // get matches to TOF in case skimmed data is produced if (mUnbinnedWriter) { // getLTIntegralOut(), ///< L,TOF integral calculated during the propagation // getSignal() mSignal = 0.0; ///< TOF time in ps o2::track::TrackLTIntegral defLT; - idxTPCTrackToTOFCluster = std::vector>(tracksTPC.size(), {-1, -999, -999, defLT, 0, 0}); + idxTPCTrackToTOFCluster = std::vector>(tracksTPC.size(), {-1, -999, -999, defLT, 0, 0, 0}); const std::vector> tofMatches{recoData.getTPCTOFMatches(), recoData.getTPCTRDTOFMatches(), recoData.getITSTPCTOFMatches(), recoData.getITSTPCTRDTOFMatches()}; + const auto& ft0rec = recoData.getFT0RecPoints(); + // fill available FT0-AC event times vs BClong + std::map t0array; + for (const auto& t0 : ft0rec) { + if (!(t0.isValidTime(1) && t0.isValidTime(2))) { // skip if !(A & C) + continue; + } + + ULong64_t bclong = (t0.mIntRecord.orbit - processing_helpers::getFirstTForbit(pc)) * o2::constants::lhc::LHCMaxBunches + t0.mIntRecord.bc; + if (t0array.find(bclong) == t0array.end()) { // add if it doesn't exist + t0array.emplace(std::make_pair(bclong, t0.getCollisionTime(0))); + } + } + + static const double BC_TIME_INPS_INV = 1E-3 / o2::constants::lhc::LHCBunchSpacingNS; + // loop over ITS-TPC-TRD-TOF and ITS-TPC-TOF tracks an store for each ITS-TPC track the TOF track index for (const auto& tofMatch : tofMatches) { for (const auto& tpctofmatch : tofMatch) { auto refTPC = recoData.getTPCContributorGID(tpctofmatch.getTrackRef()); if (refTPC.isIndexSet()) { o2::track::TrackLTIntegral ltIntegral = tpctofmatch.getLTIntegralOut(); - double signal = tpctofmatch.getSignal(); + ULong64_t bclongtof = (tpctofmatch.getSignal() - 10000) * BC_TIME_INPS_INV; + double t0 = 0; // bclongtof * o2::constants::lhc::LHCBunchSpacingNS * 1E3; // if you want to subtract also the BC uncomment this part (-> tofsignal can be a float) + if (!(t0array.find(bclongtof) == t0array.end())) { // subtract FT0-AC if it exists in the same BC + t0 += t0array.find(bclongtof)->second; + } + + double signal = tpctofmatch.getSignal() - t0; float deltaT = tpctofmatch.getDeltaT(); - idxTPCTrackToTOFCluster[refTPC] = {tpctofmatch.getIdxTOFCl(), tpctofmatch.getDXatTOF(), tpctofmatch.getDZatTOF(), ltIntegral, signal, deltaT}; + + float dy = tpctofmatch.getDYatTOF(); // residual orthogonal to the strip (it should be close to zero) + bool isMultiHitZ = tpctofmatch.getHitPatternUpDown(); + bool isMultiHitX = tpctofmatch.getHitPatternLeftRight(); + bool isMultiStripMatch = tpctofmatch.getChi2() < 1E-9; + float chi2 = tpctofmatch.getChi2(); + + int mask = 0; + if (isMultiHitX) { // 1nd bit on if multiple hits along X + mask += 1; + } + if (isMultiHitZ) { // 2nd bit on if multiple hits along Z + mask += 2; + } + if (fabs(dy) > 0.5) { // 3rd bit on if Y-residual too large + mask += 4; + } + if (isMultiStripMatch) { // 4th bit on if two strips fired + mask += 8; + } + if (chi2 > 3) { // 5th bit on if chi2 > 3 + mask += 16; + } + if (chi2 > 5) { + mask += 32; + } + + idxTPCTrackToTOFCluster[refTPC] = {tpctofmatch.getIdxTOFCl(), tpctofmatch.getDXatTOF(), tpctofmatch.getDZatTOF(), ltIntegral, signal, deltaT, mask}; } } } @@ -1055,7 +1105,7 @@ class TPCTimeSeries : public Task return isGoodTrack; } - void fillDCA(const gsl::span tracksTPC, const gsl::span tracksITSTPC, const gsl::span vertices, const int iTrk, const int iThread, const std::unordered_map>& indicesITSTPC, const gsl::span tracksITS, const std::vector>& idxTPCTrackToTOFCluster, const gsl::span tofClusters) + void fillDCA(const gsl::span tracksTPC, const gsl::span tracksITSTPC, const gsl::span vertices, const int iTrk, const int iThread, const std::unordered_map>& indicesITSTPC, const gsl::span tracksITS, const std::vector>& idxTPCTrackToTOFCluster, const gsl::span tofClusters) { const auto& trackFull = tracksTPC[iTrk]; const bool isGoodTrack = checkTrack(trackFull); @@ -1444,6 +1494,7 @@ class TPCTimeSeries : public Task << "mDeltaTTOFTPC=" << std::get<5>(idxTPCTrackToTOFCluster[iTrk]) /// delta T- TPC TOF << "vertexTime=" << vertexTime /// time stamp assigned to the vertex << "trackTime0=" << trackTime0 /// time stamp assigned to the track + << "TOFmask=" << std::get<6>(idxTPCTrackToTOFCluster[iTrk]) /// delta T- TPC TOF // TPC delta param << "deltaTPCParamInOutTgl=" << deltaTPCParamInOutTgl << "deltaTPCParamInOutQPt=" << deltaTPCParamInOutQPt @@ -1751,7 +1802,7 @@ class TPCTimeSeries : public Task } }; -o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, const o2::base::Propagator::MatCorrType matType, const bool enableUnbinnedWriter, GTrackID::mask_t src) +o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, const o2::base::Propagator::MatCorrType matType, const bool enableUnbinnedWriter, GTrackID::mask_t src, bool useft0) { auto dataRequest = std::make_shared(); bool useMC = false; @@ -1759,6 +1810,11 @@ o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, srcTracks.set(GTrackID::TPC); // TPC must be always there dataRequest->requestTracks(srcTracks, useMC); dataRequest->requestClusters(GTrackID::getSourcesMask("TPC"), useMC); + + if (useft0) { + dataRequest->requestFT0RecPoints(false); + } + bool tpcOnly = srcTracks == GTrackID::getSourcesMask("TPC"); if (!tpcOnly) { dataRequest->requestPrimaryVertices(useMC); diff --git a/Detectors/TPC/workflow/src/tpc-time-series.cxx b/Detectors/TPC/workflow/src/tpc-time-series.cxx index f7bcf00cb27ea..65345fbfefb10 100644 --- a/Detectors/TPC/workflow/src/tpc-time-series.cxx +++ b/Detectors/TPC/workflow/src/tpc-time-series.cxx @@ -29,6 +29,7 @@ void customize(std::vector& workflowOptions) {"disable-root-output", VariantType::Bool, false, {"disable root-files output writers"}}, {"enable-unbinned-root-output", VariantType::Bool, false, {"writing out unbinned track data"}}, {"track-sources", VariantType::String, std::string{o2::dataformats::GlobalTrackID::ALL}, {"comma-separated list of sources to use"}}, + {"use-ft0", VariantType::Bool, false, {"enable FT0 rec-points"}}, {"material-type", VariantType::Int, 2, {"Type for the material budget during track propagation: 0=None, 1=Geo, 2=LUT"}}}; std::swap(workflowOptions, options); } @@ -43,7 +44,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) const bool enableUnbinnedWriter = config.options().get("enable-unbinned-root-output"); auto src = o2::dataformats::GlobalTrackID::getSourcesMask(config.options().get("track-sources")); auto materialType = static_cast(config.options().get("material-type")); - workflow.emplace_back(o2::tpc::getTPCTimeSeriesSpec(disableWriter, materialType, enableUnbinnedWriter, src)); + const bool useft0 = config.options().get("use-ft0"); + workflow.emplace_back(o2::tpc::getTPCTimeSeriesSpec(disableWriter, materialType, enableUnbinnedWriter, src, useft0)); if (!disableWriter) { workflow.emplace_back(o2::tpc::getTPCTimeSeriesWriterSpec()); }