Skip to content

Commit 70f8320

Browse files
committed
Create TOF-constrained TPC tracks, optionally refit
+ clean-up of TOF-related workflow from unnecessaty initializations
1 parent fd2e2e8 commit 70f8320

File tree

13 files changed

+283
-136
lines changed

13 files changed

+283
-136
lines changed

DataFormats/Detectors/TPC/include/DataFormatsTPC/WorkflowHelper.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@ struct getWorkflowTPCInput_ret {
6262
};
6363
} // namespace internal
6464

65+
static auto getWorkflowTPCInputEmpryPtr()
66+
{
67+
/*
68+
In case the need of TPCInput is conditional, this will allow to define an empty unique_ptr to this complex structure outside
69+
of the "if" scope, i.e.
70+
auto inp = getWorkflowTPCInputEmpryPtr();
71+
if (want_TPCInput) {
72+
inp = getWorkflowTPCInput(...);
73+
consumer->setInp(inp);
74+
}
75+
*/
76+
std::unique_ptr<internal::getWorkflowTPCInput_ret> ptr;
77+
return ptr;
78+
}
79+
6580
static auto getWorkflowTPCInput(o2::framework::ProcessingContext& pc, int verbosity = 0, bool do_mcLabels = false, bool do_clusters = true, unsigned long tpcSectorMask = 0xFFFFFFFFF, bool do_digits = false)
6681
{
6782
auto retVal = std::make_unique<internal::getWorkflowTPCInput_ret>();

Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <TStopwatch.h>
2424
#include "ReconstructionDataFormats/Track.h"
2525
#include "ReconstructionDataFormats/TrackTPCITS.h"
26+
#include "ReconstructionDataFormats/TrackTPCTOF.h"
2627
#include "ReconstructionDataFormats/MatchInfoTOF.h"
2728
#include "ReconstructionDataFormats/GlobalTrackID.h"
2829
#include "DataFormatsTOF/CalibInfoTOF.h"
@@ -34,7 +35,7 @@
3435
#include "GlobalTracking/MatchTPCITS.h"
3536
#include "DataFormatsTPC/TrackTPC.h"
3637
#include "ReconstructionDataFormats/PID.h"
37-
#include <gsl/span>
38+
#include "TPCFastTransform.h"
3839

3940
// from FIT
4041
#include "DataFormatsFT0/RecPoints.h"
@@ -199,8 +200,41 @@ class MatchTOF
199200
mFITRecPoints = recpoints;
200201
}
201202

203+
///< set input TPC tracks cluster indices
204+
void setTPCTrackClusIdxInp(const gsl::span<const o2::tpc::TPCClRefElem> inp)
205+
{
206+
mTPCTrackClusIdx = inp;
207+
}
208+
209+
///< set input TPC cluster sharing map
210+
void setTPCClustersSharingMap(const gsl::span<const unsigned char> inp)
211+
{
212+
mTPCRefitterShMap = inp;
213+
}
214+
215+
///< set input TPC clusters
216+
void setTPCClustersInp(const o2::tpc::ClusterNativeAccess* inp)
217+
{
218+
mTPCClusterIdxStruct = inp;
219+
}
220+
202221
int findFITIndex(int bc);
203222

223+
///< populate externally provided container by TOF-time-constrained TPC tracks
224+
template <typename V>
225+
void makeConstrainedTPCTracks(V& container)
226+
{
227+
checkRefitter();
228+
int nmatched = mMatchedTracks.size(), nconstrained = 0;
229+
container.resize(nmatched);
230+
for (unsigned i = 0; i < nmatched; i++) {
231+
if (makeConstrainedTPCTrack(i, container[nconstrained])) {
232+
nconstrained++;
233+
}
234+
}
235+
container.resize(nconstrained);
236+
}
237+
204238
private:
205239
void attachInputTrees();
206240
void attachInputTreesTPConly();
@@ -217,6 +251,10 @@ class MatchTOF
217251
bool propagateToRefX(o2::track::TrackParCov& trc, float xRef /*in cm*/, float stepInCm /*in cm*/, o2::track::TrackLTIntegral& intLT);
218252
bool propagateToRefXWithoutCov(o2::track::TrackParCov& trc, float xRef /*in cm*/, float stepInCm /*in cm*/, float bz);
219253

