Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Detectors/TPC/workflow/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ o2_add_executable(calib-pedestal
SOURCES src/tpc-calib-pedestal.cxx
PUBLIC_LINK_LIBRARIES O2::TPCWorkflow)

o2_add_executable(track-reader
COMPONENT_NAME tpc
SOURCES src/TrackReaderWorkflow.cxx
PUBLIC_LINK_LIBRARIES O2::TPCWorkflow)

o2_add_test(workflow
COMPONENT_NAME tpc
LABELS tpc workflow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ class TrackReader : public Task
bool mUseMC = true; // use MC truth

std::string mInputFileName = "tpctracks.root";
std::string mTrackTreeName = "events";
std::string mTrackBranchName = "Tracks";
std::string mTrackTreeName = "tpcrec";
std::string mTrackBranchName = "TPCTracks";
std::string mClusRefBranchName = "ClusRefs";
std::string mTrackMCTruthBranchName = "TracksMCTruth";
std::string mTrackMCTruthBranchName = "TPCTracksMCTruth";
};

/// create a processor spec
Expand Down
97 changes: 97 additions & 0 deletions Detectors/TPC/workflow/src/TrackReaderWorkflow.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright CERN and copyright holders of ALICE O2. This software is
// distributed under the terms of the GNU General Public License v3 (GPL
// Version 3), copied verbatim in the file "COPYING".
//
// See http://alice-o2.web.cern.ch/license for full licensing information.
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// @file TrackReaderWorkflow.cxx

#include "Framework/WorkflowSpec.h"
#include "Framework/DeviceSpec.h"
#include "Framework/ConfigParamSpec.h"
#include "Framework/CompletionPolicyHelpers.h"
#include "Framework/DispatchPolicy.h"
#include "Framework/PartRef.h"
#include "Framework/ConcreteDataMatcher.h"
#include "TPCWorkflow/RecoWorkflow.h"
#include "TPCWorkflow/TPCSectorCompletionPolicy.h"
#include "DataFormatsTPC/TPCSectorHeader.h"
#include "Algorithm/RangeTokenizer.h"
#include "CommonUtils/ConfigurableParam.h"

#include "TPCWorkflow/TrackReaderSpec.h"

#include <string>
#include <stdexcept>
#include <unordered_map>
#include <regex>

// we need a global variable to propagate the type the message dispatching of the
// publisher will trigger on. This is dependent on the input type
o2::framework::Output gDispatchTrigger{"", ""};

// Global variable used to transport data to the completion policy
o2::tpc::reco_workflow::CompletionPolicyData gPolicyData;

// add workflow options, note that customization needs to be declared before
// including Framework/runDataProcessing
void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions)
{
using namespace o2::framework;

std::vector<ConfigParamSpec> options{
{"input-type", VariantType::String, "tracks", {"tracks"}},
{"dispatching-mode", VariantType::String, "prompt", {"determines when to dispatch: prompt, complete"}},
{"disable-mc", VariantType::Bool, false, {"disable sending of MC information"}}};

std::swap(workflowOptions, options);
}

// customize dispatch policy, dispatch immediately what is ready
void customize(std::vector<o2::framework::DispatchPolicy>& policies)
{
using DispatchOp = o2::framework::DispatchPolicy::DispatchOp;
// we customize all devices to dispatch data immediately
auto readerMatcher = [](auto const& spec) {
return std::regex_match(spec.name.begin(), spec.name.end(), std::regex(".*-reader"));
};
auto triggerMatcher = [](auto const& query) {
// a bit of a hack but we want this to be configurable from the command line,
// however DispatchPolicy is inserted before all other setup. Triggering depending
// on the global variable set from the command line option. If scheduled messages
// are not triggered they are sent out at the end of the computation
return gDispatchTrigger.origin == query.origin && gDispatchTrigger.description == query.description;
};
policies.push_back({"prompt-for-reader", readerMatcher, DispatchOp::WhenReady, triggerMatcher});
}

#include "Framework/runDataProcessing.h" // the main driver

using namespace o2::framework;