254+
void updateTimeDependentParams();
255+
void checkRefitter();
256+
bool makeConstrainedTPCTrack(int matchedID, o2::dataformats::TrackTPCTOF& trConstr);
257+
220258
//================================================================
221259

222260
// Data members
@@ -232,8 +270,12 @@ class MatchTOF
232270
bool mMCTruthON = false; ///< flag availability of MC truth
233271

234272
///========== Parameters to be set externally, e.g. from CCDB ====================
273+
float mBz = 0; ///< nominal Bz
235274

236275
// to be done later
276+
float mTPCTBinMUS = 0.; ///< TPC time bin duration in microseconds
277+
float mTPCTBinMUSInv = 0.; ///< inverse TPC time bin duration in microseconds
278+
float mTPCBin2Z = 0.; ///< conversion coeff from TPC time-bin to Z
237279

238280
float mTimeTolerance = 1e3; ///<tolerance in ns for track-TOF time bracket matching
239281
float mSpaceTolerance = 10; ///<tolerance in cm for track-TOF time bracket matching
@@ -258,6 +300,13 @@ class MatchTOF
258300
gsl::span<const Cluster> mTOFClustersArrayInp; ///< input TOF clusters
259301
std::vector<Cluster>* mTOFClustersArrayInpVect; ///< input TOF clusters (vector to read from tree)
260302

303+
/// data needed for refit of time-constrained TPC tracks
304+
gsl::span<const o2::tpc::TPCClRefElem> mTPCTrackClusIdx; ///< input TPC track cluster indices span
305+
gsl::span<const unsigned char> mTPCRefitterShMap; ///< externally set TPC clusters sharing map
306+
const o2::tpc::ClusterNativeAccess* mTPCClusterIdxStruct = nullptr; ///< struct holding the TPC cluster indices
307+
std::unique_ptr<o2::gpu::TPCFastTransform> mTPCTransform; ///< TPC cluster transformation
308+
std::unique_ptr<o2::gpu::GPUO2InterfaceRefit> mTPCRefitter; ///< TPC refitter used for TPC tracks refit during the reconstruction
309+
261310
o2::dataformats::MCTruthContainer<o2::MCCompLabel> mTOFClusLabels; ///< input TOF clusters MC labels
262311
o2::dataformats::MCTruthContainer<o2::MCCompLabel>* mTOFClusLabelsPtr; ///< input TOF clusters MC labels (pointer to read from tree)
263312
std::vector<o2::MCCompLabel> mTracksLblWork; ///<TPCITS track labels

Detectors/GlobalTracking/src/MatchTOF.cxx

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
#include "TPCBase/ParameterGas.h"
4040
#include "TPCBase/ParameterElectronics.h"
41+
#include "TPCReconstruction/TPCFastTransformHelperO2.h"
4142

4243
using namespace o2::globaltracking;
4344
using evGIdx = o2::dataformats::EvIndex<int, o2::dataformats::GlobalTrackID>;
@@ -49,6 +50,7 @@ ClassImp(MatchTOF);
4950
void MatchTOF::run()
5051
{
5152
///< running the matching
53+
updateTimeDependentParams();
5254

5355
if (!mWFInputAttached && !mSAInitDone) {
5456
LOG(ERROR) << "run called with mSAInitDone=" << mSAInitDone << " and mWFInputAttached=" << mWFInputAttached;
@@ -449,10 +451,7 @@ bool MatchTOF::prepareTracks()
449451
mTracksSectIndexCache[sec].reserve(100 + 1.2 * mNumOfTracks / o2::constants::math::NSectors);
450452
}
451453

452-
// getting Bz (mag field)
453-
auto o2field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField());
454-
float bzField = o2field->solenoidField(); // magnetic field in kGauss
455-
float maxInvPt = abs(bzField) > 0.1 ? 1. / (abs(bzField) * 0.05) : 999.;
454+
float maxInvPt = abs(mBz) > 0.1 ? 1. / (abs(mBz) * 0.05) : 999.;
456455