/// MC info is processed by default, disabled by using command line option `--disable-mc`
///
/// This function hooks up the the workflow specifications into the DPL driver.
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
{
WorkflowSpec specs;

auto inputType = cfgc.options().get<std::string>("input-type");
auto dispmode = cfgc.options().get<std::string>("dispatching-mode");
if (dispmode == "complete") {
// nothing to do we leave the matcher empty which will suppress the dispatch
// trigger and all messages will be sent out together at end of computation
} else if (inputType == "tracks") {
gDispatchTrigger = o2::framework::Output{"TPC", "TRACKS"};
}

bool doMC = not cfgc.options().get<bool>("disable-mc");

specs.push_back(o2::tpc::getTPCTrackReaderSpec(doMC));

return std::move(specs);
}
76 changes: 48 additions & 28 deletions GPU/GPUTracking/Standalone/qa/GPUQA.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -724,13 +724,15 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx
mClNative = clNative;

// Initialize Arrays
unsigned int nReconstructedTracks = 0;
if (tracksExternal) {
#ifdef GPUCA_O2_LIB
mTrackMCLabels.resize(tracksExternal->size());
nReconstructedTracks = tracksExternal->size();
#endif
} else {
mTrackMCLabels.resize(mTracking->mIOPtrs.nMergedTracks);
nReconstructedTracks = mTracking->mIOPtrs.nMergedTracks;
}
mTrackMCLabels.resize(nReconstructedTracks);
for (unsigned int iCol = 0; iCol < GetNMCCollissions(); iCol++) {
mTrackMCLabelsReverse[iCol].resize(GetNMCTracks(iCol));
mRecTracks[iCol].resize(GetNMCTracks(iCol));
Expand All @@ -753,7 +755,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx
mcEffBuffer.resize(mNEvents);
mcLabelBuffer.resize(mNEvents);
mcEffBuffer[mNEvents - 1].resize(GetNMCTracks(0));
mcLabelBuffer[mNEvents - 1].resize(mTracking->mIOPtrs.nMergedTracks);
mcLabelBuffer[mNEvents - 1].resize(nReconstructedTracks);
}

bool mcAvail = mcPresent() || tracksExtMC;
Expand All @@ -777,7 +779,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx
#if QA_DEBUG == 0
GPUCA_OPENMP(parallel for firstprivate(acc))
#endif
for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) {
for (unsigned int i = 0; i < nReconstructedTracks; i++) {
acc.reset();
int nClusters = 0;
const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i];
Expand Down Expand Up @@ -821,29 +823,29 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx
GPUInfo("QA Time: Assign Track Labels:\t\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6);
}

if (mQATasks & taskClusterAttach) {
// fill cluster attachment status
for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) {
const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i];
if (!track.OK()) {
for (unsigned int i = 0; i < nReconstructedTracks; i++) {
const GPUTPCGMMergedTrack* track = mTracking ? &mTracking->mIOPtrs.mergedTracks[i] : nullptr;
mcLabelI_t label = mTrackMCLabels[i];
if (mQATasks & taskClusterAttach) {
// fill cluster attachment status
if (!track->OK()) {
continue;
}
if (!mTrackMCLabels[i].isValid()) {
for (unsigned int k = 0; k < track.NClusters(); k++) {
if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) {
for (unsigned int k = 0; k < track->NClusters(); k++) {
if (mTracking->mIOPtrs.mergedTrackHits[track->FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) {
continue;
}
mClusterParam[mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num].fakeAttached++;
mClusterParam[mTracking->mIOPtrs.mergedTrackHits[track->FirstClusterRef() + k].num].fakeAttached++;
}
continue;
}
mcLabelI_t label = mTrackMCLabels[i];
if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) {
for (unsigned int k = 0; k < track.NClusters(); k++) {
if (mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) {
for (unsigned int k = 0; k < track->NClusters(); k++) {
if (mTracking->mIOPtrs.mergedTrackHits[track->FirstClusterRef() + k].state & GPUTPCGMMergedTrackHit::flagReject) {
continue;
}
int hitId = mTracking->mIOPtrs.mergedTrackHits[track.FirstClusterRef() + k].num;
int hitId = mTracking->mIOPtrs.mergedTrackHits[track->FirstClusterRef() + k].num;
bool correct = false;
for (int j = 0; j < GetMCLabelNID(hitId); j++) {
if (label == GetMCLabel(hitId, j)) {
Expand All @@ -858,12 +860,21 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx
}
}
}
if (mTrackMCLabels[i].isFake()) {
(GetMCTrackObj(mFakeTracks, label))++;
} else if (!track.MergedLooper()) {
GetMCTrackObj(mRecTracks, label)++;
if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) {
int& revLabel = GetMCTrackObj(mTrackMCLabelsReverse, label);
}

if (mTrackMCLabels[i].isFake()) {
(GetMCTrackObj(mFakeTracks, label))++;
} else if (tracksExternal || !track->MergedLooper()) {
GetMCTrackObj(mRecTracks, label)++;
if (mMCTrackMin == -1 || (label.getTrackID() >= mMCTrackMin && label.getTrackID() < mMCTrackMax)) {
int& revLabel = GetMCTrackObj(mTrackMCLabelsReverse, label);
if (tracksExternal) {
#ifdef GPUCA_O2_LIB
if (revLabel == -1 || fabsf((*tracksExternal)[i].getZ()) < fabsf((*tracksExternal)[revLabel].getZ())) {
revLabel = i;
}
#endif
} else {
const auto* trks = mTracking->mIOPtrs.mergedTracks;
bool comp;
if (revLabel == -1) {
Expand All @@ -881,6 +892,8 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx
}
}
}
}
if (mQATasks & taskClusterAttach) {
// fill cluster adjacent status
for (unsigned int i = 0; i < GetNMCLabels(); i++) {
if (mClusterParam[i].attached == 0 && mClusterParam[i].fakeAttached == 0) {
Expand All @@ -905,13 +918,14 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx
}
}
}

if (mConfig.matchMCLabels.size()) {
mGoodHits[mNEvents - 1].resize(GetNMCLabels());
std::vector<bool> allowMCLabels(GetNMCTracks(0));
for (unsigned int k = 0; k < GetNMCTracks(0); k++) {
allowMCLabels[k] = false;
}
for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) {
for (unsigned int i = 0; i < nReconstructedTracks; i++) {
if (!mGoodTracks[mNEvents - 1][i]) {
continue;
}
Expand Down Expand Up @@ -1058,6 +1072,9 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx
}

int val = (j == 0) ? (mRecTracks[iCol][i] ? 1 : 0) : (j == 1) ? (mRecTracks[iCol][i] ? mRecTracks[iCol][i] - 1 : 0) : (j == 2) ? mFakeTracks[iCol][i] : 1;
if (val == 0) {
continue;
}

for (int l = 0; l < 5; l++) {
if (info.prim && mcpt < PT_MIN_PRIM) {
Expand Down Expand Up @@ -1187,9 +1204,12 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx
continue;
}

auto getdz = [this, &param, &mc1, &side]() {
auto getdz = [this, &param, &mc1, &side, tracksExternal]() {
if (tracksExternal) {
return param.GetZ();
}
if (!mParam.par.continuousMaxTimeBin) {
return param.Z() - mc1.z;
return param.GetZ() - mc1.z;
}
#ifdef GPUCA_TPC_GEOMETRY_O2
if (!mParam.par.earlyTpcTransform) {
Expand Down Expand Up @@ -1256,7 +1276,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx

if (mQATasks & taskClusterAttach) {
// Fill cluster histograms
for (unsigned int iTrk = 0; iTrk < mTracking->mIOPtrs.nMergedTracks; iTrk++) {
for (unsigned int iTrk = 0; iTrk < nReconstructedTracks; iTrk++) {
const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[iTrk];
if (!track.OK()) {
continue;
Expand Down Expand Up @@ -1486,7 +1506,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx

if (mQATasks & taskTrackStatistics) {
// Fill track statistic histograms
for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) {
for (unsigned int i = 0; i < nReconstructedTracks; i++) {
const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i];
if (!track.OK()) {
continue;
Expand Down Expand Up @@ -1578,7 +1598,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector<o2::tpc::TrackTPC>* tracksEx

std::vector<float> clusterInfo(totalNCls);
memset(clusterInfo.data(), 0, clusterInfo.size() * sizeof(clusterInfo[0]));
for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) {
for (unsigned int i = 0; i < nReconstructedTracks; i++) {
const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i];
if (!track.OK()) {
continue;
Expand Down