457456
LOG(DEBUG) << "\n\nWe have %d tracks to try to match to TOF: " << mNumOfTracks;
458457
int nNotPropagatedToTOF = 0;
@@ -479,7 +478,7 @@ bool MatchTOF::prepareTracks()
479478
LOG(DEBUG) << "Global coordinates Before propagating to 371 cm: globalPos[0] = " << globalPos[0] << ", globalPos[1] = " << globalPos[1] << ", globalPos[2] = " << globalPos[2];
480479
LOG(DEBUG) << "Radius xy Before propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1]);
481480
LOG(DEBUG) << "Radius xyz Before propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1] + globalPos[2] * globalPos[2]);
482-
if (!propagateToRefXWithoutCov(trc, mXRef, 2, bzField)) { // we first propagate to 371 cm without considering the covariance matrix
481+
if (!propagateToRefXWithoutCov(trc, mXRef, 2, mBz)) { // we first propagate to 371 cm without considering the covariance matrix
483482
nNotPropagatedToTOF++;
484483
continue;
485484
}
@@ -567,10 +566,7 @@ bool MatchTOF::prepareTPCTracks()
567566
mTPCTracksSectIndexCache[sec].reserve(100 + 1.2 * mNumOfTracks / o2::constants::math::NSectors);
568567
}
569568

570-
// getting Bz (mag field)
571-
auto o2field = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField());
572-
float bzField = o2field->solenoidField(); // magnetic field in kGauss
573-
float maxInvPt = abs(bzField) > 0.1 ? 1. / (abs(bzField) * 0.05) : 999.;
569+
float maxInvPt = abs(mBz) > 0.1 ? 1. / (abs(mBz) * 0.05) : 999.;
574570
int nclustersMin = 0;
575571
LOG(INFO) << "Max track Inv pT allowed = " << maxInvPt;
576572
LOG(INFO) << "Min track Nclusters allowed = " << nclustersMin;
@@ -584,10 +580,10 @@ bool MatchTOF::prepareTPCTracks()
584580
// create working copy of track param
585581
timeEst timeInfo;
586582
// set
587-
timeInfo.setTimeStamp(trcOrig.getTime0() * o2::tpc::ParameterElectronics::Instance().ZbinWidth);
588-
timeInfo.setTimeStampError((trcOrig.getDeltaTBwd() + 5) * o2::tpc::ParameterElectronics::Instance().ZbinWidth);
583+
timeInfo.setTimeStamp(trcOrig.getTime0() * mTPCTBinMUS);
584+
timeInfo.setTimeStampError((trcOrig.getDeltaTBwd() + 5) * mTPCTBinMUS);
589585
mSideTPC.push_back(trcOrig.hasASideClustersOnly() ? 1 : (trcOrig.hasCSideClustersOnly() ? -1 : 0));
590-
mExtraTPCFwdTime.push_back((trcOrig.getDeltaTFwd() + 5) * o2::tpc::ParameterElectronics::Instance().ZbinWidth);
586+
mExtraTPCFwdTime.push_back((trcOrig.getDeltaTFwd() + 5) * mTPCTBinMUS);
591587

592588
o2::track::TrackLTIntegral intLT0; //mTPCTracksWork.back().getLTIntegralOut(); // we get the integrated length from TPC-ITC outward propagation
593589
// make a copy of the TPC track that we have to propagate
@@ -617,7 +613,7 @@ bool MatchTOF::prepareTPCTracks()
617613
// the "very rough" propagation worked; now we can propagate considering also the cov matrix
618614
#endif
619615

620-
if (!propagateToRefXWithoutCov(trc, mXRef, 10, bzField)) { // we first propagate to 371 cm without considering the covariance matrix
616+
if (!propagateToRefXWithoutCov(trc, mXRef, 10, mBz)) { // we first propagate to 371 cm without considering the covariance matrix
621617
nNotPropagatedToTOF++;
622618
continue;
623619
}
@@ -1137,7 +1133,6 @@ void MatchTOF::doMatching(int sec)
11371133
//______________________________________________
11381134
void MatchTOF::doMatchingForTPC(int sec)
11391135
{
1140-
printf("here, DoMatch\n");
11411136
auto& gasParam = o2::tpc::ParameterGas::Instance();
11421137
float vdrift = gasParam.DriftV;
11431138

@@ -1542,7 +1537,7 @@ void MatchTOF::selectBestMatches()
15421537
bool MatchTOF::propagateToRefX(o2::track::TrackParCov& trc, float xRef, float stepInCm, o2::track::TrackLTIntegral& intLT)
15431538
{
15441539
// propagate track to matching reference X
1545-
o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; // material correction method
1540+
o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; // material correction method
15461541
const float tanHalfSector = tan(o2::constants::math::SectorSpanRad / 2);
15471542
bool refReached = false;
15481543
float xStart = trc.getX();
@@ -1668,3 +1663,75 @@ void MatchTOF::fillTOFmatchTreeWithLabels(const char* trname, int cacheTOF, int
16681663
}
16691664
mTimerDBG.Stop();
16701665
}
1666+
1667+
//______________________________________________
1668+
void MatchTOF::updateTimeDependentParams()
1669+
{
1670+
///< update parameters depending on time (once per TF)
1671+
auto& elParam = o2::tpc::ParameterElectronics::Instance();
1672+
auto& gasParam = o2::tpc::ParameterGas::Instance();
1673+
mTPCTBinMUS = elParam.ZbinWidth; // TPC bin in microseconds
1674+
mTPCTBinMUSInv = 1. / mTPCTBinMUS;
1675+
mTPCBin2Z = mTPCTBinMUS * gasParam.DriftV;
1676+
1677+
mBz = o2::base::Propagator::Instance()->getNominalBz();
1678+
}
1679+
1680+
//_________________________________________________________
1681+
bool MatchTOF::makeConstrainedTPCTrack(int matchedID, o2::dataformats::TrackTPCTOF& trConstr)
1682+
{
1683+
auto& match = mMatchedTracks[matchedID];
1684+
const auto& tpcTrOrig = mTPCTracksArrayInp[match.getTrackIndex()];
1685+
const auto& tofCl = mTOFClustersArrayInp[match.getTOFClIndex()];
1686+
const auto& intLT = match.getLTIntegralOut();
1687+
// correct the time of the track
1688+
auto timeTOFMUS = (tofCl.getTime() - intLT.getTOF(o2::track::PID::Pion)) * 1e-6; // tof time in \mus, FIXME: account for time of flight to R TOF
1689+
auto timeTOFTB = timeTOFMUS * mTPCTBinMUSInv; // TOF time in TPC timebins
1690+
auto deltaTBins = timeTOFTB - tpcTrOrig.getTime0(); // time shift in timeBins
1691+
float timeErr = 0.010; // assume 10 ns error FIXME
1692+
auto dzCorr = deltaTBins * mTPCBin2Z;
1693+
1694+
if (mTPCClusterIdxStruct) { // refit was requested
1695+
trConstr.o2::track::TrackParCov::operator=(tpcTrOrig.getOuterParam()); // seed for inward refit of constrained track, made from the outer param
1696+
} else {
1697+
trConstr.o2::track::TrackParCov::operator=(tpcTrOrig); // inner param, we just correct is position, w/o refit
1698+
}
1699+
1700+
auto zTrack = trConstr.getZ();
1701+
1702+
if (tpcTrOrig.hasASideClustersOnly()) {
1703+
zTrack += dzCorr;
1704+
} else if (tpcTrOrig.hasCSideClustersOnly()) {
1705+
zTrack -= dzCorr;
1706+
} else {
1707+
// TODO : special treatment of tracks crossing the CE
1708+
}
1709+
trConstr.setZ(zTrack);
1710+
trConstr.setTimeMUS(timeTOFMUS, timeErr);
1711+
trConstr.setRefMatch(matchedID);
1712+
if (mTPCClusterIdxStruct) { // refit was requested
1713+
float chi2 = 0;
1714+
mTPCRefitter->setTrackReferenceX(o2::globaltracking::MatchTPCITS::XTPCInnerRef);
1715+
if (mTPCRefitter->RefitTrackAsTrackParCov(trConstr, tpcTrOrig.getClusterRef(), timeTOFTB, &chi2, false, true) < 0) { // outward refit after resetting cov.mat.
1716+
LOG(DEBUG) << "Refit failed";
1717+
return false;
1718+
}
1719+
trConstr.setChi2Refit(chi2);
1720+
}
1721+
1722+
return true;
1723+
}
1724+
1725+
//_________________________________________________________
1726+
void MatchTOF::checkRefitter()
1727+
{
1728+
if (mTPCClusterIdxStruct) {
1729+
if (!mTPCTransform) { // eventually, should be updated at every TF?
1730+
mTPCTransform = o2::tpc::TPCFastTransformHelperO2::instance()->create(0);
1731+
}
1732+
1733+
mTPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(mTPCClusterIdxStruct, mTPCTransform.get(), mBz,
1734+
mTPCTrackClusIdx.data(), mTPCRefitterShMap.data(),
1735+
nullptr, o2::base::Propagator::Instance());
1736+
}
1737+
}

Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/RecoWorkflowWithTPCSpec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace o2
1919
namespace tof
2020
{
2121

22-
o2::framework::DataProcessorSpec getTOFRecoWorkflowWithTPCSpec(bool useMC, bool useFIT);
22+
o2::framework::DataProcessorSpec getTOFRecoWorkflowWithTPCSpec(bool useMC, bool useFIT, bool doTPCRefit);
2323

2424
} // end namespace tof
2525
} // end namespace o2

Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFMatchedReaderSpec.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Framework/DataProcessorSpec.h"
2020
#include "Framework/Task.h"
2121
#include "ReconstructionDataFormats/MatchInfoTOF.h"
22+
#include "ReconstructionDataFormats/TrackTPCTOF.h"
2223
#include "SimulationDataFormat/MCCompLabel.h"
2324

2425
namespace o2
@@ -29,7 +30,7 @@ namespace tof
2930
class TOFMatchedReader : public o2::framework::Task
3031
{
3132
public:
32-
TOFMatchedReader(bool useMC) : mUseMC(useMC) {}
33+
TOFMatchedReader(bool useMC, bool tpcmatch, bool readTracks) : mUseMC(useMC), mTPCMatch(tpcmatch), mReadTracks(readTracks) {}
3334
~TOFMatchedReader() override = default;
3435
void init(o2::framework::InitContext& ic) final;
3536
void run(o2::framework::ProcessingContext& pc) final;
@@ -38,19 +39,23 @@ class TOFMatchedReader : public o2::framework::Task
3839
void connectTree(const std::string& filename);
3940

4041
bool mUseMC = false;
42+
bool mTPCMatch = false;
43+
bool mReadTracks = false;
44+
4145
std::string mInFileName{"o2match_tof.root"};
4246
std::string mInTreeName{"matchTOF"};
4347
std::unique_ptr<TFile> mFile = nullptr;
4448
std::unique_ptr<TTree> mTree = nullptr;
4549
std::vector<o2::dataformats::MatchInfoTOF> mMatches, *mMatchesPtr = &mMatches;
50+
std::vector<o2::dataformats::TrackTPCTOF> mTracks, *mTracksPtr = &mTracks;
4651
std::vector<o2::MCCompLabel> mLabelTOF, *mLabelTOFPtr = &mLabelTOF;
4752
std::vector<o2::MCCompLabel> mLabelTPC, *mLabelTPCPtr = &mLabelTPC;
4853
std::vector<o2::MCCompLabel> mLabelITS, *mLabelITSPtr = &mLabelITS;
4954
};
5055

5156
/// create a processor spec
5257
/// read matched TOF clusters from a ROOT file
53-
framework::DataProcessorSpec getTOFMatchedReaderSpec(bool useMC);
58+
framework::DataProcessorSpec getTOFMatchedReaderSpec(bool useMC, bool tpcmatch = false, bool readTracks = false);
5459

5560
} // namespace tof
5661
} // namespace o2

Detectors/GlobalTrackingWorkflow/tofworkflow/include/TOFWorkflow/TOFMatchedWriterSpec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace tof
2424

2525
/// create a processor spec
2626
/// write TOF matching info in a root file
27-
o2::framework::DataProcessorSpec getTOFMatchedWriterSpec(bool useMC, const char* outdef = "o2match_tof.root");
27+
o2::framework::DataProcessorSpec getTOFMatchedWriterSpec(bool useMC, const char* outdef = "o2match_tof.root", bool writeTracks = false);
2828

2929
} // namespace tof
3030
} // namespace o2

Detectors/GlobalTrackingWorkflow/tofworkflow/src/RecoWorkflowSpec.cxx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// or submit itself to any jurisdiction.
1010

1111
#include "TOFWorkflow/RecoWorkflowSpec.h"
12+
#include "Framework/ConfigParamRegistry.h"
1213
#include "Framework/ControlService.h"
1314
#include "Framework/DataProcessorSpec.h"
1415
#include "Framework/DataRefUtils.h"
@@ -21,6 +22,7 @@
2122
#include "ReconstructionDataFormats/TrackTPCITS.h"
2223
#include "DetectorsBase/GeometryManager.h"
2324
#include "DetectorsBase/Propagator.h"
25+
#include "DetectorsCommonDataFormats/NameConf.h"
2426
#include <gsl/span>
2527
#include "TStopwatch.h"
2628

@@ -55,6 +57,16 @@ class TOFDPLRecoWorkflowTask
5557
// nothing special to be set up
5658
o2::base::GeometryManager::loadGeometry();
5759
o2::base::Propagator::initFieldFromGRP("o2sim_grp.root");
60+
std::string matLUTPath = ic.options().get<std::string>("material-lut-path");
61+
std::string matLUTFile = o2::base::NameConf::getMatLUTFileName(matLUTPath);
62+
if (o2::base::NameConf::pathExists(matLUTFile)) {
63+
auto* lut = o2::base::MatLayerCylSet::loadFromFile(matLUTFile);
64+
o2::base::Propagator::Instance()->setMatLUT(lut);
65+
LOG(INFO) << "Loaded material LUT from " << matLUTFile;
66+
} else {
67+
LOG(INFO) << "Material LUT " << matLUTFile << " file is absent, only TGeo can be used";
68+
}
69+
5870
mTimer.Stop();
5971
mTimer.Reset();
6072
}
@@ -159,7 +171,8 @@ o2::framework::DataProcessorSpec getTOFRecoWorkflowSpec(bool useMC, bool useFIT)
159171
inputs,
160172
outputs,
161173
AlgorithmSpec{adaptFromTask<TOFDPLRecoWorkflowTask>(useMC, useFIT)},
162-
Options{/* for the moment no options */}};
174+
Options{
175+
{"material-lut-path", VariantType::String, "", {"Path of the material LUT file"}}}};
163176
}
164177

165178
} // end namespace tof

0 commit comments

Comments
 (0)