diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml new file mode 100644 index 0000000000000..2d76a3ec0c889 --- /dev/null +++ b/.github/workflows/code-formatting.yml @@ -0,0 +1,90 @@ +name: Create a PR with clang-format changes + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} +# - name: Install clang format +# run: | +# sudo apt install -y clang-format-8 + - name: Run clang format + id: clang_format + run: | + set -x + # We need to fetch the other commit. + git fetch --depth=1 origin ${{ github.event.pull_request.base.ref }} + + # We create a new branch which we will use for the eventual PR. + git config --global user.email "alibuild@cern.ch" + git config --global user.name "ALICE Action Bot" + git checkout -b alibot-cleanup-${{ github.event.pull_request.number }} ${{ github.event.pull_request.head.sha }} + + BASE_COMMIT=${{ github.event.pull_request.base.sha }} + echo "Running clang-format-8 against branch ${{ github.event.pull_request.base.ref }} , with hash ${{ github.event.pull_request.base.sha }}" + COMMIT_FILES=$(git diff --name-only $BASE_COMMIT | grep -ivE 'LinkDef|Utilities/PCG/') + RESULT_OUTPUT="$(git-clang-format-8 --commit $BASE_COMMIT --diff --binary `which clang-format-8` $COMMIT_FILES)" + git-clang-format-8 --commit $BASE_COMMIT --diff --binary `which clang-format-8` $COMMIT_FILES | patch -p1 + + for x in $COMMIT_FILES; do + case $x in + *.h|*.cxx) + # We remove the header from the diff as it contains +++ then + # we only select the added lines to check for the long ones. + # We do not need to check for the lines which have been removed + # and we do not want to check for the lines which were not changed + # to avoid extra work. + # 120 characters are allowed, meaning the error should start with 122, + # to allow for the starting + at the end of the line. + git diff $x | tail -n +5 | grep -e '^+' | grep '.\{122,\}' && { echo "Line longer than 120 chars in $x." && exit 1; } || true ;; + *.hxx|*.cc|*.hpp) echo "$x uses non-allowed extension." && exit 1 ;; + *) ;; + esac + done + + if [ "$RESULT_OUTPUT" == "no modified files to format" ] \ + || [ "$RESULT_OUTPUT" == "clang-format did not modify any files" ] ; then + echo "clang-format passed." + git push --set-upstream origin :alibot-cleanup-${{ github.event.pull_request.number }} -f || true + echo ::set-output name=clean::true + else + echo "clang-format failed." + echo "To reproduce it locally please run" + echo -e "\tgit checkout $TRAVIS_BRANCH" + echo -e "\tgit-clang-format --commit $BASE_COMMIT --diff --binary $(which clang-format)" + echo "Opening a PR to your branch with the fixes" + git commit -m "Please consider the following formatting changes" -a + git show | cat + git push --set-upstream origin HEAD:refs/heads/alibot-cleanup-${{ github.event.pull_request.number }} -f + echo ::set-output name=clean::false + fi + + - name: pull-request + uses: ktf/pull-request@master + with: + source_branch: 'ktf:alibot-cleanup-${{ github.event.pull_request.number }}' + destination_branch: '${{ github.event.pull_request.user.login }}:${{ github.event.pull_request.head.ref }}' + github_token: ${{ secrets.GITHUB_TOKEN }} + pr_title: "Please consider the following formatting changes to #${{ github.event.pull_request.number }}" + pr_body: "Please consider the following formatting changes" + continue-on-error: true # We do not create PRs if the branch is not there. + +# - name: Create Pull Request +# uses: peter-evans/create-pull-request@v3 +# with: +# base: "${{ github.event.pull_request.head.ref }}" +# branch: "alibot-cleanup-${{ github.event.pull_request.number}}" + + - name: Exit with error if the PR is not clean + run: | + case ${{ steps.clang_format.outputs.clean }} in + true) echo "PR clean" ; exit 0 ;; + false) echo "PR not clean" ; exit 1 ;; + esac + + diff --git a/.gitignore b/.gitignore index 6ba91433a67ae..ff8b7c86c8974 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,6 @@ bazel-* # direnv .envrc + +# LSP support on macOS with vim +.clangd diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index 8aeae80d51b5d..03b0393c6029e 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -16,7 +16,6 @@ o2_add_library(AnalysisCore src/HistogramManager.cxx src/AnalysisCut.cxx src/AnalysisCompositeCut.cxx - src/RunToTimestamp.cxx src/TriggerAliases.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel) @@ -28,13 +27,6 @@ o2_target_root_dictionary(AnalysisCore include/Analysis/HistogramManager.h include/Analysis/AnalysisCut.h include/Analysis/AnalysisCompositeCut.h - include/Analysis/RunToTimestamp.h include/Analysis/TriggerAliases.h include/Analysis/MC.h LINKDEF src/AnalysisCoreLinkDef.h) - -o2_add_executable(makerun2timestamp - COMPONENT_NAME AnalysisCore - SOURCES src/InsertNewRunToTimestamp.cxx - PUBLIC_LINK_LIBRARIES O2::AnalysisCore O2::CCDB) - diff --git a/Analysis/Core/include/Analysis/HistHelpers.h b/Analysis/Core/include/Analysis/HistHelpers.h new file mode 100644 index 0000000000000..1cbff6e38fa3b --- /dev/null +++ b/Analysis/Core/include/Analysis/HistHelpers.h @@ -0,0 +1,274 @@ +// 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. + +/// \author Mario Krueger +// +// Some helper templates to simplify working with histograms +// + +#ifndef HistHelpers_H +#define HistHelpers_H + +#include +#include +#include +#include +#include +#include + +#include "Framework/Logger.h" + +namespace o2 +{ +namespace experimental +{ +namespace histhelpers +{ + +template +struct is_shared_ptr : std::false_type { +}; +template +struct is_shared_ptr> : std::true_type { +}; + +//************************************************************************************************** +/** + * Container class for storing and saving root histograms of any type. + * TObjArray inheritance (and concomitant raw pointer gynmnastics) is used to interface with existing O2 file writing functionality. + */ +//************************************************************************************************** +class HistContainer : public TObjArray +{ + public: + HistContainer(const std::string& name) : TObjArray() + { + SetBit(TObject::kSingleKey, false); // not working; seems like WriteObjectAny ignores this... + SetOwner(false); // let container handle object deletion + SetName(name.data()); + } + + using HistType = std::variant, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr>; + + template + void Add(uint8_t histID, T&& hist) + { + if (mHistos.find(histID) != mHistos.end()) { + LOGF(WARNING, "HistContainer %s already holds a histogram at histID = %d. Overriding it now...", GetName(), histID); + TObject* oldPtr = nullptr; + std::visit([&](const auto& sharedPtr) { oldPtr = sharedPtr.get(); }, mHistos[histID]); + TObjArray::Remove(oldPtr); + } + // if shared poiner is provided as argument, object itself is used, otherwise copied + if constexpr (is_shared_ptr::value) + mHistos[histID] = DownCast(hist); + else { + mHistos[histID] = DownCast(std::make_shared(hist)); + } + TObject* rawPtr = nullptr; + std::visit([&](const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mHistos[histID]); + TObjArray::Add(rawPtr); + } + + // gets the underlying histogram pointer + // unfortunately we cannot automatically infer type here + // so one has to use Get(), Get(), Get(), Get(), Get() + template + std::shared_ptr Get(uint8_t histID) + { + return *std::get_if>(&mHistos[histID]); + } + + template + void Fill(uint8_t histID, Ts&&... position) + { + std::visit([this, &position...](auto&& hist) { GenericFill(hist, std::forward(position)...); }, mHistos[histID]); + } + + private: + std::map mHistos; + + // disallow user to call TObjArray::Add() + using TObjArray::Add; + + template + void GenericFill(std::shared_ptr hist, const Ts&... position) + { + constexpr bool isValidTH3 = (std::is_same_v && sizeof...(Ts) == 3); + constexpr bool isValidTH2 = (std::is_same_v && sizeof...(Ts) == 2); + constexpr bool isValidTH1 = (std::is_same_v && sizeof...(Ts) == 1); + constexpr bool isValidPrimitive = isValidTH1 || isValidTH2 || isValidTH3; + // unfortunately we dont know at compile the dimension of THn(Sparse) + constexpr bool isValidComplex = std::is_base_of::value; + + if constexpr (isValidPrimitive) { + hist->Fill(static_cast(position)...); + } else if constexpr (isValidComplex) { + // savety check for n dimensional histograms (runtime overhead) + // if(hist->GetNdimensions() != sizeof...(position)) return; + double tempArray[] = {static_cast(position)...}; + hist->Fill(tempArray); + } + }; + + template + HistType DownCast(std::shared_ptr hist) + { + // since the variant HistType only knows the interface classes (TH1,TH2,TH3) + // assigning an actual derived type of TH2 and TH3 (e.g. TH2F, TH3I) + // will confuse the compiler since they are both TH2(3) and TH1 at the same time + // it will not know which alternative of HistType to select + // therefore, in these cases we have to explicitly cast to the correct interface type first + if constexpr (std::is_base_of_v) { + return std::static_pointer_cast(hist); + } else if constexpr (std::is_base_of_v) { + return std::static_pointer_cast(hist); + } else { + // all other cases can be left untouched + return hist; + } + } +}; + +//************************************************************************************************** +/** + * Helper class to build all kinds of root histograms with a streamlined user interface. + */ +//************************************************************************************************** + +struct Axis { + std::string name{}; + std::string title{}; + std::vector binEdges{}; + int nBins{}; // 0 when bin edges are specified directly FIXME: make this std::optional +}; + +template +class HistBuilder +{ + public: + HistBuilder() : mAxes{}, mHist{nullptr} {} + HistBuilder(const HistBuilder&) = delete; // non construction-copyable + HistBuilder& operator=(const HistBuilder&) = delete; // non copyable + + void AddAxis(const Axis& axis) { mAxes.push_back(axis); } + void AddAxes(const std::vector& axes) + { + mAxes.insert(mAxes.end(), axes.begin(), axes.end()); + } + void AddAxis(const std::string& name, const std::string& title, const int& nBins, + const double& lowerEdge, const double& upperEdge) + { + mAxes.push_back({name, title, {lowerEdge, upperEdge}, nBins}); + } + void AddAxis(const std::string& name, const std::string& title, + const std::vector& binEdges) + { + mAxes.push_back({name, title, binEdges, 0}); + } + + std::shared_ptr GenerateHist(const std::string& name, bool hasWeights = false) + { + const std::size_t MAX_DIM{10}; + const std::size_t nAxes{mAxes.size()}; + if (nAxes == 0 || nAxes > MAX_DIM) + return nullptr; + + int nBins[MAX_DIM]{0}; + double lowerBounds[MAX_DIM]{0.0}; + double upperBounds[MAX_DIM]{0.0}; + + // first figure out number of bins and dimensions + std::string title = "[ "; + for (std::size_t i = 0; i < nAxes; i++) { + nBins[i] = (mAxes[i].nBins) ? mAxes[i].nBins : mAxes[i].binEdges.size() - 1; + lowerBounds[i] = mAxes[i].binEdges.front(); + upperBounds[i] = mAxes[i].binEdges.back(); + title += mAxes[i].name; + if (i < nAxes - 1) + title += " : "; + else + title += " ]"; + } + + // create histogram + mHist.reset(HistFactory(name, title, nAxes, nBins, lowerBounds, upperBounds)); + + if (!mHist) { + LOGF(WARNING, "ERROR: The number of specified dimensions does not match the type."); + return nullptr; + } + + // set axis properties + for (std::size_t i = 0; i < nAxes; i++) { + TAxis* axis{GetAxis(i)}; + if (axis) { + axis->SetTitle(mAxes[i].title.data()); + if constexpr (std::is_base_of_v) + axis->SetName((std::to_string(i) + "-" + mAxes[i].name).data()); + + // move the bin edges in case a variable binnining was requested + if (!mAxes[i].nBins) { + if (!std::is_sorted(std::begin(mAxes[i].binEdges), std::end(mAxes[i].binEdges))) { + LOGF(WARNING, "ERROR: The bin edges specified for axis %s in histogram %s are not in increasing order!", mAxes[i].name, name); + return nullptr; + } + axis->Set(nBins[i], mAxes[i].binEdges.data()); + } + } + } + if (hasWeights) + mHist->Sumw2(); + mAxes.clear(); // clean up after creating the root histogram + return mHist; + } + + private: + std::vector mAxes; + std::shared_ptr mHist; + + RootHist_t* HistFactory(const std::string& name, const std::string& title, const std::size_t nDim, + const int nBins[], const double lowerBounds[], const double upperBounds[]) + { + if constexpr (std::is_base_of_v) { + return new RootHist_t(name.data(), title.data(), nDim, nBins, lowerBounds, upperBounds); + } else if constexpr (std::is_base_of_v) { + return (nDim != 3) ? nullptr + : new RootHist_t(name.data(), title.data(), nBins[0], lowerBounds[0], + upperBounds[0], nBins[1], lowerBounds[1], upperBounds[1], + nBins[2], lowerBounds[2], upperBounds[2]); + } else if constexpr (std::is_base_of_v) { + return (nDim != 2) ? nullptr + : new RootHist_t(name.data(), title.data(), nBins[0], lowerBounds[0], + upperBounds[0], nBins[1], lowerBounds[1], upperBounds[1]); + } else if constexpr (std::is_base_of_v) { + return (nDim != 1) + ? nullptr + : new RootHist_t(name.data(), title.data(), nBins[0], lowerBounds[0], upperBounds[0]); + } + return nullptr; + } + + TAxis* GetAxis(const int i) + { + if constexpr (std::is_base_of_v) { + return mHist->GetAxis(i); + } else { + return (i == 0) ? mHist->GetXaxis() + : (i == 1) ? mHist->GetYaxis() : (i == 2) ? mHist->GetZaxis() : nullptr; + } + } +}; + +} // namespace histhelpers +} // namespace experimental +} // namespace o2 + +#endif diff --git a/Analysis/Core/include/Analysis/RunToTimestamp.h b/Analysis/Core/include/Analysis/RunToTimestamp.h deleted file mode 100644 index 6dabf861e267e..0000000000000 --- a/Analysis/Core/include/Analysis/RunToTimestamp.h +++ /dev/null @@ -1,48 +0,0 @@ -// 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. - -// -// Class for conversion between run number and timestamp -// -// Author: Nicolo' Jacazio on 2020-06-22 - -#ifndef RunToTimestamp_H -#define RunToTimestamp_H - -#include -#include - -class RunToTimestamp -{ - public: - RunToTimestamp() = default; - ~RunToTimestamp() = default; - - /// Checks if the converter has a particular run - bool Has(unsigned int runNumber) const { return mMap.count(runNumber); } - - /// Inserts a new run with a timestamp in the converter database - bool insert(unsigned int runNumber, long timestamp); - - /// Updates an already present run number with a new timestamp - bool update(unsigned int runNumber, long timestamp); - - /// Gets the timestamp of a run - long getTimestamp(unsigned int runNumber) const; - - /// Prints the content of the converter - void print() const; - - private: - std::map mMap; - ClassDefNV(RunToTimestamp, 1) // converter class between run number and timestamp -}; - -#endif diff --git a/Analysis/Core/include/Analysis/VarManager.h b/Analysis/Core/include/Analysis/VarManager.h index 9438ec0e3cfae..95df64631efd3 100644 --- a/Analysis/Core/include/Analysis/VarManager.h +++ b/Analysis/Core/include/Analysis/VarManager.h @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include @@ -43,7 +45,8 @@ class VarManager : public TObject ReducedTrackBarrel = BIT(4), ReducedTrackBarrelCov = BIT(5), ReducedTrackBarrelPID = BIT(6), - ReducedTrackMuon = BIT(7) + ReducedTrackMuon = BIT(7), + Pair = BIT(8) }; public: @@ -132,8 +135,13 @@ class VarManager : public TObject kNPairVariables, // Candidate-track correlation variables + kPairMass, + kPairPt, + kPairEta, + kPairPhi, kDeltaEta, kDeltaPhi, + kDeltaPhiSym, kNCorrelationVariables, kNVars @@ -177,6 +185,8 @@ class VarManager : public TObject static void FillTrack(T const& track, float* values = nullptr); template static void FillPair(T const& t1, T const& t2, float* values = nullptr); + template + static void FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* values = nullptr, float hadronMass = 0.0f); public: VarManager(); @@ -354,6 +364,10 @@ void VarManager::FillTrack(T const& track, float* values) values[kMuonChi2MatchTrigger] = track.chi2MatchTrigger(); } + if constexpr ((fillMap & Pair) > 0) { + values[kMass] = track.mass(); + } + FillTrackDerived(values); } @@ -363,10 +377,46 @@ void VarManager::FillPair(T const& t1, T const& t2, float* values) if (!values) values = fgValues; - // TODO: build the mass using the (pt,eta,phi) which are pre-calculated - values[kMass] = fgkElectronMass * fgkElectronMass; - values[kMass] = 2.0 * values[kMass] + 2.0 * (sqrt(values[kMass] + t1.pmom() * t1.pmom()) * sqrt(values[kMass] + t2.pmom() * t2.pmom()) - - t1.px() * t2.px() - t1.py() * t2.py() - t1.pz() * t2.pz()); + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), fgkElectronMass); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), fgkElectronMass); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + values[kMass] = v12.M(); + values[kPt] = v12.Pt(); + values[kEta] = v12.Eta(); + values[kPhi] = v12.Phi(); +} + +template +void VarManager::FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* values, float hadronMass) +{ + if (!values) + values = fgValues; + + if (fgUsedVars[kPairMass] || fgUsedVars[kPairPt] || fgUsedVars[kPairEta] || fgUsedVars[kPairPhi]) { + ROOT::Math::PtEtaPhiMVector v1(dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.mass()); + ROOT::Math::PtEtaPhiMVector v2(hadron.pt(), hadron.eta(), hadron.phi(), hadronMass); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + values[kPairMass] = v12.M(); + values[kPairPt] = v12.Pt(); + values[kPairEta] = v12.Eta(); + values[kPairPhi] = v12.Phi(); + } + if (fgUsedVars[kDeltaPhi]) { + double delta = dilepton.phi() - hadron.phi(); + if (delta > 3.0 / 2.0 * TMath::Pi()) + delta -= 2.0 * TMath::Pi(); + if (delta < -0.5 * TMath::Pi()) + delta += 2.0 * TMath::Pi(); + values[kDeltaPhi] = delta; + } + if (fgUsedVars[kDeltaPhiSym]) { + double delta = TMath::Abs(dilepton.phi() - hadron.phi()); + if (delta > TMath::Pi()) + delta = 2 * TMath::Pi() - delta; + values[kDeltaPhiSym] = delta; + } + if (fgUsedVars[kDeltaEta]) + values[kDeltaEta] = dilepton.eta() - hadron.eta(); } #endif diff --git a/Analysis/Core/src/AnalysisCoreLinkDef.h b/Analysis/Core/src/AnalysisCoreLinkDef.h index b122ef91d96c8..5eac2f6879fa5 100644 --- a/Analysis/Core/src/AnalysisCoreLinkDef.h +++ b/Analysis/Core/src/AnalysisCoreLinkDef.h @@ -18,7 +18,6 @@ #pragma link C++ typedef StepTHnF; #pragma link C++ typedef StepTHnD; -#pragma link C++ class RunToTimestamp+; #pragma link C++ class CorrelationContainer+; #pragma link C++ class TrackSelection+; #pragma link C++ class TriggerAliases+; diff --git a/Analysis/Core/src/InsertNewRunToTimestamp.cxx b/Analysis/Core/src/InsertNewRunToTimestamp.cxx deleted file mode 100644 index ae00495e2d14a..0000000000000 --- a/Analysis/Core/src/InsertNewRunToTimestamp.cxx +++ /dev/null @@ -1,103 +0,0 @@ -// 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. - -// -// A simple tool to produce objects for the conversion from run number to timestamp. -// The tool uploads the 'RunNumber -> timestamp' converter to CCDB. -// If no converter object is found in CCDB a new one is created and uploaded. -// -// Author: Nicolo' Jacazio on 2020-06-22 - -#include "Analysis/RunToTimestamp.h" -#include "CCDB/CcdbApi.h" -#include -#include - -namespace bpo = boost::program_options; - -bool initOptionsAndParse(bpo::options_description& options, int argc, char* argv[], bpo::variables_map& vm) -{ - options.add_options()( - "run,r", bpo::value()->required(), "Run number to use")( - "timestamp,t", bpo::value()->required(), "Timestamp to use equivalent to the run number")( - "path,p", bpo::value()->default_value("Analysis/Core/RunToTimestamp"), "Path to the object in the CCDB repository")( - "url,u", bpo::value()->default_value("http://ccdb-test.cern.ch:8080"), "URL of the CCDB database")( - "start,s", bpo::value()->default_value(0), "Start timestamp of object validity")( - "stop,S", bpo::value()->default_value(4108971600000), "Stop timestamp of object validity")( - "update,u", bpo::value()->default_value(0), "Flag to update the object instead of inserting the new timestamp")( - "delete_previous,d", bpo::value()->default_value(0), "Flag to delete previous versions of converter objects in the CCDB before uploading the new one so as to avoid proliferation on CCDB")( - "verbose,v", bpo::value()->default_value(0), "Verbose level 0, 1")( - "help,h", "Produce help message."); - - try { - bpo::store(parse_command_line(argc, argv, options), vm); - - // help - if (vm.count("help")) { - LOG(INFO) << options; - return false; - } - - bpo::notify(vm); - } catch (const bpo::error& e) { - LOG(ERROR) << e.what() << "\n"; - LOG(ERROR) << "Error parsing command line arguments; Available options:"; - LOG(ERROR) << options; - return false; - } - return true; -} - -int main(int argc, char* argv[]) -{ - bpo::options_description options("Allowed options"); - bpo::variables_map vm; - if (!initOptionsAndParse(options, argc, argv, vm)) { - return 1; - } - - o2::ccdb::CcdbApi api; - const std::string url = vm["url"].as(); - api.init(url); - if (!api.isHostReachable()) { - LOG(WARNING) << "CCDB host " << url << " is not reacheable, cannot go forward"; - return 1; - } - - std::string path = vm["path"].as(); - std::map metadata; - std::map* headers; - long start = vm["start"].as(); - long stop = vm["stop"].as(); - - RunToTimestamp* converter = api.retrieveFromTFileAny(path, metadata, -1, headers); - - if (!converter) { - LOG(INFO) << "Did not retrieve run number to timestamp converter, creating a new one!"; - converter = new RunToTimestamp(); - } else { - LOG(INFO) << "Retrieved run number to timestamp converter from ccdb url " << url; - } - if (vm["delete_previous"].as()) { - api.truncate(path); - } - - if (vm["update"].as()) - converter->update(vm["run"].as(), vm["timestamp"].as()); - else - converter->insert(vm["run"].as(), vm["timestamp"].as()); - - if (vm["verbose"].as()) - converter->print(); - - api.storeAsTFileAny(converter, path, metadata, start, stop); - - return 0; -} diff --git a/Analysis/Core/src/RunToTimestamp.cxx b/Analysis/Core/src/RunToTimestamp.cxx deleted file mode 100644 index dffff7b63c04d..0000000000000 --- a/Analysis/Core/src/RunToTimestamp.cxx +++ /dev/null @@ -1,60 +0,0 @@ -// 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. - -// -// Class for conversion between run number and timestamp -// -// Author: Nicolo' Jacazio on 2020-06-22 - -#include "Analysis/RunToTimestamp.h" -#include - -ClassImp(RunToTimestamp); - -bool RunToTimestamp::insert(unsigned int runNumber, long timestamp) -{ - std::pair::iterator, bool> check; - check = mMap.insert(std::pair(runNumber, timestamp)); - if (!check.second) { - LOG(FATAL) << "Run number " << runNumber << " already existed with a timestamp of " << check.first->second; - return false; - } - LOG(INFO) << "Add new run " << runNumber << " with timestamp " << timestamp << " to converter"; - return true; -} - -bool RunToTimestamp::update(unsigned int runNumber, long timestamp) -{ - if (!Has(runNumber)) { - LOG(FATAL) << "Run to Timestamp converter does not have run " << runNumber << ", cannot update converter"; - return false; - } - mMap[runNumber] = timestamp; - return true; -} - -long RunToTimestamp::getTimestamp(unsigned int runNumber) const -{ - if (!Has(runNumber)) { - LOG(ERROR) << "Run to Timestamp converter does not have run " << runNumber; - return 0; - } - return mMap.at(runNumber); -} - -void RunToTimestamp::print() const -{ - LOG(INFO) << "Printing run number -> timestamp conversion"; - int counter = 0; - for (auto e : mMap) { - LOG(INFO) << "Entry #" << counter++ << " has run number: " << e.first << " and timestamp: " << e.second; - } - LOG(INFO) << "Total number of runs in converter: " << mMap.size(); -} diff --git a/Analysis/Core/src/VarManager.cxx b/Analysis/Core/src/VarManager.cxx index b942531ac2046..837a6a76dce00 100644 --- a/Analysis/Core/src/VarManager.cxx +++ b/Analysis/Core/src/VarManager.cxx @@ -213,8 +213,18 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kPairType] = ""; fgVariableNames[kPairLxy] = "Pair Lxy"; fgVariableUnits[kPairLxy] = "cm"; + fgVariableNames[kPairMass] = "mass"; + fgVariableUnits[kPairMass] = "GeV/c2"; + fgVariableNames[kPairPt] = "p_{T}"; + fgVariableUnits[kPairPt] = "GeV/c"; + fgVariableNames[kPairEta] = "#eta"; + fgVariableUnits[kPairEta] = ""; + fgVariableNames[kPairPhi] = "#varphi"; + fgVariableUnits[kPairPhi] = "rad."; fgVariableNames[kDeltaEta] = "#Delta#eta"; fgVariableUnits[kDeltaEta] = ""; fgVariableNames[kDeltaPhi] = "#Delta#phi"; - fgVariableUnits[kDeltaPhi] = ""; + fgVariableUnits[kDeltaPhi] = "rad."; + fgVariableNames[kDeltaPhiSym] = "#Delta#phi"; + fgVariableUnits[kDeltaPhiSym] = "rad."; } diff --git a/Analysis/DataModel/include/Analysis/CandidateSelectionTables.h b/Analysis/DataModel/include/Analysis/CandidateSelectionTables.h new file mode 100644 index 0000000000000..aa7028fa27e72 --- /dev/null +++ b/Analysis/DataModel/include/Analysis/CandidateSelectionTables.h @@ -0,0 +1,26 @@ +// 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. +#ifndef O2_ANALYSIS_CANDIDATESELECTIONTABLES_H_ +#define O2_ANALYSIS_CANDIDATESELECTIONTABLES_H_ + +#include "Framework/AnalysisDataModel.h" +#include "Analysis/RecoDecay.h" + +namespace o2::aod +{ +namespace hfselcandidate +{ +DECLARE_SOA_COLUMN(IsSelD0, isSelD0, int); +DECLARE_SOA_COLUMN(IsSelD0bar, isSelD0bar, int); +} // namespace hfselcandidate +DECLARE_SOA_TABLE(HFSelD0Candidate, "AOD", "HFSELD0CAND", hfselcandidate::IsSelD0, hfselcandidate::IsSelD0bar); +} // namespace o2::aod + +#endif // O2_ANALYSIS_CANDIDATESELECTIONTABLES_H_ diff --git a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h index 5d78f05e48b7a..a04365bd5cae1 100644 --- a/Analysis/DataModel/include/Analysis/ReducedInfoTables.h +++ b/Analysis/DataModel/include/Analysis/ReducedInfoTables.h @@ -59,7 +59,7 @@ DECLARE_SOA_COLUMN(FilteringFlags, filteringFlags, uint64_t); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(Charge, charge, short); +DECLARE_SOA_COLUMN(Charge, charge, int); DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return pt * std::sin(phi); }); DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); @@ -82,7 +82,6 @@ DECLARE_SOA_TABLE(ReducedTracksBarrel, "AOD", "RTBARREL", track::ITSClusterMap, track::ITSChi2NCl, track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, track::TPCChi2NCl, - // track::TPCSignal, track::TRDSignal, track::TOFSignal, track::TRDChi2, track::TOFChi2, track::Length, track::TPCNClsFound, track::TPCNClsCrossedRows); @@ -113,7 +112,7 @@ DECLARE_SOA_COLUMN(FilteringFlags, filteringFlags, uint64_t); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(Charge, charge, short); +DECLARE_SOA_COLUMN(Charge, charge, int); DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return pt * std::sin(phi); }); DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); diff --git a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h index 4e9fa74e80198..e21df4947782c 100644 --- a/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h +++ b/Analysis/DataModel/include/Analysis/SecondaryVertexHF.h @@ -19,11 +19,22 @@ #include "Framework/AnalysisDataModel.h" #include "Analysis/RecoDecay.h" +#include "PID/PIDResponse.h" namespace o2::aod { +namespace seltrack +{ +DECLARE_SOA_COLUMN(IsSel, issel, int); +DECLARE_SOA_COLUMN(DCAPrim0, dcaprim0, float); +DECLARE_SOA_COLUMN(DCAPrim1, dcaprim1, float); +} // namespace seltrack +DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", seltrack::IsSel, seltrack::DCAPrim0, + seltrack::DCAPrim1); + +using BigTracks = soa::Join; + // FIXME: this is a workaround until we get the index columns to work with joins. -using BigTracks = soa::Join; namespace hf_track_index { @@ -189,6 +200,8 @@ DECLARE_SOA_TABLE(HfCandBase, "AOD", "HFCANDBASE", hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, + hf_track_index::Index0Id, + hf_track_index::Index1Id, /* dynamic columns */ hf_cand_prong2::ImpactParameterProduct, hf_cand_prong2::M, diff --git a/Analysis/DataModel/src/dumpDataModel.cxx b/Analysis/DataModel/src/dumpDataModel.cxx index b549f53a0af81..70652b71f9d76 100644 --- a/Analysis/DataModel/src/dumpDataModel.cxx +++ b/Analysis/DataModel/src/dumpDataModel.cxx @@ -143,19 +143,19 @@ edge[dir=back, arrowtail=empty] (dumpIndex(typename Ts::iterator::external_index_columns_t{}), ...); } -int main(int argc, char** argv) +int main(int, char**) { fmt::printf("%s", R"(digraph hierarchy { size="5,5" node[shape=plain,style=filled,fillcolor=gray95] edge[dir=back, arrowtail=empty] )"); - dumpCluster(); + /// FIXME: topology should account for predefined Joins + dumpCluster(); dumpTable(); dumpTable(); dumpTable(); - dumpTable(); - dumpTable(); + dumpCluster(); dumpTable(); dumpTable(); dumpTable(); diff --git a/Analysis/Scripts/insert_Run2_run_to_timestamps.py b/Analysis/Scripts/insert_Run2_run_to_timestamps.py deleted file mode 100755 index 227f047635a75..0000000000000 --- a/Analysis/Scripts/insert_Run2_run_to_timestamps.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Script update the CCDB with run number to timestamp conversion objects. -This is intended to define timestamps for Run2 converted data. -This script works in tandem with `AliRoot/STEER/macros/GetStartAndEndOfRunTimestamp.C`. -The input format is the same as the output of such macro. -Author: Nicolo' Jacazio on 2020-06-30 -""" - -import argparse -import subprocess - - -class run_timestamp: - run = 0 - start = 0 - stop = 0 - - def __init__(self, run, start, stop): - self.run = run - self.start = start - self.stop = stop - self.check() - - def check(self): - """ - Function to check integrity of timestamp - """ - if self.start > self.stop: - raise ValueError("start > stop", self.start, self.stop) - if self.start == 0: - raise ValueError("start is zero") - if self.stop == 0: - raise ValueError("stop is zero") - - def check_if_int(number, name): - """ - Function to check if a timestamp is an integer - """ - if not isinstance(number, int): - raise ValueError( - f"{name} '{number}' is not an integer but a '{type(number)}'") - check_if_int(self.run, "run") - check_if_int(self.start, "start") - check_if_int(self.stop, "stop") - - def check_if_milliseconds(number, name): - """ - Function to check if a timestamp is in milliseconds - """ - if not len(str(number)) == 13: - raise ValueError(f"{name} '{number}' is not in milliseconds") - check_if_milliseconds(self.start, "start") - check_if_milliseconds(self.stop, "stop") - - def __str__(self): - return f"Run {self.run} start {self.start} stop {self.stop}" - - def __eq__(self, other): - return self.run == other.run - - -def main(input_file_name, extra_args, - input_in_seconds=False, delete_previous=True, verbose=False): - """ - Given an input file with line by line runs and start and stop timestamps it updates the dedicated CCDB object. - Extra arguments can be passed to the upload script. - input_in_seconds set to True converts the input from seconds ti milliseconds. - delete_previous deletes previous uploads in the same path so as to avoid proliferation on CCDB - verbose flag can be set to 1, 2 to increase the debug level - URL of ccdb and PATH of objects are passed as default arguments - """ - infile = open(input_file_name) - if verbose: - print(f"Reading run to timestamp from input file '{input_file_name}'") - run_list = [] - for line_no, i in enumerate(infile): - i = i.strip() - if len(i) <= 1: - continue - if verbose >= 2: - print(f"Line number {line_no}: {i}") - i = i.split() - run = i[1] - if not run.isdigit(): - raise ValueError("Read run is not a number", run) - start = i[4] - if not start.isdigit(): - raise ValueError("Read start is not a number", start) - stop = i[8] - if not stop.isdigit(): - raise ValueError("Read stop is not a number", stop) - if input_in_seconds: - if verbose: - print( - f"Converting input timestamps start '{start}' and stop '{stop}' from seconds to milliseconds") - start = f"{start}000" - stop = f"{stop}000" - entry = run_timestamp(int(run), int(start), int(stop)) - if entry not in run_list: - run_list.append(entry) - print("Will set converter for", len(run_list), "runs") - successfull = [] - failed = [] - for i in run_list: - print("Setting run", i) - cmd = "o2-analysiscore-makerun2timestamp" - cmd += f" --run {i.run}" - cmd += f" --timestamp {i.start}" - if delete_previous: - cmd += f" --delete_previous 1" - cmd += f" {extra_args}" - if i == run_list[-1]: - # Printing the status of the converter as a last step - cmd += " -v 1" - if verbose: - print(cmd) - process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) - output, error = process.communicate() - output = output.decode("utf-8") - if verbose: - print(output) - if "[FATAL] " in output: - failed.append(i.run) - else: - successfull.append(i.run) - - def print_status(counter, msg): - if len(counter) > 0: - print(len(counter), msg) - if verbose >= 3: - print("Runs:", counter) - - print_status(successfull, "successfully uploaded new runs") - print_status( - failed, "failed uploads, retry with option '-vvv' for mor info") - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description='Uploads run-number-to-timestamp converter to CCDB from input file.') - parser.add_argument('input_file_name', metavar='input_file_name', type=str, - help='Name of the file with the run and corresponding timestamps') - parser.add_argument('--extra_args', metavar='Extra_Arguments', type=str, - default="", - help='Extra arguments for the upload to CCDB. E.g. for the update of the object --extra_args " --update 1"') - parser.add_argument('--input_in_seconds', '-s', action='count', default=0, - help="Use if timestamps taken from input are in seconds") - parser.add_argument('--delete_previous', '-d', action='count', - default=0, help="Deletes previous uploads in the same path so as to avoid proliferation on CCDB") - parser.add_argument('--verbose', '-v', action='count', - default=0, help="Verbose mode 0, 1, 2") - args = parser.parse_args() - main(input_file_name=args.input_file_name, - extra_args=args.extra_args, - input_in_seconds=args.input_in_seconds, - verbose=args.verbose) diff --git a/Analysis/Scripts/inspect_Run2_run_to_timestamps.py b/Analysis/Scripts/inspect_Run2_run_to_timestamps.py deleted file mode 100755 index dbc34abae02ec..0000000000000 --- a/Analysis/Scripts/inspect_Run2_run_to_timestamps.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Script inspect the CCDB object with run number to timestamp conversion. -Author: Nicolo' Jacazio on 2020-07-08 -""" - -from update_ccdb import get_ccdb_obj -from ROOT import TFile - - -def main(converter_ccdb_path="Analysis/Core/RunToTimestamp", dest="/tmp/", verbose=0): - """ - Given a path in the CCDB downloads the timestamp converte object and inspects it - """ - get_ccdb_obj(converter_ccdb_path, -1, dest=dest, verbose=1) - obj_file = TFile(f"{dest}/{converter_ccdb_path}/snapshot.root", "READ") - obj_file.ls() - obj = obj_file.Get("ccdb_object") - obj.print() - - -if __name__ == "__main__": - main() diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index d5a267f78032a..751cd40c64c8f 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory(PWGCF) add_subdirectory(PWGDQ) add_subdirectory(PWGHF) +add_subdirectory(PWGLF) o2_add_dpl_workflow(trackselection SOURCES trackselection.cxx diff --git a/Analysis/Tasks/PWGDQ/CMakeLists.txt b/Analysis/Tasks/PWGDQ/CMakeLists.txt index 9eac2e83b667b..c1e200173f10f 100644 --- a/Analysis/Tasks/PWGDQ/CMakeLists.txt +++ b/Analysis/Tasks/PWGDQ/CMakeLists.txt @@ -7,3 +7,8 @@ o2_add_dpl_workflow(table-reader SOURCES tableReader.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore COMPONENT_NAME Analysis) + +o2_add_dpl_workflow(dilepton-ee + SOURCES dileptonEE.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsBase O2::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGDQ/dileptonEE.cxx b/Analysis/Tasks/PWGDQ/dileptonEE.cxx new file mode 100644 index 0000000000000..9bf806fc14b28 --- /dev/null +++ b/Analysis/Tasks/PWGDQ/dileptonEE.cxx @@ -0,0 +1,355 @@ +// 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. +// +// Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no +// +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Analysis/ReducedInfoTables.h" +#include "Analysis/VarManager.h" +#include "Analysis/HistogramManager.h" +#include "Analysis/AnalysisCut.h" +#include "Analysis/AnalysisCompositeCut.h" +#include +#include +#include +#include +#include + +using std::cout; +using std::endl; + +using namespace o2; +using namespace o2::framework; +//using namespace o2::framework::expressions; +using namespace o2::aod; + +// Some definitions +namespace o2::aod +{ +namespace reducedtrack +{ +DECLARE_SOA_COLUMN(IsBarrelSelected, isBarrelSelected, int); +} // namespace reducedtrack +namespace reducedpair +{ +DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Charge, charge, int); +DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return pt * std::sin(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pmom, pmom, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); +} // namespace reducedpair + +DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "BARRELTRACKCUTS", reducedtrack::IsBarrelSelected); +} // namespace o2::aod + +using MyEvent = soa::Join::iterator; +using MyEventVtxCov = soa::Join::iterator; +using MyBarrelTracks = soa::Join; +using MyBarrelTracksSelected = soa::Join; + +void DefineHistograms(o2::framework::OutputObj histMan, TString histClasses); + +// HACK: In order to be able to deduce which kind of aod object is transmitted to the templated VarManager::Fill functions +// a constexpr static bit map must be defined and sent as template argument +// The user has to include in this bit map all the tables needed in analysis, as defined in VarManager::ObjTypes +// Additionally, one should make sure that the requested tables are actually provided in the process() function, +// otherwise a compile time error will be thrown. +// This is a temporary fix until the arrow/ROOT issues are solved, at which point it will be possible +// to automatically detect the object types transmitted to the VarManager +constexpr static uint32_t fgEventFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; +constexpr static uint32_t fgTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID; + +struct BarrelTrackSelection { + Produces trackSel; + OutputObj fHistMan{"output"}; + AnalysisCompositeCut* fTrackCut; + + float* fValues; // array to be used by the VarManager + + void init(o2::framework::InitContext&) + { + fValues = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + DefineHistograms(fHistMan, "TrackBarrel_BeforeCuts;TrackBarrel_AfterCuts;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + + DefineCuts(); + } + + void DefineCuts() + { + fTrackCut = new AnalysisCompositeCut(true); // true: use AND + AnalysisCut* cut1 = new AnalysisCut(); + cut1->AddCut(VarManager::kPt, 0.2, 10.0); + cut1->AddCut(VarManager::kEta, -0.8, 0.8); + cut1->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut1->AddCut(VarManager::kITSchi2, 0.0, 5.0); + cut1->AddCut(VarManager::kITSncls, 3.5, 7.5); + cut1->AddCut(VarManager::kTPCncls, 79.5, 159.5); + cut1->AddCut(VarManager::kTPCsignal, 70, 100, false); //exclude = false + cut1->AddCut(VarManager::kTOFnSigmaEl, -3, +3, false); //exclude = false + + //cut1->AddCut(VarManager::kTPCnSigmaPi, -1e+10, +3.5, true); //exclude = false + //cut1->AddCut(VarManager::kTPCnSigmaKa, -3, +3, true); //exclude = false + //cut1->AddCut(VarManager::kTPCnSigmaPr, -3, +3, true); //exclude = false + fTrackCut->AddCut(cut1); + + // //AnalysisCut* pid_TPChadrej = new AnalysisCut("pid_TPChadrej","PID TPC hadron band rejection"); + // //pid_TPChadrej->AddCut(VarManager::kTPCsignal, 70, 100,false);//exclude = false + // //pid_TPChadrej->AddCut(VarManager::kTPCnSigmaPi,-1e+10,+3.5,true); + // //pid_TPChadrej->AddCut(VarManager::kTPCnSigmaKa, -3.,+3. ,true); + // //pid_TPChadrej->AddCut(VarManager::kTPCnSigmaPr, -3.,+3. ,true); + // + // //AnalysisCut* pid_TOFrec = new AnalysisCut("pid_TOFrec","PID TOF recovery"); + // //pid_TOFrec->AddCut(VarManager::kTPCsignal, 70, 100,false);//exclude = false + // //pid_TOFrec->AddCut(VarManager::kTOFnSigmaPi,-3,+3.,false); + // + // AnalysisCut* pid_TOFrec_pi = new AnalysisCut("pid_TOFrec_pi","PID TOF recovery pion"); + // pid_TOFrec_pi->AddCut(VarManager::kTPCsignal, 70, 100,false);//exclude = false + // pid_TOFrec_pi->AddCut(VarManager::kTOFnSigmaEl,-3,+3.,false,VarManager::kTPCnSigmaPi,-1e+10,+3.5,false); + // + // AnalysisCut* pid_TOFrec_ka = new AnalysisCut("pid_TOFrec_ka","PID TOF recovery Kaon"); + // pid_TOFrec_ka->AddCut(VarManager::kTPCsignal, 70, 100,false);//exclude = false + // pid_TOFrec_ka->AddCut(VarManager::kTOFnSigmaEl,-3,+3.,false,VarManager::kTPCnSigmaKa,-3.,+3.,false); + // + // AnalysisCut* pid_TOFrec_pr = new AnalysisCut("pid_TOFrec_ka","PID TOF recovery Proton"); + // pid_TOFrec_pr->AddCut(VarManager::kTPCsignal, 70, 100,false);//exclude = false + // pid_TOFrec_pr->AddCut(VarManager::kTOFnSigmaEl,-3,+3.,false,VarManager::kTPCnSigmaPr,-3.,+3.,false); + // + // AnalysisCompositeCut *pidcut = new AnalysisCompositeCut(false); // false: use OR + // //pidcut->AddCut(pid_TPChadrej); + // //pidcut->AddCut(pid_TOFrec); + // //pidcut->AddCut(pid_TOFrec_pi); + // pidcut->AddCut(pid_TOFrec_ka); + // pidcut->AddCut(pid_TOFrec_pr); + // fTrackCut->AddCut(pidcut); + // + // //fTrackCut->AddCut(pid_TOFrec_ka); + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEvent event, MyBarrelTracks const& tracks) + { + for (int i = 0; i < VarManager::kNVars; ++i) + fValues[i] = -9999.0f; + // fill event information which might be needed in histograms that combine track and event properties + VarManager::FillEvent(event, fValues); + + for (auto& track : tracks) { + for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) + fValues[i] = -9999.0f; + VarManager::FillTrack(track, fValues); + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); + + if (fTrackCut->IsSelected(fValues)) { + trackSel(1); + fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); + } else + trackSel(0); + } + } +}; + +struct DileptonEE { + OutputObj fHistMan{"output"}; + AnalysisCompositeCut* fEventCut; + //NOTE: one could define also a dilepton cut, but for now basic selections can be supported using Partition + + Partition posTracks = aod::reducedtrack::charge > 0 && aod::reducedtrack::isBarrelSelected == 1; + Partition negTracks = aod::reducedtrack::charge < 0 && aod::reducedtrack::isBarrelSelected == 1; + + void init(o2::framework::InitContext&) + { + VarManager::SetDefaultVarNames(); + fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;PairsBarrelULS;PairsBarrelLSpp;PairsBarrelLSnn;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + + DefineCuts(); + } + + void DefineCuts() + { + fEventCut = new AnalysisCompositeCut(true); + + AnalysisCut* varCut = new AnalysisCut(); + varCut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + varCut->AddCut(VarManager::kVtxNcontrib, 0.5, 1e+10); + fEventCut->AddCut(varCut); + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEventVtxCov event, MyBarrelTracksSelected const& tracks) + { + // Reset the VarManager::fgValues array + // The reset can be done selectively, using arguments in the ResetValues() function + VarManager::ResetValues(); + + VarManager::FillEvent(event); + fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); // automatically fill all the histograms in the class Event + if (!fEventCut->IsSelected(VarManager::fgValues)) + return; + fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + + // Run the same event pairing for barrel tracks + // TODO: Use combinations() when this will work for Partitions + /* e.g. + * for (auto& [tpos, tneg] : combinations(posTracks, negTracks)) { + VarManager::FillPair(tpos, tneg); + fHistMan->FillHistClass("PairsBarrelULS", VarManager::fgValues); + } + */ + + for (auto tpos : posTracks) { + for (auto tneg : negTracks) { // +- pairs + VarManager::FillPair(tpos, tneg); + fHistMan->FillHistClass("PairsBarrelULS", VarManager::fgValues); + } + for (auto tpos2 = tpos + 1; tpos2 != posTracks.end(); ++tpos2) { // ++ pairs + VarManager::FillPair(tpos, tpos2); + fHistMan->FillHistClass("PairsBarrelLSpp", VarManager::fgValues); + } + } + for (auto tneg : negTracks) { // -- pairs + for (auto tneg2 = tneg + 1; tneg2 != negTracks.end(); ++tneg2) { + VarManager::FillPair(tneg, tneg2); + fHistMan->FillHistClass("PairsBarrelLSnn", VarManager::fgValues); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask("barrel-track-selection"), + adaptAnalysisTask("dilepton-ee")}; +} + +void DefineHistograms(o2::framework::OutputObj histMan, TString histClasses) +{ + // + // Define here the histograms for all the classes required in analysis. + // The histogram classes are provided in the histClasses string, separated by semicolon ";" + // The histogram classes and their components histograms are defined below depending on the name of the histogram class + // + const int kNRuns = 2; + int runs[kNRuns] = {244918, 244919}; + TString runsStr; + for (int i = 0; i < kNRuns; i++) + runsStr += Form("%d;", runs[i]); + VarManager::SetRunNumbers(kNRuns, runs); + + TObjArray* arr = histClasses.Tokenize(";"); + for (Int_t iclass = 0; iclass < arr->GetEntries(); ++iclass) { + TString classStr = arr->At(iclass)->GetName(); + + if (classStr.Contains("Event")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "VtxZ", "Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "VtxZ_Run", "Vtx Z", true, + kNRuns, 0.5, 0.5 + kNRuns, VarManager::kRunId, 60, -15.0, 15.0, VarManager::kVtxZ, 10, 0., 0., VarManager::kNothing, runsStr.Data()); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "VtxX_VtxY", "Vtx X vs Vtx Y", false, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "VtxX_VtxY_VtxZ", "vtx x - y - z", false, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 60, -15.0, 15.0, VarManager::kVtxZ); // TH3F histogram + histMan->AddHistogram(classStr.Data(), "NContrib_vs_VtxZ_prof", "Vtx Z vs ncontrib", true, 30, -15.0, 15.0, VarManager::kVtxZ, 10, -1., 1., VarManager::kVtxNcontrib); // TProfile histogram + histMan->AddHistogram(classStr.Data(), "VtxZ_vs_VtxX_VtxY_prof", "Vtx Z vs (x,y)", true, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 10, -1., 1., VarManager::kVtxZ); // TProfile2D histogram + histMan->AddHistogram(classStr.Data(), "Ncontrib_vs_VtxZ_VtxX_VtxY_prof", "n-contrib vs (x,y,z)", true, + 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 30, -15., 15., VarManager::kVtxZ, + "", "", "", VarManager::kVtxNcontrib); // TProfile3D + + double vtxXbinLims[10] = {0.055, 0.06, 0.062, 0.064, 0.066, 0.068, 0.070, 0.072, 0.074, 0.08}; + double vtxYbinLims[7] = {0.31, 0.32, 0.325, 0.33, 0.335, 0.34, 0.35}; + double vtxZbinLims[13] = {-15.0, -10.0, -8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 15.0}; + double nContribbinLims[9] = {0.0, 100.0, 200.0, 400.0, 600.0, 1000.0, 1500.0, 2000.0, 4000.0}; + + histMan->AddHistogram(classStr.Data(), "VtxX_VtxY_nonEqualBinning", "Vtx X vs Vtx Y", false, 9, vtxXbinLims, VarManager::kVtxX, 6, vtxYbinLims, VarManager::kVtxY); // THnF histogram with custom non-equal binning + + histMan->AddHistogram(classStr.Data(), "VtxZ_weights", "Vtx Z", false, + 60, -15.0, 15.0, VarManager::kVtxZ, 10, 0., 0., VarManager::kNothing, 10, 0., 0., VarManager::kNothing, + "", "", "", VarManager::kNothing, VarManager::kVtxNcontrib); // TH1F histogram, filled with weights using the vtx n-contributors + + Int_t vars[4] = {VarManager::kVtxX, VarManager::kVtxY, VarManager::kVtxZ, VarManager::kVtxNcontrib}; + TArrayD binLimits[4]; + binLimits[0] = TArrayD(10, vtxXbinLims); + binLimits[1] = TArrayD(7, vtxYbinLims); + binLimits[2] = TArrayD(13, vtxZbinLims); + binLimits[3] = TArrayD(9, nContribbinLims); + histMan->AddHistogram(classStr.Data(), "vtxHisto", "n contrib vs (x,y,z)", 4, vars, binLimits); + + histMan->AddHistogram(classStr.Data(), "CentV0M_vtxZ", "CentV0M vs Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ, 20, 0., 100., VarManager::kCentVZERO); // TH2F histogram + + histMan->AddHistogram(classStr.Data(), "VtxChi2", "Vtx chi2", false, 100, 0.0, 100.0, VarManager::kVtxChi2); // TH1F histogram + + continue; + } // end if(Event) + + if (classStr.Contains("Track")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "Pt", "p_{T} distribution", false, 100, 0.0, 10.0, VarManager::kPt); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "Eta", "#eta distribution", false, 200, -1.0, 1.0, VarManager::kEta); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "Phi_Eta", "#phi vs #eta distribution", false, 200, -1.0, 1.0, VarManager::kEta, 72, 0, TMath::TwoPi(), VarManager::kPhi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "P", "p distribution", false, 200, 0.0, 20.0, VarManager::kP); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "Px", "p_{x} distribution", false, 200, 0.0, 20.0, VarManager::kPx); + histMan->AddHistogram(classStr.Data(), "Py", "p_{y} distribution", false, 200, 0.0, 20.0, VarManager::kPy); + histMan->AddHistogram(classStr.Data(), "Pz", "p_{z} distribution", false, 400, -20.0, 20.0, VarManager::kPz); + + if (classStr.Contains("Barrel")) { + histMan->AddHistogram(classStr.Data(), "TPCncls", "Number of cluster in TPC", false, 160, -0.5, 159.5, VarManager::kTPCncls); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "ITSncls", "Number of cluster in ITS", false, 8, -0.5, 7.5, VarManager::kITSncls); // TH1F histogram + //for TPC PID + histMan->AddHistogram(classStr.Data(), "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 1000, 0.0, 10.0, VarManager::kPin, 200, 0.0, 200., VarManager::kTPCsignal); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaEl_pIN", "TPC dE/dx n#sigma_{e} vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaEl); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaEl_Eta", "TPC dE/dx n#sigma_{e} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaEl); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaPi_pIN", "TPC dE/dx n#sigma_{#pi} vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaPi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaPi_Eta", "TPC dE/dx n#sigma_{#pi} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaPi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaKa_pIN", "TPC dE/dx n#sigma_{K} vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaKa); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaKa_Eta", "TPC dE/dx n#sigma_{K} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaKa); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaPr_pIN", "TPC dE/dx n#sigma_{p} vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaPr); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaPr_Eta", "TPC dE/dx n#sigma_{p} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaPr); // TH2F histogram + + //for TOF PID + histMan->AddHistogram(classStr.Data(), "TOFbeta_pIN", "TOF #beta vs pIN", false, 1000, 0.0, 10.0, VarManager::kPin, 120, 0.0, 1.2, VarManager::kTOFbeta); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaEl_pIN", "TOF #beta n#sigma_{e} vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaEl); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaEl_Eta", "TOF #beta n#sigma_{e} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaEl); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaPi_pIN", "TOF #beta n#sigma_{#pi} vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaPi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaPi_Eta", "TOF #beta n#sigma_{#pi} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaPi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaKa_pIN", "TOF #beta n#sigma_{K} vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaKa); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaKa_Eta", "TOF #beta n#sigma_{K} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaKa); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaPr_pIN", "TOF #beta n#sigma_{p} vs pIN", false, 100, 0.0, 10.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaPr); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaPr_Eta", "TOF #beta n#sigma_{p} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaPr); // TH2F histogram + + histMan->AddHistogram(classStr.Data(), "Cov1Pt_Pt", "cov(1/pt,1/pt) vs p_{T} distribution", false, 100, 0.0, 10.0, VarManager::kPt, 100, 0.0, 1.0, VarManager::kTrackC1Pt21Pt2); // TH2F histogram + } + } + + if (classStr.Contains("Pairs")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "Mass_Pt", "", false, 500, 0.0, 5.0, VarManager::kMass, 200, 0.0, 20.0, VarManager::kPt); + } + + } // end loop over histogram classes +} diff --git a/Analysis/Tasks/PWGDQ/tableReader.cxx b/Analysis/Tasks/PWGDQ/tableReader.cxx index 8d372398c052e..34ff149099222 100644 --- a/Analysis/Tasks/PWGDQ/tableReader.cxx +++ b/Analysis/Tasks/PWGDQ/tableReader.cxx @@ -13,6 +13,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" #include "Analysis/ReducedInfoTables.h" #include "Analysis/VarManager.h" #include "Analysis/HistogramManager.h" @@ -23,46 +24,81 @@ #include #include #include -#include -#include using std::cout; using std::endl; -using std::vector; using namespace o2; using namespace o2::framework; //using namespace o2::framework::expressions; using namespace o2::aod; -struct TableReader { - +// Some definitions +namespace o2::aod +{ +namespace reducedtrack +{ +DECLARE_SOA_COLUMN(IsBarrelSelected, isBarrelSelected, int); +DECLARE_SOA_COLUMN(IsMuonSelected, isMuonSelected, int); +} // namespace reducedtrack +namespace reducedpair +{ +DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Charge, charge, int); +DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return pt * std::sin(phi); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pmom, pmom, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); +} // namespace reducedpair + +DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "BARRELTRACKCUTS", reducedtrack::IsBarrelSelected); +DECLARE_SOA_TABLE(MuonTrackCuts, "AOD", "MUONTRACKCUTS", reducedtrack::IsMuonSelected); +DECLARE_SOA_TABLE(Dileptons, "AOD", "DILEPTON", reducedtrack::ReducedEventId, reducedpair::Mass, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Charge, + reducedpair::Px, reducedpair::Py, + reducedpair::Pz, reducedpair::Pmom); +using Dilepton = Dileptons::iterator; +} // namespace o2::aod + +using MyEvent = soa::Join::iterator; +using MyEventVtxCov = soa::Join::iterator; +using MyBarrelTracks = soa::Join; +using MyBarrelTracksSelected = soa::Join; +using MyMuonTracks = soa::Join; +using MyMuonTracksSelected = soa::Join; + +void DefineHistograms(o2::framework::OutputObj histMan, TString histClasses); + +// HACK: In order to be able to deduce which kind of aod object is transmitted to the templated VarManager::Fill functions +// a constexpr static bit map must be defined and sent as template argument +// The user has to include in this bit map all the tables needed in analysis, as defined in VarManager::ObjTypes +// Additionally, one should make sure that the requested tables are actually provided in the process() function, +// otherwise a compile time error will be thrown. +// This is a temporary fix until the arrow/ROOT issues are solved, at which point it will be possible +// to automatically detect the object types transmitted to the VarManager +constexpr static uint32_t fgEventFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; +constexpr static uint32_t fgTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID; +constexpr static uint32_t fgMuonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackMuon; + +struct BarrelTrackSelection { + Produces trackSel; OutputObj fHistMan{"output"}; - AnalysisCompositeCut* fEventCut; AnalysisCompositeCut* fTrackCut; - AnalysisCompositeCut* fMuonCut; - - // HACK: In order to be able to deduce which kind of aod object is transmitted to the templated VarManager::Fill functions - // a constexpr static bit map must be defined and sent as template argument - // The user has to include in this bit map all the tables needed in analysis, as defined in VarManager::ObjTypes - // Additionally, one should make sure that the requested tables are actually provided in the process() function, - // otherwise a compile time error will be thrown. - // This is a temporary fix until the arrow/ROOT issues are solved, at which point it will be possible - // to automatically detect the object types transmitted to the VarManager - constexpr static uint32_t fgEventFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov; - constexpr static uint32_t fgEventMuonFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; - constexpr static uint32_t fgTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID; - constexpr static uint32_t fgMuonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackMuon; + + float* fValues; // array to be used by the VarManager void init(o2::framework::InitContext&) { + fValues = new float[VarManager::kNVars]; VarManager::SetDefaultVarNames(); fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); - fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); - DefineHistograms("Event_BeforeCuts;Event_AfterCuts;TrackBarrel_BeforeCuts;TrackBarrel_AfterCuts;TrackMuon_BeforeCuts;TrackMuon_AfterCuts;PairsBarrel;PairsMuon;"); // define all histograms + DefineHistograms(fHistMan, "TrackBarrel_BeforeCuts;TrackBarrel_AfterCuts;"); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill DefineCuts(); @@ -70,21 +106,9 @@ struct TableReader { void DefineCuts() { - fEventCut = new AnalysisCompositeCut(true); - - AnalysisCut* varCut = new AnalysisCut(); - varCut->AddCut(VarManager::kVtxZ, -10.0, 10.0); - - TF1* cutLow = new TF1("cutLow", "pol1", 0., 0.1); - cutLow->SetParameters(0.2635, 1.0); - //varCut->AddCut(VarManager::kVtxY, cutLow, 0.335, false, VarManager::kVtxX, 0.067, 0.070); - - //varCut->AddCut(VarManager::kVtxY, 0.0, 0.335); - fEventCut->AddCut(varCut); - fTrackCut = new AnalysisCompositeCut(true); // true: use AND AnalysisCut* cut1 = new AnalysisCut(); - cut1->AddCut(VarManager::kPt, 0.15, 20.0); + cut1->AddCut(VarManager::kPt, 1.5, 20.0); cut1->AddCut(VarManager::kEta, -0.9, 0.9); cut1->AddCut(VarManager::kTPCchi2, 0.0, 4.0); cut1->AddCut(VarManager::kITSchi2, 0.0, 36.0); @@ -95,21 +119,128 @@ struct TableReader { fTrackCut->AddCut(cut1); //fTrackCut->AddCut(cut2); - fMuonCut = new AnalysisCompositeCut(true); + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEvent event, MyBarrelTracks const& tracks) + { + for (int i = 0; i < VarManager::kNVars; ++i) + fValues[i] = -9999.0f; + // fill event information which might be needed in histograms that combine track and event properties + VarManager::FillEvent(event, fValues); + + for (auto& track : tracks) { + for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) + fValues[i] = -9999.0f; + VarManager::FillTrack(track, fValues); + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", fValues); + + if (fTrackCut->IsSelected(fValues)) { + trackSel(1); + fHistMan->FillHistClass("TrackBarrel_AfterCuts", fValues); + } else + trackSel(0); + } + } +}; + +struct MuonTrackSelection { + Produces trackSel; + OutputObj fHistMan{"output"}; + AnalysisCompositeCut* fTrackCut; + + float* fValues; + + void init(o2::framework::InitContext&) + { + fValues = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + DefineHistograms(fHistMan, "TrackMuon_BeforeCuts;TrackMuon_AfterCuts;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + + DefineCuts(); + } + + void DefineCuts() + { + fTrackCut = new AnalysisCompositeCut(true); AnalysisCut kineMuonCut; kineMuonCut.AddCut(VarManager::kPt, 1.5, 10.0); - fMuonCut->AddCut(&kineMuonCut); + fTrackCut->AddCut(&kineMuonCut); + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEvent event, MyMuonTracks const& muons) + { + for (int i = 0; i < VarManager::kNVars; ++i) + fValues[i] = -9999.0f; + VarManager::FillEvent(event, fValues); + + for (auto& muon : muons) { + for (int i = VarManager::kNBarrelTrackVariables; i < VarManager::kNMuonTrackVariables; ++i) + fValues[i] = -9999.0f; + VarManager::FillTrack(muon, fValues); + fHistMan->FillHistClass("TrackMuon_BeforeCuts", fValues); + + if (fTrackCut->IsSelected(fValues)) { + trackSel(1); + fHistMan->FillHistClass("TrackMuon_AfterCuts", fValues); + } else + trackSel(0); + } + } +}; + +struct TableReader { + Produces dileptonList; + OutputObj fHistMan{"output"}; + AnalysisCompositeCut* fEventCut; + //NOTE: one could define also a dilepton cut, but for now basic selections can be supported using Partition + + Partition posTracks = aod::reducedtrack::charge > 0 && aod::reducedtrack::isBarrelSelected == 1; + Partition negTracks = aod::reducedtrack::charge < 0 && aod::reducedtrack::isBarrelSelected == 1; + Partition posMuons = aod::reducedtrack::charge > 0 && aod::reducedtrack::isMuonSelected == 1; + Partition negMuons = aod::reducedtrack::charge < 0 && aod::reducedtrack::isMuonSelected == 1; + + void init(o2::framework::InitContext&) + { + VarManager::SetDefaultVarNames(); + fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;PairsBarrelPM;PairsBarrelPP;PairsBarrelMM;PairsMuon;"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + + DefineCuts(); + } + + void DefineCuts() + { + fEventCut = new AnalysisCompositeCut(true); + + AnalysisCut* varCut = new AnalysisCut(); + varCut->AddCut(VarManager::kVtxZ, -10.0, 10.0); + + TF1* cutLow = new TF1("cutLow", "pol1", 0., 0.1); + cutLow->SetParameters(0.2635, 1.0); + //varCut->AddCut(VarManager::kVtxY, cutLow, 0.335, false, VarManager::kVtxX, 0.067, 0.070); + + //varCut->AddCut(VarManager::kVtxY, 0.0, 0.335); + fEventCut->AddCut(varCut); VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill } - void process(soa::Join::iterator event, - soa::Join const& tracks, - soa::Join const& muons) + void process(MyEventVtxCov event, MyBarrelTracksSelected const& tracks, MyMuonTracksSelected const& muons) { - // Reset the fgValues array - // TODO: reseting will have to be done selectively, for example run-wise variables don't need to be reset every event, but just updated if the run changes - // The reset can be done selectively, using arguments in the ResetValues() function + // Reset the VarManager::fgValues array + // The reset can be done selectively, using arguments in the ResetValues() function VarManager::ResetValues(); VarManager::FillEvent(event); @@ -118,173 +249,271 @@ struct TableReader { return; fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); - // loop over barrel tracks and store positive and negative tracks in separate arrays - // TODO: use Partition initiaslized by vector of track indices when this will be available - std::vector::iterator> selectedTracksPos; - std::vector::iterator> selectedTracksNeg; - for (auto& track : tracks) { - - VarManager::ResetValues(VarManager::kNEventWiseVariables, VarManager::kNMuonTrackVariables); - - VarManager::FillTrack(track); - fHistMan->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); - if (!fTrackCut->IsSelected(VarManager::fgValues)) - continue; - fHistMan->FillHistClass("TrackBarrel_AfterCuts", VarManager::fgValues); - - if (track.charge() < 0) - selectedTracksNeg.push_back(track); - if (track.charge() > 0) - selectedTracksPos.push_back(track); + // Run the same event pairing for barrel tracks + // TODO: Use combinations() when this will work for Partitions + /* e.g. + * for (auto& [tpos, tneg] : combinations(posTracks, negTracks)) { + VarManager::FillPair(tpos, tneg); + fHistMan->FillHistClass("PairsBarrelPM", VarManager::fgValues); } + */ - // run the same event pairing for barrel tracks - for (auto& tpos : selectedTracksPos) { - for (auto& tneg : selectedTracksNeg) { + for (auto tpos : posTracks) { + for (auto tneg : negTracks) { // +- pairs VarManager::FillPair(tpos, tneg); - fHistMan->FillHistClass("PairsBarrel", VarManager::fgValues); + dileptonList(event, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], 0); + fHistMan->FillHistClass("PairsBarrelPM", VarManager::fgValues); + } + for (auto tpos2 = tpos + 1; tpos2 != posTracks.end(); ++tpos2) { // ++ pairs + VarManager::FillPair(tpos, tpos2); + dileptonList(event, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], 2); + fHistMan->FillHistClass("PairsBarrelPP", VarManager::fgValues); } } - - // loop over muon tracks - std::vector::iterator> selectedMuonsPos; - std::vector::iterator> selectedMuonsNeg; - for (auto& muon : muons) { - VarManager::FillTrack(muon); - fHistMan->FillHistClass("TrackMuon_BeforeCuts", VarManager::fgValues); - if (!fMuonCut->IsSelected(VarManager::fgValues)) - continue; - fHistMan->FillHistClass("TrackMuon_AfterCuts", VarManager::fgValues); - - if (muon.charge() < 0) - selectedMuonsNeg.push_back(muon); - if (muon.charge() > 0) - selectedMuonsPos.push_back(muon); + for (auto tneg : negTracks) { // -- pairs + for (auto tneg2 = tneg + 1; tneg2 != negTracks.end(); ++tneg2) { + VarManager::FillPair(tneg, tneg2); + dileptonList(event, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], -2); + fHistMan->FillHistClass("PairsBarrelMM", VarManager::fgValues); + } } // same event pairing for muons - for (auto& tpos : selectedMuonsNeg) { - for (auto& tneg : selectedMuonsPos) { + for (auto& tpos : posMuons) { + for (auto& tneg : negMuons) { + //dileptonList(event, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], 1); VarManager::FillPair(tpos, tneg); fHistMan->FillHistClass("PairsMuon", VarManager::fgValues); } } } +}; + +struct DileptonHadronAnalysis { + // + // This task combines dilepton candidates with a track and could be used for example + // in analyses with the dilepton as one of the decay products of a higher mass resonance (e.g. B0 -> Jpsi + K) + // or in dilepton + hadron correlations, etc. + // It requires the TableReader task to be in the workflow and produce the dilepton table + // + OutputObj fHistMan{"output"}; + AnalysisCompositeCut* fHadronCut; + //NOTE: no cut has been included for dileptons because that can be controlled via the TableReader task and the partition below + + // use two values array to avoid mixing up the quantities + float* fValuesDilepton; + float* fValuesHadron; + + Partition selDileptons = aod::reducedpair::charge == 0 && aod::reducedpair::mass > 2.92f && aod::reducedpair::mass<3.16f && aod::reducedpair::pt> 5.0f; + + constexpr static uint32_t fgDileptonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::Pair; + + void init(o2::framework::InitContext&) + { + fValuesDilepton = new float[VarManager::kNVars]; + fValuesHadron = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan.setObject(new HistogramManager("analysisHistos", "aa", VarManager::kNVars)); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + DefineHistograms(fHistMan, "DileptonsSelected;HadronsSelected;DileptonHadronInvMass;DileptonHadronCorrelation"); // define all histograms + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + + DefineCuts(); + } - void DefineHistograms(TString histClasses) + void DefineCuts() { - const int kNRuns = 2; - int runs[kNRuns] = {244918, 244919}; - TString runsStr; - for (int i = 0; i < kNRuns; i++) - runsStr += Form("%d;", runs[i]); - VarManager::SetRunNumbers(kNRuns, runs); - - TObjArray* arr = histClasses.Tokenize(";"); - for (Int_t iclass = 0; iclass < arr->GetEntries(); ++iclass) { - TString classStr = arr->At(iclass)->GetName(); - - if (classStr.Contains("Event")) { - fHistMan->AddHistClass(classStr.Data()); - fHistMan->AddHistogram(classStr.Data(), "VtxZ", "Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ); // TH1F histogram - fHistMan->AddHistogram(classStr.Data(), "VtxZ_Run", "Vtx Z", true, - kNRuns, 0.5, 0.5 + kNRuns, VarManager::kRunId, 60, -15.0, 15.0, VarManager::kVtxZ, 10, 0., 0., VarManager::kNothing, runsStr.Data()); // TH1F histogram - fHistMan->AddHistogram(classStr.Data(), "VtxX_VtxY", "Vtx X vs Vtx Y", false, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "VtxX_VtxY_VtxZ", "vtx x - y - z", false, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 60, -15.0, 15.0, VarManager::kVtxZ); // TH3F histogram - fHistMan->AddHistogram(classStr.Data(), "NContrib_vs_VtxZ_prof", "Vtx Z vs ncontrib", true, 30, -15.0, 15.0, VarManager::kVtxZ, 10, -1., 1., VarManager::kVtxNcontrib); // TProfile histogram - fHistMan->AddHistogram(classStr.Data(), "VtxZ_vs_VtxX_VtxY_prof", "Vtx Z vs (x,y)", true, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 10, -1., 1., VarManager::kVtxZ); // TProfile2D histogram - fHistMan->AddHistogram(classStr.Data(), "Ncontrib_vs_VtxZ_VtxX_VtxY_prof", "n-contrib vs (x,y,z)", true, - 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 30, -15., 15., VarManager::kVtxZ, - "", "", "", VarManager::kVtxNcontrib); // TProfile3D - - double vtxXbinLims[10] = {0.055, 0.06, 0.062, 0.064, 0.066, 0.068, 0.070, 0.072, 0.074, 0.08}; - double vtxYbinLims[7] = {0.31, 0.32, 0.325, 0.33, 0.335, 0.34, 0.35}; - double vtxZbinLims[13] = {-15.0, -10.0, -8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 15.0}; - double nContribbinLims[9] = {0.0, 100.0, 200.0, 400.0, 600.0, 1000.0, 1500.0, 2000.0, 4000.0}; - - fHistMan->AddHistogram(classStr.Data(), "VtxX_VtxY_nonEqualBinning", "Vtx X vs Vtx Y", false, 9, vtxXbinLims, VarManager::kVtxX, 6, vtxYbinLims, VarManager::kVtxY); // THnF histogram with custom non-equal binning - - fHistMan->AddHistogram(classStr.Data(), "VtxZ_weights", "Vtx Z", false, - 60, -15.0, 15.0, VarManager::kVtxZ, 10, 0., 0., VarManager::kNothing, 10, 0., 0., VarManager::kNothing, - "", "", "", VarManager::kNothing, VarManager::kVtxNcontrib); // TH1F histogram, filled with weights using the vtx n-contributors - - Int_t vars[4] = {VarManager::kVtxX, VarManager::kVtxY, VarManager::kVtxZ, VarManager::kVtxNcontrib}; - TArrayD binLimits[4]; - binLimits[0] = TArrayD(10, vtxXbinLims); - binLimits[1] = TArrayD(7, vtxYbinLims); - binLimits[2] = TArrayD(13, vtxZbinLims); - binLimits[3] = TArrayD(9, nContribbinLims); - fHistMan->AddHistogram(classStr.Data(), "vtxHisto", "n contrib vs (x,y,z)", 4, vars, binLimits); - - fHistMan->AddHistogram(classStr.Data(), "CentV0M_vtxZ", "CentV0M vs Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ, 20, 0., 100., VarManager::kCentVZERO); // TH2F histogram - - fHistMan->AddHistogram(classStr.Data(), "VtxChi2", "Vtx chi2", false, 100, 0.0, 100.0, VarManager::kVtxChi2); // TH1F histogram + fHadronCut = new AnalysisCompositeCut(true); // true: use AND + AnalysisCut* cut1 = new AnalysisCut(); + cut1->AddCut(VarManager::kPt, 4.0, 20.0); + cut1->AddCut(VarManager::kEta, -0.9, 0.9); + cut1->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut1->AddCut(VarManager::kITSchi2, 0.0, 36.0); + cut1->AddCut(VarManager::kITSncls, 2.5, 7.5); + cut1->AddCut(VarManager::kTPCncls, 69.5, 159.5); + fHadronCut->AddCut(cut1); + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void process(MyEvent event, MyBarrelTracks const& hadrons, aod::Dileptons const& dileptons) + { + for (int i = 0; i < VarManager::kNVars; ++i) + fValuesHadron[i] = -9999.0f; + // fill event information which might be needed in histograms that combine track/pair and event properties + VarManager::FillEvent(event, fValuesHadron); + + // loop once over dileptons for QA purposes + for (auto dilepton : selDileptons) { + for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) + fValuesDilepton[i] = -9999.0f; + VarManager::FillTrack(dilepton, fValuesDilepton); + fHistMan->FillHistClass("DileptonsSelected", fValuesDilepton); + } + + // loop over hadrons + for (auto& hadron : hadrons) { + for (int i = VarManager::kNEventWiseVariables; i < VarManager::kNMuonTrackVariables; ++i) + fValuesHadron[i] = -9999.0f; + VarManager::FillTrack(hadron, fValuesHadron); + if (!fHadronCut->IsSelected(fValuesHadron)) continue; - } // end if(Event) - - if (classStr.Contains("Track")) { - fHistMan->AddHistClass(classStr.Data()); - fHistMan->AddHistogram(classStr.Data(), "Pt", "p_{T} distribution", false, 200, 0.0, 20.0, VarManager::kPt); // TH1F histogram - fHistMan->AddHistogram(classStr.Data(), "Eta", "#eta distribution", false, 500, -5.0, 5.0, VarManager::kEta); // TH1F histogram - fHistMan->AddHistogram(classStr.Data(), "Phi_Eta", "#phi vs #eta distribution", false, 200, -5.0, 5.0, VarManager::kEta, 200, -6.3, 6.3, VarManager::kPhi); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "P", "p distribution", false, 200, 0.0, 20.0, VarManager::kP); // TH1F histogram - fHistMan->AddHistogram(classStr.Data(), "Px", "p_{x} distribution", false, 200, 0.0, 20.0, VarManager::kPx); - fHistMan->AddHistogram(classStr.Data(), "Py", "p_{y} distribution", false, 200, 0.0, 20.0, VarManager::kPy); - fHistMan->AddHistogram(classStr.Data(), "Pz", "p_{z} distribution", false, 400, -20.0, 20.0, VarManager::kPz); - - if (classStr.Contains("Barrel")) { - - fHistMan->AddHistogram(classStr.Data(), "TPCncls", "Number of cluster in TPC", false, 160, -0.5, 159.5, VarManager::kTPCncls); // TH1F histogram - fHistMan->AddHistogram(classStr.Data(), "ITSncls", "Number of cluster in ITS", false, 8, -0.5, 7.5, VarManager::kITSncls); // TH1F histogram - - //for TPC PID - fHistMan->AddHistogram(classStr.Data(), "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, 0.0, 200., VarManager::kTPCsignal); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TPCnSigmaEl_pIN", "TPC dE/dx n#sigma_{e} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaEl); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TPCnSigmaEl_Eta", "TPC dE/dx n#sigma_{e} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaEl); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TPCnSigmaPi_pIN", "TPC dE/dx n#sigma_{#pi} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaPi); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TPCnSigmaPi_Eta", "TPC dE/dx n#sigma_{#pi} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaPi); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TPCnSigmaKa_pIN", "TPC dE/dx n#sigma_{K} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaKa); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TPCnSigmaKa_Eta", "TPC dE/dx n#sigma_{K} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaKa); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TPCnSigmaPr_pIN", "TPC dE/dx n#sigma_{p} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaPr); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TPCnSigmaPr_Eta", "TPC dE/dx n#sigma_{p} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaPr); // TH2F histogram - - //for TOF PID - fHistMan->AddHistogram(classStr.Data(), "TOFbeta_pIN", "TOF #beta vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 120, 0.0, 1.2, VarManager::kTOFbeta); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TOFnSigmaEl_pIN", "TOF #beta n#sigma_{e} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaEl); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TOFnSigmaEl_Eta", "TOF #beta n#sigma_{e} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaEl); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TOFnSigmaPi_pIN", "TOF #beta n#sigma_{#pi} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaPi); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TOFnSigmaPi_Eta", "TOF #beta n#sigma_{#pi} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaPi); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TOFnSigmaKa_pIN", "TOF #beta n#sigma_{K} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaKa); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TOFnSigmaKa_Eta", "TOF #beta n#sigma_{K} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaKa); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TOFnSigmaPr_pIN", "TOF #beta n#sigma_{p} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaPr); // TH2F histogram - fHistMan->AddHistogram(classStr.Data(), "TOFnSigmaPr_Eta", "TOF #beta n#sigma_{p} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaPr); // TH2F histogram - - fHistMan->AddHistogram(classStr.Data(), "Cov1Pt_Pt", "cov(1/pt,1/pt) vs p_{T} distribution", false, 20, 0.0, 5.0, VarManager::kPt, 100, 0.0, 1.0, VarManager::kTrackC1Pt21Pt2); // TH2F histogram - } - - if (classStr.Contains("Muon")) { - fHistMan->AddHistogram(classStr.Data(), "InvBendingMom", "", false, 100, 0.0, 1.0, VarManager::kMuonInvBendingMomentum); - fHistMan->AddHistogram(classStr.Data(), "ThetaX", "", false, 100, -1.0, 1.0, VarManager::kMuonThetaX); - fHistMan->AddHistogram(classStr.Data(), "ThetaY", "", false, 100, -2.0, 2.0, VarManager::kMuonThetaY); - fHistMan->AddHistogram(classStr.Data(), "ZMu", "", false, 100, -30.0, 30.0, VarManager::kMuonZMu); - fHistMan->AddHistogram(classStr.Data(), "BendingCoor", "", false, 100, 0.32, 0.35, VarManager::kMuonBendingCoor); - fHistMan->AddHistogram(classStr.Data(), "NonBendingCoor", "", false, 100, 0.065, 0.07, VarManager::kMuonNonBendingCoor); - fHistMan->AddHistogram(classStr.Data(), "Chi2", "", false, 100, 0.0, 200.0, VarManager::kMuonChi2); - fHistMan->AddHistogram(classStr.Data(), "Chi2MatchTrigger", "", false, 100, 0.0, 20.0, VarManager::kMuonChi2MatchTrigger); - } - } - if (classStr.Contains("Pairs")) { - fHistMan->AddHistClass(classStr.Data()); - fHistMan->AddHistogram(classStr.Data(), "Mass", "", false, 100, 0.0, 5.0, VarManager::kMass); + fHistMan->FillHistClass("HadronsSelected", fValuesHadron); + + for (auto dilepton : selDileptons) { + // TODO: At the moment there is no check on whether this hadron is one of the dilepton daughters + VarManager::FillDileptonHadron(dilepton, hadron, fValuesHadron); + fHistMan->FillHistClass("DileptonHadronInvMass", fValuesHadron); + fHistMan->FillHistClass("DileptonHadronCorrelation", fValuesHadron); } - } // end loop over histogram classes + } } }; WorkflowSpec defineDataProcessing(ConfigContext const&) { return WorkflowSpec{ - adaptAnalysisTask("table-reader")}; + adaptAnalysisTask("barrel-track-selection"), + adaptAnalysisTask("muon-track-selection"), + adaptAnalysisTask("table-reader"), + adaptAnalysisTask("dilepton-hadron")}; +} + +void DefineHistograms(o2::framework::OutputObj histMan, TString histClasses) +{ + // + // Define here the histograms for all the classes required in analysis. + // The histogram classes are provided in the histClasses string, separated by semicolon ";" + // The histogram classes and their components histograms are defined below depending on the name of the histogram class + // + const int kNRuns = 2; + int runs[kNRuns] = {244918, 244919}; + TString runsStr; + for (int i = 0; i < kNRuns; i++) + runsStr += Form("%d;", runs[i]); + VarManager::SetRunNumbers(kNRuns, runs); + + TObjArray* arr = histClasses.Tokenize(";"); + for (Int_t iclass = 0; iclass < arr->GetEntries(); ++iclass) { + TString classStr = arr->At(iclass)->GetName(); + + if (classStr.Contains("Event")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "VtxZ", "Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "VtxZ_Run", "Vtx Z", true, + kNRuns, 0.5, 0.5 + kNRuns, VarManager::kRunId, 60, -15.0, 15.0, VarManager::kVtxZ, 10, 0., 0., VarManager::kNothing, runsStr.Data()); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "VtxX_VtxY", "Vtx X vs Vtx Y", false, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "VtxX_VtxY_VtxZ", "vtx x - y - z", false, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 60, -15.0, 15.0, VarManager::kVtxZ); // TH3F histogram + histMan->AddHistogram(classStr.Data(), "NContrib_vs_VtxZ_prof", "Vtx Z vs ncontrib", true, 30, -15.0, 15.0, VarManager::kVtxZ, 10, -1., 1., VarManager::kVtxNcontrib); // TProfile histogram + histMan->AddHistogram(classStr.Data(), "VtxZ_vs_VtxX_VtxY_prof", "Vtx Z vs (x,y)", true, 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 10, -1., 1., VarManager::kVtxZ); // TProfile2D histogram + histMan->AddHistogram(classStr.Data(), "Ncontrib_vs_VtxZ_VtxX_VtxY_prof", "n-contrib vs (x,y,z)", true, + 100, 0.055, 0.08, VarManager::kVtxX, 100, 0.31, 0.35, VarManager::kVtxY, 30, -15., 15., VarManager::kVtxZ, + "", "", "", VarManager::kVtxNcontrib); // TProfile3D + + double vtxXbinLims[10] = {0.055, 0.06, 0.062, 0.064, 0.066, 0.068, 0.070, 0.072, 0.074, 0.08}; + double vtxYbinLims[7] = {0.31, 0.32, 0.325, 0.33, 0.335, 0.34, 0.35}; + double vtxZbinLims[13] = {-15.0, -10.0, -8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 15.0}; + double nContribbinLims[9] = {0.0, 100.0, 200.0, 400.0, 600.0, 1000.0, 1500.0, 2000.0, 4000.0}; + + histMan->AddHistogram(classStr.Data(), "VtxX_VtxY_nonEqualBinning", "Vtx X vs Vtx Y", false, 9, vtxXbinLims, VarManager::kVtxX, 6, vtxYbinLims, VarManager::kVtxY); // THnF histogram with custom non-equal binning + + histMan->AddHistogram(classStr.Data(), "VtxZ_weights", "Vtx Z", false, + 60, -15.0, 15.0, VarManager::kVtxZ, 10, 0., 0., VarManager::kNothing, 10, 0., 0., VarManager::kNothing, + "", "", "", VarManager::kNothing, VarManager::kVtxNcontrib); // TH1F histogram, filled with weights using the vtx n-contributors + + Int_t vars[4] = {VarManager::kVtxX, VarManager::kVtxY, VarManager::kVtxZ, VarManager::kVtxNcontrib}; + TArrayD binLimits[4]; + binLimits[0] = TArrayD(10, vtxXbinLims); + binLimits[1] = TArrayD(7, vtxYbinLims); + binLimits[2] = TArrayD(13, vtxZbinLims); + binLimits[3] = TArrayD(9, nContribbinLims); + histMan->AddHistogram(classStr.Data(), "vtxHisto", "n contrib vs (x,y,z)", 4, vars, binLimits); + + histMan->AddHistogram(classStr.Data(), "CentV0M_vtxZ", "CentV0M vs Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ, 20, 0., 100., VarManager::kCentVZERO); // TH2F histogram + + histMan->AddHistogram(classStr.Data(), "VtxChi2", "Vtx chi2", false, 100, 0.0, 100.0, VarManager::kVtxChi2); // TH1F histogram + + continue; + } // end if(Event) + + if (classStr.Contains("Track")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "Pt", "p_{T} distribution", false, 200, 0.0, 20.0, VarManager::kPt); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "Eta", "#eta distribution", false, 500, -5.0, 5.0, VarManager::kEta); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "Phi_Eta", "#phi vs #eta distribution", false, 200, -5.0, 5.0, VarManager::kEta, 200, -6.3, 6.3, VarManager::kPhi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "P", "p distribution", false, 200, 0.0, 20.0, VarManager::kP); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "Px", "p_{x} distribution", false, 200, 0.0, 20.0, VarManager::kPx); + histMan->AddHistogram(classStr.Data(), "Py", "p_{y} distribution", false, 200, 0.0, 20.0, VarManager::kPy); + histMan->AddHistogram(classStr.Data(), "Pz", "p_{z} distribution", false, 400, -20.0, 20.0, VarManager::kPz); + + if (classStr.Contains("Barrel")) { + histMan->AddHistogram(classStr.Data(), "TPCncls", "Number of cluster in TPC", false, 160, -0.5, 159.5, VarManager::kTPCncls); // TH1F histogram + histMan->AddHistogram(classStr.Data(), "ITSncls", "Number of cluster in ITS", false, 8, -0.5, 7.5, VarManager::kITSncls); // TH1F histogram + //for TPC PID + histMan->AddHistogram(classStr.Data(), "TPCdedx_pIN", "TPC dE/dx vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, 0.0, 200., VarManager::kTPCsignal); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaEl_pIN", "TPC dE/dx n#sigma_{e} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaEl); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaEl_Eta", "TPC dE/dx n#sigma_{e} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaEl); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaPi_pIN", "TPC dE/dx n#sigma_{#pi} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaPi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaPi_Eta", "TPC dE/dx n#sigma_{#pi} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaPi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaKa_pIN", "TPC dE/dx n#sigma_{K} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaKa); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaKa_Eta", "TPC dE/dx n#sigma_{K} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaKa); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaPr_pIN", "TPC dE/dx n#sigma_{p} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTPCnSigmaPr); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TPCnSigmaPr_Eta", "TPC dE/dx n#sigma_{p} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTPCnSigmaPr); // TH2F histogram + + //for TOF PID + histMan->AddHistogram(classStr.Data(), "TOFbeta_pIN", "TOF #beta vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 120, 0.0, 1.2, VarManager::kTOFbeta); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaEl_pIN", "TOF #beta n#sigma_{e} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaEl); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaEl_Eta", "TOF #beta n#sigma_{e} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaEl); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaPi_pIN", "TOF #beta n#sigma_{#pi} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaPi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaPi_Eta", "TOF #beta n#sigma_{#pi} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaPi); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaKa_pIN", "TOF #beta n#sigma_{K} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaKa); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaKa_Eta", "TOF #beta n#sigma_{K} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaKa); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaPr_pIN", "TOF #beta n#sigma_{p} vs pIN", false, 200, 0.0, 20.0, VarManager::kPin, 200, -10, +10, VarManager::kTOFnSigmaPr); // TH2F histogram + histMan->AddHistogram(classStr.Data(), "TOFnSigmaPr_Eta", "TOF #beta n#sigma_{p} vs #eta", false, 20, -1, +1, VarManager::kEta, 200, -10, +10, VarManager::kTOFnSigmaPr); // TH2F histogram + + histMan->AddHistogram(classStr.Data(), "Cov1Pt_Pt", "cov(1/pt,1/pt) vs p_{T} distribution", false, 20, 0.0, 5.0, VarManager::kPt, 100, 0.0, 1.0, VarManager::kTrackC1Pt21Pt2); // TH2F histogram + } + + if (classStr.Contains("Muon")) { + histMan->AddHistogram(classStr.Data(), "InvBendingMom", "", false, 100, 0.0, 1.0, VarManager::kMuonInvBendingMomentum); + histMan->AddHistogram(classStr.Data(), "ThetaX", "", false, 100, -1.0, 1.0, VarManager::kMuonThetaX); + histMan->AddHistogram(classStr.Data(), "ThetaY", "", false, 100, -2.0, 2.0, VarManager::kMuonThetaY); + histMan->AddHistogram(classStr.Data(), "ZMu", "", false, 100, -30.0, 30.0, VarManager::kMuonZMu); + histMan->AddHistogram(classStr.Data(), "BendingCoor", "", false, 100, 0.32, 0.35, VarManager::kMuonBendingCoor); + histMan->AddHistogram(classStr.Data(), "NonBendingCoor", "", false, 100, 0.065, 0.07, VarManager::kMuonNonBendingCoor); + histMan->AddHistogram(classStr.Data(), "Chi2", "", false, 100, 0.0, 200.0, VarManager::kMuonChi2); + histMan->AddHistogram(classStr.Data(), "Chi2MatchTrigger", "", false, 100, 0.0, 20.0, VarManager::kMuonChi2MatchTrigger); + } + } + + if (classStr.Contains("DileptonsSelected")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "Mass_Pt", "", false, 100, 0.0, 5.0, VarManager::kMass, 100, 0.0, 20.0, VarManager::kPt); + } + + if (classStr.Contains("HadronsSelected")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "Eta_Pt", "", false, 20, -1.0, 1.0, VarManager::kEta, 100, 0.0, 20.0, VarManager::kPt); + histMan->AddHistogram(classStr.Data(), "Eta_Phi", "", false, 20, -1.0, 1.0, VarManager::kEta, 100, -8.0, 8.0, VarManager::kPhi); + } + + if (classStr.Contains("Pairs")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "Mass_Pt", "", false, 100, 0.0, 5.0, VarManager::kMass, 100, 0.0, 20.0, VarManager::kPt); + } + + if (classStr.Contains("DileptonHadronInvMass")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "Mass_Pt", "", false, 40, 0.0, 20.0, VarManager::kPairMass, 40, 0.0, 20.0, VarManager::kPairPt); + } + + if (classStr.Contains("DileptonHadronCorrelation")) { + histMan->AddHistClass(classStr.Data()); + histMan->AddHistogram(classStr.Data(), "DeltaEta_DeltaPhi", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -8.0, 8.0, VarManager::kDeltaPhi); + histMan->AddHistogram(classStr.Data(), "DeltaEta_DeltaPhiSym", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -8.0, 8.0, VarManager::kDeltaPhiSym); + } + } // end loop over histogram classes } diff --git a/Analysis/Tasks/PWGHF/CMakeLists.txt b/Analysis/Tasks/PWGHF/CMakeLists.txt index 862040fb645c3..1c0a8e222c81a 100644 --- a/Analysis/Tasks/PWGHF/CMakeLists.txt +++ b/Analysis/Tasks/PWGHF/CMakeLists.txt @@ -18,6 +18,11 @@ o2_add_dpl_workflow(hf-candidate-creator-2prong PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing ROOT::EG COMPONENT_NAME Analysis) +o2_add_dpl_workflow(hf-d0-candidate-selector + SOURCES HFD0CandidateSelector.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(hf-task-d0 SOURCES taskD0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::DetectorsVertexing diff --git a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx index 88c95eac5fd2a..a8116701e9902 100644 --- a/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx +++ b/Analysis/Tasks/PWGHF/HFCandidateCreator2Prong.cxx @@ -20,6 +20,11 @@ #include "Analysis/SecondaryVertexHF.h" #include "Analysis/trackUtilities.h" #include "ReconstructionDataFormats/DCA.h" +#include "Analysis/RecoDecay.h" +#include "PID/PIDResponse.h" +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -48,7 +53,7 @@ struct HFCandidateCreator2Prong { void process(aod::Collision const& collision, aod::HfTrackIndexProng2 const& rowsTrackIndexProng2, - soa::Join const& tracks) + aod::BigTracks const& tracks) { // 2-prong vertex fitter o2::vertexing::DCAFitterN<2> df; @@ -109,7 +114,8 @@ struct HFCandidateCreator2Prong { pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2], impactParameter0.getY(), impactParameter1.getY(), - std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2())); + std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2()), + rowTrackIndexProng2.index0Id(), rowTrackIndexProng2.index1Id()); // fill histograms if (b_dovalplots) { diff --git a/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx new file mode 100644 index 0000000000000..8061d4538fe78 --- /dev/null +++ b/Analysis/Tasks/PWGHF/HFD0CandidateSelector.cxx @@ -0,0 +1,412 @@ +// 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 HFD0CandidateSelector.cxx +/// \brief D0 selection task. +/// +/// \author Nima Zardoshti , CERN + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Analysis/SecondaryVertexHF.h" +#include "Analysis/CandidateSelectionTables.h" +#include "Analysis/RecoDecay.h" +#include "PID/PIDResponse.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::hf_cand_prong2; +using std::array; + +static const int npTBins = 25; +static const int nCutVars = 11; +//temporary until 2D array in configurable is solved - then move to json +//m dca cost* ptk ptpi d0k d0pi d0d0 cosp cosxy normdxy +constexpr double cuts[npTBins][nCutVars] = {{0.400, 350. * 1E-4, 0.8, 0.5, 0.5, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.80, 0., 0.}, /* pt<0.5*/ + {0.400, 350. * 1E-4, 0.8, 0.5, 0.5, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.80, 0., 0.}, /* 0.550 */ + +/// Struct for applying D0 selection cuts + +struct HFD0CandidateSelector { + + Produces hfSelD0Candidate; + + Configurable d_pTCandMin{"d_pTCandMin", 0.0, "Lower bound of candidate pT"}; + Configurable d_pTCandMax{"d_pTCandMax", 50.0, "Upper bound of candidate pT"}; + + Configurable d_pidTPCMinpT{"d_pidTPCMinpT", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable d_pidTPCMaxpT{"d_pidTPCMaxpT", 5.0, "Upper bound of track pT for TPC PID"}; + Configurable d_pidTOFMinpT{"d_pidTOFMinpT", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable d_pidTOFMaxpT{"d_pidTOFMaxpT", 5.0, "Upper bound of track pT for TOF PID"}; + + Configurable d_TPCNClsFindablePIDCut{"d_TPCNClsFindablePIDCut", 50.0, "Lower bound of TPC findable clusters for good PID"}; + Configurable d_nSigmaTPC{"d_nSigmaTPC", 3.0, "Nsigma cut on TPC only"}; + Configurable d_nSigmaTPCCombined{"d_nSigmaTPCCombined", 5.0, "Nsigma cut on TPC combined with TOF"}; + Configurable d_nSigmaTOF{"d_nSigmaTOF", 3.0, "Nsigma cut on TOF only"}; + Configurable d_nSigmaTOFCombined{"d_nSigmaTOFCombined", 5.0, "Nsigma cut on TOF combined with TPC"}; + + /// Gets corresponding pT bin from cut file array + /// \param candpT is the pT of the candidate + /// \return corresponding bin number of array + template + int getpTBin(T candpT) + { + double pTBins[npTBins + 1] = {0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 9.0, 10.0, 12.0, 16.0, 20.0, 24.0, 36.0, 50.0, 100.0}; + for (int i = 0; i < npTBins; i++) { + if (candpT >= pTBins[i] && candpT < pTBins[i + 1]) { + return i; + } + } + return -1; + } + + /// Selection on goodness of daughter tracks + /// \note should be applied at candidate selection + /// \param track is daughter track + /// \return true if track is good + template + bool daughterSelection(const T& track) + { + if (track.charge() == 0) { + return false; + } + if (track.tpcNClsFound() == 0) { + return false; //is it clusters findable or found - need to check + } + return true; + } + + /// Conjugate independent toplogical cuts + /// \param hfcandprong2 is candidate + /// \return true if candidate passes all cuts + template + bool selectionTopol(const T& hfCandProng2) + { + auto candpT = hfCandProng2.pt(); + int pTBin = getpTBin(candpT); + if (pTBin == -1) + return false; + + if (candpT < d_pTCandMin || candpT >= d_pTCandMax) { + return false; //check that the candidate pT is within the analysis range + } + if (hfCandProng2.impactParameterProduct() > cuts[pTBin][7]) { + return false; //product of daughter impact parameters + } + if (hfCandProng2.cpa() < cuts[pTBin][8]) { + return false; //cosine of pointing angle + } + if (hfCandProng2.cpaXY() < cuts[pTBin][9]) { + return false; //cosine of pointing angle XY + } + if (hfCandProng2.decayLengthXYNormalised() < cuts[pTBin][10]) { + return false; //normalised decay length in XY plane + } + // if (hfCandProng2.dca() > cuts[pTBin][1]) return false; //candidate DCA + //if (hfCandProng2.chi2PCA() > cuts[pTBin][1]) return false; //candidate DCA + + //decay exponentail law, with tau = beta*gamma*ctau + //decay length > ctau retains (1-1/e) + double decayLengthCut = TMath::Min((hfCandProng2.p() * 0.0066) + 0.01, 0.06); + if (TMath::Abs(hfCandProng2.impactParameterNormalised0()) < 0.5 || TMath::Abs(hfCandProng2.impactParameterNormalised1()) < 0.5) { + return false; + } + if (hfCandProng2.decayLength() * hfCandProng2.decayLength() < decayLengthCut * decayLengthCut) { + return false; + } + if (hfCandProng2.decayLengthNormalised() * hfCandProng2.decayLengthNormalised() < 1.0) { + return false; + } + return true; + } + + /// Conjugate dependent toplogical cuts + /// \param hfCandProng2 is candidate + /// \param trackPion is the track with the pion hypothesis + /// \param trackKaon is the track with the kaon hypothesis + /// \note trackPion = positive and trackKaon = negative for D0 selection and inverse for D0bar + /// \return true if candidate passes all cuts for the given Conjugate + template + bool selectionTopolConjugate(const T1& hfCandProng2, const T2& trackPion, const T2& trackKaon) + { + + auto candpT = hfCandProng2.pt(); + int pTBin = getpTBin(candpT); + if (pTBin == -1) + return false; + + if (trackPion.charge() > 0) { //invariant mass cut + if (TMath::Abs(InvMassD0(hfCandProng2) - RecoDecay::getMassPDG(421)) > cuts[pTBin][0]) { + return false; + } + } else { + if (TMath::Abs(InvMassD0bar(hfCandProng2) - RecoDecay::getMassPDG(421)) > cuts[pTBin][0]) { + return false; + } + } + + if (TMath::Abs(trackPion.signed1Pt()) < TMath::Abs(cuts[pTBin][4]) || TMath::Abs(trackKaon.signed1Pt()) < TMath::Abs(cuts[pTBin][3])) { + return false; //cut on daughter pT + } + if (TMath::Abs(trackPion.dcaprim0()) > cuts[pTBin][6] || TMath::Abs(trackKaon.dcaprim0()) > cuts[pTBin][5]) { + return false; //cut on daughter dca - need to add secondary vertex constraint here + } + + if (trackPion.charge() > 0) { //cut on cos(theta *) + if (TMath::Abs(CosThetaStarD0(hfCandProng2)) > cuts[pTBin][2]) { + return false; + } + } else { + if (TMath::Abs(CosThetaStarD0bar(hfCandProng2)) > cuts[pTBin][2]) { + return false; + } + } + + return true; + } + + /// Check if track is ok for TPC PID + /// \param track is the track + /// \note function to be expanded + /// \return true if track is ok for TPC PID + template + bool validTPCPID(const T& track) + { + if (TMath::Abs(track.signed1Pt()) < d_pidTPCMinpT || TMath::Abs(track.signed1Pt()) >= d_pidTPCMaxpT) { + return false; + } + //if (track.TPCNClsFindable() < d_TPCNClsFindablePIDCut) return false; + return true; + } + + /// Check if track is ok for TOF PID + /// \param track is the track + /// \note function to be expanded + /// \return true if track is ok for TOF PID + template + bool validTOFPID(const T& track) + { + if (TMath::Abs(track.signed1Pt()) < d_pidTOFMinpT || TMath::Abs(track.signed1Pt()) >= d_pidTOFMaxpT) { + return false; + } + return true; + } + + /// Check if track is compatible with given TPC Nsigma cut for a given flavour hypothesis + /// \param track is the track + /// \param nPDG is the flavour hypothesis pdg number + /// \param nSigmaCut is the nsigma threshold to test against + /// \note nPDG=211 pion nPDG=321 kaon + /// \return true if track satisfies TPC PID hypothesis for given Nsigma cut + template + bool selectionPIDTPC(const T& track, int nPDG, int nSigmaCut) + { + double nSigma = 0.0; + nPDG = TMath::Abs(nPDG); + if (nPDG == 111) { + nSigma = track.tpcNSigmaPi(); + } else if (nPDG == 321) { + nSigma = track.tpcNSigmaKa(); + } else { + return nSigma = 100; //arbitarily large value + } + if (nSigma < nSigmaCut) { + return true; + } else { + return false; + } + } + + /// Check if track is compatible with given TOF NSigma cut for a given flavour hypothesis + /// \param track is the track + /// \param nPDG is the flavour hypothesis pdg number + /// \param nSigmaCut is the nSigma threshold to test against + /// \note nPDG=211 pion nPDG=321 kaon + /// \return true if track satisfies TOF PID hypothesis for given NSigma cut + template + bool selectionPIDTOF(const T& track, int nPDG, int nSigmaCut) + { + double nSigma = 0.0; + nPDG = TMath::Abs(nPDG); + if (nPDG == 111) + nSigma = track.tofNSigmaPi(); + else if (nPDG == 321) + nSigma = track.tofNSigmaKa(); + else + return nSigma = 100; //arbitarily large value + if (nSigma < nSigmaCut) + return true; + else + return false; + } + + /// PID selection on daughter track + /// \param track is the daughter track + /// \param nPDG is the pdg code of the flavour hypothesis + /// \note nPDG=211 pion nPDG=321 kaon + /// \return 1 if succesful PID match, 0 if sucessful PID rejection, -1 if no PID info + template + int selectionPID(const T& track, int nPDG) + { + int statusTPC = -1; + int statusTOF = -1; + + if (validTPCPID(track)) { + if (!selectionPIDTPC(track, nPDG, d_nSigmaTPC)) { + if (!selectionPIDTPC(track, nPDG, d_nSigmaTPCCombined)) { + statusTPC = 0; //rejected by PID + } else { + statusTPC = 1; //potential to be acceepted if combined with TOF + } + } else { + statusTPC = 2; //positive PID + } + } else { + statusTPC = -1; //no PID info + } + + if (validTOFPID(track)) { + if (!selectionPIDTOF(track, nPDG, d_nSigmaTOF)) { + if (!selectionPIDTOF(track, nPDG, d_nSigmaTOFCombined)) { + statusTOF = 0; //rejected by PID + } else { + statusTOF = 1; //potential to be acceepted if combined with TOF + } + } else { + statusTOF = 2; //positive PID + } + } else { + statusTOF = -1; //no PID info + } + + if (statusTPC == 2 || statusTOF == 2) { + return 1; //what if we have 2 && 0 ? + } else if (statusTPC == 1 && statusTOF == 1) { + return 1; + } else if (statusTPC == 0 || statusTOF == 0) { + return 0; + } else { + return -1; + } + } + + void process(aod::HfCandProng2 const& hfCandProng2s, aod::BigTracks const& tracks) + { + int statusD0, statusD0bar; // final selection flag : 0-rejected 1-accepted + bool topolD0, topolD0bar; + int pidD0, pidD0bar, piPlus, piMinus, kPlus, kMinus; + + for (auto& hfCandProng2 : hfCandProng2s) { //looping over 2 prong candidates + + auto trackPos = hfCandProng2.index0(); //positive daughter + auto trackNeg = hfCandProng2.index1(); //negative daughter + + statusD0 = 0; + statusD0bar = 0; + topolD0 = true; + topolD0bar = true; + pidD0 = -1; + pidD0bar = -1; + piPlus = -1; + piMinus = -1; + kPlus = -1; + kMinus = -1; + + // daughter track validity selection + if (!daughterSelection(trackPos) || !daughterSelection(trackNeg)) { + hfSelD0Candidate(statusD0, statusD0bar); + continue; + } + + //implement filter bit 4 cut - should be done before this task at the track selection level + //need to add special cuts (additional cuts on decay length and d0 norm) + + //conjugate independent topological selection + if (!selectionTopol(hfCandProng2)) { + hfSelD0Candidate(statusD0, statusD0bar); + continue; + } + + //conjugate dependent toplogical selection for D0 + topolD0 = selectionTopolConjugate(hfCandProng2, trackPos, trackNeg); + //conjugate dependent toplogical selection for D0bar + topolD0bar = selectionTopolConjugate(hfCandProng2, trackNeg, trackPos); + + if (!topolD0 && !topolD0bar) { + hfSelD0Candidate(statusD0, statusD0bar); + continue; + } + + piPlus = selectionPID(trackPos, 211); + kMinus = selectionPID(trackNeg, 321); + piMinus = selectionPID(trackNeg, 211); + kPlus = selectionPID(trackPos, 321); + + if (piPlus == 0 || kMinus == 0 || piMinus == 1 || kPlus == 1) + pidD0 = 0; //exclude D0 + if (piPlus == 1 || kMinus == 1 || piMinus == 0 || kPlus == 0) + pidD0bar = 0; //exclude D0bar + if (piPlus == 1 && kMinus == 1) + pidD0 = 1; //accept D0 + if (piMinus == 1 && kPlus == 1) + pidD0bar = 1; //accept D0bar + + if (pidD0 == 0 && pidD0bar == 0) { + hfSelD0Candidate(statusD0, statusD0bar); + continue; + } + + if ((pidD0 == -1 || pidD0 == 1) && topolD0) { + statusD0 = 1; //identified as D0 + } + if ((pidD0bar == -1 || pidD0bar == 1) && topolD0bar) { + statusD0bar = 1; //identified as D0bar + } + + hfSelD0Candidate(statusD0, statusD0bar); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask("hf-d0-candidate-selector")}; +} diff --git a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx index 5647cfb773d90..92945bb64cc23 100644 --- a/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx +++ b/Analysis/Tasks/PWGHF/HFTrackIndexSkimsCreator.cxx @@ -25,17 +25,6 @@ using namespace o2::framework; using namespace o2::framework::expressions; using std::array; -namespace o2::aod -{ -namespace seltrack -{ -DECLARE_SOA_COLUMN(IsSel, isSel, int); -DECLARE_SOA_COLUMN(DCAPrim0, dcaPrim0, float); -DECLARE_SOA_COLUMN(DCAPrim1, dcaPrim1, float); -} // namespace seltrack -DECLARE_SOA_TABLE(SelTrack, "AOD", "SELTRACK", seltrack::IsSel, seltrack::DCAPrim0, seltrack::DCAPrim1); -} // namespace o2::aod - /// Track selection struct SelectTracks { Produces rowSelectedTrack; @@ -97,7 +86,7 @@ struct HFTrackIndexSkimsCreator { OutputObj hmass2{TH1F("hmass2", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; OutputObj hmass3{TH1F("hmass3", "; Inv Mass (GeV/c^{2})", 500, 0, 5.0)}; - Filter filterSelectTracks = aod::seltrack::isSel == 1; + Filter filterSelectTracks = aod::seltrack::issel == 1; using SelectedTracks = soa::Filtered>; // FIXME //Partition tracksPos = aod::track::signed1Pt > 0.f; diff --git a/Analysis/Tasks/PWGHF/taskD0.cxx b/Analysis/Tasks/PWGHF/taskD0.cxx index 9005341ea7844..8372ffa1c9d10 100644 --- a/Analysis/Tasks/PWGHF/taskD0.cxx +++ b/Analysis/Tasks/PWGHF/taskD0.cxx @@ -17,10 +17,20 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Analysis/SecondaryVertexHF.h" +#include "DetectorsVertexing/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Analysis/CandidateSelectionTables.h" + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::aod::hf_cand_prong2; +using namespace o2::framework::expressions; using std::array; /// D0 analysis task @@ -36,12 +46,22 @@ struct TaskD0 { OutputObj hCTS{TH1F("hCTS", "cos #it{#theta}*", 120, -1.1, 1.1)}; OutputObj hCt{TH1F("hCt", "proper lifetime * #it{c} (cm)", 120, -20, 100)}; OutputObj hEta{TH1F("hEta", "#it{#eta}", 100, -2, 2)}; + OutputObj hselectionstatus{TH1F("selectionstatus", "selection status", 5, -0.5, 4.5)}; + + Configurable d_selectionFlagD0{"d_selectionFlagD0", 1, "Selection Flag for D0"}; + Configurable d_selectionFlagD0bar{"d_selectionFlagD0bar", 1, "Selection Flag for D0bar"}; + + Filter seltrack = (aod::hfselcandidate::isSelD0 >= d_selectionFlagD0 || aod::hfselcandidate::isSelD0bar >= d_selectionFlagD0bar); - void process(aod::HfCandProng2 const& candidates) + void process(soa::Filtered> const& candidates) { for (auto& candidate : candidates) { - hmass->Fill(InvMassD0(candidate)); - hmass->Fill(InvMassD0bar(candidate)); + if (candidate.isSelD0() >= d_selectionFlagD0) { + hmass->Fill(InvMassD0(candidate)); + } + if (candidate.isSelD0bar() >= d_selectionFlagD0bar) { + hmass->Fill(InvMassD0bar(candidate)); + } hptcand->Fill(candidate.pt()); hptprong0->Fill(candidate.ptProng0()); hptprong1->Fill(candidate.ptProng1()); @@ -53,6 +73,7 @@ struct TaskD0 { hCTS->Fill(CosThetaStarD0(candidate)); hCt->Fill(CtD0(candidate)); hEta->Fill(candidate.eta()); + hselectionstatus->Fill(candidate.isSelD0() + (candidate.isSelD0bar() * 2)); } } }; diff --git a/Analysis/Tasks/PWGLF/CMakeLists.txt b/Analysis/Tasks/PWGLF/CMakeLists.txt new file mode 100644 index 0000000000000..a517969a90861 --- /dev/null +++ b/Analysis/Tasks/PWGLF/CMakeLists.txt @@ -0,0 +1,14 @@ +# 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. + +o2_add_dpl_workflow(nuclei-spectra + SOURCES NucleiSpectraTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx new file mode 100644 index 0000000000000..902385b40b8dd --- /dev/null +++ b/Analysis/Tasks/PWGLF/NucleiSpectraTask.cxx @@ -0,0 +1,63 @@ +// 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. +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" + +#include "PID/PIDResponse.h" + +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct NucleiSpecraTask { + + OutputObj hTPCsignal{TH2F("hTPCsignal", ";#it{p} (GeV/#it{c}); d#it{E} / d#it{X} (a. u.)", 600, 0., 3, 1400, 0, 1400)}; + OutputObj hMomentum{TH1F("hMomentum", ";#it{p} (GeV/#it{c});", 600, 0., 3.)}; + + Configurable absEtaMax{"absEtaMax", 0.8, "pseudo-rapidity edges"}; + Configurable absYmax{"absYmax", 0.5, "rapidity edges"}; + Configurable beamRapidity{"yBeam", 0., "beam rapidity"}; + Configurable chi2TPCperNDF{"chi2TPCperNDF", 4., "chi2 per NDF in TPC"}; + Configurable foundFractionTPC{"foundFractionTPC", 0., "TPC clusters / TPC crossed rows"}; + Configurable recPointsTPC{"recPointsTPC", 0, "clusters in TPC"}; + Configurable signalClustersTPC{"signalClustersTPC", 70, "clusters with PID in TPC"}; + Configurable minEnergyLoss{"minEnergyLoss", 0., "energy loss in TPC"}; + Configurable recPointsITS{"recPointsITS", 2, "number of ITS points"}; + Configurable recPointsITSInnerBarrel{"recPointsITSInnerBarrel", 1, "number of points in ITS Inner Barrel"}; + + Filter etaFilter = aod::track::eta > -1 * absEtaMax&& aod::track::eta < absEtaMax; + Filter chi2Filter = aod::track::tpcChi2NCl < chi2TPCperNDF; + + void process(soa::Filtered> const& tracks) + { + for (auto& track : tracks) { + // Part not covered by filters + if (track.tpcNClsFound() < recPointsTPC) + continue; + if (track.itsNCls() < recPointsITS) + continue; + if (track.itsNClsInnerBarrel() < recPointsITSInnerBarrel) + continue; + + hTPCsignal->Fill(track.p(), track.tpcSignal()); + hMomentum->Fill(track.p()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask("nuclei-spectra")}; +} diff --git a/Analysis/Tasks/PWGMM/CMakeLists.txt b/Analysis/Tasks/PWGMM/CMakeLists.txt new file mode 100644 index 0000000000000..b0a6b6fadcc0f --- /dev/null +++ b/Analysis/Tasks/PWGMM/CMakeLists.txt @@ -0,0 +1,14 @@ +# 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. + +o2_add_dpl_workflow(dNdetaRun2Tracklets-analysis + SOURCES dNdetaRun2Tracklets.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME Analysis) diff --git a/Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx b/Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx new file mode 100644 index 0000000000000..ac949f823fcb5 --- /dev/null +++ b/Analysis/Tasks/PWGMM/dNdetaRun2Tracklets.cxx @@ -0,0 +1,64 @@ +// 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. +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Analysis/Multiplicity.h" +#include "Analysis/EventSelection.h" +#include "Analysis/Centrality.h" +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct PseudorapidityDensity { + + Configurable etaBinWidth{"etaBinWidth", 0.1, "eta bin width"}; + Configurable etaMax{"etaMax", 1.5, "max eta value"}; + Configurable etaMin{"etaMin", -1.5, "min eta value"}; + Configurable vtxZMax{"vtxZMax", 10, "max z vertex"}; + Configurable vtxZMin{"vtxZMin", -10, "min z vertex"}; + int etaBins = TMath::Nint((etaMax - etaMin) / etaBinWidth); + int vtxZBins = TMath::Nint(vtxZMax - vtxZMin); + + OutputObj hStat{TH1F("hStat", "TotalEvents", 1, 0.5, 1.5)}; + OutputObj hdNdeta{TH1F("hdNdeta", "dNdeta", 50, -2.5, 2.5)}; + OutputObj vtxZEta{TH2F("vtxZEta", ";#eta;vtxZ", 50, -2.5, 2.5, 60, -30, 30)}; + OutputObj phiEta{TH2F("phiEta", ";#eta;#varphi", 50, -2.5, 2.5, 200, 0., 2 * TMath::Pi())}; + + // TODO remove static casts for configurables when fixed + Filter etaFilter = (aod::track::eta < (float)etaMax) && (aod::track::eta > (float)etaMin); + Filter trackTypeFilter = (aod::track::trackType == static_cast(aod::track::TrackTypeEnum::Run2Tracklet)); + Filter posZFilter = (aod::collision::posZ < (float)vtxZMax) && (aod::collision::posZ > (float)vtxZMin); + + void process(soa::Filtered>::iterator const& collisions, soa::Filtered const& tracklets) + { + // TODO change to sel7 filter expression when implemented + if (!collisions.sel7()) + return; + hStat->Fill(collisions.size()); + auto vtxZ = collisions.posZ(); + for (auto& track : tracklets) { + vtxZEta->Fill(track.eta(), vtxZ); + phiEta->Fill(track.eta(), track.phi()); + hdNdeta->Fill(track.eta()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask("dNdetaRun2Tracklets-analysis")}; +} diff --git a/Analysis/Tasks/correlations.cxx b/Analysis/Tasks/correlations.cxx index 560c8cbd006df..4b53c581c88f7 100644 --- a/Analysis/Tasks/correlations.cxx +++ b/Analysis/Tasks/correlations.cxx @@ -30,16 +30,11 @@ using namespace o2::framework::expressions; struct CorrelationTask { - // Filters and input definitions - Filter trackFilter = (aod::track::eta > -0.8f) && (aod::track::eta < 0.8f) && (aod::track::pt > 0.5f) && (aod::track::isGlobalTrack == (uint8_t)1); - using myTracks = soa::Filtered>; - - // Output definitions - OutputObj same{"sameEvent"}; - OutputObj mixed{"mixedEvent"}; - //OutputObj qaOutput{"qa"}; - // Configuration + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 7.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutPt, float, 0.5f, "Minimal pT for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") + O2_DEFINE_CONFIGURABLE(cfgTriggerCharge, int, 0, "Select on charge of trigger particle: 0 = all; 1 = positive; -1 = negative"); O2_DEFINE_CONFIGURABLE(cfgAssociatedCharge, int, 0, "Select on charge of associated particle: 0 = all; 1 = positive; -1 = negative"); O2_DEFINE_CONFIGURABLE(cfgPairCharge, int, 0, "Select on charge of particle pair: 0 = all; 1 = like sign; -1 = unlike sign"); @@ -53,6 +48,16 @@ struct CorrelationTask { O2_DEFINE_CONFIGURABLE(cfgPairCutPhi, float, -1, "Pair cut on Phi: -1 = off; >0 otherwise distance value") O2_DEFINE_CONFIGURABLE(cfgPairCutRho, float, -1, "Pair cut on Rho: -1 = off; >0 otherwise distance value") + // Filters and input definitions + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && (aod::track::isGlobalTrack == (uint8_t)1); + using myTracks = soa::Filtered>; + + // Output definitions + OutputObj same{"sameEvent"}; + OutputObj mixed{"mixedEvent"}; + //OutputObj qaOutput{"qa"}; + enum PairCuts { Photon = 0, K0, Lambda, diff --git a/Analysis/Tasks/eventSelection.cxx b/Analysis/Tasks/eventSelection.cxx index b48adecd40b24..15ccf4cf87bcb 100644 --- a/Analysis/Tasks/eventSelection.cxx +++ b/Analysis/Tasks/eventSelection.cxx @@ -55,6 +55,8 @@ struct EvSelParameters { struct EventSelectionTask { Produces evsel; Service ccdb; + Configurable isMC{"isMC", 0, "0 - data, 1 - MC"}; + EvSelParameters par; aod::Run2V0 getVZero(aod::BC const& bc, aod::Run2V0s const& vzeros) @@ -138,6 +140,11 @@ struct EventSelectionTask { bool bgFDA = timeFDA > par.fFDABGlower && timeFDA < par.fFDABGupper; bool bgFDC = timeFDC > par.fFDCBGlower && timeFDC < par.fFDCBGupper; + if (isMC) { + bbZNA = 1; + bbZNC = 1; + } + // Fill event selection columns evsel(alias, bbV0A, bbV0C, bgV0A, bgV0C, bbZNA, bbZNC, bbFDA, bbFDC, bgFDA, bgFDC); } diff --git a/Analysis/Tasks/eventSelectionQa.cxx b/Analysis/Tasks/eventSelectionQa.cxx index 599a235c6b90f..fdbb8eaef6459 100644 --- a/Analysis/Tasks/eventSelectionQa.cxx +++ b/Analysis/Tasks/eventSelectionQa.cxx @@ -56,9 +56,11 @@ struct EventSelectionTask { OutputObj hTimeFDAacc{TH1F("hTimeFDAacc", "", 1000, -100., 100.)}; OutputObj hTimeFDCacc{TH1F("hTimeFDCacc", "", 1000, -100., 100.)}; + Configurable isMC{"isMC", 0, "0 - data, 1 - MC"}; + void process(soa::Join::iterator const& col, aod::BCs const& bcs, aod::Zdcs const& zdcs, aod::Run2V0s const& vzeros, aod::FDDs fdds) { - if (!col.alias()[kINT7]) + if (!isMC && !col.alias()[kINT7]) return; auto vzero = getVZero(col.bc(), vzeros); diff --git a/Analysis/Tasks/timestamp.cxx b/Analysis/Tasks/timestamp.cxx index 496baa443bc1a..79d823ed5e21b 100644 --- a/Analysis/Tasks/timestamp.cxx +++ b/Analysis/Tasks/timestamp.cxx @@ -10,55 +10,90 @@ // // A task to fill the timestamp table from run number. -// Uses RunToTimestamp object from CCDB, fails if not available. +// Uses headers from CCDB // // Author: Nicolo' Jacazio on 2020-06-22 #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Analysis/RunToTimestamp.h" #include #include "CommonDataFormat/InteractionRecord.h" #include "DetectorsRaw/HBFUtils.h" #include + using namespace o2::framework; using namespace o2::header; using namespace o2; struct TimestampTask { - Produces ts_table; - RunToTimestamp* converter = nullptr; - std::map* mapStartOrbit = nullptr; - Service ccdb; - Configurable path{"ccdb-path", "Analysis/Core/RunToTimestamp", "path to the ccdb object"}; - Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + Produces ts_table; /// Table with SOR timestamps produced by the task + Service ccdb; /// Object manager in CCDB + o2::ccdb::CcdbApi api; /// API to access CCDB + std::map* mapStartOrbit = nullptr; /// Map of the starting orbit for the run + std::pair lastCall; /// Last run number processed and its timestamp, needed for caching + std::map mapRunToTimestamp; /// Cache of processed run numbers + + // Configurables + Configurable verbose{"verbose", false, "verbose mode"}; + Configurable path{"ccdb-path", "RCT/RunInformation/", "path to the ccdb object"}; + Configurable url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "URL of the CCDB database"}; + Configurable isMC{"isMC", 0, "0 - data, 1 - MC"}; void init(o2::framework::InitContext&) { LOGF(info, "Initializing TimestampTask"); - converter = ccdb->get(path.value); - if (converter) { - LOGF(info, "Run-number to timestamp converter found!"); - } else { - LOGF(fatal, "Cannot find run-number to timestamp converter in path '%s'.", path.value.data()); - } mapStartOrbit = ccdb->get>("Trigger/StartOrbit"); if (!mapStartOrbit) { LOGF(fatal, "Cannot find map of SOR orbits in CCDB in path Trigger/StartOrbit"); } + api.init(url.value); + if (!api.isHostReachable()) { + LOGF(fatal, "CCDB host %s is not reacheable, cannot go forward", url.value.data()); + } } void process(aod::BC const& bc) { - long timestamp = converter->getTimestamp(bc.runNumber()); - uint16_t currentBC = bc.globalBC() % o2::constants::lhc::LHCMaxBunches; - uint32_t currentOrbit = bc.globalBC() / o2::constants::lhc::LHCMaxBunches; + long ts = 0; + if (bc.runNumber() == lastCall.first) { // The run number coincides to the last run processed + LOGF(debug, "Getting timestamp from last call"); + ts = lastCall.second; + } else if (mapRunToTimestamp.count(bc.runNumber())) { // The run number was already requested before: getting it from cache! + LOGF(debug, "Getting timestamp from cache"); + ts = mapRunToTimestamp[bc.runNumber()]; + } else { // The run was not requested before: need to acccess CCDB! + LOGF(debug, "Getting timestamp from CCDB"); + std::map metadata, headers; + const std::string run_path = Form("%s/%i", path.value.data(), bc.runNumber()); + headers = api.retrieveHeaders(run_path, metadata, -1); + if (headers.count("SOR") == 0) { + LOGF(fatal, "Cannot find run-number to timestamp in path '%s'.", run_path.data()); + } + ts = atol(headers["SOR"].c_str()); // timestamp of the SOR in ms + + // Adding the timestamp to the cache map + std::pair::iterator, bool> check; + check = mapRunToTimestamp.insert(std::pair(bc.runNumber(), ts)); + if (!check.second) { + LOGF(fatal, "Run number %i already existed with a timestamp of %llu", bc.runNumber(), check.first->second); + } + LOGF(info, "Add new run %i with timestamp %llu to cache", bc.runNumber(), ts); + } + + // Setting latest run information + lastCall = std::make_pair(bc.runNumber(), ts); + + if (verbose.value) { + LOGF(info, "Run-number to timestamp found! %i %llu ms", bc.runNumber(), ts); + } uint16_t initialBC = 0; // exact bc number not relevant due to ms precision of timestamps uint32_t initialOrbit = mapStartOrbit->at(bc.runNumber()); + uint16_t currentBC = isMC ? initialBC : bc.globalBC() % o2::constants::lhc::LHCMaxBunches; + uint32_t currentOrbit = isMC ? initialOrbit : bc.globalBC() / o2::constants::lhc::LHCMaxBunches; InteractionRecord current(currentBC, currentOrbit); InteractionRecord initial(initialBC, initialOrbit); - timestamp += (current - initial).bc2ns() / 1000000; - ts_table(timestamp); + ts += (current - initial).bc2ns() / 1000000; + ts_table(ts); } }; diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index 84a1ae813f974..c3624626bc491 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -119,3 +119,8 @@ o2_add_dpl_workflow(extended-columns o2_add_dpl_workflow(zdc-vzero-iteration SOURCES src/ZDCVZeroIteration.cxx COMPONENT_NAME AnalysisTutorial) + +o2_add_dpl_workflow(hist-helpers-test + SOURCES src/histHelpersTest.cxx + PUBLIC_LINK_LIBRARIES O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/associatedExample.cxx b/Analysis/Tutorials/src/associatedExample.cxx index 424c9298b87bc..cbb44589fc32e 100644 --- a/Analysis/Tutorials/src/associatedExample.cxx +++ b/Analysis/Tutorials/src/associatedExample.cxx @@ -15,15 +15,13 @@ namespace o2::aod { namespace etaphi { -DECLARE_SOA_COLUMN(Eta, etas, float); -DECLARE_SOA_COLUMN(Phi, phis, float); -DECLARE_SOA_COLUMN(Pt, pts, float); +DECLARE_SOA_COLUMN(AEta, etas, float); +DECLARE_SOA_COLUMN(APhi, phis, float); +DECLARE_SOA_COLUMN(APt, pts, float); } // namespace etaphi DECLARE_SOA_TABLE(EtaPhi, "AOD", "ETAPHI", - etaphi::Eta, etaphi::Phi); -DECLARE_SOA_TABLE(EtaPhiPt, "AOD", "ETAPHIPT", - etaphi::Eta, etaphi::Phi, etaphi::Pt); + etaphi::AEta, etaphi::APhi); namespace collision { @@ -43,16 +41,13 @@ using namespace o2::framework; // we need GCC 7.4+ for that struct ATask { Produces etaphi; - Produces etaphipt; void process(aod::Tracks const& tracks) { for (auto& track : tracks) { float phi = asin(track.snp()) + track.alpha() + static_cast(M_PI); float eta = log(tan(0.25f * static_cast(M_PI) - 0.5f * atan(track.tgl()))); - float pt = 1.f / track.signed1Pt(); etaphi(eta, phi); - etaphipt(eta, phi, pt); } } }; @@ -72,23 +67,20 @@ struct BTask { LOGF(INFO, "ID: %d", collision.globalIndex()); LOGF(INFO, "Tracks: %d", extTracks.size()); for (auto& track : extTracks) { - LOGF(INFO, "(%f, %f) - (%f, %f)", track.eta(), track.phi(), track.etas(), track.phis()); + LOGF(INFO, "(%f, %f) - (%f, %f)", track.eta(), track.phiraw(), track.etas(), track.phis()); } } }; -struct CTask { - void process(aod::Collision const& collision, soa::Concat const& concatenated) - { - LOGF(INFO, "ID: %d", collision.globalIndex()); - LOGF(INFO, "Tracks: %d", concatenated.size()); - } -}; - struct TTask { + using myCol = soa::Join; void process(soa::Join::iterator const& col, aod::Tracks const& tracks) { - LOGF(INFO, "ID: %d; %d == %d", col.globalIndex(), col.mult(), tracks.size()); + LOGF(INFO, "[direct] ID: %d; %d == %d", col.globalIndex(), col.mult(), tracks.size()); + if (tracks.size() > 0) { + auto track0 = tracks.begin(); + LOGF(INFO, "[index ] ID: %d; %d == %d", track0.collision_as().globalIndex(), track0.collision_as().mult(), tracks.size()); + } } }; @@ -97,7 +89,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) return WorkflowSpec{ adaptAnalysisTask("produce-etaphi"), adaptAnalysisTask("consume-etaphi"), - adaptAnalysisTask("consume-etaphi-twice"), adaptAnalysisTask("produce-mult"), adaptAnalysisTask("consume-mult")}; } diff --git a/Analysis/Tutorials/src/ccdbaccess.cxx b/Analysis/Tutorials/src/ccdbaccess.cxx index 5c9036542f3fc..2061a23532a79 100644 --- a/Analysis/Tutorials/src/ccdbaccess.cxx +++ b/Analysis/Tutorials/src/ccdbaccess.cxx @@ -15,7 +15,6 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "Analysis/RunToTimestamp.h" #include #include "CommonDataFormat/InteractionRecord.h" diff --git a/Analysis/Tutorials/src/dynamicColumns.cxx b/Analysis/Tutorials/src/dynamicColumns.cxx index e8e2c25eec425..a4c2492d7f443 100644 --- a/Analysis/Tutorials/src/dynamicColumns.cxx +++ b/Analysis/Tutorials/src/dynamicColumns.cxx @@ -28,7 +28,9 @@ struct ATask { auto table_with_extra_dynamic_columns = soa::Attach>(tracks); for (auto& row : table_with_extra_dynamic_columns) { if (row.trackType() != 3) { - LOGF(info, "P^2 = %.3f", row.p2()); + if (row.index() % 100 == 0) { + LOGF(info, "P^2 = %.3f", row.p2()); + } } } } diff --git a/Analysis/Tutorials/src/extendedColumns.cxx b/Analysis/Tutorials/src/extendedColumns.cxx index ad93833eb09d4..7d1ec1185ac41 100644 --- a/Analysis/Tutorials/src/extendedColumns.cxx +++ b/Analysis/Tutorials/src/extendedColumns.cxx @@ -28,7 +28,9 @@ struct ATask { auto table_extension = soa::Extend(tracks); for (auto& row : table_extension) { if (row.trackType() != 3) { - LOGF(info, "P^2 = %.3f", row.p2()); + if (row.index() % 100 == 0) { + LOGF(info, "P^2 = %.3f", row.p2()); + } } } } diff --git a/Analysis/Tutorials/src/histHelpersTest.cxx b/Analysis/Tutorials/src/histHelpersTest.cxx new file mode 100644 index 0000000000000..ab75b660b8b75 --- /dev/null +++ b/Analysis/Tutorials/src/histHelpersTest.cxx @@ -0,0 +1,147 @@ +// 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. + +#include "Framework/AnalysisTask.h" +#include "Analysis/HistHelpers.h" + +#include "Framework/AnalysisDataModel.h" +#include "Framework/runDataProcessing.h" +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::experimental::histhelpers; + +struct HistHelpersTest { + + // some unique names for the histograms + enum HistNames : uint8_t { + Hist_pt = 0, + Hist_eta, + Hist_phi, + Hist_nClsTPC, + Hist_nCrossedRowsTPC, + Hist_Chi2PerClTPC, + Hist_nClsITS, + Hist_Chi2PerClITS, + + // for testing + Hist_test_1d_TH1D, + Hist_test_2d_TH2F, + Hist_test_3d_TH3I, + Hist_test_1d_TH1D_Builder, + Hist_test_2d_TH2F_Builder, + + Hist_test_3d_THnI, + Hist_test_5d_THnSparseI, + LAST, + }; + + OutputObj test{HistContainer("Test"), OutputObjHandlingPolicy::QAObject}; + OutputObj kine{HistContainer("Kine"), OutputObjHandlingPolicy::QAObject}; + OutputObj tpc{HistContainer("TPC"), OutputObjHandlingPolicy::QAObject}; + OutputObj its{HistContainer("ITS"), OutputObjHandlingPolicy::QAObject}; + + void init(o2::framework::InitContext&) + { + // add some plain and simple histograms + test->Add(Hist_test_1d_TH1D, TH1D("testHist_TH1", ";x", 100, 0., 50.)); + test->Add(Hist_test_2d_TH2F, TH2F("testHist_TH2", ";x;y", 100, -0.5, 0.5, 100, -0.5, 0.5)); + test->Add(Hist_test_3d_TH3I, TH3I("testHist_TH3", ";x;y;z", 100, 0., 20., 100, 0., 20., 100, 0., 20.)); + + // alternatively use HistBuilder to generate the histogram and add it to container afterwards + HistBuilder sameAsBefore; + sameAsBefore.AddAxis({"x", "x", {0., 50.}, 100}); + test->Add(Hist_test_1d_TH1D_Builder, sameAsBefore.GenerateHist("testHist_TH1_Builder")); + + // the builder enables us to have combinations of flexible + fixed binning in 2d or 3d histograms + // (which are not available via default root constructors) + HistBuilder sameButDifferent; + sameButDifferent.AddAxis({"x", "x", {-0.5, 0.5}, 100}); + sameButDifferent.AddAxis({"y", "y", {-0.5, -0.48, -0.3, 0.4, 0.5}}); // use variable binning for y axsis this time + test->Add(Hist_test_2d_TH2F_Builder, sameButDifferent.GenerateHist("testHist_TH2_Builder")); + + // also for n dimensional histograms things become much simpler: + std::vector ptBins = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, + 1.1, 1.2, 1.3, 1.4, 1.5, 2.0, 5.0, 10.0, 20.0, 50.0}; + std::vector centBins = {0., 30., 60., 90.}; + + // varaiable binning + Axis ptAxis = {"pt", "#it{p}_{T} (GeV/c)", ptBins}; + Axis centAxis = {"cent", "centrality", centBins}; + // equidistant binning + Axis etaAxis = {"eta", "#eta", {-0.8, 0.8}, 5}; + Axis phiAxis = {"phi", "#phi", {0., 2. * M_PI}, 4}; // 36 to see tpc sectors + const int nCuts = 5; + Axis cutAxis = {"cut", "cut setting", {-0.5, nCuts - 0.5}, nCuts}; + + HistBuilder myHistogram; + myHistogram.AddAxis(ptAxis); + myHistogram.AddAxis(etaAxis); + myHistogram.AddAxis("signed1Pt", "q/p_{T}", 200, -8, 8); + test->Add(Hist_test_3d_THnI, myHistogram.GenerateHist("testHist_THn")); + + HistBuilder testSparseHist; + testSparseHist.AddAxis(ptAxis); + testSparseHist.AddAxis(etaAxis); + testSparseHist.AddAxis(phiAxis); + testSparseHist.AddAxis(centAxis); + testSparseHist.AddAxis(cutAxis); + test->Add(Hist_test_5d_THnSparseI, testSparseHist.GenerateHist("testHist_THnSparse")); + + // now add some more useful histograms + + kine->Add(Hist_pt, TH1F("track-pt", "p_{T};p_{T} [GeV/c]", 100, 0., 50.)); + kine->Add(Hist_eta, TH1F("track-eta", "#eta;#eta", 101, -1.0, 1.0)); + kine->Add(Hist_phi, TH1F("track-phi", "#phi;#phi [rad]", 100, 0., 2 * M_PI)); + + tpc->Add(Hist_nCrossedRowsTPC, TH1F("tpc-crossedRows", "number of crossed TPC rows;# crossed rows TPC", 165, -0.5, 164.5)); + tpc->Add(Hist_nClsTPC, TH1F("tpc-foundClusters", "number of found TPC clusters;# clusters TPC", 165, -0.5, 164.5)); + tpc->Add(Hist_Chi2PerClTPC, TH1F("tpc-chi2PerCluster", "chi2 per cluster in TPC;chi2 / cluster TPC", 100, 0, 10)); + + its->Add(Hist_Chi2PerClITS, TH1F("its-chi2PerCluster", "chi2 per ITS cluster;chi2 / cluster ITS", 100, 0, 40)); + } + + void process(soa::Join::iterator const& track) + { + test->Fill(Hist_test_1d_TH1D, 1.); + test->Fill(Hist_test_2d_TH2F, 0.1, 0.3); + test->Fill(Hist_test_3d_TH3I, 10, 10, 15); + + test->Fill(Hist_test_1d_TH1D_Builder, 1.); + test->Fill(Hist_test_2d_TH2F_Builder, 0.1, 0.3); + + test->Fill(Hist_test_3d_THnI, 1., 0., 1.5); + test->Fill(Hist_test_5d_THnSparseI, 1., 0., 1.5, 30, 1); + + // or directly access to the underlying histogram: + test->Get(Hist_test_2d_TH2F)->Fill(0.2, 0.2); + + kine->Fill(Hist_pt, track.pt()); + kine->Fill(Hist_eta, track.eta()); + kine->Fill(Hist_phi, track.phi()); + + tpc->Fill(Hist_nClsTPC, track.tpcNClsFound()); + tpc->Fill(Hist_nCrossedRowsTPC, track.tpcNClsCrossedRows()); + tpc->Fill(Hist_Chi2PerClTPC, track.itsChi2NCl()); + + its->Fill(Hist_Chi2PerClITS, track.tpcChi2NCl()); + } +}; + +//-------------------------------------------------------------------- +// Workflow definition +//-------------------------------------------------------------------- +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + return WorkflowSpec{ + adaptAnalysisTask("hist-helpers-test")}; +} diff --git a/Analysis/Tutorials/src/partitions.cxx b/Analysis/Tutorials/src/partitions.cxx index d0c5e10f1af45..6479356a48cfa 100644 --- a/Analysis/Tutorials/src/partitions.cxx +++ b/Analysis/Tutorials/src/partitions.cxx @@ -46,15 +46,15 @@ struct ATask { for (auto& track : leftPhi) { LOGF(INFO, "id = %d, from collision: %d, collision: %d; eta: %.3f < %.3f < %.3f; phi: %.3f < %.3f; pt: %.3f < %.3f < %.3f", - track.collisionId(), track.collision().globalIndex(), collision.globalIndex(), etalow, track.eta(), etaup, track.phiraw(), philow, ptlow, track.pt(), ptup); + track.collisionId(), track.collision().globalIndex(), collision.globalIndex(), (float)etalow, track.eta(), (float)etaup, track.phiraw(), (float)philow, (float)ptlow, track.pt(), (float)ptup); } for (auto& track : midPhi) { LOGF(INFO, "id = %d, from collision: %d, collision: %d; eta: %.3f < %.3f < %.3f; phi: %.3f <= %.3f < %.3f; pt: %.3f < %.3f < %.3f", - track.collisionId(), track.collision().globalIndex(), collision.globalIndex(), etalow, track.eta(), etaup, philow, track.phiraw(), phiup, ptlow, track.pt(), ptup); + track.collisionId(), track.collision().globalIndex(), collision.globalIndex(), (float)etalow, track.eta(), (float)etaup, (float)philow, track.phiraw(), (float)phiup, (float)ptlow, track.pt(), (float)ptup); } for (auto& track : rightPhi) { LOGF(INFO, "id = %d, from collision: %d, collision: %d; eta: %.3f < %.3f < %.3f; phi: %.3f < %.3f; pt: %.3f < %.3f < %.3f", - track.collisionId(), track.collision().globalIndex(), collision.globalIndex(), etalow, track.eta(), etaup, phiup, track.phiraw(), ptlow, track.pt(), ptup); + track.collisionId(), track.collision().globalIndex(), collision.globalIndex(), (float)etalow, track.eta(), (float)etaup, (float)phiup, track.phiraw(), (float)ptlow, track.pt(), (float)ptup); } } }; diff --git a/Common/Field/include/Field/MagneticField.h b/Common/Field/include/Field/MagneticField.h index 4d19c6800b99b..d4241fe49c498 100644 --- a/Common/Field/include/Field/MagneticField.h +++ b/Common/Field/include/Field/MagneticField.h @@ -68,6 +68,9 @@ class MagneticField : public FairField /// Default destructor ~MagneticField() override = default; + /// create field from rounded value, i.e. +-5 or +-2 kGauss + static MagneticField* createNominalField(int fld); + /// real field creation is here void CreateField(); diff --git a/Common/Field/src/MagneticField.cxx b/Common/Field/src/MagneticField.cxx index 5fb485ee1c3f1..f53ac5a42cfdc 100644 --- a/Common/Field/src/MagneticField.cxx +++ b/Common/Field/src/MagneticField.cxx @@ -148,6 +148,29 @@ MagneticField::MagneticField(const MagFieldParam& param) CreateField(); } +MagneticField* MagneticField::createNominalField(int fld) +{ + float fldCoeff; + o2::field::MagFieldParam::BMap_t fldType; + switch (std::abs(fld)) { + case 5: + fldType = o2::field::MagFieldParam::k5kG; + fldCoeff = fld > 0 ? 1. : -1; + break; + case 0: + fldType = o2::field::MagFieldParam::k5kG; + fldCoeff = 0; + break; + case 2: + fldType = o2::field::MagFieldParam::k2kG; + fldCoeff = fld > 0 ? 1. : -1; + break; + default: + LOG(FATAL) << "Field option " << fld << " is not supported, use +-2, +-5 or 0"; + }; + return new o2::field::MagneticField("Maps", "Maps", fldCoeff, fldCoeff, fldType); +} + void MagneticField::CreateField() { /* diff --git a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h index e39917d94afe2..4799d43fa7d2d 100644 --- a/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h +++ b/DataFormats/Detectors/ITSMFT/ITS/include/DataFormatsITS/TrackITS.h @@ -43,7 +43,7 @@ class TrackITS : public o2::track::TrackParCov TrackITS(const TrackITS& t) = default; TrackITS(const o2::track::TrackParCov& parcov) : TrackParCov{parcov} {} TrackITS(const o2::track::TrackParCov& parCov, float chi2, const o2::track::TrackParCov& outer) - : o2::track::TrackParCov{parCov}, mChi2{chi2}, mParamOut{outer} {} + : o2::track::TrackParCov{parCov}, mParamOut{outer}, mChi2{chi2} {} TrackITS& operator=(const TrackITS& tr) = default; ~TrackITS() = default; diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h index 6cb7b62a36e47..e0e734e552587 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/TrackTPC.h @@ -59,10 +59,10 @@ class TrackTPC : public o2::track::TrackParCov void setHasCSideClusters() { mFlags |= HasCSideClusters; } float getTime0() const { return mTime0; } ///< Reference time of the track, i.e. t-bins of a primary track with eta=0. - short getDeltaTBwd() const { return mDeltaTBwd; } ///< max possible decrement to getTimeVertex - short getDeltaTFwd() const { return mDeltaTFwd; } ///< max possible increment to getTimeVertex - void setDeltaTBwd(short t) { mDeltaTBwd = t; } ///< set max possible decrement to getTimeVertex - void setDeltaTFwd(short t) { mDeltaTFwd = t; } ///< set max possible increment to getTimeVertex + float getDeltaTBwd() const { return mDeltaTBwd; } ///< max possible decrement to getTimeVertex + float getDeltaTFwd() const { return mDeltaTFwd; } ///< max possible increment to getTimeVertex + void setDeltaTBwd(float t) { mDeltaTBwd = t; } ///< set max possible decrement to getTimeVertex + void setDeltaTFwd(float t) { mDeltaTFwd = t; } ///< set max possible increment to getTimeVertex float getChi2() const { return mChi2; } const o2::track::TrackParCov& getOuterParam() const { return mOuterParam; } @@ -112,15 +112,15 @@ class TrackTPC : public o2::track::TrackParCov float mTime0 = 0.f; ///< Reference Z of the track assumed for the vertex, scaled with pseudo ///< VDrift and reference timeframe length, unless it was moved to be on the ///< side of TPC compatible with edge clusters sides. - short mDeltaTFwd = 0; ///< max possible increment to track time - short mDeltaTBwd = 0; ///< max possible decrement to track time + float mDeltaTFwd = 0; ///< max possible increment to track time + float mDeltaTBwd = 0; ///< max possible decrement to track time short mFlags = 0; ///< various flags, see Flags enum float mChi2 = 0.f; // Chi2 of the track o2::track::TrackParCov mOuterParam; // Track parameters at outer end of TPC. dEdxInfo mdEdx; // dEdx Information ClusRef mClustersReference; // reference to externale cluster indices - ClassDefNV(TrackTPC, 3); + ClassDefNV(TrackTPC, 4); }; } // namespace tpc diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h index a7cbef0dc42bf..8b2498de7425e 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/LinkRecord.h @@ -23,6 +23,19 @@ namespace o2 namespace trd { +struct LinkId { + public: + union { + uint16_t word; + struct { + uint16_t spare : 4; + uint16_t side : 1; + uint16_t layer : 3; + uint16_t stack : 3; + uint16_t supermodule : 5; + }; + }; +}; /// \class LinkRecord /// \brief Header for data corresponding to the indexing of the links in the raw data output /// adapted from DataFormatsTRD/TriggerRecord @@ -32,32 +45,46 @@ class LinkRecord public: LinkRecord() = default; - LinkRecord(const uint32_t hcid, int firstentry, int nentries) : mLinkId(hcid), mDataRange(firstentry, nentries) {} + LinkRecord(const uint32_t linkid, int firstentry, int nentries) : mDataRange(firstentry, nentries) { mLinkId.word = linkid; } + // LinkRecord(const LinkRecord::LinkId linkid, int firstentry, int nentries) : mDataRange(firstentry, nentries) {mLinkId.word=linkid.word;} + LinkRecord(uint32_t sector, int stack, int layer, int side, int firstentry, int nentries) : mDataRange(firstentry, nentries) { setLinkId(sector, stack, layer, side); } + ~LinkRecord() = default; - void setLinkId(const uint32_t linkid) { mLinkId = linkid; } + void setLinkId(const uint32_t linkid) { mLinkId.word = linkid; } + void setLinkId(const LinkId linkid) { mLinkId.word = linkid.word; } + void setLinkId(const uint32_t sector, const uint32_t stack, const uint32_t layer, const uint32_t side); void setDataRange(int firstentry, int nentries) { mDataRange.set(firstentry, nentries); } void setIndexFirstObject(int firstentry) { mDataRange.setFirstEntry(firstentry); } void setNumberOfObjects(int nentries) { mDataRange.setEntries(nentries); } - uint32_t getLinkId() { return mLinkId; } - uint32_t getLinkHCID() { return mLinkId & 0x7ff; } // the last 11 bits. + const uint32_t getLinkId() { return mLinkId.word; } + //TODO come backwith a ccdb lookup. const uint32_t getLinkHCID() { return mLinkId & 0x7ff; } // the last 11 bits. + const uint32_t getSector() { return mLinkId.supermodule; } + const uint32_t getStack() { return mLinkId.stack; } + const uint32_t getLayer() { return mLinkId.layer; } + const uint32_t getSide() { return mLinkId.side; } int getNumberOfObjects() const { return mDataRange.getEntries(); } int getFirstEntry() const { return mDataRange.getFirstEntry(); } + static uint32_t getHalfChamberLinkId(uint32_t detector, uint32_t rob); + static uint32_t getHalfChamberLinkId(uint32_t sector, uint32_t stack, uint32_t layer, uint32_t side); - void printStream(std::ostream& stream) const; + void printStream(std::ostream& stream); private: - uint32_t mLinkId; /// The link ID for this set of data, hcid as well + LinkId mLinkId; DataRange mDataRange; /// Index of the triggering event (event index and first entry in the container) - - ClassDefNV(LinkRecord, 1); + ClassDefNV(LinkRecord, 2); }; -std::ostream& operator<<(std::ostream& stream, const LinkRecord& trg); +std::ostream& operator<<(std::ostream& stream, LinkRecord& trg); +extern void buildTrackletHCHeader(TrackletHCHeader& header, int sector, int stack, int layer, int side, int chipclock, int format); +extern void buildTrakcletHCHeader(TrackletHCHeader& header, int detector, int rob, int chipclock, int format); } // namespace trd } // namespace o2 #endif +//extern void buildTrackletHCHeader(TrackletHCHeader& header, int sector, int stack, int layer, int side, int chipclock, int format) +//extern void buildTrakcletlHCHeader(TrackletHCHeader& header, int detector, int rob, int chipclock, int format) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h index 226ee073932ce..678138301c9d6 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/RawData.h @@ -123,18 +123,23 @@ struct TrackletHCHeader { union { // 10987654321098765432109876543210 // uint32_t: 00000000000000000000000000000000 - // cccccccccccccccc iiiiiiiiiii - // ffff| y| - // | | |------ 0-10 half chamber id - // | | ------------- 11 always 0x1 - // | ----------------------------- 12-72 MCM Clock counter + // cccccccccccccccX LLL SSSSS + // ffff| |y| sss| + // | | ||| | |----- 0-4 supermodule + // | | ||| |-------- 5-7 stack + // | | ||------------ 8-10 layer + // | | |------------- 11 always 0x1 + // | | |------------- 12 side of chamber + // | ----------------------------- 13-72 MCM Clock counter // --------------------------------- 28-31 tracklet data format number uint32_t word; - struct { - uint32_t HCID : 11; // half chamber id 0:1079 + uint32_t supermodule : 5; + uint32_t stack : 3; + uint32_t layer : 3; uint32_t one : 1; //always 1 - uint32_t MCLK : 16; // MCM clock counter 120MHz ... for simulation -- incrementing, and same number in all for each event. + uint32_t side : 1; // side of chamber + uint32_t MCLK : 15; // MCM clock counter 120MHz ... for simulation -- incrementing, and same number in all for each event. uint32_t format : 4; // 0 baseline PID 3 time slices, 7 bit each // 1 DO NOT USE ! reserved for tracklet end marker disambiguation @@ -213,6 +218,8 @@ struct TRDFeeID { }; }; +void buildTrackletHCHeader(TrackletHCHeader& header, int sector, int stack, int layer, int side, int chipclock, int format); +void buildTrackletHCHeaderd(TrackletHCHeader& header, int detector, int rob, int chipclock, int format); uint16_t buildTRDFeeID(int supermodule, int side, int endpoint); uint32_t setHalfCRUHeader(HalfCRUHeader& cruhead, int crurdhversion, int bunchcrossing, int stopbits, int endpoint, int eventtype, int feeid, int cruid); uint32_t setHalfCRUHeaderLinkData(HalfCRUHeader& cruhead, int link, int size, int errors); diff --git a/DataFormats/Detectors/TRD/src/LinkRecord.cxx b/DataFormats/Detectors/TRD/src/LinkRecord.cxx index bafdbcf73d15d..e78b564277dc5 100644 --- a/DataFormats/Detectors/TRD/src/LinkRecord.cxx +++ b/DataFormats/Detectors/TRD/src/LinkRecord.cxx @@ -10,6 +10,7 @@ #include #include "DataFormatsTRD/LinkRecord.h" +#include "DataFormatsTRD/Constants.h" namespace o2 { @@ -17,12 +18,41 @@ namespace o2 namespace trd { -void LinkRecord::printStream(std::ostream& stream) const +uint32_t LinkRecord::getHalfChamberLinkId(uint32_t detector, uint32_t rob) { - stream << "Data for link 0x" << std::hex << mLinkId << std::dec << ", starting from entry " << getFirstEntry() << " with " << getNumberOfObjects() << " objects"; + int sector = (detector % (constants::NLAYER * constants::NSTACK)); + int stack = (detector % constants::NLAYER); + int layer = ((detector % (constants::NLAYER * constants::NSTACK)) / constants::NLAYER); + int side = rob % 2; + return getHalfChamberLinkId(sector, stack, layer, side); } -std::ostream& operator<<(std::ostream& stream, const LinkRecord& trg) +uint32_t LinkRecord::getHalfChamberLinkId(uint32_t sector, uint32_t stack, uint32_t layer, uint32_t side) +{ + LinkId tmplinkid; + tmplinkid.supermodule = sector; + tmplinkid.stack = stack; + tmplinkid.layer = layer; + ; + tmplinkid.side = side; + return tmplinkid.word; +} + +void LinkRecord::setLinkId(const uint32_t sector, const uint32_t stack, const uint32_t layer, const uint32_t side) +{ + mLinkId.supermodule = sector; + mLinkId.stack = stack; + mLinkId.layer = layer; + ; + mLinkId.side = side; +} + +void LinkRecord::printStream(std::ostream& stream) +{ + stream << "Data for link from supermodule:" << this->getSector() << " stack:" << this->getStack() << " layer:" << this->getLayer() << "side :" << this->getSide() << ", starting from entry " << this->getFirstEntry() << " with " << this->getNumberOfObjects() << " objects"; +} + +std::ostream& operator<<(std::ostream& stream, LinkRecord& trg) { trg.printStream(stream); return stream; diff --git a/DataFormats/Detectors/TRD/src/RawData.cxx b/DataFormats/Detectors/TRD/src/RawData.cxx index 80b2ac4a1aad1..189ffb2126b67 100644 --- a/DataFormats/Detectors/TRD/src/RawData.cxx +++ b/DataFormats/Detectors/TRD/src/RawData.cxx @@ -12,6 +12,8 @@ #include #include #include "DataFormatsTRD/RawData.h" +#include "DataFormatsTRD/LinkRecord.h" +#include "DataFormatsTRD/Constants.h" namespace o2 { @@ -19,6 +21,26 @@ namespace o2 namespace trd { +void buildTrackletHCHeader(TrackletHCHeader& header, int sector, int stack, int layer, int side, int chipclock, int format) +{ + header.MCLK = chipclock; + header.format = format; + header.one = 1; + header.supermodule = sector; + header.stack = stack; + header.layer = layer; + header.side = side; +} + +void buildTrackletHCHeaderd(TrackletHCHeader& header, int detector, int rob, int chipclock, int format) +{ + int sector = (detector % (constants::NLAYER * constants::NSTACK)); + int stack = (detector % constants::NLAYER); + int layer = ((detector % (constants::NLAYER * constants::NSTACK)) / constants::NLAYER); + int side = rob % 2; + buildTrackletHCHeader(header, sector, stack, layer, side, chipclock, format); +} + uint16_t buildTRDFeeID(int supermodule, int side, int endpoint) { TRDFeeID feeid; @@ -93,7 +115,9 @@ std::ostream& operator<<(std::ostream& stream, const TrackletHCHeader halfchambe { stream << "TrackletHCHeader : Raw:0x" << std::hex << halfchamberheader.word << " " << halfchamberheader.format << " ;; " << halfchamberheader.MCLK << " :: " - << halfchamberheader.one << " :: " << halfchamberheader.HCID << std::endl; + << halfchamberheader.one << " :: (" << halfchamberheader.supermodule << "," + << halfchamberheader.stack << "," << halfchamberheader.layer << ") on side :" + << halfchamberheader.side << std::endl; return stream; } @@ -129,8 +153,8 @@ std::ostream& operator<<(std::ostream& stream, const TrackletMCMHeader& mcmhead) void printHalfChamber(o2::trd::TrackletHCHeader const& halfchamber) { - LOGF(INFO, "TrackletHCHeader: Raw:0x%08x HCID : 0x%0x MCLK: 0x%0x Format: 0x%0x Always1:0x%0x", - halfchamber.HCID, halfchamber.MCLK, halfchamber.format, halfchamber.one); + LOGF(INFO, "TrackletHCHeader: Raw:0x%08x SM : %d stack %d layer %d side : %d MCLK: 0x%0x Format: 0x%0x Always1:0x%0x", + halfchamber.supermodule, halfchamber.stack, halfchamber.layer, halfchamber.side, halfchamber.MCLK, halfchamber.format, halfchamber.one); } void dumpHalfChamber(o2::trd::TrackletHCHeader const& halfchamber) diff --git a/DataFormats/Reconstruction/CMakeLists.txt b/DataFormats/Reconstruction/CMakeLists.txt index 5ba2f75d63cf1..578ceb660a0dd 100644 --- a/DataFormats/Reconstruction/CMakeLists.txt +++ b/DataFormats/Reconstruction/CMakeLists.txt @@ -19,6 +19,7 @@ o2_add_library(ReconstructionDataFormats src/TrackLTIntegral.cxx src/PID.cxx src/DCA.cxx + src/VtxTrackIndex.cxx PUBLIC_LINK_LIBRARIES O2::GPUCommon O2::DetectorsCommonDataFormats O2::CommonDataFormat) @@ -34,7 +35,8 @@ o2_target_root_dictionary( include/ReconstructionDataFormats/MatchInfoTOF.h include/ReconstructionDataFormats/TrackLTIntegral.h include/ReconstructionDataFormats/PID.h - include/ReconstructionDataFormats/DCA.h) + include/ReconstructionDataFormats/DCA.h + include/ReconstructionDataFormats/VtxTrackIndex.h) o2_add_test(Vertex SOURCES test/testVertex.cxx diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h index 90d6f8ab74277..8d319333a24da 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertex.h @@ -29,8 +29,12 @@ class PrimaryVertex : public Vertex> PrimaryVertex(const PrimaryVertex&) = default; ~PrimaryVertex() = default; - const InteractionRecord& getIR() const { return mIR; } - void setIR(const InteractionRecord& ir) { mIR = ir; } + const InteractionRecord& getIRMax() const { return mIRMax; } + void setIRMax(const InteractionRecord& ir) { mIRMax = ir; } + const InteractionRecord& getIRMin() const { return mIRMin; } + void setIRMin(const InteractionRecord& ir) { mIRMin = ir; } + void setIR(const InteractionRecord& ir) { mIRMin = mIRMax = ir; } + bool hasUniqueIR() const { return !mIRMin.isDummy() && (mIRMin == mIRMax); } #ifndef ALIGPU_GPUCODE void print() const; @@ -38,7 +42,8 @@ class PrimaryVertex : public Vertex> #endif protected: - InteractionRecord mIR{}; ///< by default not assigned! + InteractionRecord mIRMin{}; ///< by default not assigned! + InteractionRecord mIRMax{}; ///< by default not assigned! ClassDefNV(PrimaryVertex, 1); }; @@ -48,5 +53,16 @@ std::ostream& operator<<(std::ostream& os, const o2::dataformats::PrimaryVertex& #endif } // namespace dataformats + +/// Defining PrimaryVertex explicitly as messageable +namespace framework +{ +template +struct is_messageable; +template <> +struct is_messageable : std::true_type { +}; +} // namespace framework + } // namespace o2 #endif diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h index 655d4409fe440..e30d2cc090135 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Track.h @@ -200,6 +200,9 @@ class TrackPar void invertParam(); + bool isValid() const { return mX != InvalidX; } + void invalidate() { mX = InvalidX; } + #ifndef GPUCA_ALIGPUCODE void printParam() const; std::string asString() const; @@ -217,6 +220,7 @@ class TrackPar private: // + static constexpr float InvalidX = -99999.; float mX = 0.f; /// X of track evaluation float mAlpha = 0.f; /// track frame angle float mP[kNParams] = {0.f}; /// 5 parameters: Y,Z,sin(phi),tg(lambda),q/pT diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h new file mode 100644 index 0000000000000..b001d3f8a73c1 --- /dev/null +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/VtxTrackIndex.h @@ -0,0 +1,56 @@ +// 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 VtxTrackIndex.h +/// \brief Index of track attached to vertx: index in its proper container, container source and flags +/// \author ruben.shahoyan@cern.ch + +#ifndef O2_VERTEX_TRACK_INDEX +#define O2_VERTEX_TRACK_INDEX + +#include "CommonDataFormat/AbstractRef.h" +#include +#include + +namespace o2 +{ +namespace dataformats +{ + +class VtxTrackIndex : public AbstractRef<26, 3, 3> +{ + public: + enum Source : uint8_t { // provenance of the track + TPCITS, + ITS, + TPC, + NSources + }; + enum Flags : uint8_t { + Contributor, // flag that it contributes to vertex fit + Reserved, // + Ambiguous, // flag that attachment is ambiguous + NFlags + }; + + using AbstractRef<26, 3, 3>::AbstractRef; + + void print() const; + std::string asString() const; + + ClassDefNV(VtxTrackIndex, 1); +}; + +std::ostream& operator<<(std::ostream& os, const o2::dataformats::VtxTrackIndex& v); + +} // namespace dataformats +} // namespace o2 + +#endif diff --git a/DataFormats/Reconstruction/src/PrimaryVertex.cxx b/DataFormats/Reconstruction/src/PrimaryVertex.cxx index 387e707d47fe5..f94606c2e203a 100644 --- a/DataFormats/Reconstruction/src/PrimaryVertex.cxx +++ b/DataFormats/Reconstruction/src/PrimaryVertex.cxx @@ -22,9 +22,13 @@ namespace dataformats std::string PrimaryVertex::asString() const { - return o2::utils::concat_string(VertexBase::asString(), - fmt::format("Chi2={:.2f} NCont={:d}: T={:.3f}+-{:.3f} IR=", mChi2, mNContributors, mTimeStamp.getTimeStamp(), mTimeStamp.getTimeStampError()), - mIR.asString()); + auto str = o2::utils::concat_string(VertexBase::asString(), + fmt::format("Chi2={:.2f} NCont={:d}: T={:.3f}+-{:.3f} IR=", mChi2, mNContributors, mTimeStamp.getTimeStamp(), mTimeStamp.getTimeStampError()), + mIRMin.asString()); + if (!hasUniqueIR()) { + str = o2::utils::concat_string(str, " : ", mIRMax.asString()); + } + return str; } std::ostream& operator<<(std::ostream& os, const o2::dataformats::PrimaryVertex& v) diff --git a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h index 8016fc3888756..1cf45dcc23905 100644 --- a/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h +++ b/DataFormats/Reconstruction/src/ReconstructionDataFormatsLinkDef.h @@ -41,6 +41,9 @@ #pragma link C++ class std::vector < o2::dataformats::Vertex < o2::dataformats::TimeStampWithError < float, float>>> + ; #pragma link C++ class std::vector < o2::dataformats::PrimaryVertex> + ; +#pragma link C++ class o2::dataformats::VtxTrackIndex + ; +#pragma link C++ class std::vector < o2::dataformats::VtxTrackIndex> + ; + #pragma link C++ class o2::dataformats::DCA + ; #endif diff --git a/DataFormats/Reconstruction/src/VtxTrackIndex.cxx b/DataFormats/Reconstruction/src/VtxTrackIndex.cxx new file mode 100644 index 0000000000000..62d0b39905443 --- /dev/null +++ b/DataFormats/Reconstruction/src/VtxTrackIndex.cxx @@ -0,0 +1,39 @@ +// 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 VtxTrackIndex.h +/// \brief Index of track attached to vertx: index in its proper container, container source and flags +/// \author ruben.shahoyan@cern.ch + +#include "ReconstructionDataFormats/VtxTrackIndex.h" +#include "Framework/Logger.h" +#include +#include +#include + +using namespace o2::dataformats; + +std::string VtxTrackIndex::asString() const +{ + std::bitset bits{getFlags()}; + return fmt::format("[{:d}/{:d}/{:s}]", getIndex(), getSource(), bits.to_string()); +} + +std::ostream& operator<<(std::ostream& os, const o2::dataformats::VtxTrackIndex& v) +{ + // stream itself + os << v.asString(); + return os; +} + +void VtxTrackIndex::print() const +{ + LOG(INFO) << asString(); +} diff --git a/DataFormats/common/CMakeLists.txt b/DataFormats/common/CMakeLists.txt index df5fd75cac3fb..1a1e512672fa0 100644 --- a/DataFormats/common/CMakeLists.txt +++ b/DataFormats/common/CMakeLists.txt @@ -18,7 +18,8 @@ o2_target_root_dictionary(CommonDataFormat include/CommonDataFormat/EvIndex.h include/CommonDataFormat/RangeReference.h include/CommonDataFormat/InteractionRecord.h - include/CommonDataFormat/BunchFilling.h) + include/CommonDataFormat/BunchFilling.h + include/CommonDataFormat/AbstractRef.h) o2_add_test(TimeStamp SOURCES test/testTimeStamp.cxx diff --git a/DataFormats/common/include/CommonDataFormat/AbstractRef.h b/DataFormats/common/include/CommonDataFormat/AbstractRef.h new file mode 100644 index 0000000000000..fbfc95d49d213 --- /dev/null +++ b/DataFormats/common/include/CommonDataFormat/AbstractRef.h @@ -0,0 +1,82 @@ +// 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 AbstractRef.h +/// \brief Class to refer to object indicating its Indec, Source and status flags +/// \author ruben.shahoyan@cern.ch + +#ifndef ALICEO2_ABSTRACT_REF_H +#define ALICEO2_ABSTRACT_REF_H + +#include + +namespace o2 +{ +namespace dataformats +{ + +template +class AbstractRef +{ + template + static constexpr auto MVAR() + { + typename std::conditional<(NBIT > 32), uint64_t, typename std::conditional<(NBIT > 16), uint32_t, typename std::conditional<(NBIT > 8), uint16_t, uint8_t>::type>::type>::type tp = 0; + return tp; + } + + public: + using Base_t = decltype(AbstractRef::MVAR()); + using Idx_t = decltype(AbstractRef::MVAR()); + using Src_t = decltype(AbstractRef::MVAR()); + using Flg_t = decltype(AbstractRef::MVAR()); + + static constexpr Base_t BaseMask = Base_t((((0x1U << (NBIdx + NBSrc + NBFlg - 1)) - 1) << 1) + 1); + static constexpr Idx_t IdxMask = Idx_t((((0x1U << (NBIdx - 1)) - 1) << 1) + 1); + static constexpr Src_t SrcMask = Src_t((((0x1U << (NBSrc - 1)) - 1) << 1) + 1); + static constexpr Flg_t FlgMask = Flg_t((((0x1U << (NBFlg - 1)) - 1) << 1) + 1); + static constexpr int NBitsIndex() { return NBIdx; } + static constexpr int NBitsSource() { return NBSrc; } + static constexpr int NBitsFlags() { return NBFlg; } + + AbstractRef() = default; + + AbstractRef(Idx_t idx) { setIndex(idx); } + + AbstractRef(Idx_t idx, Src_t src) { set(idx, src); } + + // + Idx_t getIndex() const { return static_cast(mRef & IdxMask); } + void setIndex(Idx_t idx) { mRef = (mRef & (BaseMask & ~IdxMask)) | (IdxMask & idx); } + + // + Src_t getSource() const { return static_cast((mRef >> NBIdx) & SrcMask); } + void setSource(Src_t src) { mRef = (mRef & (BaseMask & ~(SrcMask << NBIdx))) | ((SrcMask & src) << NBIdx); } + + // + Flg_t getFlags() const { return static_cast((mRef >> (NBIdx + NBSrc)) & FlgMask); } + void setFlags(Flg_t f) { mRef = (mRef & (BaseMask & ~(FlgMask << (NBIdx + NBSrc)))) | ((FlgMask & f) << NBIdx); } + bool testBit(int i) const { return (mRef >> (NBIdx + NBSrc)) & ((0x1U << i) & FlgMask); } + void setBit(int i) { mRef = (mRef & (BaseMask & ~(0x1U << (i + NBIdx + NBSrc)))) | (((0x1U << i) & FlgMask) << (NBIdx + NBSrc)); } + void resetBit(int i) { mRef = (mRef & (BaseMask & ~(0x1U << (i + NBIdx + NBSrc)))); } + void set(Idx_t idx, Src_t src) { mRef = (mRef & (BaseMask & ~((SrcMask << NBIdx) | (BaseMask & ~IdxMask)))) | ((SrcMask & Src_t(src)) << NBIdx) | (IdxMask & Idx_t(idx)); } + + Base_t getRaw() const { return mRef; } + + protected: + Base_t mRef = 0; // packed reference + + ClassDefNV(AbstractRef, 1); +}; + +} // namespace dataformats +} // namespace o2 + +#endif diff --git a/DataFormats/common/include/CommonDataFormat/BunchFilling.h b/DataFormats/common/include/CommonDataFormat/BunchFilling.h index 14775e468f9bf..30d50109a6c5c 100644 --- a/DataFormats/common/include/CommonDataFormat/BunchFilling.h +++ b/DataFormats/common/include/CommonDataFormat/BunchFilling.h @@ -29,6 +29,8 @@ class BunchFilling void setBCTrains(int nTrains, int trainSpacingInBC, int nBC, int bcSpacing, int firstBC); void print(int bcPerLine = 100) const; const auto& getPattern() const { return mPattern; } + int getFirstFilledBC() const; + int getLastFilledBC() const; // set BC filling a la TPC TDR, 12 50ns trains of 48 BCs // but instead of uniform train spacing we add 96empty BCs after each train void setDefault() diff --git a/DataFormats/common/include/CommonDataFormat/InteractionRecord.h b/DataFormats/common/include/CommonDataFormat/InteractionRecord.h index b6d34aa5d7605..e68f0260266a6 100644 --- a/DataFormats/common/include/CommonDataFormat/InteractionRecord.h +++ b/DataFormats/common/include/CommonDataFormat/InteractionRecord.h @@ -98,6 +98,16 @@ struct InteractionRecord { return diffBC; } + float differenceInBCns(const InteractionRecord& other) const + { + // return differenc in bunch-crossings + int64_t diffBC = int(bc) - other.bc; + if (orbit != other.orbit) { + diffBC += (int64_t(orbit) - other.orbit) * o2::constants::lhc::LHCMaxBunches; + } + return diffBC; + } + int64_t toLong() const { // return as single long number diff --git a/DataFormats/common/src/BunchFilling.cxx b/DataFormats/common/src/BunchFilling.cxx index 328c63ff50707..818be2c9361b0 100644 --- a/DataFormats/common/src/BunchFilling.cxx +++ b/DataFormats/common/src/BunchFilling.cxx @@ -15,6 +15,28 @@ using namespace o2; +//_________________________________________________ +int BunchFilling::getFirstFilledBC() const +{ + for (int bc = 0; bc < o2::constants::lhc::LHCMaxBunches; bc++) { + if (testBC(bc)) { + return bc; + } + } + return -1; +} + +//_________________________________________________ +int BunchFilling::getLastFilledBC() const +{ + for (int bc = o2::constants::lhc::LHCMaxBunches; bc--;) { + if (testBC(bc)) { + return bc; + } + } + return -1; +} + //_________________________________________________ void BunchFilling::setBC(int bcID, bool active) { diff --git a/DataFormats/common/src/CommonDataFormatLinkDef.h b/DataFormats/common/src/CommonDataFormatLinkDef.h index 269fb2c5433b2..502697b733e6d 100644 --- a/DataFormats/common/src/CommonDataFormatLinkDef.h +++ b/DataFormats/common/src/CommonDataFormatLinkDef.h @@ -46,4 +46,6 @@ #pragma link C++ class o2::InteractionTimeRecord + ; #pragma link C++ class o2::BunchFilling + ; +#pragma link C++ class o2::dataformats::AbstractRef < 26, 3, 3> + ; + #endif diff --git a/DataFormats/simulation/CMakeLists.txt b/DataFormats/simulation/CMakeLists.txt index 27aab16c6496c..9ed5155633744 100644 --- a/DataFormats/simulation/CMakeLists.txt +++ b/DataFormats/simulation/CMakeLists.txt @@ -37,6 +37,7 @@ o2_target_root_dictionary( include/SimulationDataFormat/LabelContainer.h include/SimulationDataFormat/MCEventHeader.h include/SimulationDataFormat/MCEventStats.h + include/SimulationDataFormat/IOMCTruthContainerView.h LINKDEF src/SimulationDataLinkDef.h) # note the explicit LINKDEF as the linkdef in src is # diff --git a/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h new file mode 100644 index 0000000000000..da263e5da9c1c --- /dev/null +++ b/DataFormats/simulation/include/SimulationDataFormat/ConstMCTruthContainer.h @@ -0,0 +1,118 @@ +// 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 ConstMCTruthContainer.h +/// \brief A const (ready only) version of MCTruthContainer +/// \author Sandro Wenzel - August 2020 + +#ifndef O2_CONSTMCTRUTHCONTAINER_H +#define O2_CONSTMCTRUTHCONTAINER_H + +#include +#include + +namespace o2 +{ +namespace dataformats +{ + +/// @class ConstMCTruthContainer +/// @brief A read-only version of MCTruthContainer allowing for storage optimisation +/// +/// This provides access functionality to MCTruthContainer with optimized linear storage +/// so that the data can easily be shared in memory or sent over network. +/// This container needs to be initialized by calling "flatten_to" from an existing +/// MCTruthContainer +template +class ConstMCTruthContainer : public std::vector +{ + public: + // (unfortunately we need these constructors for DPL) + using std::vector::vector; + ConstMCTruthContainer() = default; + + // const data access + // get individual const "view" container for a given data index + // the caller can't do modifications on this view + MCTruthHeaderElement const& getMCTruthHeader(uint32_t dataindex) const + { + return getHeaderStart()[dataindex]; + } + + gsl::span getLabels(uint32_t dataindex) const + { + if (dataindex >= getIndexedSize()) { + return gsl::span(); + } + const auto start = getMCTruthHeader(dataindex).index; + const auto labelsptr = getLabelStart(); + return gsl::span(&labelsptr[start], getSize(dataindex)); + } + + // return the number of original data indexed here + size_t getIndexedSize() const { return size() >= sizeof(FlatHeader) ? getHeader().nofHeaderElements : 0; } + + // return the number of labels managed in this container + size_t getNElements() const { return size() >= sizeof(FlatHeader) ? getHeader().nofTruthElements : 0; } + + private: + using FlatHeader = typename MCTruthContainer::FlatHeader; + + size_t getSize(uint32_t dataindex) const + { + // calculate size / number of labels from a difference in pointed indices + const auto size = (dataindex < getIndexedSize() - 1) + ? getMCTruthHeader(dataindex + 1).index - getMCTruthHeader(dataindex).index + : getNElements() - getMCTruthHeader(dataindex).index; + return size; + } + + /// Restore internal vectors from a raw buffer + /// The two vectors are resized according to the information in the \a FlatHeader + /// struct at the beginning of the buffer. Data is copied to the vectors. + TruthElement const* const getLabelStart() const + { + auto* source = &(*this)[0]; + auto flatheader = getHeader(); + source += sizeof(FlatHeader); + const size_t headerSize = flatheader.sizeofHeaderElement * flatheader.nofHeaderElements; + source += headerSize; + return (TruthElement const* const)source; + } + + FlatHeader const& getHeader() const + { + const auto* source = &(*this)[0]; + const auto& flatheader = *reinterpret_cast(source); + return flatheader; + } + + MCTruthHeaderElement const* const getHeaderStart() const + { + auto* source = &(*this)[0]; + source += sizeof(FlatHeader); + return (MCTruthHeaderElement const* const)source; + } +}; +} // namespace dataformats +} // namespace o2 + +// This is done so that DPL treats this container as a vector. +// In particular in enables +// a) --> snapshot without ROOT dictionary (as a flat buffer) +// b) --> requesting the resource in shared mem using make +namespace o2::framework +{ +template +struct is_specialization, std::vector> : std::true_type { +}; +} // namespace o2::framework + +#endif //O2_CONSTMCTRUTHCONTAINER_H diff --git a/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h b/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h new file mode 100644 index 0000000000000..db9f80cc7de9b --- /dev/null +++ b/DataFormats/simulation/include/SimulationDataFormat/IOMCTruthContainerView.h @@ -0,0 +1,105 @@ +// 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 IOMCTruthContainerView.h +/// \brief A special IO container - splitting a given vector to enable ROOT IO +/// \author Sandro Wenzel - August 2020 + +#ifndef ALICEO2_DATAFORMATS_IOMCTRUTHVIEW_H_ +#define ALICEO2_DATAFORMATS_IOMCTRUTHVIEW_H_ + +#include "GPUCommonRtypes.h" // to have the ClassDef macros +#include +#include + +namespace o2 +{ +namespace dataformats +{ + +/// +/// A specially constructed class allowing to stream a very large +/// vector buffer to a ROOT file. This is needed since ROOT currently has a size +/// limitation of ~1GB for data that it can stream per entry in a branch. +/// The solution is based on the ability of ROOT to split entries per data member, so +/// some input buffer gets divided into multiple parts. +/// +/// TODO: We could template this class to encode original type information (for the input buffer). +class IOMCTruthContainerView +{ + public: + IOMCTruthContainerView() = default; + + /// Constructor taking an existing flat vector as input; No copy is done - the + /// container is just a split view on the original buffer. + IOMCTruthContainerView(std::vector const& input) + { + const auto delta = input.size() / N; + N2 = input.size() - (N - 1) * delta; + N1 = delta; + // TODO: this could benefit from a loop expansion + part1 = &input[0]; + part2 = &input[delta]; + part3 = &input[2 * delta]; + part4 = &input[3 * delta]; + part5 = &input[4 * delta]; + part6 = &input[5 * delta]; + part7 = &input[6 * delta]; + part8 = &input[7 * delta]; + part9 = &input[8 * delta]; + part10 = &input[9 * delta]; + } + + /// A function to recreate a flat output vector from this buffer. This + /// function is copying the data. + template + void copyandflatten(std::vector& output) const + { + // TODO: this could benefit from a loop expansion + copyhelper(part1, N1, output); + copyhelper(part2, N1, output); + copyhelper(part3, N1, output); + copyhelper(part4, N1, output); + copyhelper(part5, N1, output); + copyhelper(part6, N1, output); + copyhelper(part7, N1, output); + copyhelper(part8, N1, output); + copyhelper(part9, N1, output); + copyhelper(part10, N2, output); + } + + private: + static constexpr int N = 10; + int N1 = 0; + int N2 = 0; + const char* part1 = nullptr; //[N1] + const char* part2 = nullptr; //[N1] + const char* part3 = nullptr; //[N1] + const char* part4 = nullptr; //[N1] + const char* part5 = nullptr; //[N1] + const char* part6 = nullptr; //[N1] + const char* part7 = nullptr; //[N1] + const char* part8 = nullptr; //[N1] + const char* part9 = nullptr; //[N1] + const char* part10 = nullptr; //[N2] + + template + void copyhelper(const char* input, int size, std::vector& output) const + { + gsl::span tmp(input, size); + std::copy(tmp.begin(), tmp.end(), std::back_inserter(output)); + } + + ClassDefNV(IOMCTruthContainerView, 1); +}; +} // namespace dataformats +} // namespace o2 + +#endif diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h index 3fbac958bbbc1..801276ecad36b 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCTruthContainer.h @@ -310,7 +310,7 @@ class MCTruthContainer /// The flattened data starts with a specific header @ref FlatHeader describing /// size and content of the two vectors within the raw buffer. template - size_t flatten_to(ContainerType& container) + size_t flatten_to(ContainerType& container) const { size_t bufferSize = sizeof(FlatHeader) + sizeof(MCTruthHeaderElement) * mHeaderArray.size() + sizeof(TruthElement) * mTruthArray.size(); container.resize((bufferSize / sizeof(typename ContainerType::value_type)) + ((bufferSize % sizeof(typename ContainerType::value_type)) > 0 ? 1 : 0)); diff --git a/DataFormats/simulation/src/SimulationDataLinkDef.h b/DataFormats/simulation/src/SimulationDataLinkDef.h index 8977197322fec..8c18aee9724ee 100644 --- a/DataFormats/simulation/src/SimulationDataLinkDef.h +++ b/DataFormats/simulation/src/SimulationDataLinkDef.h @@ -68,4 +68,6 @@ #pragma link C++ class o2::dataformats::MCEventStats + ; #pragma link C++ class o2::dataformats::MCEventHeader + ; +#pragma link C++ class o2::dataformats::IOMCTruthContainerView + ; + #endif diff --git a/DataFormats/simulation/test/testMCTruthContainer.cxx b/DataFormats/simulation/test/testMCTruthContainer.cxx index 7045309196d2b..725e0eb9015cb 100644 --- a/DataFormats/simulation/test/testMCTruthContainer.cxx +++ b/DataFormats/simulation/test/testMCTruthContainer.cxx @@ -13,9 +13,14 @@ #define BOOST_TEST_DYN_LINK #include #include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/LabelContainer.h" +#include "SimulationDataFormat/IOMCTruthContainerView.h" #include #include +#include +#include namespace o2 { @@ -180,6 +185,19 @@ BOOST_AUTO_TEST_CASE(MCTruthContainer_flatten) BOOST_CHECK(restoredContainer.getElement(1) == 2); BOOST_CHECK(restoredContainer.getElement(2) == 1); BOOST_CHECK(restoredContainer.getElement(3) == 10); + + // check the special version ConstMCTruthContainer + using ConstMCTruthContainer = dataformats::ConstMCTruthContainer; + ConstMCTruthContainer cc; + container.flatten_to(cc); + + BOOST_CHECK(cc.getIndexedSize() == container.getIndexedSize()); + BOOST_CHECK(cc.getNElements() == container.getNElements()); + BOOST_CHECK(cc.getLabels(0).size() == container.getLabels(0).size()); + BOOST_CHECK(cc.getLabels(1).size() == container.getLabels(1).size()); + BOOST_CHECK(cc.getLabels(2).size() == container.getLabels(2).size()); + BOOST_CHECK(cc.getLabels(2)[0] == container.getLabels(2)[0]); + BOOST_CHECK(cc.getLabels(2)[0] == 10); } BOOST_AUTO_TEST_CASE(LabelContainer_noncont) @@ -305,4 +323,52 @@ BOOST_AUTO_TEST_CASE(MCTruthContainer_move) BOOST_CHECK(container.getNElements() == 4); } +BOOST_AUTO_TEST_CASE(MCTruthContainer_ROOTIO) +{ + using TruthElement = o2::MCCompLabel; + using Container = dataformats::MCTruthContainer; + Container container; + const size_t BIGSIZE{1000000}; + for (int i = 0; i < BIGSIZE; ++i) { + container.addElement(i, TruthElement(i, i, i)); + container.addElement(i, TruthElement(i + 1, i, i)); + } + std::vector buffer; + container.flatten_to(buffer); + + // We use the special IO split container to stream to a file and back + dataformats::IOMCTruthContainerView io(buffer); + { + TFile f("tmp2.root", "RECREATE"); + TTree tree("o2sim", "o2sim"); + auto br = tree.Branch("Labels", &io, 32000, 2); + tree.Fill(); + tree.Write(); + f.Close(); + } + + // read back + TFile f2("tmp2.root", "OPEN"); + auto tree2 = (TTree*)f2.Get("o2sim"); + dataformats::IOMCTruthContainerView* io2 = nullptr; + auto br2 = tree2->GetBranch("Labels"); + BOOST_CHECK(br2 != nullptr); + br2->SetAddress(&io2); + br2->GetEntry(0); + + // make a const MC label container out of it + using ConstMCTruthContainer = dataformats::ConstMCTruthContainer; + ConstMCTruthContainer cc; + io2->copyandflatten(cc); + + BOOST_CHECK(cc.getNElements() == BIGSIZE * 2); + BOOST_CHECK(cc.getIndexedSize() == BIGSIZE); + BOOST_CHECK(cc.getLabels(0).size() == 2); + BOOST_CHECK(cc.getLabels(0)[0] == TruthElement(0, 0, 0)); + BOOST_CHECK(cc.getLabels(0)[1] == TruthElement(1, 0, 0)); + BOOST_CHECK(cc.getLabels(BIGSIZE - 1).size() == 2); + BOOST_CHECK(cc.getLabels(BIGSIZE - 1)[0] == TruthElement(BIGSIZE - 1, BIGSIZE - 1, BIGSIZE - 1)); + BOOST_CHECK(cc.getLabels(BIGSIZE - 1)[1] == TruthElement(BIGSIZE, BIGSIZE - 1, BIGSIZE - 1)); +} + } // namespace o2 diff --git a/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h b/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h index 74373e7137ae3..35ae9e3d7a48d 100644 --- a/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h +++ b/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h @@ -52,6 +52,7 @@ class TimeSlotCalibration virtual bool process(TFType tf, const gsl::span data); virtual void checkSlotsToFinalize(TFType tf, int maxDelay = 0); + virtual void finalizeOldestSlot(); // Methods to be implemented by the derived user class @@ -136,6 +137,20 @@ void TimeSlotCalibration::checkSlotsToFinalize(TFType tf, int } } +//_________________________________________________ +template +void TimeSlotCalibration::finalizeOldestSlot() +{ + // Enforce finalization and removal of the oldest slot + if (mSlots.empty()) { + LOG(WARNING) << "There are no slots defined"; + return; + } + finalizeSlot(mSlots.front()); + mLastClosedTF = mSlots.front().getTFEnd() + 1; // do not accept any TF below this + mSlots.erase(mSlots.begin()); +} + //________________________________________ template inline TFType TimeSlotCalibration::tf2SlotMin(TFType tf) const diff --git a/Detectors/EMCAL/base/src/Geometry.cxx b/Detectors/EMCAL/base/src/Geometry.cxx index d3f3476a6a082..08688e4a24657 100644 --- a/Detectors/EMCAL/base/src/Geometry.cxx +++ b/Detectors/EMCAL/base/src/Geometry.cxx @@ -1509,7 +1509,7 @@ const TGeoHMatrix* Geometry::GetMatrixForSuperModuleFromGeoManager(Int_t smod) c LOG(ERROR) << "Unkown SM Type!!\n"; } - snprintf(path, buffersize, "/cave/%s_%d", smName.Data(), smOrder); + snprintf(path, buffersize, "/cave/barrel_1/%s_%d", smName.Data(), smOrder); if (!gGeoManager->cd(path)) { LOG(FATAL) << "Geo manager can not find path " << path << "!\n"; @@ -1531,7 +1531,7 @@ void Geometry::RecalculateTowerPosition(Float_t drow, Float_t dcol, const Int_t const Int_t nSMod = mNumberOfSuperModules; - gGeoManager->cd("/cave/barrel/"); + gGeoManager->cd("/cave/barrel_1/"); TGeoNode* geoXEn1 = gGeoManager->GetCurrentNode(); TGeoNodeMatrix* geoSM[nSMod]; TGeoVolume* geoSMVol[nSMod]; diff --git a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h b/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h index 5eff51302fe83..1ba5f43562e16 100644 --- a/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h +++ b/Detectors/EMCAL/simulation/include/EMCALSimulation/RawWriter.h @@ -89,17 +89,13 @@ class RawWriter void setOutputLocation(const char* outputdir) { mOutputLocation = outputdir; } void setDigits(gsl::span digits) { mDigits = digits; } void setFileFor(FileFor_t filefor) { mFileFor = filefor; } - void setTriggerRecords(gsl::span triggers); void setNumberOfADCSamples(int nsamples) { mNADCSamples = nsamples; } void setPedestal(int pedestal) { mPedestal = pedestal; } void setGeometry(o2::emcal::Geometry* geo) { mGeometry = geo; } - bool hasNextTrigger() const { return mCurrentTrigger != mTriggers.end(); } - void init(); - void process(); void digitsToRaw(gsl::span digits, gsl::span triggers); - bool processNextTrigger(); + bool processTrigger(const o2::emcal::TriggerRecord& trg); int carryOverMethod(const header::RDHAny* rdh, const gsl::span data, const char* ptr, int maxSize, int splitID, @@ -115,17 +111,15 @@ class RawWriter std::vector encodeBunchData(const std::vector& data); private: - int mNADCSamples = 15; ///< Number of time samples - int mPedestal = 0; ///< Pedestal - FileFor_t mFileFor = FileFor_t::kFullDet; ///< Granularity of the output files - o2::emcal::Geometry* mGeometry = nullptr; ///< EMCAL geometry - std::string mOutputLocation; ///< Rawfile name - std::unique_ptr mMappingHandler; ///< Mapping handler - gsl::span mDigits; ///< Digits input vector - must be in digitized format including the time response - gsl::span mTriggers; ///< Trigger records, separating the data from different triggers - std::vector mSRUdata; ///< Internal helper of digits assigned to SRUs - gsl::span::iterator mCurrentTrigger; ///< Current trigger in the trigger records - std::unique_ptr mRawWriter; ///< Raw writer + int mNADCSamples = 15; ///< Number of time samples + int mPedestal = 0; ///< Pedestal + FileFor_t mFileFor = FileFor_t::kFullDet; ///< Granularity of the output files + o2::emcal::Geometry* mGeometry = nullptr; ///< EMCAL geometry + std::string mOutputLocation; ///< Rawfile name + std::unique_ptr mMappingHandler; ///< Mapping handler + gsl::span mDigits; ///< Digits input vector - must be in digitized format including the time response + std::vector mSRUdata; ///< Internal helper of digits assigned to SRUs + std::unique_ptr mRawWriter; ///< Raw writer ClassDefNV(RawWriter, 1); }; diff --git a/Detectors/EMCAL/simulation/src/RawCreator.cxx b/Detectors/EMCAL/simulation/src/RawCreator.cxx index 01bdcc1fabad0..57c60140cea4e 100644 --- a/Detectors/EMCAL/simulation/src/RawCreator.cxx +++ b/Detectors/EMCAL/simulation/src/RawCreator.cxx @@ -109,5 +109,5 @@ int main(int argc, const char** argv) for (auto en : *treereader) { rawwriter.digitsToRaw(*digitbranch, *triggerbranch); } - rawwriter.getWriter().writeConfFile("EMC", "RAWDATA", o2::utils::concat_string(outputdir, "raw.cfg")); + rawwriter.getWriter().writeConfFile("EMC", "RAWDATA", o2::utils::concat_string(outputdir, "/EMCraw.cfg")); } diff --git a/Detectors/EMCAL/simulation/src/RawWriter.cxx b/Detectors/EMCAL/simulation/src/RawWriter.cxx index 2bac5412c1e0c..b4c6d3b202b4b 100644 --- a/Detectors/EMCAL/simulation/src/RawWriter.cxx +++ b/Detectors/EMCAL/simulation/src/RawWriter.cxx @@ -20,12 +20,6 @@ using namespace o2::emcal; -void RawWriter::setTriggerRecords(gsl::span triggers) -{ - mTriggers = triggers; - mCurrentTrigger = triggers.begin(); -} - void RawWriter::init() { mRawWriter = std::make_unique(o2::header::gDataOriginEMC, false); @@ -41,7 +35,7 @@ void RawWriter::init() std::string rawfilename = mOutputLocation; switch (mFileFor) { case FileFor_t::kFullDet: - rawfilename += "/emcal.root"; + rawfilename += "/emcal.raw"; break; case FileFor_t::kSubDet: { std::string detstring; @@ -49,11 +43,11 @@ void RawWriter::init() detstring = "emcal"; else detstring = "dcal"; - rawfilename += fmt::format("/%s", detstring.data()); + rawfilename += fmt::format("/{:s}.raw", detstring.data()); break; }; case FileFor_t::kLink: - rawfilename += fmt::format("/emcal_%d_%d.root", crorc, link); + rawfilename += fmt::format("/emcal_{:d}_{:d}.raw", crorc, link); } mRawWriter->registerLink(iddl, crorc, link, 0, rawfilename.data()); } @@ -69,31 +63,26 @@ void RawWriter::init() } } -void RawWriter::process() -{ - while (processNextTrigger()) - ; -} - void RawWriter::digitsToRaw(gsl::span digitsbranch, gsl::span triggerbranch) { setDigits(digitsbranch); - setTriggerRecords(triggerbranch); - process(); + for (auto trg : triggerbranch) { + processTrigger(trg); + } } -bool RawWriter::processNextTrigger() +bool RawWriter::processTrigger(const o2::emcal::TriggerRecord& trg) { - if (mCurrentTrigger == mTriggers.end()) - return false; for (auto srucont : mSRUdata) srucont.mChannels.clear(); std::vector* bunchDigits; int lasttower = -1; - for (auto& dig : gsl::span(mDigits.data() + mCurrentTrigger->getFirstEntry(), mCurrentTrigger->getNumberOfObjects())) { + for (auto& dig : gsl::span(mDigits.data() + trg.getFirstEntry(), trg.getNumberOfObjects())) { auto tower = dig.getTower(); if (tower != lasttower) { lasttower = tower; + if (tower > 20000) + std::cout << "Wrong cell ID " << tower << std::endl; auto onlineindices = getOnlineID(tower); int sruID = std::get<0>(onlineindices); auto towerdata = mSRUdata[sruID].mChannels.find(tower); @@ -104,19 +93,21 @@ bool RawWriter::processNextTrigger() } else { bunchDigits = &(towerdata->second.mDigits); } - // Get time sample of the digit: - // Digitizer stores the time sample in ns, needs to be converted to time sample dividing - // by the length of the time sample - auto timesample = int(dig.getTimeStamp() / emcal::constants::EMCAL_TIMESAMPLE); - if (timesample >= mNADCSamples) { - LOG(ERROR) << "Digit time sample " << timesample << " outside range [0," << mNADCSamples << "]"; - continue; - } - (*bunchDigits)[timesample] = &dig; } + + // Get time sample of the digit: + // Digitizer stores the time sample in ns, needs to be converted to time sample dividing + // by the length of the time sample + auto timesample = int(dig.getTimeStamp() / emcal::constants::EMCAL_TIMESAMPLE); + if (timesample >= mNADCSamples) { + LOG(ERROR) << "Digit time sample " << timesample << " outside range [0," << mNADCSamples << "]"; + continue; + } + (*bunchDigits)[timesample] = &dig; } // Create and fill DMA pages for each channel + std::cout << "encode data" << std::endl; std::vector payload; for (auto srucont : mSRUdata) { @@ -153,9 +144,9 @@ bool RawWriter::processNextTrigger() auto ddlid = srucont.mSRUid; auto [crorc, link] = getLinkAssignment(ddlid); LOG(DEBUG1) << "Adding payload with size " << payload.size() << " (" << payload.size() / 4 << " ALTRO words)"; - mRawWriter->addData(ddlid, crorc, link, 0, mCurrentTrigger->getBCData(), payload); + mRawWriter->addData(ddlid, crorc, link, 0, trg.getBCData(), payload); } - mCurrentTrigger++; + std::cout << "Done" << std::endl; return true; } @@ -307,4 +298,4 @@ int RawWriter::carryOverMethod(const header::RDHAny* rdh, const gsl::span actualSize = sizeNoTrailer; } return actualSize; -} \ No newline at end of file +} diff --git a/Detectors/FIT/FDD/workflow/src/DigitReaderSpec.cxx b/Detectors/FIT/FDD/workflow/src/DigitReaderSpec.cxx index 82b3e98d58d3a..819673b77a37e 100644 --- a/Detectors/FIT/FDD/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/FIT/FDD/workflow/src/DigitReaderSpec.cxx @@ -16,6 +16,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" +#include "Framework/Logger.h" #include "FDDWorkflow/DigitReaderSpec.h" using namespace o2::framework; diff --git a/Detectors/FIT/FDD/workflow/src/RecPointReaderSpec.cxx b/Detectors/FIT/FDD/workflow/src/RecPointReaderSpec.cxx index baf223ac2b8f7..2fd688e96c490 100644 --- a/Detectors/FIT/FDD/workflow/src/RecPointReaderSpec.cxx +++ b/Detectors/FIT/FDD/workflow/src/RecPointReaderSpec.cxx @@ -16,6 +16,7 @@ #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" #include "FDDWorkflow/RecPointReaderSpec.h" using namespace o2::framework; diff --git a/Detectors/FIT/FDD/workflow/src/ReconstructorSpec.cxx b/Detectors/FIT/FDD/workflow/src/ReconstructorSpec.cxx index 9bbbf9086293b..3cacc248e5fda 100644 --- a/Detectors/FIT/FDD/workflow/src/ReconstructorSpec.cxx +++ b/Detectors/FIT/FDD/workflow/src/ReconstructorSpec.cxx @@ -13,6 +13,7 @@ #include #include "SimulationDataFormat/MCTruthContainer.h" #include "Framework/ControlService.h" +#include "Framework/Logger.h" #include "FDDWorkflow/ReconstructorSpec.h" #include "DataFormatsFDD/Digit.h" #include "DataFormatsFDD/MCLabel.h" diff --git a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h index ca781e4d02009..21edc29013c30 100644 --- a/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h +++ b/Detectors/FIT/FT0/reconstruction/include/FT0Reconstruction/InteractionTag.h @@ -26,7 +26,6 @@ namespace ft0 // These are configurable params for FT0 selection as interaction tag struct InteractionTag : public o2::conf::ConfigurableParamHelper { int minAmplitudeAC = 20; ///< use only FT0 triggers with high enough amplitude - float timeBiasMS = 35.0; ///< relative bias in ns to add bool isSelected(const RecPoints& rp) const { @@ -35,7 +34,7 @@ struct InteractionTag : public o2::conf::ConfigurableParamHelper float getInteractionTimeNS(const RecPoints& rp, const o2::InteractionRecord& refIR) const { - return rp.getInteractionRecord().differenceInBC(refIR) * o2::constants::lhc::LHCBunchSpacingNS + timeBiasMS; // RS FIXME do we want use precise MeanTime? + return rp.getInteractionRecord().differenceInBCns(refIR); // RS FIXME do we want use precise MeanTime? } O2ParamDef(InteractionTag, "ft0tag"); diff --git a/Detectors/FIT/FT0/workflow/src/DigitReaderSpec.cxx b/Detectors/FIT/FT0/workflow/src/DigitReaderSpec.cxx index b1f99a2b598e4..ab683709b7269 100644 --- a/Detectors/FIT/FT0/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/DigitReaderSpec.cxx @@ -16,6 +16,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" +#include "Framework/Logger.h" #include "FT0Workflow/DigitReaderSpec.h" #include "DataFormatsFT0/Digit.h" #include "DataFormatsFT0/ChannelData.h" diff --git a/Detectors/FIT/FT0/workflow/src/RecPointReaderSpec.cxx b/Detectors/FIT/FT0/workflow/src/RecPointReaderSpec.cxx index 328447acfbd47..ef9c03c8b6618 100644 --- a/Detectors/FIT/FT0/workflow/src/RecPointReaderSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/RecPointReaderSpec.cxx @@ -16,6 +16,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" +#include "Framework/Logger.h" #include "FT0Workflow/RecPointReaderSpec.h" using namespace o2::framework; diff --git a/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx b/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx index a38147e1f446b..c75caeb9b1c4f 100644 --- a/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx +++ b/Detectors/FIT/FT0/workflow/src/ReconstructionSpec.cxx @@ -13,6 +13,7 @@ #include #include "SimulationDataFormat/MCTruthContainer.h" #include "Framework/ControlService.h" +#include "Framework/Logger.h" #include "FT0Workflow/ReconstructionSpec.h" #include "DataFormatsFT0/Digit.h" #include "DataFormatsFT0/ChannelData.h" diff --git a/Detectors/FIT/FV0/workflow/src/DigitReaderSpec.cxx b/Detectors/FIT/FV0/workflow/src/DigitReaderSpec.cxx index 2643f32a13aa4..781950909edc1 100644 --- a/Detectors/FIT/FV0/workflow/src/DigitReaderSpec.cxx +++ b/Detectors/FIT/FV0/workflow/src/DigitReaderSpec.cxx @@ -16,6 +16,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" +#include "Framework/Logger.h" #include "FV0Workflow/DigitReaderSpec.h" #include "DataFormatsFV0/BCData.h" #include "DataFormatsFV0/ChannelData.h" diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index acef77170e097..2901067b0298b 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -834,6 +834,7 @@ void MatchTPCITS::doMatching(int sec) if (trefTPC.timeBins > timeITS) { // its bracket precedes TPC bracket continue; } + nCheckITSControl++; float chi2 = -1; int rejFlag = compareTPCITSTracks(trefITS, trefTPC, chi2); @@ -846,7 +847,7 @@ void MatchTPCITS::doMatching(int sec) if (rejFlag == RejectOnTgl) { // ITS tracks in each ROFrame are ordered in Tgl, hence if this check failed on Tgl check - // (i.e. tgl_its>tgl_tpc+tolerance), tnem all other ITS tracks in this ROFrame will also have tgl too large. + // (i.e. tgl_its>tgl_tpc+tolerance), then all other ITS tracks in this ROFrame will also have tgl too large. // Jump on the 1st ITS track of the next ROFrame int rof = trefITS.roFrame; bool stop = false; @@ -865,16 +866,21 @@ void MatchTPCITS::doMatching(int sec) if (rejFlag != Accept) { continue; } + auto deltaT = (trefITS.getZ() - trefTPC.getZ()) * mZ2TPCBin; // time difference in TPC time bins corresponding to Z differences + auto timeTB = getTPCTrackCorrectedTimeBin(mTPCTracksArray[trefTPC.sourceID], deltaT); + auto timeTBErr = std::sqrt(trefITS.getSigmaZ2() + trefTPC.getSigmaZ2()) * t2nbs; // nsigma*error in number of TPC time bins + o2::utils::Bracket trange(timeTB - timeTBErr, timeTB + timeTBErr); + // is corrected TPC track time compatible with ITS ROF expressed in TPC bins? + if (timeITS.isOutside(trange)) { + continue; + } + int matchedIC = MinusOne; if (checkInteractionCandidates) { // check if corrected TPC track time is compatible with any of interaction times auto interactionRefs = mITSROFIntCandEntries[trefITS.roFrame]; // reference on interaction candidates compatible with this track int nic = interactionRefs.getEntries(); if (nic) { - auto deltaT = (trefITS.getZ() - trefTPC.getZ()) * mZ2TPCBin; // time difference in TPC time bins corresponding to Z differences - auto timeTB = getTPCTrackCorrectedTimeBin(mTPCTracksArray[trefTPC.sourceID], deltaT); - auto timeTBErr = std::sqrt(trefITS.getSigmaZ2() + trefTPC.getSigmaZ2()) * t2nbs; // nsigma*error in number of TPC time bins - o2::utils::Bracket trange(timeTB - timeTBErr, timeTB + timeTBErr); int idIC = interactionRefs.getFirstEntry(), maxIC = idIC + nic; for (; idIC < maxIC; idIC++) { auto cmp = mInteractions[idIC].timeBins.isOutside(trange); diff --git a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt index 2ab0a946f9025..ce3b5df0d4986 100644 --- a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt @@ -17,12 +17,14 @@ o2_add_library(GlobalTrackingWorkflow src/PrimaryVertexingSpec.cxx src/PrimaryVertexWriterSpec.cxx src/PrimaryVertexReaderSpec.cxx + src/VertexTrackMatcherSpec.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTracking O2::ITStracking O2::ITSWorkflow O2::TPCWorkflow O2::FT0Workflow O2::ITSMFTWorkflow + O2::SimulationDataFormat O2::DetectorsVertexing) o2_add_executable(match-workflow @@ -40,5 +42,6 @@ o2_add_executable(vertex-reader-workflow SOURCES src/primary-vertex-reader-workflow.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTrackingWorkflow ) + add_subdirectory(tofworkflow) add_subdirectory(tpcinterpolationworkflow) diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h index a9b9f5729c0ce..d99b6a0227334 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexReaderSpec.h @@ -21,6 +21,7 @@ #include "CommonDataFormat/TimeStamp.h" #include "CommonDataFormat/RangeReference.h" +#include "ReconstructionDataFormats/VtxTrackIndex.h" #include "ReconstructionDataFormats/PrimaryVertex.h" #include "SimulationDataFormat/MCEventLabel.h" @@ -35,6 +36,7 @@ class PrimaryVertexReader : public o2::framework::Task using Label = o2::MCEventLabel; using V2TRef = o2::dataformats::RangeReference; using PVertex = o2::dataformats::PrimaryVertex; + using GIndex = o2::dataformats::VtxTrackIndex; public: PrimaryVertexReader(bool useMC) : mUseMC(useMC) {} @@ -43,18 +45,20 @@ class PrimaryVertexReader : public o2::framework::Task void run(o2::framework::ProcessingContext& pc) final; protected: - void connectTree(const std::string& filename); + void connectTree(); + bool mVerbose = false; bool mUseMC = false; std::vector mVertices, *mVerticesPtr = &mVertices; - std::vector mPVTrIdx, *mPVTrIdxPtr = &mPVTrIdx; - std::vector mPV2TrIdx, *mPV2TrIdxPtr = &mPV2TrIdx; std::vector
::value) { if constexpr (std::is_same_v) { - eInfos.push_back({At, o2::soa::createSchemaFromColumns(typename dT::table_t::persistent_columns_t{}), nullptr}); + eInfos.push_back({at, o2::soa::createSchemaFromColumns(typename dT::table_t::persistent_columns_t{}), nullptr}); } } doAppendInputWithMetadata(soa::make_originals_from_type
(), inputs); @@ -85,7 +84,7 @@ struct AnalysisDataProcessorBuilder { template static void inputsFromArgs(R (C::*)(Args...), std::vector& inputs, std::vector& eInfos) { - (appendSomethingWithMetadata(pack{})>(inputs, eInfos), ...); + (appendSomethingWithMetadata(inputs, eInfos, o2::framework::has_type_at_v(pack{})), ...); } template @@ -97,7 +96,7 @@ struct AnalysisDataProcessorBuilder { template static auto bindGroupingTable(InputRecord& record, R (C::*)(Grouping, Args...), std::vector const& infos) { - return extractSomethingFromRecord(record, infos); + return extractSomethingFromRecord(record, infos, 0); } template @@ -138,20 +137,20 @@ struct AnalysisDataProcessorBuilder { } } - template - static auto extractSomethingFromRecord(InputRecord& record, std::vector const infos) + template + static auto extractSomethingFromRecord(InputRecord& record, std::vector const infos, size_t at) { using decayed = std::decay_t; if constexpr (soa::is_soa_filtered_t::value) { for (auto& info : infos) { - if (info.index == At) + if (info.index == at) return extractFilteredFromRecord(record, info, soa::make_originals_from_type()); } } else if constexpr (soa::is_soa_iterator_t::value) { if constexpr (std::is_same_v) { for (auto& info : infos) { - if (info.index == At) + if (info.index == at) return extractFilteredFromRecord(record, info, soa::make_originals_from_type()); } } else { @@ -166,7 +165,7 @@ struct AnalysisDataProcessorBuilder { template static auto bindAssociatedTables(InputRecord& record, R (C::*)(Grouping, Args...), std::vector const infos) { - return std::make_tuple(extractSomethingFromRecord(pack{}) + 1u>(record, infos)...); + return std::make_tuple(extractSomethingFromRecord(record, infos, has_type_at_v(pack{}) + 1u)...); } template @@ -237,7 +236,7 @@ struct AnalysisDataProcessorBuilder { /// auto splitter = [&](auto&& x) { using xt = std::decay_t; - constexpr auto index = framework::has_type_at>(associated_pack_t{}); + constexpr auto index = framework::has_type_at_v>(associated_pack_t{}); if (hasIndexTo>(typename xt::persistent_columns_t{})) { auto result = o2::framework::sliceByColumn(indexColumnName.c_str(), x.asArrowTable(), @@ -262,7 +261,7 @@ struct AnalysisDataProcessorBuilder { auto extractor = [&](auto&& x) { using xt = std::decay_t; if constexpr (soa::is_soa_filtered_t::value) { - constexpr auto index = framework::has_type_at>(associated_pack_t{}); + constexpr auto index = framework::has_type_at_v>(associated_pack_t{}); selections[index] = &x.getSelectedRows(); starts[index] = selections[index]->begin(); offsets[index].push_back(std::get(at).tableSize()); @@ -342,7 +341,7 @@ struct AnalysisDataProcessorBuilder { template auto prepareArgument() { - constexpr auto index = framework::has_type_at(associated_pack_t{}); + constexpr auto index = framework::has_type_at_v(associated_pack_t{}); if (hasIndexTo(typename std::decay_t::persistent_columns_t{})) { uint64_t pos; if constexpr (soa::is_soa_filtered_t>::value) { diff --git a/Framework/Core/include/Framework/BoostOptionsRetriever.h b/Framework/Core/include/Framework/BoostOptionsRetriever.h index 6d33627e8bdc2..148d5c4192b20 100644 --- a/Framework/Core/include/Framework/BoostOptionsRetriever.h +++ b/Framework/Core/include/Framework/BoostOptionsRetriever.h @@ -14,9 +14,17 @@ #include "Framework/ParamRetriever.h" #include -#include +#include #include +namespace boost +{ +namespace program_options +{ +class options_description; +} +} // namespace boost + namespace o2::framework { @@ -32,7 +40,7 @@ class BoostOptionsRetriever : public ParamRetriever boost::property_tree::ptree& provenance) override; private: - boost::program_options::options_description mDescription; + std::unique_ptr mDescription; int mArgc; char** mArgv; bool mIgnoreUnknown; diff --git a/Framework/Core/include/Framework/ChannelConfigurationPolicy.h b/Framework/Core/include/Framework/ChannelConfigurationPolicy.h index 29387ac05cc8e..0fa3be6f1dd86 100644 --- a/Framework/Core/include/Framework/ChannelConfigurationPolicy.h +++ b/Framework/Core/include/Framework/ChannelConfigurationPolicy.h @@ -12,8 +12,8 @@ #include "Framework/ChannelConfigurationPolicyHelpers.h" #include "Framework/ChannelSpec.h" -#include "Framework/DeviceSpec.h" +#include #include namespace o2 diff --git a/Framework/Core/include/Framework/Kernels.h b/Framework/Core/include/Framework/Kernels.h index 2dc39e85619c5..00fac405fc8ed 100644 --- a/Framework/Core/include/Framework/Kernels.h +++ b/Framework/Core/include/Framework/Kernels.h @@ -14,13 +14,6 @@ #include "Framework/BasicOps.h" #include "Framework/TableBuilder.h" -#if __has_include() -#include -#endif -#if __has_include() -#include -#endif - #include #include #include @@ -28,145 +21,8 @@ #include -#if (ARROW_VERSION < 1000000) -namespace arrow -{ -using Datum = compute::Datum; -} -#endif - namespace o2::framework { -#if (ARROW_VERSION < 1000000) -template -struct ARROW_EXPORT GroupByOptions { - std::string columnName; - T size; -}; - -/// Build ranges -template -class ARROW_EXPORT SortedGroupByKernel : public arrow::compute::UnaryKernel -{ - public: - explicit SortedGroupByKernel(GroupByOptions options = {}) : mOptions(options){}; - arrow::Status Call(arrow::compute::FunctionContext*, - arrow::compute::Datum const& table, - arrow::compute::Datum* outputRanges) override - { - using namespace arrow; - if (table.kind() == arrow::compute::Datum::TABLE) { - auto atable = util::get>(table.value); - auto columnIndex = atable->schema()->GetFieldIndex(mOptions.columnName); - auto chunkedArray = atable->column(columnIndex); - return doGrouping(chunkedArray, outputRanges); - }; - return arrow::Status::OK(); - }; -#pragma GCC diagnostic push -#ifdef __clang__ -#pragma GCC diagnostic ignored "-Winconsistent-missing-override" -#endif // __clang__ - std::shared_ptr out_type() const final - { - return mType; - } -#pragma GCC diagnostic pop - - private: - arrow::Status doGrouping(std::shared_ptr chunkedArray, arrow::compute::Datum* outputRanges) - { - o2::framework::TableBuilder builder; - auto writer = builder.persist({"start", "count", "index"}); - auto zeroChunk = std::static_pointer_cast(chunkedArray->chunk(0)); - if (zeroChunk->length() == 0) { - *outputRanges = std::move(builder.finalize()); - return arrow::Status::OK(); - } - T currentIndex = 0; - T currentCount = 0; - T currentOffset = 0; - for (auto ci = 0; ci < chunkedArray->num_chunks(); ++ci) { - auto chunk = chunkedArray->chunk(ci); - T const* data = std::static_pointer_cast(chunk)->raw_values(); - for (auto ai = 0; ai < chunk->length(); ++ai) { - if (currentIndex == data[ai]) { - currentCount++; - } else { - writer(0, currentOffset, currentCount, currentIndex); - currentOffset += currentCount; - while (data[ai] - currentIndex > 1) { - writer(0, currentOffset, 0, ++currentIndex); - } - currentIndex++; - currentCount = 1; - } - } - } - writer(0, currentOffset, currentCount, currentIndex); - while (currentIndex < mOptions.size - 1) { - writer(0, currentOffset, 0, ++currentIndex); - } - *outputRanges = std::move(builder.finalize()); - return arrow::Status::OK(); - } - std::shared_ptr mType; - GroupByOptions mOptions; -}; - -/// Slice a given table is a vector of tables each containing a slice. -/// @a outputSlices the arrow tables in which the original @a inputTable -/// is split into. -/// @a offset the offset in the original table at which the corresponding -/// slice was split. -/// Slice a given table is a vector of tables each containing a slice. -template -arrow::Status sliceByColumn(std::string const& key, - std::shared_ptr const& input, - T size, - std::vector* outputSlices, - std::vector* offsets = nullptr) -{ - arrow::compute::Datum inputTable{input}; - // build all the ranges on the fly. - arrow::compute::Datum outRanges; - auto table = arrow::util::get>(inputTable.value); - o2::framework::SortedGroupByKernel> kernel{GroupByOptions{key, size}}; - - ARROW_RETURN_NOT_OK(kernel.Call(nullptr, inputTable, &outRanges)); - auto ranges = arrow::util::get>(outRanges.value); - outputSlices->reserve(ranges->num_rows()); - if (offsets) { - offsets->reserve(ranges->num_rows()); - } - - auto startChunks = ranges->column(0); - assert(startChunks->num_chunks() == 1); - auto countChunks = ranges->column(1); - assert(countChunks->num_chunks() == 1); - auto startData = std::static_pointer_cast>(startChunks->chunk(0))->raw_values(); - auto countData = std::static_pointer_cast>(countChunks->chunk(0))->raw_values(); - - for (auto ri = 0; ri < ranges->num_rows(); ++ri) { - auto start = startData[ri]; - auto count = countData[ri]; - auto schema = table->schema(); - std::vector> slicedColumns; - slicedColumns.reserve(schema->num_fields()); - // if (count != 0) { - for (auto ci = 0; ci < schema->num_fields(); ++ci) { - slicedColumns.emplace_back(table->column(ci)->Slice(start, count)); - } - // } - outputSlices->emplace_back(arrow::compute::Datum(arrow::Table::Make(table->schema(), slicedColumns))); - if (offsets) { - offsets->emplace_back(start); - } - } - return arrow::Status::OK(); -} - -#else /// Slice a given table in a vector of tables each containing a slice. /// @a slices the arrow tables in which the original @a input /// is split into. @@ -235,7 +91,6 @@ auto sliceByColumn(char const* key, return arrow::Status::OK(); } -#endif } // namespace o2::framework diff --git a/Framework/Core/include/Framework/RawDeviceService.h b/Framework/Core/include/Framework/RawDeviceService.h index 360de775adfbc..700df3c9b62a4 100644 --- a/Framework/Core/include/Framework/RawDeviceService.h +++ b/Framework/Core/include/Framework/RawDeviceService.h @@ -7,16 +7,14 @@ // 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. -#ifndef FRAMEWORK_RAWDEVICESERVICE_H -#define FRAMEWORK_RAWDEVICESERVICE_H +#ifndef O2_FRAMEWORK_RAWDEVICESERVICE_H_ +#define O2_FRAMEWORK_RAWDEVICESERVICE_H_ #include "Framework/ServiceHandle.h" class FairMQDevice; -namespace o2 -{ -namespace framework +namespace o2::framework { class DeviceSpec; @@ -33,8 +31,12 @@ class RawDeviceService virtual FairMQDevice* device() = 0; virtual void setDevice(FairMQDevice* device) = 0; virtual DeviceSpec const& spec() = 0; + /// Expose FairMQDevice::WaitFor method to avoid having to include + /// FairMQDevice.h. + /// + /// @a time in millisecond to sleep + virtual void waitFor(unsigned int time) = 0; }; -} // namespace framework -} // namespace o2 -#endif // FRAMEWORK_RAWDEVICESERVICE_H +} // namespace o2::framework +#endif // O2_FRAMEWORK_RAWDEVICESERVICE_H_ diff --git a/Framework/Core/include/Framework/RootAnalysisHelpers.h b/Framework/Core/include/Framework/RootAnalysisHelpers.h new file mode 100644 index 0000000000000..7341d330b736f --- /dev/null +++ b/Framework/Core/include/Framework/RootAnalysisHelpers.h @@ -0,0 +1,32 @@ +// 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. +#ifndef O2_FRAMEWORK_ROOTANALYSISHELPERS_H_ +#define O2_FRAMEWORK_ROOTANALYSISHELPERS_H_ + +#include "Framework/TableConsumer.h" +#include + +namespace o2::analysis +{ + +/// Do a single loop on all the entries of the @a input table +ROOT::RDataFrame doSingleLoopOn(std::unique_ptr& input); + +/// Do a double loop on all the entries with the same value for the \a grouping +/// of the @a input table, where the entries for the outer index are prefixed +/// with `_` while the entries for the inner loop are prefixed with +/// `bar_`. +ROOT::RDataFrame doSelfCombinationsWith(std::unique_ptr& input, + std::string name = "p", + std::string grouping = "eventID"); + +} // namespace o2::analysis + +#endif // O2_FRAMEWORK_ROOTANALYSISHELPERS_H_ diff --git a/Framework/Core/include/Framework/SimpleRawDeviceService.h b/Framework/Core/include/Framework/SimpleRawDeviceService.h index b4b8503e194c2..03e3e75e0c2db 100644 --- a/Framework/Core/include/Framework/SimpleRawDeviceService.h +++ b/Framework/Core/include/Framework/SimpleRawDeviceService.h @@ -7,15 +7,13 @@ // 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. -#ifndef FRAMEWORK_SIMPLERAWDEVICESERVICE_H -#define FRAMEWORK_SIMPLERAWDEVICESERVICE_H +#ifndef O2_FRAMEWORK_SIMPLERAWDEVICESERVICE_H_ +#define O2_FRAMEWORK_SIMPLERAWDEVICESERVICE_H_ #include "Framework/RawDeviceService.h" #include "Framework/DeviceSpec.h" -namespace o2 -{ -namespace framework +namespace o2::framework { /// Fairly unsophisticated service which simply stores and returns the @@ -43,11 +41,12 @@ class SimpleRawDeviceService : public RawDeviceService return mSpec; } + void waitFor(unsigned int ms) final; + private: FairMQDevice* mDevice; DeviceSpec const& mSpec; }; -} // namespace framework -} // namespace o2 -#endif // FRAMEWORK_SIMPLERAWDEVICESERVICE_H +} // namespace o2::framework +#endif // O2_FRAMEWORK_SIMPLERAWDEVICESERVICE_H__ diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index 9cc22025c0d46..3d8d3cdc1209c 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -511,19 +511,17 @@ class TableBuilder template auto cursor() { - using persistent_filter = soa::FilterPersistentColumns; - using persistent_columns_pack = typename persistent_filter::persistent_columns_pack; + using persistent_columns_pack = typename T::table_t::persistent_columns_t; constexpr auto persistent_size = pack_size(persistent_columns_pack{}); - return cursorHelper(std::make_index_sequence()); + return cursorHelper::table>(std::make_index_sequence()); } template auto cursor() { - using persistent_filter = soa::FilterPersistentColumns; - using persistent_columns_pack = typename persistent_filter::persistent_columns_pack; + using persistent_columns_pack = typename T::table_t::persistent_columns_t; constexpr auto persistent_size = pack_size(persistent_columns_pack{}); - return cursorHelper(std::make_index_sequence()); + return cursorHelper::table, E>(std::make_index_sequence()); } template diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 2ee228f1e8be6..3bed257a41fe4 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -13,16 +13,13 @@ #include "Framework/ChannelConfigurationPolicy.h" #include "Framework/CompletionPolicy.h" #include "Framework/DispatchPolicy.h" -#include "Framework/ConfigParamsHelper.h" #include "Framework/DataProcessorSpec.h" #include "Framework/WorkflowSpec.h" #include "Framework/ConfigContext.h" #include "Framework/BoostOptionsRetriever.h" #include "Framework/CustomWorkflowTerminationHook.h" #include "Framework/CommonServices.h" - -#include -#include +#include "Framework/Logger.h" #include #include diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index ca839bb14cdfa..9e41ec0cd72ba 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -27,7 +27,6 @@ #include "Framework/ChannelInfo.h" #include "Framework/Logger.h" -#include #include #include #include @@ -116,7 +115,7 @@ uint64_t getMask(header::DataDescription description) } } -uint64_t calculateReadMask(std::vector const& routes, header::DataOrigin const& origin) +uint64_t calculateReadMask(std::vector const& routes, header::DataOrigin const&) { uint64_t readMask = None; for (auto& route : routes) { @@ -176,11 +175,11 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector reques }; if (description == header::DataDescription{"TRACKPAR"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::TracksMetadata{})); + outputs.adopt(Output{origin, description}, maker(o2::aod::TracksExtensionMetadata{})); } else if (description == header::DataDescription{"TRACKPARCOV"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::TracksCovMetadata{})); + outputs.adopt(Output{origin, description}, maker(o2::aod::TracksCovExtensionMetadata{})); } else if (description == header::DataDescription{"MUON"}) { - outputs.adopt(Output{origin, description}, maker(o2::aod::MuonsMetadata{})); + outputs.adopt(Output{origin, description}, maker(o2::aod::MuonsExtensionMetadata{})); } else { throw std::runtime_error("Not an extended table"); } diff --git a/Framework/Core/src/AnalysisManagers.h b/Framework/Core/src/AnalysisManagers.h index b0473f96780ed..e5045f3c81bc7 100644 --- a/Framework/Core/src/AnalysisManagers.h +++ b/Framework/Core/src/AnalysisManagers.h @@ -233,9 +233,9 @@ struct OutputManager> { static bool prepare(ProcessingContext& pc, Spawns& what) { - using metadata = typename std::decay_t::metadata; - auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(typename metadata::originals{}, pc)); - what.table = std::make_shared(o2::soa::spawner(what.pack(), original_table.get())); + auto original_table = soa::ArrowHelpers::joinTables(extractOriginals(what.sources_pack(), pc)); + what.extension = std::make_shared::extension_t>(o2::soa::spawner(what.pack(), original_table.get())); + what.table = std::make_shared(soa::ArrowHelpers::joinTables({what.extension->asArrowTable(), original_table})); return true; } @@ -246,8 +246,7 @@ struct OutputManager> { static bool postRun(EndOfStreamContext& eosc, Spawns& what) { - using metadata = typename std::decay_t::metadata; - eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); + eosc.outputs().adopt(what.output(), what.asArrowTable()); return true; } }; @@ -276,10 +275,9 @@ struct OutputManager> { static bool prepare(ProcessingContext& pc, Builds& what) { - using metadata = typename std::decay_t::metadata; - return what.build(typename metadata::index_pack_t{}, - extractTypedOriginal(pc), - extractOriginalsTuple(typename metadata::originals{}, pc)); + return what.build(what.pack(), + extractTypedOriginal::Key>(pc), + extractOriginalsTuple(what.sources_pack(), pc)); } static bool finalize(ProcessingContext&, Builds&) @@ -289,8 +287,7 @@ struct OutputManager> { static bool postRun(EndOfStreamContext& eosc, Builds& what) { - using metadata = typename std::decay_t::metadata; - eosc.outputs().adopt(Output{metadata::origin(), metadata::description()}, what.asArrowTable()); + eosc.outputs().adopt(what.output(), what.asArrowTable()); return true; } }; diff --git a/Framework/Core/src/BoostOptionsRetriever.cxx b/Framework/Core/src/BoostOptionsRetriever.cxx index e3081aee4b143..892574e3eae11 100644 --- a/Framework/Core/src/BoostOptionsRetriever.cxx +++ b/Framework/Core/src/BoostOptionsRetriever.cxx @@ -14,6 +14,7 @@ #include "PropertyTreeHelpers.h" #include +#include #include #include @@ -28,7 +29,7 @@ namespace o2::framework BoostOptionsRetriever::BoostOptionsRetriever(bool ignoreUnknown, int argc, char** argv) - : mDescription{"ALICE O2 Framework - Available options"}, + : mDescription{std::make_unique("ALICE O2 Framework - Available options")}, mIgnoreUnknown{ignoreUnknown}, mArgc{argc}, mArgv{argv} @@ -39,7 +40,7 @@ void BoostOptionsRetriever::update(std::vector const& specs, boost::property_tree::ptree& store, boost::property_tree::ptree& provenance) { - auto options = mDescription.add_options(); + auto options = mDescription->add_options(); for (auto& spec : specs) { const char* name = spec.name.c_str(); const char* help = spec.help.c_str(); @@ -72,8 +73,8 @@ void BoostOptionsRetriever::update(std::vector const& specs, using namespace bpo::command_line_style; auto style = (allow_short | short_allow_adjacent | short_allow_next | allow_long | long_allow_adjacent | long_allow_next | allow_sticky | allow_dash_for_short); - auto parsed = mIgnoreUnknown ? bpo::command_line_parser(mArgc, mArgv).options(mDescription).style(style).allow_unregistered().run() - : bpo::parse_command_line(mArgc, mArgv, mDescription, style); + auto parsed = mIgnoreUnknown ? bpo::command_line_parser(mArgc, mArgv).options(*mDescription).style(style).allow_unregistered().run() + : bpo::parse_command_line(mArgc, mArgv, *mDescription, style); bpo::variables_map vmap; bpo::store(parsed, vmap); PropertyTreeHelpers::populate(specs, store, vmap, provenance); diff --git a/Framework/Core/src/DataSpecUtils.cxx b/Framework/Core/src/DataSpecUtils.cxx index 6cdf4faaf6d43..73080bc144e93 100644 --- a/Framework/Core/src/DataSpecUtils.cxx +++ b/Framework/Core/src/DataSpecUtils.cxx @@ -11,6 +11,7 @@ #include "Framework/DataDescriptorMatcher.h" #include "Framework/DataMatcherWalker.h" #include "Framework/VariantHelpers.h" +#include "Framework/Logger.h" #include #include diff --git a/Framework/Core/src/DriverInfo.h b/Framework/Core/src/DriverInfo.h index 80907e71e9519..494e5604e6f90 100644 --- a/Framework/Core/src/DriverInfo.h +++ b/Framework/Core/src/DriverInfo.h @@ -20,6 +20,8 @@ #include "Framework/ChannelConfigurationPolicy.h" #include "Framework/ConfigParamSpec.h" #include "Framework/TerminationPolicy.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/DispatchPolicy.h" #include "DataProcessorInfo.h" namespace o2::framework diff --git a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx index 1822dc750b31e..058c998e75ac7 100644 --- a/Framework/Core/src/FrameworkGUIDeviceInspector.cxx +++ b/Framework/Core/src/FrameworkGUIDeviceInspector.cxx @@ -16,6 +16,7 @@ #include "Framework/DeviceInfo.h" #include "Framework/DeviceMetricsInfo.h" #include "Framework/ChannelSpec.h" +#include "Framework/Logger.h" #include "DebugGUI/imgui.h" #include diff --git a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx index 28550e67600ee..7b81fd8618f28 100644 --- a/Framework/Core/src/FrameworkGUIDevicesGraph.cxx +++ b/Framework/Core/src/FrameworkGUIDevicesGraph.cxx @@ -15,6 +15,7 @@ #include "Framework/LogParsingHelpers.h" #include "Framework/PaletteHelpers.h" #include "FrameworkGUIDeviceInspector.h" +#include "Framework/Logger.h" #include "../src/WorkflowHelpers.h" #include "DebugGUI/imgui.h" #if __has_include("DebugGUI/icons_font_awesome.h") diff --git a/Framework/Core/src/SimpleRawDeviceService.cxx b/Framework/Core/src/SimpleRawDeviceService.cxx new file mode 100644 index 0000000000000..daf1cb54e0c4d --- /dev/null +++ b/Framework/Core/src/SimpleRawDeviceService.cxx @@ -0,0 +1,23 @@ +// 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. + +#include "Framework/SimpleRawDeviceService.h" + +#include + +namespace o2::framework +{ + +void SimpleRawDeviceService::waitFor(unsigned int ms) +{ + mDevice->WaitFor(std::chrono::milliseconds(ms)); +} + +} // namespace o2::framework diff --git a/Framework/Core/src/TableTreeHelpers.cxx b/Framework/Core/src/TableTreeHelpers.cxx index 9ea4ac8e5febf..76776141befac 100644 --- a/Framework/Core/src/TableTreeHelpers.cxx +++ b/Framework/Core/src/TableTreeHelpers.cxx @@ -10,13 +10,6 @@ #include "Framework/TableTreeHelpers.h" #include "Framework/Logger.h" -#if __has_include() -#include -#endif -#if __has_include() -#include -#endif - #include "arrow/type_traits.h" namespace o2 @@ -39,19 +32,11 @@ BranchIterator::BranchIterator(TTree* tree, std::shared_ptr mNumberElements = 1; if (mFieldType == arrow::Type::type::FIXED_SIZE_LIST) { -#if (ARROW_VERSION < 1000000) - // element type - if (mField->type()->num_children() <= 0) { - LOGP(FATAL, "Field {} of type {} has no children!", mField->name(), mField->type()->ToString().c_str()); - } - mElementType = mField->type()->child(0)->type()->id(); -#else // element type if (mField->type()->num_fields() <= 0) { LOGP(FATAL, "Field {} of type {} has no children!", mField->name(), mField->type()->ToString().c_str()); } mElementType = mField->type()->field(0)->type()->id(); -#endif // number of elements mNumberElements = static_cast(mField->type().get())->list_size(); mLeaflistString += "[" + std::to_string(mNumberElements) + "]"; diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 275f4746cac23..aa9646ef59cc3 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -19,7 +19,6 @@ #include "Framework/RawDeviceService.h" #include "Framework/StringHelpers.h" -#include "fairmq/FairMQDevice.h" #include "Headers/DataHeader.h" #include #include @@ -166,7 +165,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext return [](ProcessingContext& pc) { // this callback is never called since there is no expiring input - pc.services().get().device()->WaitFor(std::chrono::seconds(2)); + pc.services().get().waitFor(2000); }; }}; @@ -335,7 +334,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // This is to inject a file sink so that any dangling ATSK object is written // to a ROOT file. - if (providedOutputObj.size() != 0) { + if (providedOutputObj.empty() == false) { auto rootSink = CommonDataProcessors::getOutputObjSink(outObjMap, outTskMap); extraSpecs.push_back(rootSink); } @@ -356,7 +355,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // select outputs of type AOD std::vector OutputsInputsAOD; std::vector isdangling; - for (int ii = 0; ii < OutputsInputs.size(); ii++) { + for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { if ((outputtypes[ii] & 2) == 2) { // temporarily also request to be dangling @@ -379,7 +378,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext // select dangling outputs which are not of type AOD std::vector OutputsInputsDangling; - for (int ii = 0; ii < OutputsInputs.size(); ii++) { + for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { if ((outputtypes[ii] & 1) == 1 && (outputtypes[ii] & 2) == 0) OutputsInputsDangling.emplace_back(OutputsInputs[ii]); } @@ -783,7 +782,7 @@ std::vector WorkflowHelpers::computeDanglingOutputs(WorkflowSpec cons auto [OutputsInputs, outputtypes] = analyzeOutputs(workflow); std::vector results; - for (int ii = 0; ii < OutputsInputs.size(); ii++) { + for (auto ii = 0u; ii < OutputsInputs.size(); ii++) { if ((outputtypes[ii] & 1) == 1) { results.emplace_back(OutputsInputs[ii]); } diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 1300530fa8eb2..966860f191da1 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -310,7 +310,7 @@ void cleanupSHM(std::string const& uniqueWorkflowId) { #if __has_include() using namespace fair::mq::shmem; - Monitor::Cleanup(SessionId{"dpl_" + uniqueWorkflowId}); + Monitor::Cleanup(SessionId{"dpl_" + uniqueWorkflowId}, false); #else // Old code, invoking external fairmq-shmmonitor auto shmCleanup = fmt::format("fairmq-shmmonitor --cleanup -s dpl_{} 2>&1 >/dev/null", uniqueWorkflowId); diff --git a/Framework/Core/src/verifyAODFile.cxx b/Framework/Core/src/verifyAODFile.cxx index 2864a259d2b45..6c4d8aa23f163 100644 --- a/Framework/Core/src/verifyAODFile.cxx +++ b/Framework/Core/src/verifyAODFile.cxx @@ -43,11 +43,11 @@ int main(int argc, char** argv) return 1; } - verifyTable(infile.get(), "O2collisions"); - verifyTable(infile.get(), "O2tracks"); - verifyTable(infile.get(), "O2tracks"); - verifyTable(infile.get(), "O2tracks"); + verifyTable(infile.get(), "O2collision"); + verifyTable(infile.get(), "O2track"); + verifyTable(infile.get(), "O2track"); + verifyTable(infile.get(), "O2track"); verifyTable(infile.get(), "O2calo"); - verifyTable(infile.get(), "O2muon"); + verifyTable(infile.get(), "O2muon"); return 0; } diff --git a/Framework/Core/test/benchmark_ASoA.cxx b/Framework/Core/test/benchmark_ASoA.cxx index 88448f5e04dd0..941187159c9cb 100644 --- a/Framework/Core/test/benchmark_ASoA.cxx +++ b/Framework/Core/test/benchmark_ASoA.cxx @@ -19,6 +19,7 @@ using namespace o2::framework; using namespace arrow; using namespace o2::soa; +DECLARE_SOA_STORE(); namespace test { DECLARE_SOA_COLUMN_FULL(X, x, float, "x"); @@ -27,6 +28,8 @@ DECLARE_SOA_COLUMN_FULL(Z, z, float, "z"); DECLARE_SOA_DYNAMIC_COLUMN(Sum, sum, [](float x, float y) { return x + y; }); } // namespace test +DECLARE_SOA_TABLE(TestTable, "AOD", "TESTTBL", test::X, test::Y, test::Z, test::Sum); + #ifdef __APPLE__ constexpr unsigned int maxrange = 10; #else @@ -47,13 +50,13 @@ static void BM_SimpleForLoop(benchmark::State& state) std::default_random_engine e1(1234567891); std::uniform_real_distribution uniform_dist(0, 1); - for (size_t i = 0; i < state.range(0); ++i) { + for (auto i = 0; i < state.range(0); ++i) { foo[i] = XYZ{uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)}; } for (auto _ : state) { float sum = 0; - for (auto& xyz : foo) { + for (auto& _ : foo) { benchmark::DoNotOptimize(sum++); } } @@ -79,7 +82,7 @@ static void BM_TrackForLoop(benchmark::State& state) std::default_random_engine e1(1234567891); std::uniform_real_distribution uniform_dist(0, 1); - for (size_t i = 0; i < state.range(0); ++i) { + for (auto i = 0; i < state.range(0); ++i) { foo[i] = TestTrack{ uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)}; @@ -114,7 +117,7 @@ static void BM_WholeTrackForLoop(benchmark::State& state) std::default_random_engine e1(1234567891); std::uniform_real_distribution uniform_dist(0, 1); - for (auto i = 0u; i < state.range(0); ++i) { + for (auto i = 0; i < state.range(0); ++i) { foo[i] = TestTrack{ uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)}; @@ -149,7 +152,7 @@ static void BM_TrackForPhi(benchmark::State& state) std::default_random_engine e1(1234567891); std::uniform_real_distribution uniform_dist(0, 1); - for (auto i = 0u; i < state.range(0); ++i) { + for (auto i = 0; i < state.range(0); ++i) { foo[i] = TestTrack{ uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)}; @@ -183,7 +186,7 @@ static void BM_SimpleForLoopWithOp(benchmark::State& state) std::default_random_engine e1(1234567891); std::uniform_real_distribution uniform_dist(0, 1); - for (auto i = 0u; i < state.range(0); ++i) { + for (auto i = 0; i < state.range(0); ++i) { foo[i] = XYZ{uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)}; } @@ -308,98 +311,6 @@ static void BM_ASoADynamicColumnCall(benchmark::State& state) } state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2); } - BENCHMARK(BM_ASoADynamicColumnCall)->Range(8, 8 << maxrange); -static void BM_ASoAGettersPhi(benchmark::State& state) -{ - // Seed with a real random value, if available - std::default_random_engine e1(1234567891); - std::uniform_real_distribution uniform_dist(0, 1); - - TableBuilder builder; - auto rowWriter = builder.cursor(); - for (auto i = 0; i < state.range(0); ++i) { - rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)); - } - auto table = builder.finalize(); - - o2::aod::Tracks tracks{table}; - for (auto _ : state) { - state.PauseTiming(); - std::vector out; - out.resize(state.range(0)); - float* result = out.data(); - state.ResumeTiming(); - for (auto& track : tracks) { - *result++ = asin(track.snp()) + track.alpha() + M_PI; - } - benchmark::DoNotOptimize(result); - } - state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2); -} - -BENCHMARK(BM_ASoAGettersPhi)->Range(8, 8 << maxrange); - -static void BM_ASoAWholeTrackForLoop(benchmark::State& state) -{ - // Seed with a real random value, if available - std::default_random_engine e1(1234567891); - std::uniform_real_distribution uniform_dist(0, 1); - - TableBuilder builder; - auto rowWriter = builder.cursor(); - for (auto i = 0; i < state.range(0); ++i) { - rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)); - } - auto table = builder.finalize(); - - o2::aod::Tracks tracks{table}; - for (auto _ : state) { - float sum = 0; - for (auto& track : tracks) { - sum += track.x() + track.alpha() + track.y() + track.z() + track.snp() + track.tgl() + track.signed1Pt(); - } - benchmark::DoNotOptimize(sum); - } - state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 6); -} - -BENCHMARK(BM_ASoAWholeTrackForLoop)->Range(8, 8 << maxrange); - -static void BM_ASoADynamicColumnPhi(benchmark::State& state) -{ - // Seed with a real random value, if available - std::default_random_engine e1(1234567891); - std::uniform_real_distribution uniform_dist(0, 1); - - TableBuilder builder; - auto rowWriter = builder.cursor(); - for (auto i = 0; i < state.range(0); ++i) { - rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)); - } - auto table = builder.finalize(); - - o2::aod::Tracks tracks{table}; - for (auto _ : state) { - state.PauseTiming(); - std::vector out; - out.resize(state.range(0)); - float* result = out.data(); - state.ResumeTiming(); - for (auto& track : tracks) { - *result++ = track.phi(); - } - benchmark::DoNotOptimize(result); - } - state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2); -} -BENCHMARK(BM_ASoADynamicColumnPhi)->Range(8, 8 << maxrange); - BENCHMARK_MAIN(); diff --git a/Framework/Core/test/benchmark_ASoAHelpers.cxx b/Framework/Core/test/benchmark_ASoAHelpers.cxx index 3e17b294ab340..4c8bb53a0c0b9 100644 --- a/Framework/Core/test/benchmark_ASoAHelpers.cxx +++ b/Framework/Core/test/benchmark_ASoAHelpers.cxx @@ -19,6 +19,8 @@ using namespace o2::framework; using namespace arrow; using namespace o2::soa; +/// FIXME: do not use data model tables + namespace test { DECLARE_SOA_COLUMN_FULL(X, x, float, "x"); @@ -162,21 +164,20 @@ static void BM_ASoAHelpersNaiveTracksPairs(benchmark::State& state) std::uniform_real_distribution uniform_dist(0, 1); TableBuilder builder; - auto rowWriter = builder.cursor(); + auto rowWriter = builder.cursor(); for (auto i = 0; i < state.range(0); ++i) { rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)); } auto table = builder.finalize(); - o2::aod::Tracks tracks{table}; + o2::aod::Calos Calos{table}; int64_t count = 0; for (auto _ : state) { count = 0; - for (auto t0 = tracks.begin(); t0 + 1 != tracks.end(); ++t0) { - for (auto t1 = t0 + 1; t1 != tracks.end(); ++t1) { + for (auto t0 = Calos.begin(); t0 + 1 != Calos.end(); ++t0) { + for (auto t1 = t0 + 1; t1 != Calos.end(); ++t1) { auto comb = std::make_tuple(t0, t1); count++; benchmark::DoNotOptimize(comb); @@ -197,24 +198,23 @@ static void BM_ASoAHelpersNaiveTracksFives(benchmark::State& state) std::uniform_real_distribution uniform_dist(0, 1); TableBuilder builder; - auto rowWriter = builder.cursor(); + auto rowWriter = builder.cursor(); for (auto i = 0; i < state.range(0); ++i) { rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)); } auto table = builder.finalize(); - o2::aod::Tracks tracks{table}; + o2::aod::Calos calos{table}; int64_t count = 0; for (auto _ : state) { count = 0; - for (auto t0 = tracks.begin(); t0 + 4 != tracks.end(); ++t0) { - for (auto t1 = t0 + 1; t1 + 3 != tracks.end(); ++t1) { - for (auto t2 = t1 + 1; t2 + 2 != tracks.end(); ++t2) { - for (auto t3 = t2 + 1; t3 + 1 != tracks.end(); ++t3) { - for (auto t4 = t3 + 1; t4 != tracks.end(); ++t4) { + for (auto t0 = calos.begin(); t0 + 4 != calos.end(); ++t0) { + for (auto t1 = t0 + 1; t1 + 3 != calos.end(); ++t1) { + for (auto t2 = t1 + 1; t2 + 2 != calos.end(); ++t2) { + for (auto t3 = t2 + 1; t3 + 1 != calos.end(); ++t3) { + for (auto t4 = t3 + 1; t4 != calos.end(); ++t4) { auto comb = std::make_tuple(t0, t1, t2, t3, t4); count++; benchmark::DoNotOptimize(comb); @@ -300,21 +300,20 @@ static void BM_ASoAHelpersCombGenTracksPairs(benchmark::State& state) std::uniform_real_distribution uniform_dist(0, 1); TableBuilder builder; - auto rowWriter = builder.cursor(); + auto rowWriter = builder.cursor(); for (auto i = 0; i < state.range(0); ++i) { rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)); } auto table = builder.finalize(); - o2::aod::Tracks tracks{table}; + o2::aod::Calos calos{table}; int64_t count = 0; for (auto _ : state) { count = 0; - for (auto& comb : combinations(tracks, tracks)) { + for (auto& comb : combinations(calos, calos)) { count++; } benchmark::DoNotOptimize(count); @@ -332,21 +331,20 @@ static void BM_ASoAHelpersCombGenTracksFives(benchmark::State& state) std::uniform_real_distribution uniform_dist(0, 1); TableBuilder builder; - auto rowWriter = builder.cursor(); + auto rowWriter = builder.cursor(); for (auto i = 0; i < state.range(0); ++i) { rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)); } auto table = builder.finalize(); - o2::aod::Tracks tracks{table}; + o2::aod::Calos calos{table}; int64_t count = 0; for (auto _ : state) { count = 0; - for (auto& comb : combinations(tracks, tracks, tracks, tracks, tracks)) { + for (auto& comb : combinations(calos, calos, calos, calos, calos)) { count++; } benchmark::DoNotOptimize(count); @@ -405,32 +403,30 @@ static void BM_ASoAHelpersCombGenTracksFivesMultipleChunks(benchmark::State& sta std::uniform_real_distribution uniform_dist(0, 1); TableBuilder builderA; - auto rowWriterA = builderA.cursor(); + auto rowWriterA = builderA.cursor(); for (auto i = 0; i < state.range(0); ++i) { rowWriterA(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)); } auto tableA = builderA.finalize(); TableBuilder builderB; - auto rowWriterB = builderB.cursor(); + auto rowWriterB = builderB.cursor(); for (auto i = 0; i < state.range(0); ++i) { rowWriterB(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), - uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)); } auto tableB = builderB.finalize(); - using ConcatTest = Concat; + using ConcatTest = Concat; - ConcatTest tracks{tableA, tableB}; + ConcatTest calos{tableA, tableB}; int64_t count = 0; for (auto _ : state) { count = 0; - for (auto& comb : combinations(tracks, tracks, tracks, tracks, tracks)) { + for (auto& comb : combinations(calos, calos, calos, calos, calos)) { count++; } benchmark::DoNotOptimize(count); diff --git a/Framework/Core/test/benchmark_TreeToTable.cxx b/Framework/Core/test/benchmark_TreeToTable.cxx index dd2275c93ac51..3224d31ccf484 100644 --- a/Framework/Core/test/benchmark_TreeToTable.cxx +++ b/Framework/Core/test/benchmark_TreeToTable.cxx @@ -10,6 +10,7 @@ #include "Framework/CommonDataProcessors.h" #include "Framework/TableTreeHelpers.h" +#include "Framework/Logger.h" #include #include #include diff --git a/Framework/Core/test/test_AnalysisDataModel.cxx b/Framework/Core/test/test_AnalysisDataModel.cxx index c517d571875bd..77b4264b289db 100644 --- a/Framework/Core/test/test_AnalysisDataModel.cxx +++ b/Framework/Core/test/test_AnalysisDataModel.cxx @@ -22,30 +22,41 @@ using namespace o2::framework; using namespace arrow; -using namespace o2::soa; -using namespace o2::aod; + +DECLARE_SOA_STORE(); + +namespace col +{ +DECLARE_SOA_COLUMN(X, x, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(Z, z, float); +DECLARE_SOA_COLUMN(D, d, float); +} // namespace col + +DECLARE_SOA_TABLE(XY, "AOD", "XY", col::X, col::Y); +DECLARE_SOA_TABLE(ZD, "AOD", "ZD", col::Z, col::D); BOOST_AUTO_TEST_CASE(TestJoinedTables) { - TableBuilder trackBuilder; + TableBuilder XYBuilder; //FIXME: using full tracks, instead of stored because of unbound dynamic // column (normalized phi) - auto trackWriter = trackBuilder.cursor(); - trackWriter(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - auto tracks = trackBuilder.finalize(); + auto xyWriter = XYBuilder.cursor(); + xyWriter(0, 0, 0); + auto tXY = XYBuilder.finalize(); - TableBuilder trackParCovBuilder; - auto trackParCovWriter = trackParCovBuilder.cursor(); - trackParCovWriter(0, 7, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4); - auto covs = trackParCovBuilder.finalize(); + TableBuilder ZDBuilder; + auto zdWriter = ZDBuilder.cursor(); + zdWriter(0, 7, 1); + auto tZD = ZDBuilder.finalize(); - using Test = Join; + using Test = o2::soa::Join; - Test tests{0, tracks, covs}; + Test tests{0, tXY, tZD}; BOOST_REQUIRE(tests.asArrowTable()->num_columns() != 0); BOOST_REQUIRE_EQUAL(tests.asArrowTable()->num_columns(), - tracks->num_columns() + covs->num_columns()); - auto tests2 = join(Tracks{tracks}, StoredTracksCov{covs}); + tXY->num_columns() + tZD->num_columns()); + auto tests2 = join(XY{tXY}, ZD{tZD}); static_assert(std::is_same_v, "Joined tables should have the same type, regardless how we construct them"); } diff --git a/Framework/Core/test/test_AnalysisTask.cxx b/Framework/Core/test/test_AnalysisTask.cxx index 4043351815d10..fb4a0e70cd13b 100644 --- a/Framework/Core/test/test_AnalysisTask.cxx +++ b/Framework/Core/test/test_AnalysisTask.cxx @@ -146,29 +146,34 @@ struct JTask { BOOST_AUTO_TEST_CASE(AdaptorCompilation) { auto task1 = adaptAnalysisTask("test1"); - BOOST_CHECK_EQUAL(task1.inputs.size(), 1); + BOOST_CHECK_EQUAL(task1.inputs.size(), 2); BOOST_CHECK_EQUAL(task1.outputs.size(), 1); - BOOST_CHECK_EQUAL(task1.inputs[0].binding, std::string("Tracks")); + BOOST_CHECK_EQUAL(task1.inputs[0].binding, std::string("TracksExtension")); + BOOST_CHECK_EQUAL(task1.inputs[1].binding, std::string("Tracks")); BOOST_CHECK_EQUAL(task1.outputs[0].binding.value, std::string("FooBars")); auto task2 = adaptAnalysisTask("test2"); - BOOST_CHECK_EQUAL(task2.inputs.size(), 7); + BOOST_CHECK_EQUAL(task2.inputs.size(), 9); BOOST_CHECK_EQUAL(task2.inputs[0].binding, "Collisions"); - BOOST_CHECK_EQUAL(task2.inputs[1].binding, "Tracks"); - BOOST_CHECK_EQUAL(task2.inputs[2].binding, "TracksExtra"); - BOOST_CHECK_EQUAL(task2.inputs[3].binding, "TracksCov"); - BOOST_CHECK_EQUAL(task2.inputs[4].binding, "UnassignedTracks"); - BOOST_CHECK_EQUAL(task2.inputs[5].binding, "Calos"); - BOOST_CHECK_EQUAL(task2.inputs[6].binding, "CaloTriggers"); + BOOST_CHECK_EQUAL(task2.inputs[1].binding, "TracksExtension"); + BOOST_CHECK_EQUAL(task2.inputs[2].binding, "Tracks"); + BOOST_CHECK_EQUAL(task2.inputs[3].binding, "TracksExtra"); + BOOST_CHECK_EQUAL(task2.inputs[4].binding, "TracksCovExtension"); + BOOST_CHECK_EQUAL(task2.inputs[5].binding, "TracksCov"); + BOOST_CHECK_EQUAL(task2.inputs[6].binding, "UnassignedTracks"); + BOOST_CHECK_EQUAL(task2.inputs[7].binding, "Calos"); + BOOST_CHECK_EQUAL(task2.inputs[8].binding, "CaloTriggers"); auto task3 = adaptAnalysisTask("test3"); - BOOST_CHECK_EQUAL(task3.inputs.size(), 2); + BOOST_CHECK_EQUAL(task3.inputs.size(), 3); BOOST_CHECK_EQUAL(task3.inputs[0].binding, "Collisions"); - BOOST_CHECK_EQUAL(task3.inputs[1].binding, "Tracks"); + BOOST_CHECK_EQUAL(task3.inputs[1].binding, "TracksExtension"); + BOOST_CHECK_EQUAL(task3.inputs[2].binding, "Tracks"); auto task4 = adaptAnalysisTask("test4"); - BOOST_CHECK_EQUAL(task4.inputs.size(), 1); - BOOST_CHECK_EQUAL(task4.inputs[0].binding, "Tracks"); + BOOST_CHECK_EQUAL(task4.inputs.size(), 2); + BOOST_CHECK_EQUAL(task4.inputs[0].binding, "TracksExtension"); + BOOST_CHECK_EQUAL(task4.inputs[1].binding, "Tracks"); auto task5 = adaptAnalysisTask("test5"); BOOST_CHECK_EQUAL(task5.inputs.size(), 1); diff --git a/Framework/Core/test/test_DataOutputDirector.cxx b/Framework/Core/test/test_DataOutputDirector.cxx index 7fde2c6fc7977..e6f198197618e 100644 --- a/Framework/Core/test/test_DataOutputDirector.cxx +++ b/Framework/Core/test/test_DataOutputDirector.cxx @@ -12,9 +12,9 @@ #define BOOST_TEST_DYN_LINK #include - #include "Headers/DataHeader.h" #include "Framework/DataOutputDirector.h" +#include BOOST_AUTO_TEST_CASE(TestDataOutputDirector) { diff --git a/Framework/Core/test/test_Expressions.cxx b/Framework/Core/test/test_Expressions.cxx index c95db424ef650..c188a5710af99 100644 --- a/Framework/Core/test/test_Expressions.cxx +++ b/Framework/Core/test/test_Expressions.cxx @@ -29,6 +29,7 @@ static BindingNode eta{"eta", atype::FLOAT}; static BindingNode tgl{"tgl", atype::FLOAT}; static BindingNode signed1Pt{"signed1Pt", atype::FLOAT}; +static BindingNode testInt{"testInt", atype::INT32}; } // namespace nodes namespace o2::aod::track diff --git a/Framework/Core/test/test_Kernels.cxx b/Framework/Core/test/test_Kernels.cxx index 46a2087c22b95..b7f48bcc82c9f 100644 --- a/Framework/Core/test/test_Kernels.cxx +++ b/Framework/Core/test/test_Kernels.cxx @@ -21,12 +21,6 @@ using namespace o2::framework; using namespace arrow; using namespace arrow::compute; -#if (ARROW_VERSION < 1000000) -namespace arrow -{ -using Datum = compute::Datum; -} -#else BOOST_AUTO_TEST_CASE(TestSlicing) { TableBuilder builder; @@ -57,7 +51,6 @@ BOOST_AUTO_TEST_CASE(TestSlicing) BOOST_REQUIRE_EQUAL(arr1.Value(i), c[i]); } } -#endif BOOST_AUTO_TEST_CASE(TestSlicingFramework) { diff --git a/Framework/Core/test/test_RegionInfoCallbackService.cxx b/Framework/Core/test/test_RegionInfoCallbackService.cxx index a357583194840..571da32501584 100644 --- a/Framework/Core/test/test_RegionInfoCallbackService.cxx +++ b/Framework/Core/test/test_RegionInfoCallbackService.cxx @@ -34,6 +34,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) AlgorithmSpec{ [](ProcessingContext& ctx) { auto& out = ctx.outputs().make(OutputRef{"test", 0}); + ctx.services().get().endOfStream(); + ctx.services().get().readyToQuit(QuitRequest::Me); }}}, {"dest", Inputs{ diff --git a/Framework/Core/test/test_SimpleDataProcessingDevice01.cxx b/Framework/Core/test/test_SimpleDataProcessingDevice01.cxx index a45b048e52757..5b485bb186be4 100644 --- a/Framework/Core/test/test_SimpleDataProcessingDevice01.cxx +++ b/Framework/Core/test/test_SimpleDataProcessingDevice01.cxx @@ -14,7 +14,6 @@ #include "Framework/RawDeviceService.h" #include "Framework/runDataProcessing.h" #include -#include using namespace o2::framework; @@ -40,7 +39,7 @@ std::vector defineDataProcessing(ConfigContext const&) {OutputSpec{"TPC", "CLUSTERS"}, OutputSpec{"ITS", "CLUSTERS"}}, adaptStateless([](DataAllocator& outputs, ControlService& control, RawDeviceService& service) { - service.device()->WaitFor(std::chrono::milliseconds(1000)); + service.waitFor(1000); // Creates a new message of size 1000 which // has "TPC" as data origin and "CLUSTERS" as data description. auto& tpcClusters = outputs.make(Output{"TPC", "CLUSTERS", 0}, 1000); diff --git a/Framework/Core/test/test_SimpleTracksED.cxx b/Framework/Core/test/test_SimpleTracksED.cxx index 57a10996970c9..35d113a0e85a2 100644 --- a/Framework/Core/test/test_SimpleTracksED.cxx +++ b/Framework/Core/test/test_SimpleTracksED.cxx @@ -33,7 +33,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) return WorkflowSpec{ {"trackDisplay", Inputs{ - {"tracks", "AOD", "TRACKPAR"}}, + {"Collisions", "AOD", "COLLISION"}}, Outputs{}, AlgorithmSpec{adaptStateful( [](CallbackService& callbacks) { @@ -51,12 +51,12 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) [count, window, guiCallback]() { (*count)++; window ? pollGUI(window, guiCallback) : false; }); return adaptStateless([count](InputRecord& inputs, ControlService& control) { - auto input = inputs.get("tracks"); + auto input = inputs.get("Collisions"); - o2::aod::Tracks myTracks{input->asArrowTable()}; + o2::aod::Collisions myCollisions{{input->asArrowTable()}}; - for (auto& track : myTracks) { - LOGF(info, "CollisionId %d", track.collisionId()); + for (auto& collision : myCollisions) { + LOGF(info, "CollisionId %d", collision.globalIndex()); } if (*count > 1000) { diff --git a/Framework/Core/test/test_StaggeringWorkflow.cxx b/Framework/Core/test/test_StaggeringWorkflow.cxx index 126551647d2d5..f124d099dc4ba 100644 --- a/Framework/Core/test/test_StaggeringWorkflow.cxx +++ b/Framework/Core/test/test_StaggeringWorkflow.cxx @@ -24,8 +24,6 @@ #include "Framework/DispatchPolicy.h" #include "Framework/DeviceSpec.h" #include "Framework/Output.h" -#include -#include #include #include #include @@ -88,9 +86,9 @@ std::vector defineDataProcessing(ConfigContext const&) // because of the CompletionPolicy trigger matcher. This message will be // sent together with the second message. outputs.snapshot(Output{"PROD", "CHANNEL", subspec, Lifetime::Timeframe}, subspec); - device.device()->WaitFor(std::chrono::milliseconds(100)); + device.waitFor(100); outputs.snapshot(Output{"PROD", "TRIGGER", subspec, Lifetime::Timeframe}, subspec); - device.device()->WaitFor(std::chrono::milliseconds(100)); + device.waitFor(100); } control.endOfStream(); control.readyToQuit(QuitRequest::Me); diff --git a/Framework/Foundation/include/Framework/Pack.h b/Framework/Foundation/include/Framework/Pack.h index 983a256b6e7b9..b357e51af53af 100644 --- a/Framework/Foundation/include/Framework/Pack.h +++ b/Framework/Foundation/include/Framework/Pack.h @@ -33,6 +33,13 @@ constexpr std::size_t pack_size(pack const&) template struct pack_element; +#ifdef __clang__ +template +struct pack_element> { + using type = __type_pack_element; +}; +#else + // recursive case template struct pack_element> @@ -44,10 +51,20 @@ template struct pack_element<0, pack> { typedef Head type; }; +#endif template using pack_element_t = typename pack_element::type; +template +using pack_head_t = typename pack_element<0, T>::type; + +template +constexpr auto pack_tail(pack) +{ + return pack{}; +} + /// Templates for manipulating type lists in pack /// (see https://codereview.stackexchange.com/questions/201209/filter-template-meta-function/201222#201222) /// Example of use: @@ -144,6 +161,42 @@ constexpr size_t has_type_at(pack const&) return sizeof...(Ts) + 2; } +namespace +{ +template +struct indexed { + using type = T; + constexpr static std::size_t index = I; +}; + +template +struct indexer; + +template +struct indexer, Ts...> + : indexed... { +}; + +template +indexed select(indexed); + +template +constexpr std::size_t has_type_at_t = decltype(select( + indexer, Ts...>{}))::index; +} // namespace + +template +constexpr std::size_t has_type_at_v(o2::framework::pack<>) +{ + return -1; +} + +template +constexpr std::size_t has_type_at_v(o2::framework::pack) +{ + return has_type_at_t; +} + /// Intersect two packs template struct intersect_pack { @@ -161,6 +214,36 @@ struct intersect_pack { template using intersected_pack_t = typename intersect_pack::type; +/// Subtract two packs +template +struct subtract_pack { + template + static constexpr auto make_subtraction(std::index_sequence) + { + return filtered_pack, S2>, + pack_element_t, void>...>{}; + } + using type = decltype(make_subtraction(std::make_index_sequence{})); +}; + +template +constexpr auto concatenate_pack_unique(pack, pack) +{ + using p1 = typename subtract_pack, pack>::type; + return concatenate_pack(p1{}, pack{}); +} + +template +constexpr auto concatenate_pack_unique(P1 p1, P2 p2, Ps... ps) +{ + return concatenate_pack_unique(p1, concatenate_pack_unique(p2, ps...)); +} + +template +using concatenated_pack_unique_t = decltype(concatenate_pack_unique(Ps{}...)); + } // namespace o2::framework #endif // O2_FRAMEWORK_PACK_H_ diff --git a/Framework/Foundation/test/test_FunctionalHelpers.cxx b/Framework/Foundation/test/test_FunctionalHelpers.cxx index db6ff3449274b..af49a4c3ce7c8 100644 --- a/Framework/Foundation/test/test_FunctionalHelpers.cxx +++ b/Framework/Foundation/test/test_FunctionalHelpers.cxx @@ -44,6 +44,12 @@ BOOST_AUTO_TEST_CASE(TestOverride) static_assert(std::is_same_v, pack>, pack>, "pack should be concatenated"); static_assert(std::is_same_v, pack, pack>, pack>, "pack should be concatenated"); + using p1 = pack; + using p2 = pack; + using p3 = concatenated_pack_unique_t; + print_pack(); + static_assert(std::is_same_v>, "pack should not have duplicated types"); + struct ForwardDeclared; static_assert(is_type_complete_v == false, "This should not be complete because the struct is simply forward declared."); diff --git a/Framework/TestWorkflows/CMakeLists.txt b/Framework/TestWorkflows/CMakeLists.txt index f1e0bf0c7d3a4..7ae2e382ce8ec 100644 --- a/Framework/TestWorkflows/CMakeLists.txt +++ b/Framework/TestWorkflows/CMakeLists.txt @@ -78,28 +78,10 @@ o2_add_dpl_workflow(test_CompletionPolicies SOURCES src/test_CompletionPolicies.cxx COMPONENT_NAME TestWorkflows) -o2_data_file(COPY etc/exampleDataSamplingConfig.json DESTINATION etc) - -o2_add_dpl_workflow(datasampling-pod-and-root - SOURCES src/dataSamplingPodAndRoot.cxx - COMPONENT_NAME TestWorkflows) - -o2_add_dpl_workflow(datasampling-parallel - SOURCES src/dataSamplingParallel.cxx - COMPONENT_NAME TestWorkflows) - -o2_add_dpl_workflow(datasampling-time-pipeline - SOURCES src/dataSamplingTimePipeline.cxx - COMPONENT_NAME TestWorkflows) - o2_add_dpl_workflow(ccdb-fetch-to-timeframe SOURCES src/test_CCDBFetchToTimeframe.cxx COMPONENT_NAME TestWorkflows) -o2_add_dpl_workflow(datasampling-benchmark - SOURCES src/dataSamplingBenchmark.cxx - COMPONENT_NAME TestWorkflows) - o2_add_dpl_workflow(simple-source SOURCES src/o2SimpleSource.cxx COMPONENT_NAME TestWorkflows) diff --git a/Framework/TestWorkflows/src/o2D0Analysis.cxx b/Framework/TestWorkflows/src/o2D0Analysis.cxx index 393dcc20e7fa7..728f3ca50a35a 100644 --- a/Framework/TestWorkflows/src/o2D0Analysis.cxx +++ b/Framework/TestWorkflows/src/o2D0Analysis.cxx @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #include "Framework/runDataProcessing.h" #include "Framework/AnalysisHelpers.h" +#include "Framework/RootAnalysisHelpers.h" #include diff --git a/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx b/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx index eaa6eb2d081aa..d42924ae64095 100644 --- a/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx +++ b/Framework/TestWorkflows/src/o2SimpleTracksAnalysis.cxx @@ -9,6 +9,7 @@ // or submit itself to any jurisdiction. #include "Framework/runDataProcessing.h" #include "Framework/AnalysisHelpers.h" +#include "Framework/RootAnalysisHelpers.h" #include "Framework/TableBuilder.h" #include "Framework/AnalysisDataModel.h" @@ -20,9 +21,7 @@ using namespace ROOT::RDF; using namespace o2; using namespace o2::framework; -namespace o2 -{ -namespace aod +namespace o2::aod { namespace tracks { @@ -31,9 +30,7 @@ DECLARE_SOA_COLUMN(Phi, phi, float); } // namespace tracks using TracksDerived = o2::soa::Table; - -} // namespace aod -} // namespace o2 +} // namespace o2::aod // A dummy workflow which creates a few of the tables proposed by Ruben, // using ARROW @@ -57,8 +54,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& specs) // in Ruben's table. The first string is just a label so that the // algorithm can be in principle be reused for different kind of // tracks. - InputSpec{"tracks", "AOD", "TRACKPAR"}, - }, + InputSpec{"Tracks", "DYN", "TRACKPAR"}, + InputSpec{"TracksExtension", "AOD", "TRACKPAR"}}, // No outputs for the time being. Outputs{ OutputSpec{{"derived"}, "AOD", "TRACKDERIVED"}}, @@ -68,15 +65,13 @@ WorkflowSpec defineDataProcessing(ConfigContext const& specs) // FIXME: Too much boilerplate. adaptStateless([](InputRecord& inputs, DataAllocator& outputs) { /// Get the input from the converter. - auto input = inputs.get("tracks"); + auto input1 = inputs.get("Tracks"); + auto input2 = inputs.get("TracksExtension"); /// Get a table builder to build the results auto& etaPhiBuilder = outputs.make(Output{"AOD", "TRACKDERIVED"}); auto etaPhiWriter = etaPhiBuilder.cursor(); - /// Documentation for arrow at: - /// - /// https://arrow.apache.org/docs/cpp/namespacearrow.html - auto tracks = aod::Tracks(input->asArrowTable()); + auto tracks = aod::Tracks({input1->asArrowTable(), input2->asArrowTable()}); for (auto& track : tracks) { auto phi = asin(track.snp()) + track.alpha() + M_PI; diff --git a/Framework/Utils/include/DPLUtils/DPLRawParser.h b/Framework/Utils/include/DPLUtils/DPLRawParser.h index 9548eba2c2b19..a227ebaa753a9 100644 --- a/Framework/Utils/include/DPLUtils/DPLRawParser.h +++ b/Framework/Utils/include/DPLUtils/DPLRawParser.h @@ -19,6 +19,7 @@ #include "Framework/InputRecord.h" #include "Framework/DataRef.h" #include "Framework/DataRefUtils.h" +#include "Framework/Logger.h" #include "Headers/DataHeader.h" #include // std::declval diff --git a/Framework/Utils/include/DPLUtils/RootTreeReader.h b/Framework/Utils/include/DPLUtils/RootTreeReader.h index d5a20d708c9dd..3e60052df8b30 100644 --- a/Framework/Utils/include/DPLUtils/RootTreeReader.h +++ b/Framework/Utils/include/DPLUtils/RootTreeReader.h @@ -18,6 +18,7 @@ #include "Framework/RootSerializationSupport.h" #include "Framework/Output.h" #include "Framework/ProcessingContext.h" +#include "Framework/Logger.h" #include "Headers/DataHeader.h" #include #include diff --git a/Framework/Utils/include/DPLUtils/RootTreeWriter.h b/Framework/Utils/include/DPLUtils/RootTreeWriter.h index 5161c5c77028c..9722f8e0b918e 100644 --- a/Framework/Utils/include/DPLUtils/RootTreeWriter.h +++ b/Framework/Utils/include/DPLUtils/RootTreeWriter.h @@ -18,6 +18,7 @@ #include "Framework/RootSerializationSupport.h" #include "Framework/InputRecord.h" #include "Framework/DataRef.h" +#include "Framework/Logger.h" #include #include #include diff --git a/GPU/Common/GPUCommonAlgorithm.h b/GPU/Common/GPUCommonAlgorithm.h index b4822e1cf441a..4893eb99a07c2 100644 --- a/GPU/Common/GPUCommonAlgorithm.h +++ b/GPU/Common/GPUCommonAlgorithm.h @@ -212,7 +212,7 @@ typedef GPUCommonAlgorithm CAAlgo; } // namespace gpu } // namespace GPUCA_NAMESPACE -#if ((defined(__CUDACC__) && !defined(__clang__)) || defined(__HIPCC__)) && !defined(GPUCA_GPUCODE_GENRTC) +#if ((defined(__CUDACC__) && !defined(__clang__)) || defined(__HIPCC__)) #include "GPUCommonAlgorithmThrust.h" @@ -332,7 +332,7 @@ GPUdi() void GPUCommonAlgorithm::swap(T& a, T& b) #ifdef __OPENCL__ // Nothing to do, work_group functions available -#elif (defined(__CUDACC__) || defined(__HIPCC__)) && !defined(GPUCA_GPUCODE_GENRTC) +#elif (defined(__CUDACC__) || defined(__HIPCC__)) // CUDA and HIP work the same way using cub, need just different header #ifndef GPUCA_GPUCODE_GENRTC diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 924b045feff75..71fc0517c2afd 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -16,7 +16,7 @@ #include "GPUCommonDef.h" -#if defined(__CUDACC__) && !defined(__clang__) +#if defined(__CUDACC__) && !defined(__clang__) && !defined(GPUCA_GPUCODE_GENRTC) #include #endif diff --git a/GPU/GPUTracking/Base/GPUDataTypes.h b/GPU/GPUTracking/Base/GPUDataTypes.h index de0e15928f535..bea67a6f06113 100644 --- a/GPU/GPUTracking/Base/GPUDataTypes.h +++ b/GPU/GPUTracking/Base/GPUDataTypes.h @@ -20,10 +20,10 @@ // Please add complex data types required on the host but not GPU to GPUHostDataTypes.h and forward-declare! #ifndef GPUCA_GPUCODE_DEVICE #include -#endif #ifdef GPUCA_NOCOMPAT_ALLOPENCL #include #endif +#endif #ifdef GPUCA_NOCOMPAT #include "GPUTRDDef.h" diff --git a/GPU/GPUTracking/Base/GPUGeneralKernels.h b/GPU/GPUTracking/Base/GPUGeneralKernels.h index f9e7d8a9e6a52..250a0420ad19f 100644 --- a/GPU/GPUTracking/Base/GPUGeneralKernels.h +++ b/GPU/GPUTracking/Base/GPUGeneralKernels.h @@ -17,14 +17,18 @@ #include "GPUDef.h" #include "GPUDataTypes.h" +#if defined(__HIPCC__) +#define GPUCA_CUB hipcub +#else +#define GPUCA_CUB cub +#endif + #ifndef GPUCA_GPUCODE_GENRTC #ifdef GPUCA_GPUCODE #ifdef __CUDACC__ #include -#define GPUCA_CUB cub #elif defined(__HIPCC__) #include -#define GPUCA_CUB hipcub #endif #endif #endif @@ -54,7 +58,7 @@ class GPUKernelTemplate template struct GPUSharedMemoryScan64 { // Provides the shared memory resources for CUB collectives -#if (defined(__CUDACC__) || defined(__HIPCC__)) && defined(GPUCA_GPUCODE) && !defined(GPUCA_GPUCODE_GENRTC) +#if (defined(__CUDACC__) || defined(__HIPCC__)) && defined(GPUCA_GPUCODE) typedef GPUCA_CUB::BlockScan BlockScan; typedef GPUCA_CUB::BlockReduce BlockReduce; typedef GPUCA_CUB::WarpScan WarpScan; @@ -98,4 +102,6 @@ class GPUMemClean16 : public GPUKernelTemplate } // namespace gpu } // namespace GPUCA_NAMESPACE +#undef GPUCA_CUB + #endif diff --git a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h index d08ed50241ac7..8ba82395794b3 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionIncludes.h +++ b/GPU/GPUTracking/Base/GPUReconstructionIncludes.h @@ -14,12 +14,6 @@ #ifndef GPURECONSTRUCTIONINCLUDES_H #define GPURECONSTRUCTIONINCLUDES_H -// Disable assertions since they produce errors in GPU Code -#ifdef assert -#undef assert -#endif -#define assert(param) - #ifndef WIN32 #include #include diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index 526b7eab68458..a7e91bd89d488 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -113,6 +113,7 @@ AddOption(deviceTimers, bool, true, "", 0, "Use device timers instead of host-ba AddOption(registerStandaloneInputMemory, bool, false, "registerInputMemory", 0, "Automatically register input memory buffers for the GPU") AddOption(memoryScalingFactor, float, 1.f, "", 0, "Factor to apply to all memory scalers") AddOption(alternateBorderSort, int, -1, "", 0, "Alternative implementation for sorting of border tracks") +AddOption(enableRTC, bool, false, "", 0, "Use RTC to optimize GPU code") AddVariable(eventDisplay, GPUCA_NAMESPACE::gpu::GPUDisplayBackend*, nullptr) AddHelp("help", 'h') EndConfig() diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 22a2ba4e7fc4e..5d5e41b5fa28d 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -16,7 +16,91 @@ endif() message(STATUS "Building GPUTracking with CUDA support ${TMP_TARGET}") set(SRCS GPUReconstructionCUDA.cu) -set(HDRS GPUReconstructionCUDA.h GPUReconstructionCUDAInternals.h) +set(HDRS GPUReconstructionCUDA.h GPUReconstructionCUDAInternals.h GPUReconstructionCUDADef.h GPUReconstructionCUDAIncludes.h) + +# -------------------------------- Prepare RTC ------------------------------------------------------- +if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") + set(CURTC_DEFINES "-D$,$-D>" + -DGPUCA_GPUCODE_GENRTC -DGPUCA_GPULIBRARY=CUDA + ) + set(CURTC_INCLUDES "-I$,$-I>" + -I${CMAKE_SOURCE_DIR}/Detectors/Base/src + -I${CMAKE_SOURCE_DIR}/Detectors/TRD/base/src + ) + if(ALIGPU_BUILD_TYPE STREQUAL "O2") + set(CURTC_INCLUDES ${CURTC_INCLUDES} "-I$,$-I>") + endif() + #set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -keep") + + set(CUDARTC_FLAGS "${CMAKE_CUDA_FLAGS} ${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE}} -std=c++${CMAKE_CUDA_STANDARD}") + if(CUDA_COMPUTETARGET) + set(CUDARTC_FLAGS "${CUDARTC_FLAGS} -gencode arch=compute_${CUDA_COMPUTETARGET},code=sm_${CUDA_COMPUTETARGET}") + set(RTC_CUDA_ARCH "${CUDA_COMPUTETARGET}0") + else() + set(RTC_CUDA_ARCH "750") + endif() + separate_arguments(CUDARTC_FLAGS) + + # convenience variables + if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") + get_filename_component(GPUDIR ${CMAKE_SOURCE_DIR}/../ ABSOLUTE) + else() + set(GPUDIR ${CMAKE_SOURCE_DIR}/GPU/GPUTracking) + endif() + set(CURTC_SRC ${GPUDIR}/Base/cuda/GPUReconstructionCUDArtc.cu) + set(CURTC_BIN ${CMAKE_CURRENT_BINARY_DIR}/GPUReconstructionCUDArtc) + + # cmake-format: off + add_custom_command( + OUTPUT ${CURTC_BIN}.src + COMMAND cat ${GPUDIR}/Base/cuda/GPUReconstructionCUDAIncludes.h > ${CURTC_BIN}.src + COMMAND ${CMAKE_CXX_COMPILER} ${CURTC_DEFINES} ${CURTC_INCLUDES} -std=c++${CMAKE_CUDA_STANDARD} -D__CUDA_ARCH__=${RTC_CUDA_ARCH} -D__CUDACC__ -x c++ -E ${CURTC_SRC} >> ${CURTC_BIN}.src + MAIN_DEPENDENCY ${CURTC_SRC} + IMPLICIT_DEPENDS CXX ${CURTC_SRC} + COMMAND_EXPAND_LISTS + ) + + add_custom_command( + OUTPUT ${CURTC_BIN}.src.S + COMMAND cat ${GPUDIR}/Standalone/makefiles/include.S | sed "s/FILENAMEMOD/_curtc_GPUReconstructionCUDArtc_cu_src/g" | sed "s,FILENAMENORMAL,${CURTC_BIN}.src,g" > ${CURTC_BIN}.src.S + MAIN_DEPENDENCY ${GPUDIR}/Standalone/makefiles/include.S + ) + + add_custom_command( + OUTPUT ${CURTC_BIN}.command + COMMAND echo -n "${CMAKE_CUDA_COMPILER} ${CUDARTC_FLAGS} ${CURTC_DEFINES}" > ${CURTC_BIN}.command + COMMAND_EXPAND_LISTS + VERBATIM + ) + + add_custom_command( + OUTPUT ${CURTC_BIN}.command.S + COMMAND cat ${GPUDIR}/Standalone/makefiles/include.S | sed "s/FILENAMEMOD/_curtc_GPUReconstructionCUDArtc_cu_command/g" | sed "s,FILENAMENORMAL,${CURTC_BIN}.command,g" > ${CURTC_BIN}.command.S + MAIN_DEPENDENCY ${GPUDIR}/Standalone/makefiles/include.S + DEPENDS ${CURTC_BIN}.command + ) + # cmake-format: on + + # make cmake compile the assembler file, add proper dependency on included + # binary code + set_source_files_properties( + ${CURTC_BIN}.src.S + PROPERTIES + LANGUAGE + CXX + OBJECT_DEPENDS + "${CURTC_BIN}.src;${GPUDIR}/Standalone/makefiles/include.S") + + set_source_files_properties( + ${CURTC_BIN}.command.S + PROPERTIES + LANGUAGE + CXX + ) + + set(SRCS ${SRCS} ${CURTC_BIN}.src.S ${CURTC_BIN}.command.S) +endif() +# -------------------------------- End RTC ------------------------------------------------------- if(ALIGPU_BUILD_TYPE STREQUAL "O2") o2_add_library( @@ -32,8 +116,6 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") ${targetName} PUBLIC GPUCA_GPULIBRARY=CUDA $) - target_compile_options(${targetName} PUBLIC --expt-relaxed-constexpr) - set_target_properties(${targetName} PROPERTIES LINKER_LANGUAGE CXX) install(FILES ${HDRS} DESTINATION include/GPU) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index dcaabc9bc781d..0e0d0636b1e4a 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -11,34 +11,11 @@ /// \file GPUReconstructionCUDA.cu /// \author David Rohr -#define GPUCA_GPUTYPE_TURING -#define GPUCA_UNROLL(CUDA, HIP) GPUCA_M_UNROLL_##CUDA -#define GPUdic(CUDA, HIP) GPUCA_GPUdic_select_##CUDA() +#include "GPUReconstructionCUDADef.h" +#include "GPUReconstructionCUDAIncludes.h" -#include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#include -#include -#pragma GCC diagnostic pop - -#ifdef __clang__ -#define assert(...) -#endif - -#include "GPUDef.h" - -#ifndef GPUCA_NO_CONSTANT_MEMORY -#define GPUCA_CONSMEM_PTR -#define GPUCA_CONSMEM_CALL -#define GPUCA_CONSMEM (gGPUConstantMemBuffer.v) -#else -#define GPUCA_CONSMEM_PTR const GPUConstantMem *gGPUConstantMemBuffer, -#define GPUCA_CONSMEM_CALL me->mDeviceConstantMem, -#define GPUCA_CONSMEM ((GPUConstantMem&)(*gGPUConstantMemBuffer)) -#endif -#define GPUCA_KRNL_BACKEND_CLASS GPUReconstructionCUDABackend +#include #include "GPUReconstructionCUDA.h" #include "GPUReconstructionCUDAInternals.h" @@ -114,6 +91,12 @@ class GPUDebugTiming #include "GPUReconstructionIncludesDevice.h" +#ifndef GPUCA_ALIROOT_LIB +extern "C" char _curtc_GPUReconstructionCUDArtc_cu_src[]; +extern "C" unsigned int _curtc_GPUReconstructionCUDArtc_cu_src_size; +extern "C" char _curtc_GPUReconstructionCUDArtc_cu_command[]; +#endif + /* // Not using templated kernel any more, since nvidia profiler does not resolve template names template @@ -137,6 +120,16 @@ GPUg() void runKernelCUDA(GPUCA_CONSMEM_PTR int iSlice_internal, Args... args) #include "GPUReconstructionKernels.h" #undef GPUCA_KRNL +template +int GPUReconstructionCUDAInternals::getRTCkernelNum(int k) +{ + static int num = k; + if (num < 0) { + throw std::runtime_error("Invalid kernel"); + } + return num; +} + template <> void GPUReconstructionCUDABackend::runKernelBackendInternal(krnlSetup& _xyz, void* const& ptr, unsigned long const& size) { @@ -144,11 +137,36 @@ void GPUReconstructionCUDABackend::runKernelBackendInternal(kr GPUFailedMsg(cudaMemsetAsync(ptr, 0, size, mInternals->Streams[_xyz.x.stream])); } +static void getArgPtrs(const void** pArgs) {} +template +static void getArgPtrs(const void** pArgs, const T& arg, const Args&... args) +{ + *pArgs = &arg; + getArgPtrs(pArgs + 1, args...); +} + template void GPUReconstructionCUDABackend::runKernelBackendInternal(krnlSetup& _xyz, const Args&... args) { GPUDebugTiming timer(mProcessingSettings.deviceTimers && mProcessingSettings.debugLevel > 0, (void**)mDebugEvents, mInternals->Streams, _xyz); - backendInternal::runKernelBackendMacro(_xyz, this, args...); + if (mProcessingSettings.enableRTC) { + auto& x = _xyz.x; + auto& y = _xyz.y; + if (y.num <= 1) { + const void* pArgs[sizeof...(Args) + 1]; + pArgs[0] = &y.start; + getArgPtrs(&pArgs[1], args...); + GPUFailedMsg(cuLaunchKernel(*mInternals->rtcFunctions[mInternals->getRTCkernelNum()], x.nBlocks, 1, 1, x.nThreads, 1, 1, 0, mInternals->Streams[x.stream], (void**)pArgs, nullptr)); + } else { + const void* pArgs[sizeof...(Args) + 2]; + pArgs[0] = &y.start; + pArgs[1] = &y.num; + getArgPtrs(&pArgs[2], args...); + GPUFailedMsg(cuLaunchKernel(*mInternals->rtcFunctions[mInternals->getRTCkernelNum()], x.nBlocks, 1, 1, x.nThreads, 1, 1, 0, mInternals->Streams[x.stream], (void**)pArgs, nullptr)); + } + } else { + backendInternal::runKernelBackendMacro(_xyz, this, args...); + } } template @@ -409,25 +427,74 @@ int GPUReconstructionCUDABackend::InitDevice_Runtime() } } + dummyInitKernel<<>>(mDeviceMemoryBase); + GPUInfo("CUDA Initialisation successfull (Device %d: %s (Frequency %d, Cores %d), %lld / %lld bytes host / global memory, Stack frame %d, Constant memory %lld)", mDeviceId, cudaDeviceProp.name, cudaDeviceProp.clockRate, cudaDeviceProp.multiProcessorCount, (long long int)mHostMemorySize, + (long long int)mDeviceMemorySize, (int)GPUCA_GPU_STACK_SIZE, (long long int)gGPUConstantMemBufferSize); + +#ifndef GPUCA_ALIROOT_LIB + if (mProcessingSettings.enableRTC) { + if (mProcessingSettings.debugLevel >= 0) { + GPUInfo("Starting CUDA RTC Compilation"); + } + HighResTimer rtcTimer; + rtcTimer.ResetStart(); + std::string filename = "/tmp/o2cagpu_rtc_"; + filename += std::to_string(getpid()); + filename += "_"; + filename += std::to_string(rand()); + if (mProcessingSettings.debugLevel >= 3) { + printf("Writing to %s\n", filename.c_str()); + } + FILE* fp = fopen((filename + ".cu").c_str(), "w+b"); + if (fp == nullptr) { + throw std::runtime_error("Error opening file"); + } + if (fwrite(_curtc_GPUReconstructionCUDArtc_cu_src, 1, _curtc_GPUReconstructionCUDArtc_cu_src_size, fp) != _curtc_GPUReconstructionCUDArtc_cu_src_size) { + throw std::runtime_error("Error writing file"); + } + fclose(fp); + std::string command = _curtc_GPUReconstructionCUDArtc_cu_command; + command += " -cubin -c " + filename + ".cu -o " + filename + ".o"; + if (mProcessingSettings.debugLevel >= 3) { + printf("Running command %s\n", command.c_str()); + } + if (system(command.c_str())) { + throw std::runtime_error("Runtime compilation failed"); + } + GPUFailedMsg(cuModuleLoad(&mInternals->rtcModule, (filename + ".o").c_str())); + +#define GPUCA_KRNL(x_class, x_attributes, x_arguments, x_forward) GPUCA_KRNL_WRAP(GPUCA_KRNL_LOAD_, x_class, x_attributes, x_arguments, x_forward) +#define GPUCA_KRNL_LOAD_single(x_class, x_attributes, x_arguments, x_forward) \ + mInternals->getRTCkernelNum(mInternals->rtcFunctions.size()); \ + mInternals->rtcFunctions.emplace_back(new CUfunction); \ + GPUFailedMsg(cuModuleGetFunction(mInternals->rtcFunctions.back().get(), mInternals->rtcModule, GPUCA_M_STR(GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class))))); +#define GPUCA_KRNL_LOAD_multi(x_class, x_attributes, x_arguments, x_forward) \ + mInternals->getRTCkernelNum(mInternals->rtcFunctions.size()); \ + mInternals->rtcFunctions.emplace_back(new CUfunction); \ + GPUFailedMsg(cuModuleGetFunction(mInternals->rtcFunctions.back().get(), mInternals->rtcModule, GPUCA_M_STR(GPUCA_M_CAT3(krnl_, GPUCA_M_KRNL_NAME(x_class), _multi)))); +#include "GPUReconstructionKernels.h" +#undef GPUCA_KRNL +#undef GPUCA_KRNL_LOAD_single +#undef GPUCA_KRNL_LOAD_multi + + remove((filename + ".cu").c_str()); + remove((filename + ".o").c_str()); + if (mProcessingSettings.debugLevel >= 0) { + GPUInfo("RTC Compilation finished (%f seconds)", rtcTimer.GetCurrentElapsedTime()); + } + } +#endif void* devPtrConstantMem; #ifndef GPUCA_NO_CONSTANT_MEMORY - if (GPUFailedMsgI(cudaGetSymbolAddress(&devPtrConstantMem, gGPUConstantMemBuffer))) { - GPUError("Error getting ptr to constant memory"); - GPUFailedMsgI(cudaDeviceReset()); - return 1; + if (mProcessingSettings.enableRTC) { + GPUFailedMsg(cuModuleGetGlobal((CUdeviceptr*)&devPtrConstantMem, nullptr, mInternals->rtcModule, "gGPUConstantMemBuffer")); + } else { + GPUFailedMsg(cudaGetSymbolAddress(&devPtrConstantMem, gGPUConstantMemBuffer)); } #else - if (GPUFailedMsgI(cudaMalloc(&devPtrConstantMem, gGPUConstantMemBufferSize))) { - GPUError("CUDA Memory Allocation Error"); - GPUFailedMsgI(cudaDeviceReset()); - return (1); - } + GPUFailedMsg(cudaMalloc(&devPtrConstantMem, gGPUConstantMemBufferSize)); #endif mDeviceConstantMem = (GPUConstantMem*)devPtrConstantMem; - - dummyInitKernel<<>>(mDeviceMemoryBase); - GPUInfo("CUDA Initialisation successfull (Device %d: %s (Frequency %d, Cores %d), %lld / %lld bytes host / global memory, Stack frame %d, Constant memory %lld)", mDeviceId, cudaDeviceProp.name, cudaDeviceProp.clockRate, cudaDeviceProp.multiProcessorCount, (long long int)mHostMemorySize, - (long long int)mDeviceMemorySize, (int)GPUCA_GPU_STACK_SIZE, (long long int)gGPUConstantMemBufferSize); } else { GPUReconstructionCUDABackend* master = dynamic_cast(mMaster); mDeviceId = master->mDeviceId; @@ -546,15 +613,15 @@ size_t GPUReconstructionCUDABackend::WriteToConstantMemory(size_t offset, const } else { GPUFailedMsg(cudaMemcpyToSymbolAsync(gGPUConstantMemBuffer, src, size, offset, cudaMemcpyHostToDevice, mInternals->Streams[stream])); } - -#else - if (stream == -1) { - GPUFailedMsg(cudaMemcpy(((char*)mDeviceConstantMem) + offset, src, size, cudaMemcpyHostToDevice)); - } else { - GPUFailedMsg(cudaMemcpyAsync(((char*)mDeviceConstantMem) + offset, src, size, cudaMemcpyHostToDevice, mInternals->Streams[stream])); - } - + if (mProcessingSettings.enableRTC) #endif + { + if (stream == -1) { + GPUFailedMsg(cudaMemcpy(((char*)mDeviceConstantMem) + offset, src, size, cudaMemcpyHostToDevice)); + } else { + GPUFailedMsg(cudaMemcpyAsync(((char*)mDeviceConstantMem) + offset, src, size, cudaMemcpyHostToDevice, mInternals->Streams[stream])); + } + } if (ev && stream != -1) { GPUFailedMsg(cudaEventRecord(*(cudaEvent_t*)ev, mInternals->Streams[stream])); } diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h new file mode 100644 index 0000000000000..ce3d0c53b4d78 --- /dev/null +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDADef.h @@ -0,0 +1,34 @@ +// 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 GPUReconstructionCUDDef.h +/// \author David Rohr + +#ifndef O2_GPU_GPURECONSTRUCTIONCUDADEF_H +#define O2_GPU_GPURECONSTRUCTIONCUDADEF_H + +#define GPUCA_GPUTYPE_TURING +#define GPUCA_UNROLL(CUDA, HIP) GPUCA_M_UNROLL_##CUDA +#define GPUdic(CUDA, HIP) GPUCA_GPUdic_select_##CUDA() + +#include "GPUDef.h" + +#ifndef GPUCA_NO_CONSTANT_MEMORY +#define GPUCA_CONSMEM_PTR +#define GPUCA_CONSMEM_CALL +#define GPUCA_CONSMEM (gGPUConstantMemBuffer.v) +#else +#define GPUCA_CONSMEM_PTR const GPUConstantMem *gGPUConstantMemBuffer, +#define GPUCA_CONSMEM_CALL me->mDeviceConstantMem, +#define GPUCA_CONSMEM ((GPUConstantMem&)(*gGPUConstantMemBuffer)) +#endif +#define GPUCA_KRNL_BACKEND_CLASS GPUReconstructionCUDABackend + +#endif diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h similarity index 50% rename from GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h rename to GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h index d994f04c93a1e..fff90de9349f8 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAIncludes.h @@ -8,24 +8,23 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file GPUReconstructionCUDArtcPre.h +/// \file GPUReconstructionCUDIncludes.h /// \author David Rohr -//#include -//#include -//#include -//#include +#ifndef O2_GPU_GPURECONSTRUCTIONCUDAINCLUDES_H +#define O2_GPU_GPURECONSTRUCTIONCUDAINCLUDES_H -#define GPUCA_CONSMEM (gGPUConstantMemBuffer.v) -using uint64_t = unsigned long; -using uint32_t = unsigned int; -using uint16_t = unsigned short; -using uint8_t = unsigned char; -using uint = unsigned int; -using ushort = unsigned short; -using ulong = unsigned long; -#undef assert -#define assert(...) -void printf(...) -{ -} +#include +#include +#include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include +#include +#include +#include +#include +#pragma GCC diagnostic pop +#include + +#endif diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAInternals.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAInternals.h index a02f6133ee354..11a41fdb4fba7 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAInternals.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAInternals.h @@ -17,15 +17,22 @@ #define GPURECONSTRUCTIONCUDAINTERNALS_H #include "GPULogging.h" +#include +#include namespace GPUCA_NAMESPACE { namespace gpu { struct GPUReconstructionCUDAInternals { - CUcontext CudaContext; // Pointer to CUDA context - unsigned int cudaContextObtained = 0; // If multiple instances of GPUThreadContextCUDA are obtained, we count them and return the context only after all are destroyed - cudaStream_t Streams[GPUCA_MAX_STREAMS]; // Pointer to array of CUDA Streams + CUcontext CudaContext; // CUDA context + CUmodule rtcModule; // module for RTC compilation + std::vector> rtcFunctions; // vector of ptrs to RTC kernels + unsigned int cudaContextObtained = 0; // If multiple instances of GPUThreadContextCUDA are obtained, we count them and return the context only after all are destroyed + cudaStream_t Streams[GPUCA_MAX_STREAMS]; // Pointer to array of CUDA Streams + + template + static int getRTCkernelNum(int k = -1); }; #define GPUFailedMsg(x) GPUFailedMsgA(x, __FILE__, __LINE__) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu index 52ebaf6fb9a03..194093439f34b 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu @@ -11,17 +11,22 @@ /// \file GPUReconstructionCUDArtc.cu /// \author David Rohr -#include -#include - -#include "GPUReconstructionCUDArtcPre.h" - -#define GPUCA_GPUTYPE_TURING +#include "GPUReconstructionCUDADef.h" #include "GPUReconstructionIncludesDevice.h" -extern "C" __global__ void foo() -{ - if (threadIdx.x || blockIdx.x) - return; - printf("test\n"); +#ifndef GPUCA_GPUCODE_DEVICE +#error RTC Preprocessing must run on device code +#endif +#ifdef GPUCA_NO_CONSTANT_MEMORY +#error CUDA RTC does not support processing without constant memory +#endif + +extern "C" { +#undef GPUCA_KRNL_REG +#define GPUCA_KRNL_REG(args) __launch_bounds__(GPUCA_M_MAX2_3(GPUCA_M_STRIP(args))) +#define GPUCA_KRNL(x_class, x_attributes, x_arguments, x_forward) GPUCA_KRNL_WRAP(GPUCA_KRNL_LOAD_, x_class, x_attributes, x_arguments, x_forward) +#define GPUCA_KRNL_LOAD_single(x_class, x_attributes, x_arguments, x_forward) GPUCA_KRNLGPU_SINGLE(x_class, x_attributes, x_arguments, x_forward) +#define GPUCA_KRNL_LOAD_multi(x_class, x_attributes, x_arguments, x_forward) GPUCA_KRNLGPU_MULTI(x_class, x_attributes, x_arguments, x_forward) +#include "GPUReconstructionKernels.h" +#undef GPUCA_KRNL } diff --git a/GPU/GPUTracking/Base/opencl2/CMakeLists.txt b/GPU/GPUTracking/Base/opencl2/CMakeLists.txt index 2a97b94f6e5ee..df3dc5eb959d4 100644 --- a/GPU/GPUTracking/Base/opencl2/CMakeLists.txt +++ b/GPU/GPUTracking/Base/opencl2/CMakeLists.txt @@ -25,7 +25,7 @@ set(CL_SRC ${GPUDIR}/Base/opencl-common/GPUReconstructionOCL.cl) set(CL_BIN ${CMAKE_CURRENT_BINARY_DIR}/GPUReconstructionOCL2Code) set(OCL_FLAGS -cl-denorms-are-zero -cl-mad-enable -cl-no-signed-zeros -ferror-limit=1000 -Xclang -finclude-default-header -Dcl_clang_storage_class_specifiers -Wno-invalid-constexpr -Wno-unused-command-line-argument -cl-std=clc++) -set(OCL_DEFINCL "-D$,$-D>" +set(OCL_DEFINECL "-D$,$-D>" "-I$,$-I>" -I${CMAKE_SOURCE_DIR}/Detectors/TRD/base/src -I${CMAKE_SOURCE_DIR}/Detectors/Base/src @@ -47,7 +47,7 @@ if(OPENCL2_ENABLED_AMD) # BUILD OpenCL2 binaries for AMD target OUTPUT ${CL_BIN}.amd COMMAND ${CLANG_OCL} ${OCL_FLAGS} - ${OCL_DEFINCL} + ${OCL_DEFINECL} -mcpu=${OCL2_GPUTARGET} -o ${CL_BIN}.amd ${CL_SRC} MAIN_DEPENDENCY ${CL_SRC} @@ -82,7 +82,7 @@ if(OPENCL2_ENABLED_SPIRV) # BUILD OpenCL2 intermediate code for SPIR-V target COMMAND clang -emit-llvm --target=spir64-unknown-unknown ${OCL_FLAGS} - ${OCL_DEFINCL} + ${OCL_DEFINECL} -o ${CL_BIN}.bc -c ${CL_SRC} MAIN_DEPENDENCY ${CL_SRC} IMPLICIT_DEPENDS CXX ${CL_SRC} @@ -116,11 +116,11 @@ if(OPENCL2_ENABLED_SPIRV) # BUILD OpenCL2 intermediate code for SPIR-V target endif() if(OPENCL2_ENABLED) # BUILD OpenCL2 source code for runtime compilation target - # executes clang to create llvm IL code + # executes clang to preprocess add_custom_command( OUTPUT ${CL_BIN}.src COMMAND clang - ${OCL_DEFINCL} + ${OCL_DEFINECL} -E ${CL_SRC} > ${CL_BIN}.src MAIN_DEPENDENCY ${CL_SRC} IMPLICIT_DEPENDS CXX ${CL_SRC} diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 947c8fc5b3d7b..a8b4268b277be 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -1301,6 +1301,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) runKernel(GetGrid(GPUCA_ROW_COUNT, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}); GPUTPCCFMCLabelFlattener::setGlobalOffsetsAndAllocate(clusterer, mcLinearLabels); runKernel(GetGrid(GPUCA_ROW_COUNT, lane, GPUReconstruction::krnlDeviceType::CPU), {iSlice}, {}, &mcLinearLabels); + clusterer.clearMCMemory(); } if (buildNativeHost && buildNativeGPU && anyLaneHasData) { if (GetProcessingSettings().delayedOutput) { @@ -2074,12 +2075,14 @@ int GPUChainTracking::RunTPCCompression() runKernel(GetGridAuto(0), krnlRunRangeNone, krnlEventNone); runKernel(GetGridAuto(0), krnlRunRangeNone, krnlEventNone); TransferMemoryResourcesToHost(myStep, &Compressor, 0); +#ifdef GPUCA_TPC_GEOMETRY_O2 if (mPipelineFinalizationCtx && GetProcessingSettings().doublePipelineClusterizer) { SynchronizeEvents(&mEvents->single); ReleaseEvent(&mEvents->single); ((GPUChainTracking*)GetNextChainInQueue())->RunTPCClusterizer_prepare(false); ((GPUChainTracking*)GetNextChainInQueue())->mCFContext->ptrClusterNativeSave = processorsShadow()->ioPtrs.clustersNative; } +#endif SynchronizeStream(0); o2::tpc::CompressedClusters* O = Compressor.mOutput; memset((void*)O, 0, sizeof(*O)); diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCGrid.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCGrid.cxx index 5b3262825749f..310f77dcb5230 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCGrid.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCGrid.cxx @@ -15,7 +15,7 @@ #include "GPUCommonMath.h" using namespace GPUCA_NAMESPACE::gpu; -#ifndef assert +#if !defined(assert) && !defined(GPUCA_GPUCODE) #include #endif diff --git a/GPU/GPUTracking/Standalone/standalone.cxx b/GPU/GPUTracking/Standalone/standalone.cxx index 10f48ca9e0439..f0b3e67f6896e 100644 --- a/GPU/GPUTracking/Standalone/standalone.cxx +++ b/GPU/GPUTracking/Standalone/standalone.cxx @@ -734,8 +734,6 @@ int main(int argc, char** argv) pipelineThread.reset(new std::thread([]() { rec->RunPipelineWorker(); })); } - // hlt.SetRunMerger(configStandalone.merger); //TODO! - if (configStandalone.seed == -1) { std::random_device rd; configStandalone.seed = (int)rd(); diff --git a/GPU/GPUTracking/Standalone/tools/rtc/rtcsource.sh b/GPU/GPUTracking/Standalone/tools/rtc/rtcsource.sh index a23e8a23e1a78..6eeb456d272c1 100755 --- a/GPU/GPUTracking/Standalone/tools/rtc/rtcsource.sh +++ b/GPU/GPUTracking/Standalone/tools/rtc/rtcsource.sh @@ -2,15 +2,14 @@ cat < source.cu # 1 "/home/qon/alice/O2/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu" # 1 "/home/qon/alice/O2/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtcPre.h" 1 -#include -int main(int, char**) {return 0;} EOT -nvcc -E \ +cat src/Base/cuda/GPUReconstructionCUDArtcPre2.h >> source.cu +nvcc -std=c++17 -gencode arch=compute_75,code=sm_75 -E \ -I src/ -I src/Common/ -I src/Base/ -I src/SliceTracker/ -I src/Merger/ -I src/TRDTracking/ -I src/TPCClusterFinder/ -I src/TPCConvert/ -I src/Global/ -I src/dEdx/ -I src/TPCFastTransformation/ -I src/GPUUtils/ -I src/DataCompression -I src/ITS \ -I$HOME/alice/O2/DataFormats/Detectors/TPC/include -I$HOME/alice/O2/Detectors/Base/include -I$HOME/alice/O2/Detectors/Base/src -I$HOME/alice/O2/Common/MathUtils/include -I$HOME/alice/O2/DataFormats/Headers/include \ -I$HOME/alice/O2/Detectors/TRD/base/include -I$HOME/alice/O2/Detectors/TRD/base/src -I$HOME/alice/O2/Detectors/ITSMFT/ITS/tracking/include -I$HOME/alice/O2/Detectors/ITSMFT/ITS/tracking/cuda/include -I$HOME/alice/O2/Common/Constants/include \ -I$HOME/alice/O2/DataFormats/common/include -I$HOME/alice/O2/DataFormats/Detectors/TRD/include -I$HOME/alice/O2/Detectors/Raw/include \ - -DHAVE_O2HEADERS -DGPUCA_TPC_GEOMETRY_O2 -DGPUCA_STANDALONE -DGPUCA_NO_ITS_TRAITS -DGPUCA_GPUCODE_GENRTC -D__CUDA_ARCH__=750 \ + -DHAVE_O2HEADERS -DGPUCA_TPC_GEOMETRY_O2 -DGPUCA_STANDALONE -DGPUCA_NO_ITS_TRAITS -DGPUCA_GPUCODE_GENRTC \ ~/alice/O2/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDArtc.cu \ | sed '1,/^# 1 ".*GPUReconstructionCUDArtcPre.h" 1$/d' \ >> source.cu diff --git a/GPU/GPUTracking/Standalone/utils/bitfield.h b/GPU/GPUTracking/Standalone/utils/bitfield.h index 366de17584713..bf102cee5e343 100644 --- a/GPU/GPUTracking/Standalone/utils/bitfield.h +++ b/GPU/GPUTracking/Standalone/utils/bitfield.h @@ -14,7 +14,7 @@ #ifndef Q_BITFIELD_H #define Q_BITFIELD_H -#ifdef GPUCA_NOCOMPAT_ALLOPENCL +#if !defined(GPUCA_NOCOMPAT_ALLOPENCL) && !defined(GPUCA_GPUCODE_GENRTC) #include #endif diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx index 4beb572999aff..8af28459db03c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFChargeMapFiller.cxx @@ -88,6 +88,9 @@ GPUdii() void GPUTPCCFChargeMapFiller::Thread #endif diff --git a/Generators/CMakeLists.txt b/Generators/CMakeLists.txt index 178ed69529ab5..0fca05335777c 100644 --- a/Generators/CMakeLists.txt +++ b/Generators/CMakeLists.txt @@ -32,6 +32,7 @@ o2_add_library(Generators src/TriggerParticleParam.cxx src/BoxGunParam.cxx src/QEDGenParam.cxx + src/GenCosmicsParam.cxx src/GeneratorFactory.cxx $<$:src/GeneratorPythia6.cxx> $<$:src/GeneratorPythia6Param.cxx> @@ -70,7 +71,8 @@ set(headers include/Generators/TriggerParticleParam.h include/Generators/ConfigurationMacroHelper.h include/Generators/BoxGunParam.h - include/Generators/QEDGenParam.h) + include/Generators/QEDGenParam.h + include/Generators/GenCosmicsParam.h) if (pythia6_FOUND) list(APPEND headers include/Generators/GeneratorPythia6.h @@ -107,6 +109,11 @@ if(doBuildSimulation) PUBLIC_LINK_LIBRARIES O2::Generators O2::SimConfig LABELS generators) + + o2_add_test_root_macro(share/external/GenCosmicsLoader.C + PUBLIC_LINK_LIBRARIES O2::Generators + O2::SimConfig + LABELS generators) endif() o2_add_test_root_macro(share/external/tgenerator.C diff --git a/Generators/include/Generators/GenCosmicsParam.h b/Generators/include/Generators/GenCosmicsParam.h new file mode 100644 index 0000000000000..372bd9ec3b0a0 --- /dev/null +++ b/Generators/include/Generators/GenCosmicsParam.h @@ -0,0 +1,56 @@ +// 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. + +#ifndef ALICEO2_GENCOSMICSPARAM_H +#define ALICEO2_GENCOSMICSPARAM_H + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +// @file GenCosmicsParam +// @author ruben.shahoyan@cern.ch +// @brief Parameters for cosmics generation + +namespace o2 +{ +namespace eventgen +{ +struct GenCosmicsParam : public o2::conf::ConfigurableParamHelper { + enum GenParamType : int { ParamMI, + ParamACORDE, + ParamTPC }; // source parameterizations + enum AccType : int { ITS0, + ITS1, + ITS2, + ITS3, + ITS4, + ITS5, + ITS6, + TPC, + Custom }; + GenParamType param = ParamTPC; + AccType accept = TPC; + int nPart = 1; ///< number of particles per event + int maxTrials = 10000000; ///< number of failed trials to abandon generation + float maxAngle = 45.; ///< max angle wrt azimuth to generate (in degrees) + float origin = 550.; ///< create particle at this radius + float pmin = 0.5; ///< min total momentum + float pmax = 100; ///< max total momentum + float customAccX = 250; ///< require particle to pass within this |X| at Y=0 if AccType=custom is selected + float customAccZ = 250; ///< require particle to pass within this |Z| at Y=0 if AccType=custom is selected + + // boilerplate stuff + make principal key + O2ParamDef(GenCosmicsParam, "cosmics"); +}; + +} // namespace eventgen +} // namespace o2 + +#endif diff --git a/Generators/share/external/GenCosmics.C b/Generators/share/external/GenCosmics.C new file mode 100644 index 0000000000000..493bfcf6c1311 --- /dev/null +++ b/Generators/share/external/GenCosmics.C @@ -0,0 +1,80 @@ +// 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. + +//< Macro to run QED background generator, us it as e.g. +//< o2-sim -n10000 -m PIPE ITS TPC -g extgen --extGenFile $O2_ROOT/share/Generators/external/GenCosmicsLoader.C + +R__LOAD_LIBRARY(libGeneratorCosmics.so) + +using namespace o2::eventgen; + +o2::eventgen::GeneratorTGenerator* GenCosmics() +{ + auto genCosm = new GeneratorCosmics(); + auto& cosmParam = GenCosmicsParam::Instance(); + + if (cosmParam.param == GenCosmicsParam::ParamMI) { + genCosm->setParamMI(); + } else if (cosmParam.param == GenCosmicsParam::ParamACORDE) { + genCosm->setParamACORDE(); + } else if (cosmParam.param == GenCosmicsParam::ParamTPC) { + genCosm->setParamTPC(); + } else { + LOG(FATAL) << "Unknown cosmics param type " << cosmParam.param; + } + + genCosm->setNPart(cosmParam.nPart); + genCosm->setPRange(cosmParam.pmin, cosmParam.pmax); + + switch (cosmParam.accept) { + case GenCosmicsParam::ITS0: + genCosm->requireITS0(); + break; + case GenCosmicsParam::ITS1: + genCosm->requireITS1(); + break; + case GenCosmicsParam::ITS2: + genCosm->requireITS2(); + break; + case GenCosmicsParam::ITS3: + genCosm->requireITS3(); + break; + case GenCosmicsParam::ITS4: + genCosm->requireITS4(); + break; + case GenCosmicsParam::ITS5: + genCosm->requireITS5(); + break; + case GenCosmicsParam::ITS6: + genCosm->requireITS6(); + break; + case GenCosmicsParam::TPC: + genCosm->requireTPC(); + break; + case GenCosmicsParam::Custom: + genCosm->requireXZAccepted(cosmParam.customAccX, cosmParam.customAccZ); + break; + default: + LOG(FATAL) << "Unknown cosmics acceptance type " << cosmParam.accept; + break; + } + + genCosm->Init(); + + // instance and configure TGenerator interface + auto tgen = new o2::eventgen::GeneratorTGenerator(); + tgen->setMomentumUnit(1.); // [GeV/c] + tgen->setEnergyUnit(1.); // [GeV/c] + tgen->setPositionUnit(1.); // [cm] + tgen->setTimeUnit(1.); // [s] + tgen->setTGenerator(genCosm); + fg = tgen; + return tgen; +} diff --git a/Generators/share/external/GenCosmicsLoader.C b/Generators/share/external/GenCosmicsLoader.C new file mode 100644 index 0000000000000..fa646743e674e --- /dev/null +++ b/Generators/share/external/GenCosmicsLoader.C @@ -0,0 +1,35 @@ +// 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. + +//< Loader macro to run QED background generator from QEDepem.C macro, use it as e.g. +//< o2-sim -n10000 -m PIPE ITS TPC -g extgen --extGenFile $O2_ROOT/share/Generators/external/GenCosmicsLoader.C +//< Generation options can be changed by providing --configKeyValues "cosmics.maxAngle=30.;cosmics.accept=ITS0" etc. +//< See GenCosmicsParam for available options + +#include + +FairGenerator* fg = nullptr; + +FairGenerator* GenCosmicsLoader() +{ + const TString macroName = "GenCosmics"; + gSystem->Load("libGeneratorCosmics.so"); + + // the path of the macro to load depends on where it was installed, we assume that its installation + // directory is the same as of the loader macro + std::ostringstream mstr; + mstr << __FILE__; + TString macroFullName = Form("%s/%s.C", gSystem->DirName(mstr.str().c_str()), macroName.Data()); + LOG(INFO) << "\nLoading " << macroFullName.Data() << "\n"; + + gROOT->LoadMacro(macroFullName.Data()); + gInterpreter->ProcessLine(Form("%s()", macroName.Data())); + return fg; +} diff --git a/Generators/share/external/README.md b/Generators/share/external/README.md index da3d956209bbb..959f4551b5c3d 100644 --- a/Generators/share/external/README.md +++ b/Generators/share/external/README.md @@ -8,7 +8,7 @@ ------------ -## qedbkg.C +## QEDLoader.C / QEDepem.C - Invokes TGenEpEmv1 generator from [AEGIS](https://github.com/AliceO2Group/AEGIS) package for Pb-Pb → e+e- generation. + optional parameters are rapidity and pT ranges to generate, can be provided as key/value option, e.g. @@ -17,4 +17,16 @@ o2-sim -n 1000 -m PIPE ITS -g extgen --extGenFile $O2_ROOT/share/Generators/exte `` The x-section of the process depends on the applied cuts, it is calculated on the fly and stored in the ``qedgenparam.ini`` file. +## GenCosmicsLoader.C / GenCosmics.C + +- Invokes GenerateCosmics generators from [AEGIS](https://github.com/AliceO2Group/AEGIS) package. + +``o2-sim -n1000 -m PIPE ITS TPC -g extgen --extGenFile $O2_ROOT/share/Generators/external/GenCosmicsLoader.C`` + +Generation options can be changed by providing ``--configKeyValues "cosmics.maxAngle=30.;cosmics.accept=ITS0"`` etc. +For instance, to generate track defined at radius 500 cm, with maximal angle wrt the azimuth of 40 degress and passing via ITS layer 0 at Y=0: + +``o2-sim -n100 -m PIPE ITS TPC --configKeyValues "cosmics.maxAngle=40.;cosmics.accept=ITS0;cosmics.origin=500" -g extgen --extGenFile $O2_ROOT/share/Generators/external/GenCosmicsLoader.C`` + +See GenCosmicsParam class for available options. ------------ diff --git a/Generators/share/pythia8/decays/force_hadronic_D.cfg b/Generators/share/pythia8/decays/force_hadronic_D.cfg new file mode 100644 index 0000000000000..e51167aae4398 --- /dev/null +++ b/Generators/share/pythia8/decays/force_hadronic_D.cfg @@ -0,0 +1,96 @@ +### author: Roberto Preghenella (preghenella@bo.infn.it) +### since: July 2020 + +### Force golden D decay modes +### the origin is from AliRoot AliDecayerPythia8::ForceHadronicD (Latest commit c509466 on May 17) +### +### This file reproduces the configuration achieved with ForceHadronicD(0,0,0) + +### add D+ decays absent in PYTHIA8 decay table and set BRs from PDG for other +411:oneChannel = 1 0.0752 0 -321 211 211 +411:addChannel = 1 0.0104 0 -313 211 +411:addChannel = 1 0.0156 0 311 211 +411:addChannel = 1 0.00276 0 333 211 +## add Lc decays absent in PYTHIA8 decay table and set BRs from PDG for other +4122:oneChannel = 1 0.0196 100 2212 -313 +4122:addChannel = 1 0.0108 100 2224 -321 +4122:addChannel = 1 0.022 100 3124 211 +4122:addChannel = 1 0.035 0 2212 -321 211 +4122:addChannel = 1 0.0159 0 2212 311 +4122:addChannel = 1 0.0130 0 3122 211 +### add Xic+ decays absent in PYTHIA8 decay table +4232:addChannel = 1 0.2 0 2212 -313 +4232:addChannel = 1 0.2 0 2212 -321 211 +4232:addChannel = 1 0.2 0 3324 211 +4232:addChannel = 1 0.2 0 3312 211 211 +### add Xic0 decays absent in PYTHIA8 decay table +4132:addChannel = 1 0.2 0 3312 211 + +### K* -> K pi +313:onMode = off +313:onIfAll = 321 211 +### for Ds -> Phi pi+ +333:onMode = off +333:onIfAll = 321 321 +### for D0 -> rho0 pi+ k- +113:onMode = off +113:onIfAll = 211 211 +### for Lambda_c -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Lambda_c -> Lambda(1520) K- +3124:onMode = off +3124:onIfAll = 2212 321 + +### Omega_c -> Omega pi +4332:onMode = off +4332:onIfMatch = 3334 211 + +### switch off all decay channels +411:onMode = off +421:onMode = off +431:onMode = off +4112:onMode = off +4122:onMode = off +4232:onMode = off +4132:onMode = off + +### D+/- -> K pi pi +411:onIfMatch = 321 211 211 +### D+/- -> K* pi +411:onIfMatch = 313 211 +### D+/- -> phi pi +411:onIfMatch = 333 211 + +### D0 -> K pi +421:onIfMatch = 321 211 + +### D_s -> K K* +431:onIfMatch = 321 313 +### D_s -> Phi pi +431:onIfMatch = 333 211 + +### Lambda_c -> p K* +4122:onIfMatch = 2212 313 +### Lambda_c -> Delta K +4122:onIfMatch = 2224 321 +### Lambda_c -> Lambda(1520) pi +4122:onIfMatch = 3124 211 +### Lambda_c -> p K pi +4122:onIfMatch = 2212 321 211 +### Lambda_c -> Lambda pi +4122:onIfMatch = 3122 211 +### Lambda_c -> p K0 +4122:onIfMatch = 2212 311 + +### Xic+ -> pK*0 +4232:onIfMatch = 2212 313 +### Xic+ -> p K- pi+ +4232:onIfMatch = 2212 321 211 +### Xic+ -> Xi*0 pi+, Xi*->Xi- pi+ +4232:onIfMatch = 3324 211 +### Xic+ -> Xi- pi+ pi+ +4232:onIfMatch = 3312 211 211 + +### Xic0 -> Xi- pi+ +4132:onIfMatch = 3312 211 diff --git a/Generators/share/pythia8/decays/force_hadronic_D_forceLcChannel1.cfg b/Generators/share/pythia8/decays/force_hadronic_D_forceLcChannel1.cfg new file mode 100644 index 0000000000000..33abbb1b6f340 --- /dev/null +++ b/Generators/share/pythia8/decays/force_hadronic_D_forceLcChannel1.cfg @@ -0,0 +1,12 @@ +### author: Roberto Preghenella (preghenella@bo.infn.it) +### since: July 2020 + +### Force golden D decay modes (force Lc channel 1) +### the origin is from AliRoot AliDecayerPythia8::ForceHadronicD (Latest commit c509466 on May 17) +### +### This file has to be used in conjunction with force_hadronic_D.cfg and loaded +### afterwards to reproduce the configuration achieved with ForceHadronicD(0,0,1) + +### force Lc -> p K pi +4122:onMode = off +4122:onIfMatch = 2212 321 211 diff --git a/Generators/share/pythia8/decays/force_hadronic_D_forceLcChannel2.cfg b/Generators/share/pythia8/decays/force_hadronic_D_forceLcChannel2.cfg new file mode 100644 index 0000000000000..d79dec4d8b88f --- /dev/null +++ b/Generators/share/pythia8/decays/force_hadronic_D_forceLcChannel2.cfg @@ -0,0 +1,12 @@ +### author: Roberto Preghenella (preghenella@bo.infn.it) +### since: July 2020 + +### Force golden D decay modes (force Lc channel 2) +### the origin is from AliRoot AliDecayerPythia8::ForceHadronicD (Latest commit c509466 on May 17) +### +### This file has to be used in conjunction with force_hadronic_D.cfg and loaded +### afterwards to reproduce the configuration achieved with ForceHadronicD(0,0,2) + +### force Lc -> p K0s +4122:onMode = off +4122:onIfMatch = 2212 311 diff --git a/Generators/share/pythia8/decays/force_hadronic_D_use4bodies.cfg b/Generators/share/pythia8/decays/force_hadronic_D_use4bodies.cfg new file mode 100644 index 0000000000000..3178dad7d368b --- /dev/null +++ b/Generators/share/pythia8/decays/force_hadronic_D_use4bodies.cfg @@ -0,0 +1,15 @@ +### author: Roberto Preghenella (preghenella@bo.infn.it) +### since: July 2020 + +### Force golden D decay modes (use 4 bodies option) +### the origin is from AliRoot AliDecayerPythia8::ForceHadronicD (Latest commit c509466 on May 17) +### +### This file has to be used in conjunction with force_hadronic_D.cfg and loaded +### afterwards to reproduce the configuration achieved with ForceHadronicD(1,0,0) + +### D0 -> K pi pi pi +421:onIfMatch = 321 211 211 211 +### D0 -> K pi rho +421:onIfMatch = 321 211 113 +### D0 -> K*0 pi pi +421:onIfMatch = 313 211 211 diff --git a/Generators/share/pythia8/decays/force_hadronic_D_useDtoV0.cfg b/Generators/share/pythia8/decays/force_hadronic_D_useDtoV0.cfg new file mode 100644 index 0000000000000..5b50c59e0130c --- /dev/null +++ b/Generators/share/pythia8/decays/force_hadronic_D_useDtoV0.cfg @@ -0,0 +1,13 @@ +### author: Roberto Preghenella (preghenella@bo.infn.it) +### since: July 2020 + +### Force golden D decay modes (use D to V0 option) +### the origin is from AliRoot AliDecayerPythia8::ForceHadronicD (Latest commit c509466 on May 17) +### +### This file has to be used in conjunction with force_hadronic_D.cfg and loaded +### afterwards to reproduce the configuration achieved with ForceHadronicD(0,1,0) + +### Ds -> K0K +431:onIfMatch = 311 321 +### Ds -> K0pi +411:onIfMatch = 311 211 diff --git a/Generators/share/pythia8/decays/hypertriton.cfg b/Generators/share/pythia8/decays/hypertriton.cfg new file mode 100644 index 0000000000000..518fbbf6418ba --- /dev/null +++ b/Generators/share/pythia8/decays/hypertriton.cfg @@ -0,0 +1,12 @@ +### particle definition +### id:all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 + +### helium-3 +1000020030:all = helium3 helium3_bar 0 6 0 2.80923 0. 0. 0. 0. +1000020030:mayDecay = off + +### hypertriton +1010010030:all = hypertriton hypertriton_bar 0 3 0 2.99131 0. 0. 0. 78.9 +1010010030:mayDecay = on +1010010030:oneChannel = 1 1. 0 1000020030 -211 + diff --git a/Generators/src/GenCosmicsParam.cxx b/Generators/src/GenCosmicsParam.cxx new file mode 100644 index 0000000000000..6d23cdf0747fa --- /dev/null +++ b/Generators/src/GenCosmicsParam.cxx @@ -0,0 +1,15 @@ +// 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. + +#include "Generators/GenCosmicsParam.h" + +using namespace o2::eventgen; + +O2ParamImpl(o2::eventgen::GenCosmicsParam); diff --git a/Generators/src/GeneratorsLinkDef.h b/Generators/src/GeneratorsLinkDef.h index 0d0d00c3a2064..93f83e72beb59 100644 --- a/Generators/src/GeneratorsLinkDef.h +++ b/Generators/src/GeneratorsLinkDef.h @@ -58,5 +58,7 @@ #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::eventgen::BoxGunParam > +; #pragma link C++ class o2::eventgen::QEDGenParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::eventgen::QEDGenParam > +; +#pragma link C++ class o2::eventgen::GenCosmicsParam + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::eventgen::GenCosmicsParam> + ; #endif diff --git a/Steer/DigitizerWorkflow/CMakeLists.txt b/Steer/DigitizerWorkflow/CMakeLists.txt index e24058089e4f9..b210068b113d9 100644 --- a/Steer/DigitizerWorkflow/CMakeLists.txt +++ b/Steer/DigitizerWorkflow/CMakeLists.txt @@ -54,3 +54,12 @@ o2_add_executable(digitizer-workflow O2::TRDWorkflow O2::DataFormatsTRD O2::ZDCSimulation) + + +o2_add_executable(mctruth-testworkflow + COMPONENT_NAME sim + SOURCES src/MCTruthTestWorkflow.cxx + src/MCTruthSourceSpec.cxx + src/MCTruthWriterSpec.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::SimulationDataFormat) diff --git a/Steer/DigitizerWorkflow/src/MCTruthReaderSpec.h b/Steer/DigitizerWorkflow/src/MCTruthReaderSpec.h new file mode 100644 index 0000000000000..1be0084edd2ce --- /dev/null +++ b/Steer/DigitizerWorkflow/src/MCTruthReaderSpec.h @@ -0,0 +1,104 @@ +// 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. + +#ifndef STEER_DIGITIZERWORKFLOW_SRC_MCTRUTHREADERSPEC_H_ +#define STEER_DIGITIZERWORKFLOW_SRC_MCTRUTHREADERSPEC_H_ + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataRefUtils.h" +#include "Framework/Lifetime.h" +#include +#include +#include +#include "SimulationDataFormat/IOMCTruthContainerView.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" +#include "TTree.h" +#include "TFile.h" +#include "TString.h" +#include + +using namespace o2::framework; + +namespace o2 +{ + +class MCTruthReaderTask : public o2::framework::Task +{ + public: + MCTruthReaderTask(bool newmctruth) : mNew{newmctruth} {} + + void init(framework::InitContext& ic) override + { + LOG(INFO) << "Initializing MCTruth reader "; + } + + void run(framework::ProcessingContext& pc) override + { + if (mFinished) { + return; + } + LOG(INFO) << "Running MCTruth reader "; + auto labelfilename = pc.inputs().get("trigger"); + LOG(INFO) << "Opening file " << labelfilename->Data(); + TFile f(labelfilename->Data(), "OPEN"); + auto tree = (TTree*)f.Get("o2sim"); + auto br = tree->GetBranch("Labels"); + + if (mNew) { + // + dataformats::IOMCTruthContainerView* iocontainer = nullptr; + br->SetAddress(&iocontainer); + br->GetEntry(0); + + // publish the labels in a const shared memory container + auto& sharedlabels = pc.outputs().make>(Output{"TST", "LABELS2", 0, Lifetime::Timeframe}); + iocontainer->copyandflatten(sharedlabels); + + } else { + // the original way with the MCTruthContainer + dataformats::MCTruthContainer* mccontainer = nullptr; + br->SetAddress(&mccontainer); + br->GetEntry(0); + + LOG(INFO) << "MCCONTAINER CHECK" << mccontainer; + LOG(INFO) << "MCCONTAINER CHECK" << mccontainer->getNElements(); + + // publish the original labels + pc.outputs().snapshot(Output{"TST", "LABELS2", 0, Lifetime::Timeframe}, *mccontainer); + } + // we should be only called once; tell DPL that this process is ready to exit + pc.services().get().readyToQuit(QuitRequest::Me); + mFinished = true; + } + + private: + bool mFinished = false; + bool mNew = false; +}; + +o2::framework::DataProcessorSpec getMCTruthReaderSpec(bool newmctruth) +{ + std::vector inputs; + // input to notify that labels can be read + inputs.emplace_back("trigger", "TST", "TRIGGERREAD", 0, Lifetime::Timeframe); + return DataProcessorSpec{ + "MCTruthReader", + inputs, + Outputs{{"TST", "LABELS2", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask(newmctruth)}, + Options{}}; +} + +} // end namespace o2 + +#endif diff --git a/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.cxx b/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.cxx new file mode 100644 index 0000000000000..759c5edfffacd --- /dev/null +++ b/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.cxx @@ -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. + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataRefUtils.h" +#include "Framework/Lifetime.h" +#include +#include +#include +#include "Framework/Task.h" +#include "Framework/Logger.h" + +using namespace o2::framework; + +namespace o2 +{ + +class MCTruthSourceTask : public o2::framework::Task +{ + public: + MCTruthSourceTask(bool newmctruth) : mNew{newmctruth} {} + + void init(framework::InitContext& ic) override + { + LOG(INFO) << "Initializing MCTruth source"; + mSize = ic.options().get("size"); + } + + void run(framework::ProcessingContext& pc) override + { + if (mFinished) { + return; + } + LOG(INFO) << "Creating MCTruth container"; + + using TruthElement = o2::MCCompLabel; + using Container = dataformats::MCTruthContainer; + Container container; + // create a very large container and stream it to TTree + for (int i = 0; i < mSize; ++i) { + container.addElement(i, TruthElement(i, i, i)); + container.addElement(i, TruthElement(i + 1, i, i)); + } + + if (mNew) { + LOG(INFO) << "New serialization"; + // we need to flatten it and write to managed shared memory container + auto& sharedlabels = pc.outputs().make>(Output{"TST", "LABELS", 0, Lifetime::Timeframe}); + container.flatten_to(sharedlabels); + sleep(1); + } else { + LOG(INFO) << "Old serialization"; + pc.outputs().snapshot({"TST", "LABELS", 0, Lifetime::Timeframe}, container); + sleep(1); + } + + // we should be only called once; tell DPL that this process is ready to exit + pc.services().get().readyToQuit(QuitRequest::Me); + mFinished = true; + } + + private: + bool mFinished = false; + int mSize = 0; + bool mNew = false; + o2::dataformats::MCTruthContainer mLabels; // labels which get filled +}; + +o2::framework::DataProcessorSpec getMCTruthSourceSpec(bool newmctruth) +{ + // create the full data processor spec using + // a name identifier + // input description + // algorithmic description (here a lambda getting called once to setup the actual processing function) + // options that can be used for this processor (here: input file names where to take the hits) + std::vector outputs; + outputs.emplace_back("TST", "LABELS", 0, Lifetime::Timeframe); + + return DataProcessorSpec{ + "MCTruthSource", + Inputs{}, + outputs, + AlgorithmSpec{adaptFromTask(newmctruth)}, + Options{ + {"size", VariantType::Int, 100000, {"Sample size"}}}}; +} + +} // end namespace o2 diff --git a/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.h b/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.h new file mode 100644 index 0000000000000..e9a23c36c260e --- /dev/null +++ b/Steer/DigitizerWorkflow/src/MCTruthSourceSpec.h @@ -0,0 +1,21 @@ +// 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. + +#ifndef STEER_DIGITIZERWORKFLOW_SRC_MCTRUTHSOURCESPEC_H_ +#define STEER_DIGITIZERWORKFLOW_SRC_MCTRUTHSOURCESPEC_H_ + +#include "Framework/DataProcessorSpec.h" + +namespace o2 +{ +o2::framework::DataProcessorSpec getMCTruthSourceSpec(bool mctruth = true); +} // end namespace o2 + +#endif diff --git a/Steer/DigitizerWorkflow/src/MCTruthTestWorkflow.cxx b/Steer/DigitizerWorkflow/src/MCTruthTestWorkflow.cxx new file mode 100644 index 0000000000000..4f91872726a8a --- /dev/null +++ b/Steer/DigitizerWorkflow/src/MCTruthTestWorkflow.cxx @@ -0,0 +1,53 @@ +// 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. + +#include + +#include "Framework/WorkflowSpec.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/CompletionPolicyHelpers.h" +#include "Framework/DeviceSpec.h" +#include "MCTruthSourceSpec.h" +#include "MCTruthWriterSpec.h" +#include "MCTruthReaderSpec.h" + +using namespace o2::framework; + +void customize(std::vector& workflowOptions) +{ + // option to disable MC truth + workflowOptions.push_back(ConfigParamSpec{"newmctruth", o2::framework::VariantType::Bool, false, {"enable new container"}}); + workflowOptions.push_back(ConfigParamSpec{"consumers", o2::framework::VariantType::Int, 1, {"number of mc consumers"}}); +} + +#include "Framework/runDataProcessing.h" + +/// This function is required to be implemented to define the workflow +/// specifications +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + WorkflowSpec specs; + + bool newmctruth = configcontext.options().get("newmctruth"); + + // connect the source + specs.emplace_back(o2::getMCTruthSourceSpec(newmctruth)); + // connect some consumers + for (int i = 0; i < configcontext.options().get("consumers"); ++i) { + specs.emplace_back(o2::getMCTruthWriterSpec(i, i == 0, newmctruth)); + } + // connect a device reading back the labels + specs.emplace_back(o2::getMCTruthReaderSpec(newmctruth)); + // connect a device reading back the labels + specs.emplace_back(o2::getMCTruthWriterSpec(-1, false, newmctruth)); + + return specs; +} diff --git a/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.cxx b/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.cxx new file mode 100644 index 0000000000000..96dc0628d5ceb --- /dev/null +++ b/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.cxx @@ -0,0 +1,127 @@ +// 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. + +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataRefUtils.h" +#include "Framework/Lifetime.h" +#include +#include +#include +#include "SimulationDataFormat/IOMCTruthContainerView.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" +#include "TTree.h" +#include "TFile.h" +#include "TString.h" +#include + +using namespace o2::framework; + +namespace o2 +{ + +class MCTruthWriterTask : public o2::framework::Task +{ + public: + MCTruthWriterTask(int id, bool doio, bool newmctruth) : mID{id}, mIO{doio}, mNew{newmctruth} {} + + void init(framework::InitContext& ic) override + { + LOG(INFO) << "Initializing MCTruth consumer " << mID; + } + + void run(framework::ProcessingContext& pc) override + { + if (mFinished) { + return; + } + LOG(INFO) << "Running MCTruth consumer " << mID; + TString labelfilename; + if (mNew) { + auto labels = pc.inputs().get>(mID >= 0 ? "labels" : "labels2"); + LOG(INFO) << "GOT " << labels.getNElements() << " labels"; + + sleep(1); + + if (mIO) { + dataformats::IOMCTruthContainerView io(labels); + labelfilename = "labels_new.root"; + TFile f(labelfilename.Data(), "RECREATE"); + TTree tree("o2sim", "o2sim"); + auto br = tree.Branch("Labels", &io); + tree.Fill(); + f.Write(); + f.Close(); + } + + sleep(1); + } else { + auto labels = pc.inputs().get*>(mID >= 0 ? "labels" : "labels2"); + LOG(INFO) << "GOT " << labels->getNElements() << " labels"; + + sleep(1); + + if (mIO) { + labelfilename = "labels_old.root"; + TFile f(labelfilename.Data(), "RECREATE"); + TTree tree("o2sim", "o2sim"); + auto rawptr = labels.get(); + auto br = tree.Branch("Labels", &rawptr); + tree.Fill(); + f.Write(); + f.Close(); + } + sleep(1); + } + if (mIO) { + // this triggers the reader process + pc.outputs().snapshot({"TST", "TRIGGERREAD", 0, Lifetime::Timeframe}, labelfilename); + } + + // we should be only called once; tell DPL that this process is ready to exit + pc.services().get().readyToQuit(QuitRequest::Me); + mFinished = true; + } + + private: + bool mFinished = false; + bool mNew = false; + bool mIO = false; + int mID = 0; + o2::dataformats::MCTruthContainer mLabels; // labels which get filled +}; + +o2::framework::DataProcessorSpec getMCTruthWriterSpec(int id, bool doio, bool newmctruth) +{ + std::vector inputs; + if (id == -1) { + // we use this id as a secondary consumer of the LABELS2 channel + inputs.emplace_back("labels2", "TST", "LABELS2", 0, Lifetime::Timeframe); + } else { + inputs.emplace_back("labels", "TST", "LABELS", 0, Lifetime::Timeframe); + } + std::stringstream str; + str << "MCTruthWriter" << id; + + std::vector outputs; + if (doio) { + outputs.emplace_back("TST", "TRIGGERREAD", 0, Lifetime::Timeframe); + } + return DataProcessorSpec{ + str.str(), + inputs, + outputs, + AlgorithmSpec{adaptFromTask(id, doio, newmctruth)}, + Options{}}; +} + +} // end namespace o2 diff --git a/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.h b/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.h new file mode 100644 index 0000000000000..436077f1b0386 --- /dev/null +++ b/Steer/DigitizerWorkflow/src/MCTruthWriterSpec.h @@ -0,0 +1,26 @@ +// 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. + +#ifndef STEER_DIGITIZERWORKFLOW_SRC_ZDCDIGITWRITERSPEC_H_ +#define STEER_DIGITIZERWORKFLOW_SRC_ZDCDIGITWRITERSPEC_H_ + +#include "Framework/DataProcessorSpec.h" +#include "Framework/InputSpec.h" +#include "SimulationDataFormat/MCTruthContainer.h" +#include "SimulationDataFormat/MCCompLabel.h" + +namespace o2 +{ + +o2::framework::DataProcessorSpec getMCTruthWriterSpec(int id, bool doio, bool newmctruth = true); + +} // end namespace o2 + +#endif /* STEER_DIGITIZERWORKFLOW_SRC_ZDCDIGITWRITERSPEC_H_ */ diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index 54813f2448236..440514c381c6a 100644 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -16,6 +16,7 @@ endif(ALIROOT) add_subdirectory(aliceHLTwrapper) add_subdirectory(O2MessageMonitor) add_subdirectory(DataFlow) +add_subdirectory(DataSampling) add_subdirectory(Publishers) add_subdirectory(DataCompression) add_subdirectory(Mergers) diff --git a/Utilities/DataFlow/src/TimeframeValidationTool.cxx b/Utilities/DataFlow/src/TimeframeValidationTool.cxx index 71a5904b76447..81ff1038ff78a 100644 --- a/Utilities/DataFlow/src/TimeframeValidationTool.cxx +++ b/Utilities/DataFlow/src/TimeframeValidationTool.cxx @@ -10,6 +10,7 @@ #include "DataFlow/TimeframeParser.h" #include "fairmq/FairMQParts.h" +#include "Framework/Logger.h" #include #include #include diff --git a/Utilities/DataFlow/test/test_TimeframeParser.cxx b/Utilities/DataFlow/test/test_TimeframeParser.cxx index 338d491c25ac8..37e6f5af09c36 100644 --- a/Utilities/DataFlow/test/test_TimeframeParser.cxx +++ b/Utilities/DataFlow/test/test_TimeframeParser.cxx @@ -11,6 +11,7 @@ #include "DataFlow/TimeframeParser.h" #include "DataFlow/FakeTimeframeBuilder.h" #include "Headers/DataHeader.h" +#include "Framework/Logger.h" #include #include #include diff --git a/Utilities/DataSampling/CMakeLists.txt b/Utilities/DataSampling/CMakeLists.txt new file mode 100644 index 0000000000000..d580da86be76f --- /dev/null +++ b/Utilities/DataSampling/CMakeLists.txt @@ -0,0 +1,82 @@ +# 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. + +# FIXME: the LinkDef should not be in the public area + +o2_add_library(DataSampling + SOURCES src/DataSampling.cxx + src/DataSamplingConditionFactory.cxx + src/DataSamplingHeader.cxx + src/DataSamplingConditionCustom.cxx + src/DataSamplingConditionNConsecutive.cxx + src/DataSamplingConditionPayloadSize.cxx + src/DataSamplingConditionRandom.cxx + src/DataSamplingHeader.cxx + src/DataSamplingPolicy.cxx + src/DataSamplingReadoutAdapter.cxx + src/Dispatcher.cxx + + PUBLIC_LINK_LIBRARIES O2::Framework O2::DataSampling) + +#o2_target_root_dictionary( +# Mergers +# HEADERS include/Mergers/MergeInterface.h +# include/Mergers/CustomMergeableObject.h +# include/Mergers/CustomMergeableTObject.h +# LINKDEF include/Mergers/LinkDef.h) + +# tests with input data + +o2_data_file(COPY test/test_DataSampling.json DESTINATION tests) + +o2_add_test(DataSampling NAME test_DataSampling_test_DataSampling + SOURCES test/test_DataSampling.cxx + COMPONENT_NAME DataSampling + LABELS datasampling + PUBLIC_LINK_LIBRARIES O2::DataSampling + ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage) + +foreach(t + DataSamplingCondition + DataSamplingHeader + DataSamplingPolicy + ) + + # FIXME ? The NAME parameter of o2_add_test is only needed to help the current + # o2.sh recipe. If the recipe is changed, those params can go away, if needed. + + o2_add_test(${t} NAME test_DataSampling_test_${t} + SOURCES test/test_${t}.cxx + COMPONENT_NAME DataSampling + LABELS datasampling + PUBLIC_LINK_LIBRARIES O2::DataSampling) +endforeach() + +o2_data_file(COPY etc/exampleDataSamplingConfig.json DESTINATION etc) + +o2_add_dpl_workflow(datasampling-pod-and-root + SOURCES test/dataSamplingPodAndRoot.cxx + COMPONENT_NAME DataSampling + PUBLIC_LINK_LIBRARIES O2::DataSampling) + +o2_add_dpl_workflow(datasampling-parallel + SOURCES test/dataSamplingParallel.cxx + COMPONENT_NAME DataSampling + PUBLIC_LINK_LIBRARIES O2::DataSampling) + +o2_add_dpl_workflow(datasampling-time-pipeline + SOURCES test/dataSamplingTimePipeline.cxx + COMPONENT_NAME DataSampling + PUBLIC_LINK_LIBRARIES O2::DataSampling) + +o2_add_dpl_workflow(datasampling-benchmark + SOURCES test/dataSamplingBenchmark.cxx + COMPONENT_NAME DataSampling + PUBLIC_LINK_LIBRARIES O2::DataSampling) \ No newline at end of file diff --git a/Utilities/DataSampling/README.md b/Utilities/DataSampling/README.md new file mode 100644 index 0000000000000..68281ac7de8b5 --- /dev/null +++ b/Utilities/DataSampling/README.md @@ -0,0 +1,95 @@ +## Data Sampling + +Data Sampling provides possibility to sample data in DPL workflows, basing on certain conditions ( 5% randomly, when payload is greater than 4234 bytes, etc.). The job of passing the right data is done by a data processor called `Dispatcher`. A desired data stream is specified in form of Data Sampling Policies, configured by JSON structures (example below). +``` +{ + "id": "policy_example1", # name of the policy + "active": "false", # activation flag + "machines": [ # list of machines where the policy should be run (now ignored) + "aido2flp1", + "aido2flp2" + ], # list of data that should be sampled, the format is: + # binding1:origin1/description1/subSpec1[;binding2:...] + "query": "clusters:TPC/CLUSTERS/0;tracks:TPC/TRACKS/0", + "samplingConditions": [ # list of sampling conditions + { + "condition": "random", # condition type + "fraction": "0.1", # condition-dependent parameter: fraction of data to sample + "seed": "2112" # condition-dependent parameter: seed of PRNG + } + ], + "blocking": "false" # should the dispatcher block the main data flow? (now ignored) +} +``` + +### Usage + +To use Data Sampling in a DPL workflow insert following lines to your code: +```cpp +#include "DataSampling/DataSampling.h" +using namespace o2::framework; +using namespace o2::utilities; +void customize(std::vector& policies) +{ + DataSampling::CustomizeInfrastructure(policies); +} + +void customize(std::vector& policies) +{ + DataSampling::CustomizeInfrastructure(policies); +} + +#include "Framework/runDataProcessing.h" + +std::vector defineDataProcessing(ConfigContext &ctx) +{ + + WorkflowSpec workflow; +// + + DataSampling::GenerateInfrastructure(workflow, "json:///absolute/path/to/config/file.json"); + + return workflow; +} +``` + +Sampled data can be subscribed to by adding `InputSpecs` provided by `std::vector DataSampling::InputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName)` to a chosen data processor. Then, they can be accessed by the bindings specified in the configuration file. Dispatcher adds a `DataSamplingHeader` to the header stack, which contains statistics like total number of evaluated/accepted messages for a given Policy or the sampling time since epoch. + +The [o2-datasampling-pod-and-root](https://github.com/AliceO2Group/AliceO2/blob/dev/Utilities/DataSampling/test/dataSamplingPodAndRoot.cxx) workflow can serve as a usage example. + +## Data Sampling Conditions + +The following sampling conditions are available. When more than one is used, a positive decision is taken when all the conditions are fulfilled. +- **DataSamplingConditionRandom** - pseudo-randomly accepts specified fraction of incoming messages. +```json +{ + "condition": "random", + "fraction": "0.1", + "seed": "22222" +} +``` +- **DataSamplingConditionNConsecutive** - approves n consecutive samples in defined cycle. It assumes that timesliceID always increments by one. +```json +{ + "condition": "nConsecutive", + "samplesNumber": "3", + "cycleSize": "100" +} +``` +- **DataSamplingConditionPayloadSize** - approves messages having payload size within specified boundaries. +```json +{ + "condition": "payloadSize", + "lowerLimit": "300", + "upperLimit": "500" +} +``` +- **DataSamplingConditionCustom** - loads a custom condition, which should inherit from DataSamplingCondition, from a specified library. +```json +{ + "condition": "custom", + "moduleName": "QcExample", + "className": "o2::quality_control_modules::example::ExampleCondition", + "customParam": "value" +} +``` \ No newline at end of file diff --git a/Framework/TestWorkflows/etc/exampleDataSamplingConfig.json b/Utilities/DataSampling/etc/exampleDataSamplingConfig.json similarity index 100% rename from Framework/TestWorkflows/etc/exampleDataSamplingConfig.json rename to Utilities/DataSampling/etc/exampleDataSamplingConfig.json diff --git a/Framework/Core/include/Framework/DataSampling.h b/Utilities/DataSampling/include/DataSampling/DataSampling.h similarity index 78% rename from Framework/Core/include/Framework/DataSampling.h rename to Utilities/DataSampling/include/DataSampling/DataSampling.h index 8a6e097c5bfe8..2ca8f02cb15c6 100644 --- a/Framework/Core/include/Framework/DataSampling.h +++ b/Utilities/DataSampling/include/DataSampling/DataSampling.h @@ -28,9 +28,13 @@ class ConfigurationInterface; namespace o2::framework { - class CompletionPolicy; class ChannelConfigurationPolicy; +} // namespace o2::framework + +namespace o2::utilities +{ + class Dispatcher; /// A class responsible for providing data from main processing flow to QC tasks. @@ -75,26 +79,26 @@ class DataSampling /// QC tasks. /// \param policiesSource Path to configuration file. /// \param threads Number of dispatcher threads, that will handle the data - static void GenerateInfrastructure(WorkflowSpec& workflow, const std::string& policiesSource, size_t threads = 1); + static void GenerateInfrastructure(framework::WorkflowSpec& workflow, const std::string& policiesSource, size_t threads = 1); /// \brief Generates data sampling infrastructure. /// \param workflow DPL workflow with already declared data processors which provide data desired by /// QC tasks. /// \param policiesSource boost::property_tree::ptree with the configuration /// \param threads Number of dispatcher threads, that will handle the data - static void GenerateInfrastructure(WorkflowSpec& workflow, boost::property_tree::ptree const& policies, size_t threads = 1); + static void GenerateInfrastructure(framework::WorkflowSpec& workflow, boost::property_tree::ptree const& policies, size_t threads = 1); /// \brief Configures dispatcher to consume any data immediately. - static void CustomizeInfrastructure(std::vector&); + static void CustomizeInfrastructure(std::vector&); /// \brief Applies blocking/nonblocking data sampling configuration to the workflow. - static void CustomizeInfrastructure(std::vector&); + static void CustomizeInfrastructure(std::vector&); /// \brief Provides InputSpecs to receive data for given DataSamplingPolicy - static std::vector InputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); + static std::vector InputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); /// \brief Provides InputSpecs to receive data for given DataSamplingPolicy - static std::vector InputSpecsForPolicy(configuration::ConfigurationInterface* const config, const std::string& policyName); + static std::vector InputSpecsForPolicy(configuration::ConfigurationInterface* const config, const std::string& policyName); /// \brief Provides OutputSpecs of given DataSamplingPolicy - static std::vector OutputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); + static std::vector OutputSpecsForPolicy(const std::string& policiesSource, const std::string& policyName); /// \brief Provides OutputSpecs of given DataSamplingPolicy - static std::vector OutputSpecsForPolicy(configuration::ConfigurationInterface* const config, const std::string& policyName); + static std::vector OutputSpecsForPolicy(configuration::ConfigurationInterface* const config, const std::string& policyName); /// \brief Provides the port to be used for a proxy of given DataSamplingPolicy static uint16_t PortForPolicy(configuration::ConfigurationInterface* const config, const std::string& policyName); /// \brief Provides the port to be used for a proxy of given DataSamplingPolicy @@ -105,11 +109,11 @@ class DataSampling static std::vector MachinesForPolicy(const std::string& policiesSource, const std::string& policyName); private: - static void DoGenerateInfrastructure(Dispatcher&, WorkflowSpec& workflow, boost::property_tree::ptree const& policies, size_t threads = 1); + static void DoGenerateInfrastructure(Dispatcher&, framework::WorkflowSpec& workflow, boost::property_tree::ptree const& policies, size_t threads = 1); // Internal functions, used by GenerateInfrastructure() static std::string createDispatcherName(); }; -} // namespace o2::framework +} // namespace o2::utilities #endif // FRAMEWORK_DATASAMPLING_H diff --git a/Framework/Core/include/Framework/DataSamplingCondition.h b/Utilities/DataSampling/include/DataSampling/DataSamplingCondition.h similarity index 96% rename from Framework/Core/include/Framework/DataSamplingCondition.h rename to Utilities/DataSampling/include/DataSampling/DataSamplingCondition.h index a5710b199ca3a..98a02978e92b4 100644 --- a/Framework/Core/include/Framework/DataSamplingCondition.h +++ b/Utilities/DataSampling/include/DataSampling/DataSamplingCondition.h @@ -21,7 +21,7 @@ #include #include -namespace o2::framework +namespace o2::utilities { /// A standarised data sampling condition, to decide if given data sample should be passed forward. @@ -39,6 +39,6 @@ class DataSamplingCondition virtual bool decide(const o2::framework::DataRef&) = 0; }; -} // namespace o2::framework +} // namespace o2::utilities #endif //ALICEO2_DATASAMPLINGCONDITION_H diff --git a/Framework/Core/include/Framework/DataSamplingConditionFactory.h b/Utilities/DataSampling/include/DataSampling/DataSamplingConditionFactory.h similarity index 94% rename from Framework/Core/include/Framework/DataSamplingConditionFactory.h rename to Utilities/DataSampling/include/DataSampling/DataSamplingConditionFactory.h index 2728010607dc9..fb62efa80e89f 100644 --- a/Framework/Core/include/Framework/DataSamplingConditionFactory.h +++ b/Utilities/DataSampling/include/DataSampling/DataSamplingConditionFactory.h @@ -16,11 +16,11 @@ /// /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#include "DataSamplingCondition.h" +#include "DataSampling/DataSamplingCondition.h" #include #include -namespace o2::framework +namespace o2::utilities { /// A factory of DataSamplingConditions children. @@ -42,6 +42,6 @@ class DataSamplingConditionFactory static std::unique_ptr createDataSamplingConditionCustom(); }; -} // namespace o2::framework +} // namespace o2::utilities #endif //ALICEO2_DATASAMPLINGCONDITIONFACTORY_H diff --git a/Framework/Core/include/Framework/DataSamplingHeader.h b/Utilities/DataSampling/include/DataSampling/DataSamplingHeader.h similarity index 97% rename from Framework/Core/include/Framework/DataSamplingHeader.h rename to Utilities/DataSampling/include/DataSampling/DataSamplingHeader.h index 10d9eb5899edf..03856ccec2348 100644 --- a/Framework/Core/include/Framework/DataSamplingHeader.h +++ b/Utilities/DataSampling/include/DataSampling/DataSamplingHeader.h @@ -20,7 +20,7 @@ #include "Headers/DataHeader.h" -namespace o2::framework +namespace o2::utilities { struct DataSamplingHeader : public header::BaseHeader { @@ -48,6 +48,6 @@ struct DataSamplingHeader : public header::BaseHeader { static const DataSamplingHeader* Get(const BaseHeader* baseHeader); }; -} // namespace o2::framework +} // namespace o2::utilities #endif //ALICEO2_DATASAMPLINGHEADER_H diff --git a/Framework/Core/include/Framework/DataSamplingPolicy.h b/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h similarity index 82% rename from Framework/Core/include/Framework/DataSamplingPolicy.h rename to Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h index 647c7a57ff331..6a82ac5f1c0b1 100644 --- a/Framework/Core/include/Framework/DataSamplingPolicy.h +++ b/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h @@ -20,12 +20,12 @@ #include "Framework/InputSpec.h" #include "Framework/Output.h" #include "Framework/OutputSpec.h" -#include "Framework/DataSamplingCondition.h" +#include "DataSampling/DataSamplingCondition.h" #include "Framework/DataSpecUtils.h" #include -namespace o2::framework +namespace o2::utilities { /// A class representing certain policy of sampling data. @@ -35,16 +35,16 @@ namespace o2::framework class DataSamplingPolicy { private: - using PathVectorBase = std::vector>; + using PathVectorBase = std::vector>; class PathMap : public PathVectorBase { public: ~PathMap() = default; PathMap() = default; - const PathVectorBase::const_iterator find(const ConcreteDataMatcher& input) const + const PathVectorBase::const_iterator find(const framework::ConcreteDataMatcher& input) const { return std::find_if(begin(), end(), [input](const auto& el) { - return DataSpecUtils::match(el.first, input); + return framework::DataSpecUtils::match(el.first, input); }); } }; @@ -60,11 +60,11 @@ class DataSamplingPolicy /// \brief Configures a policy using structured configuration entry. void configure(const boost::property_tree::ptree&); /// \brief Returns true if this policy requires data with given InputSpec. - bool match(const ConcreteDataMatcher& input) const; + bool match(const framework::ConcreteDataMatcher& input) const; /// \brief Returns true if user-defined conditions of sampling are fulfilled. bool decide(const o2::framework::DataRef&); /// \brief Returns Output for given InputSpec to pass data forward. - const Output prepareOutput(const ConcreteDataMatcher& input, Lifetime lifetime = Lifetime::Timeframe) const; + const framework::Output prepareOutput(const framework::ConcreteDataMatcher& input, framework::Lifetime lifetime = framework::Lifetime::Timeframe) const; const std::string& getName() const; const PathMap& getPathMap() const; @@ -88,6 +88,6 @@ class DataSamplingPolicy uint32_t mTotalEvaluatedMessages = 0; }; -} // namespace o2::framework +} // namespace o2::utilities #endif // ALICEO2_DATASAMPLINGPOLICY_H diff --git a/Framework/Core/include/Framework/DataSamplingReadoutAdapter.h b/Utilities/DataSampling/include/DataSampling/DataSamplingReadoutAdapter.h similarity index 83% rename from Framework/Core/include/Framework/DataSamplingReadoutAdapter.h rename to Utilities/DataSampling/include/DataSampling/DataSamplingReadoutAdapter.h index c9a185ab10509..74084dde0112c 100644 --- a/Framework/Core/include/Framework/DataSamplingReadoutAdapter.h +++ b/Utilities/DataSampling/include/DataSampling/DataSamplingReadoutAdapter.h @@ -11,19 +11,19 @@ #ifndef ALICEO2_DATASAMPLINGREADOUTADAPTER_H #define ALICEO2_DATASAMPLINGREADOUTADAPTER_H -#include "ExternalFairMQDeviceProxy.h" +#include "Framework/ExternalFairMQDeviceProxy.h" namespace o2 { -namespace framework +namespace utilities { /// An adapter function for data sent by Readout for Data Sampling / Quality control purposes. /// It adds DataHeader and DataProcessingHeader using information found in received DataBlockHeaderBase /// header and given OutputSpec. It **IGNORES** SubSpecification in OutputSpec and uses linkID instead. -InjectorFunction dataSamplingReadoutAdapter(OutputSpec const& spec); +framework::InjectorFunction dataSamplingReadoutAdapter(framework::OutputSpec const& spec); -} // namespace framework +} // namespace utilities } // namespace o2 #endif //ALICEO2_DATASAMPLINGREADOUTADAPTER_H diff --git a/Framework/Core/include/Framework/Dispatcher.h b/Utilities/DataSampling/include/DataSampling/Dispatcher.h similarity index 72% rename from Framework/Core/include/Framework/Dispatcher.h rename to Utilities/DataSampling/include/DataSampling/Dispatcher.h index 9ffbd06478dd0..565de10bb35f7 100644 --- a/Framework/Core/include/Framework/Dispatcher.h +++ b/Utilities/DataSampling/include/DataSampling/Dispatcher.h @@ -31,13 +31,13 @@ namespace o2::monitoring class Monitoring; } -namespace o2::framework +namespace o2::utilities { class DataSamplingHeader; class DataSamplingPolicy; -class Dispatcher : public Task +class Dispatcher : public framework::Task { public: /// \brief Constructor @@ -46,33 +46,33 @@ class Dispatcher : public Task ~Dispatcher() override; /// \brief Dispatcher init callback - void init(InitContext& ctx) override; + void init(framework::InitContext& ctx) override; /// \brief Dispatcher process callback - void run(ProcessingContext& ctx) override; + void run(framework::ProcessingContext& ctx) override; /// \brief Create appropriate inputSpecs and outputSpecs for sampled data during the workflow declaration phase. - void registerPath(const std::pair&); + void registerPath(const std::pair&); const std::string& getName(); - Inputs getInputSpecs(); - Outputs getOutputSpecs(); + framework::Inputs getInputSpecs(); + framework::Outputs getOutputSpecs(); private: - DataSamplingHeader prepareDataSamplingHeader(const DataSamplingPolicy& policy, const DeviceSpec& spec); + DataSamplingHeader prepareDataSamplingHeader(const DataSamplingPolicy& policy, const framework::DeviceSpec& spec); header::Stack extractAdditionalHeaders(const char* inputHeaderStack) const; void reportStats(monitoring::Monitoring& monitoring) const; - void send(DataAllocator& dataAllocator, const DataRef& inputData, Output&& output) const; - void sendFairMQ(FairMQDevice* device, const DataRef& inputData, const std::string& fairMQChannel, + void send(framework::DataAllocator& dataAllocator, const framework::DataRef& inputData, framework::Output&& output) const; + void sendFairMQ(FairMQDevice* device, const framework::DataRef& inputData, const std::string& fairMQChannel, header::Stack&& stack) const; std::string mName; std::string mReconfigurationSource; - Inputs inputs; - Outputs outputs; + framework::Inputs inputs; + framework::Outputs outputs; // policies should be shared between all pipeline threads std::vector> mPolicies; }; -} // namespace o2::framework +} // namespace o2::utilities #endif //ALICEO2_DISPATCHER_H diff --git a/Framework/Core/scripts/o2-datasampling-benchmark.sh b/Utilities/DataSampling/scripts/o2-datasampling-benchmark.sh similarity index 100% rename from Framework/Core/scripts/o2-datasampling-benchmark.sh rename to Utilities/DataSampling/scripts/o2-datasampling-benchmark.sh diff --git a/Framework/Core/src/DataSampling.cxx b/Utilities/DataSampling/src/DataSampling.cxx similarity index 97% rename from Framework/Core/src/DataSampling.cxx rename to Utilities/DataSampling/src/DataSampling.cxx index baea5b9f05489..13ce66fc3d0ca 100644 --- a/Framework/Core/src/DataSampling.cxx +++ b/Utilities/DataSampling/src/DataSampling.cxx @@ -13,9 +13,9 @@ /// /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#include "Framework/DataSampling.h" -#include "Framework/DataSamplingPolicy.h" -#include "Framework/Dispatcher.h" +#include "DataSampling/DataSampling.h" +#include "DataSampling/DataSamplingPolicy.h" +#include "DataSampling/Dispatcher.h" #include "Framework/CompletionPolicyHelpers.h" #include "Framework/DataSpecUtils.h" #include "Framework/Logger.h" @@ -24,9 +24,10 @@ #include using namespace o2::configuration; +using namespace o2::framework; using SubSpecificationType = o2::header::DataHeader::SubSpecificationType; -namespace o2::framework +namespace o2::utilities { std::string DataSampling::createDispatcherName() @@ -194,4 +195,4 @@ std::vector DataSampling::MachinesForPolicy(const std::string& poli return MachinesForPolicy(config.get(), policyName); } -} // namespace o2::framework +} // namespace o2::utilities diff --git a/Framework/Core/src/DataSamplingConditionCustom.cxx b/Utilities/DataSampling/src/DataSamplingConditionCustom.cxx similarity index 93% rename from Framework/Core/src/DataSamplingConditionCustom.cxx rename to Utilities/DataSampling/src/DataSamplingConditionCustom.cxx index f02d9128df274..f9dca006e8b5b 100644 --- a/Framework/Core/src/DataSamplingConditionCustom.cxx +++ b/Utilities/DataSampling/src/DataSamplingConditionCustom.cxx @@ -13,8 +13,8 @@ /// /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#include "Framework/DataSamplingCondition.h" -#include "Framework/DataSamplingConditionFactory.h" +#include "DataSampling/DataSamplingCondition.h" +#include "DataSampling/DataSamplingConditionFactory.h" #include "Headers/DataHeader.h" #include @@ -24,7 +24,9 @@ #include #include -namespace o2::framework +using namespace o2::framework; + +namespace o2::utilities { /// \brief A DataSamplingCondition which makes decisions based on payload size. @@ -81,4 +83,4 @@ std::unique_ptr DataSamplingConditionFactory::createDataS return std::make_unique(); } -} // namespace o2::framework +} // namespace o2::utilities diff --git a/Framework/Core/src/DataSamplingConditionFactory.cxx b/Utilities/DataSampling/src/DataSamplingConditionFactory.cxx similarity index 90% rename from Framework/Core/src/DataSamplingConditionFactory.cxx rename to Utilities/DataSampling/src/DataSamplingConditionFactory.cxx index 251b4925320ec..94dc64bd746a4 100644 --- a/Framework/Core/src/DataSamplingConditionFactory.cxx +++ b/Utilities/DataSampling/src/DataSamplingConditionFactory.cxx @@ -16,9 +16,10 @@ #include #include -#include "Framework/DataSamplingConditionFactory.h" +#include "DataSampling/DataSamplingConditionFactory.h" +using namespace o2::framework; -namespace o2::framework +namespace o2::utilities { std::unique_ptr DataSamplingConditionFactory::create(std::string name) @@ -35,4 +36,4 @@ std::unique_ptr DataSamplingConditionFactory::create(std: throw std::runtime_error("DataSamplingCondition '" + name + "' unknown."); } -} // namespace o2::framework +} // namespace o2::utilities diff --git a/Framework/Core/src/DataSamplingConditionNConsecutive.cxx b/Utilities/DataSampling/src/DataSamplingConditionNConsecutive.cxx similarity index 92% rename from Framework/Core/src/DataSamplingConditionNConsecutive.cxx rename to Utilities/DataSampling/src/DataSamplingConditionNConsecutive.cxx index 4d42df42f4ae0..48f63f4c79e44 100644 --- a/Framework/Core/src/DataSamplingConditionNConsecutive.cxx +++ b/Utilities/DataSampling/src/DataSamplingConditionNConsecutive.cxx @@ -13,14 +13,16 @@ /// /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#include "Framework/DataSamplingCondition.h" -#include "Framework/DataSamplingConditionFactory.h" +#include "DataSampling/DataSamplingCondition.h" +#include "DataSampling/DataSamplingConditionFactory.h" #include "Framework/DataProcessingHeader.h" #include "Framework/Logger.h" #include -namespace o2::framework +using namespace o2::framework; + +namespace o2::utilities { using namespace o2::header; @@ -65,4 +67,4 @@ std::unique_ptr DataSamplingConditionFactory::createDataS return std::make_unique(); } -} // namespace o2::framework +} // namespace o2::utilities diff --git a/Framework/Core/src/DataSamplingConditionPayloadSize.cxx b/Utilities/DataSampling/src/DataSamplingConditionPayloadSize.cxx similarity index 91% rename from Framework/Core/src/DataSamplingConditionPayloadSize.cxx rename to Utilities/DataSampling/src/DataSamplingConditionPayloadSize.cxx index 5a5b1adc3582f..3afa25b0d4dbd 100644 --- a/Framework/Core/src/DataSamplingConditionPayloadSize.cxx +++ b/Utilities/DataSampling/src/DataSamplingConditionPayloadSize.cxx @@ -13,13 +13,15 @@ /// /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#include "Framework/DataSamplingCondition.h" -#include "Framework/DataSamplingConditionFactory.h" +#include "DataSampling/DataSamplingCondition.h" +#include "DataSampling/DataSamplingConditionFactory.h" #include "Headers/DataHeader.h" #include "Framework/Logger.h" #include -namespace o2::framework +using namespace o2::framework; + +namespace o2::utilities { using namespace o2::header; @@ -62,4 +64,4 @@ std::unique_ptr DataSamplingConditionFactory::createDataS return std::make_unique(); } -} // namespace o2::framework +} // namespace o2::utilities diff --git a/Framework/Core/src/DataSamplingConditionRandom.cxx b/Utilities/DataSampling/src/DataSamplingConditionRandom.cxx similarity index 93% rename from Framework/Core/src/DataSamplingConditionRandom.cxx rename to Utilities/DataSampling/src/DataSamplingConditionRandom.cxx index 60b7def97440c..48b00b929a9cb 100644 --- a/Framework/Core/src/DataSamplingConditionRandom.cxx +++ b/Utilities/DataSampling/src/DataSamplingConditionRandom.cxx @@ -13,15 +13,17 @@ /// /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#include "Framework/DataSamplingCondition.h" -#include "Framework/DataSamplingConditionFactory.h" +#include "DataSampling/DataSamplingCondition.h" +#include "DataSampling/DataSamplingConditionFactory.h" #include "Framework/DataProcessingHeader.h" #include "PCG/pcg_random.hpp" #include -namespace o2::framework +using namespace o2::framework; + +namespace o2::utilities { // todo: consider using run number as a seed @@ -82,4 +84,4 @@ std::unique_ptr DataSamplingConditionFactory::createDataS return std::make_unique(); } -} // namespace o2::framework +} // namespace o2::utilities diff --git a/Framework/Core/src/DataSamplingHeader.cxx b/Utilities/DataSampling/src/DataSamplingHeader.cxx similarity index 84% rename from Framework/Core/src/DataSamplingHeader.cxx rename to Utilities/DataSampling/src/DataSamplingHeader.cxx index b887e7b4fc787..95e21088a9df7 100644 --- a/Framework/Core/src/DataSamplingHeader.cxx +++ b/Utilities/DataSampling/src/DataSamplingHeader.cxx @@ -13,9 +13,9 @@ /// /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#include "Framework/DataSamplingHeader.h" +#include "DataSampling/DataSamplingHeader.h" -namespace o2::framework +namespace o2::utilities { DataSamplingHeader::DataSamplingHeader() : BaseHeader(sizeof(DataSamplingHeader), sHeaderType, sSerializationMethod, sVersion) @@ -37,8 +37,8 @@ const DataSamplingHeader* DataSamplingHeader::Get(const BaseHeader* baseHeader) } // storage for DataSamplingHeader static members -const uint32_t o2::framework::DataSamplingHeader::sVersion = 1; -const o2::header::HeaderType o2::framework::DataSamplingHeader::sHeaderType = header::String2("DataSamp"); -const o2::header::SerializationMethod o2::framework::DataSamplingHeader::sSerializationMethod = o2::header::gSerializationMethodNone; +const uint32_t o2::utilities::DataSamplingHeader::sVersion = 1; +const o2::header::HeaderType o2::utilities::DataSamplingHeader::sHeaderType = header::String2("DataSamp"); +const o2::header::SerializationMethod o2::utilities::DataSamplingHeader::sSerializationMethod = o2::header::gSerializationMethodNone; -} // namespace o2::framework \ No newline at end of file +} // namespace o2::utilities \ No newline at end of file diff --git a/Framework/Core/src/DataSamplingPolicy.cxx b/Utilities/DataSampling/src/DataSamplingPolicy.cxx similarity index 95% rename from Framework/Core/src/DataSamplingPolicy.cxx rename to Utilities/DataSampling/src/DataSamplingPolicy.cxx index 2a6684a16397c..a68fb6394f1af 100644 --- a/Framework/Core/src/DataSamplingPolicy.cxx +++ b/Utilities/DataSampling/src/DataSamplingPolicy.cxx @@ -13,15 +13,18 @@ /// /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#include "Framework/DataSamplingPolicy.h" -#include "Framework/DataSamplingHeader.h" -#include "Framework/DataSamplingConditionFactory.h" +#include "DataSampling/DataSamplingPolicy.h" +#include "DataSampling/DataSamplingHeader.h" +#include "DataSampling/DataSamplingConditionFactory.h" #include "Framework/DataSpecUtils.h" #include "Framework/DataDescriptorQueryBuilder.h" +#include "Framework/Logger.h" #include -namespace o2::framework +using namespace o2::framework; + +namespace o2::utilities { using boost::property_tree::ptree; @@ -165,4 +168,4 @@ header::DataDescription DataSamplingPolicy::createPolicyDataDescription(std::str return outputDescription; } -} // namespace o2::framework \ No newline at end of file +} // namespace o2::utilities diff --git a/Framework/Core/src/DataSamplingReadoutAdapter.cxx b/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx similarity index 92% rename from Framework/Core/src/DataSamplingReadoutAdapter.cxx rename to Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx index ed574c189679c..408adb7029d87 100644 --- a/Framework/Core/src/DataSamplingReadoutAdapter.cxx +++ b/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx @@ -7,14 +7,16 @@ // 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. -#include "Framework/DataSamplingReadoutAdapter.h" +#include "DataSampling/DataSamplingReadoutAdapter.h" #include "Framework/DataProcessingHeader.h" #include "Headers/DataHeader.h" #include "Framework/DataSpecUtils.h" #include -namespace o2::framework +using namespace o2::framework; + +namespace o2::utilities { using DataHeader = o2::header::DataHeader; @@ -42,4 +44,4 @@ InjectorFunction dataSamplingReadoutAdapter(OutputSpec const& spec) }; } -} // namespace o2::framework +} // namespace o2::utilities diff --git a/Framework/Core/src/Dispatcher.cxx b/Utilities/DataSampling/src/Dispatcher.cxx similarity index 97% rename from Framework/Core/src/Dispatcher.cxx rename to Utilities/DataSampling/src/Dispatcher.cxx index 275d02e96dd3b..9f517d207ff72 100644 --- a/Framework/Core/src/Dispatcher.cxx +++ b/Utilities/DataSampling/src/Dispatcher.cxx @@ -13,10 +13,10 @@ /// /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#include "Framework/Dispatcher.h" +#include "DataSampling/Dispatcher.h" #include "Framework/RawDeviceService.h" -#include "Framework/DataSamplingPolicy.h" -#include "Framework/DataSamplingHeader.h" +#include "DataSampling/DataSamplingPolicy.h" +#include "DataSampling/DataSamplingHeader.h" #include "Framework/DataProcessingHeader.h" #include "Framework/DataSpecUtils.h" #include "Framework/Logger.h" @@ -30,8 +30,9 @@ using namespace o2::configuration; using namespace o2::monitoring; +using namespace o2::framework; -namespace o2::framework +namespace o2::utilities { Dispatcher::Dispatcher(std::string name, const std::string reconfigurationSource) @@ -220,4 +221,4 @@ Outputs Dispatcher::getOutputSpecs() return outputs; } -} // namespace o2::framework +} // namespace o2::utilities diff --git a/Framework/TestWorkflows/src/dataSamplingBenchmark.cxx b/Utilities/DataSampling/test/dataSamplingBenchmark.cxx similarity index 98% rename from Framework/TestWorkflows/src/dataSamplingBenchmark.cxx rename to Utilities/DataSampling/test/dataSamplingBenchmark.cxx index cd111e16ae2f0..8d5773b9eeb75 100644 --- a/Framework/TestWorkflows/src/dataSamplingBenchmark.cxx +++ b/Utilities/DataSampling/test/dataSamplingBenchmark.cxx @@ -9,11 +9,12 @@ // or submit itself to any jurisdiction. #include "Framework/ConfigParamSpec.h" -#include "Framework/DataSampling.h" +#include "DataSampling/DataSampling.h" #include "Framework/CompletionPolicyHelpers.h" #include using namespace o2::framework; +using namespace o2::utilities; void customize(std::vector& policies) { @@ -62,12 +63,13 @@ void sysinfo(sysinfo* info) #include "Headers/DataHeader.h" #include "Framework/ControlService.h" -#include "Framework/DataSampling.h" -#include "Framework/DataSamplingPolicy.h" +#include "DataSampling/DataSampling.h" +#include "DataSampling/DataSamplingPolicy.h" #include "Framework/RawDeviceService.h" #include "Framework/runDataProcessing.h" using namespace o2::framework; +using namespace o2::utilities; using SubSpec = o2::header::DataHeader::SubSpecificationType; namespace bipc = ::boost::interprocess; diff --git a/Framework/TestWorkflows/src/dataSamplingParallel.cxx b/Utilities/DataSampling/test/dataSamplingParallel.cxx similarity index 96% rename from Framework/TestWorkflows/src/dataSamplingParallel.cxx rename to Utilities/DataSampling/test/dataSamplingParallel.cxx index b0b70f52567b7..280f2733f2920 100644 --- a/Framework/TestWorkflows/src/dataSamplingParallel.cxx +++ b/Utilities/DataSampling/test/dataSamplingParallel.cxx @@ -8,11 +8,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/DataSampling.h" +#include "DataSampling/DataSampling.h" #include using namespace o2::framework; +using namespace o2::utilities; void customize(std::vector& policies) { DataSampling::CustomizeInfrastructure(policies); @@ -24,7 +25,7 @@ void customize(std::vector& policies) #include "Framework/InputSpec.h" #include "Framework/DataProcessorSpec.h" -#include "Framework/DataSampling.h" +#include "DataSampling/DataSampling.h" #include "Framework/DataSpecUtils.h" #include "Framework/ParallelContext.h" #include "Framework/runDataProcessing.h" @@ -97,8 +98,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) DataProcessorSpec simpleQcTask{ "simpleQcTask", Inputs{ - { "TPC_CLUSTERS_S", { "DS", "simpleQcTask-0" } }, - { "TPC_CLUSTERS_P_S", { "DS", "simpleQcTask-1" } } + { "TPC_CLUSTERS_S", { "DS", "simpleQcTask0" } }, + { "TPC_CLUSTERS_P_S", { "DS", "simpleQcTask1" } } }, Outputs{}, AlgorithmSpec{ diff --git a/Framework/TestWorkflows/src/dataSamplingPodAndRoot.cxx b/Utilities/DataSampling/test/dataSamplingPodAndRoot.cxx similarity index 96% rename from Framework/TestWorkflows/src/dataSamplingPodAndRoot.cxx rename to Utilities/DataSampling/test/dataSamplingPodAndRoot.cxx index 17b49d7c084b7..eeb8220985119 100644 --- a/Framework/TestWorkflows/src/dataSamplingPodAndRoot.cxx +++ b/Utilities/DataSampling/test/dataSamplingPodAndRoot.cxx @@ -9,10 +9,12 @@ // or submit itself to any jurisdiction. #include "Framework/RootSerializationSupport.h" -#include "Framework/DataSampling.h" +#include "DataSampling/DataSampling.h" #include using namespace o2::framework; +using namespace o2::utilities; + void customize(std::vector& policies) { DataSampling::CustomizeInfrastructure(policies); @@ -26,7 +28,7 @@ void customize(std::vector& policies) #include "Framework/DataProcessorSpec.h" #include "Framework/runDataProcessing.h" #include "Framework/TMessageSerializer.h" -#include "Framework/DataSamplingHeader.h" +#include "DataSampling/DataSamplingHeader.h" #include "Framework/Logger.h" #include #include @@ -85,8 +87,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) DataProcessorSpec qcTaskTpc{ "qcTaskTpc", Inputs{ - { "TPC_CLUSTERS_S", {"DS", "simpleQcTask-0"}}, - { "TPC_CLUSTERS_P_S", {"DS", "simpleQcTask-1"}} + { "TPC_CLUSTERS_S", {"DS", "simpleQcTask0"}}, + { "TPC_CLUSTERS_P_S", {"DS", "simpleQcTask1"}} }, Outputs{}, AlgorithmSpec{ @@ -178,8 +180,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) DataProcessorSpec rootQcTask{ "rootQcTask", { - InputSpec{ "TST_HISTOS_S", {"DS", "rootQcTask-0"}}, - InputSpec{ "TST_STRING_S", {"DS", "rootQcTask-1"}}, + InputSpec{ "TST_HISTOS_S", {"DS", "rootQcTask0"}}, + InputSpec{ "TST_STRING_S", {"DS", "rootQcTask1"}}, }, Outputs{}, AlgorithmSpec{ diff --git a/Framework/TestWorkflows/src/dataSamplingTimePipeline.cxx b/Utilities/DataSampling/test/dataSamplingTimePipeline.cxx similarity index 96% rename from Framework/TestWorkflows/src/dataSamplingTimePipeline.cxx rename to Utilities/DataSampling/test/dataSamplingTimePipeline.cxx index 255d5773f3de3..c5cc028d14c81 100644 --- a/Framework/TestWorkflows/src/dataSamplingTimePipeline.cxx +++ b/Utilities/DataSampling/test/dataSamplingTimePipeline.cxx @@ -8,11 +8,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/DataSampling.h" +#include "DataSampling/DataSampling.h" #include using namespace o2::framework; +using namespace o2::utilities; + void customize(std::vector& policies) { DataSampling::CustomizeInfrastructure(policies); @@ -24,7 +26,7 @@ void customize(std::vector& policies) #include "Framework/InputSpec.h" #include "Framework/DataProcessorSpec.h" -#include "Framework/DataSampling.h" +#include "DataSampling/DataSampling.h" #include "Framework/ParallelContext.h" #include "Framework/runDataProcessing.h" @@ -83,8 +85,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) DataProcessorSpec simpleQcTask{ "simpleQcTask", Inputs{ - { "TPC_CLUSTERS_S", { "DS", "simpleQcTask-0" } }, - { "TPC_CLUSTERS_P_S", { "DS", "simpleQcTask-1" } } + { "TPC_CLUSTERS_S", { "DS", "simpleQcTask0" } }, + { "TPC_CLUSTERS_P_S", { "DS", "simpleQcTask1" } } }, Outputs{}, AlgorithmSpec{ diff --git a/Framework/Core/test/test_DataSampling.cxx b/Utilities/DataSampling/test/test_DataSampling.cxx similarity index 98% rename from Framework/Core/test/test_DataSampling.cxx rename to Utilities/DataSampling/test/test_DataSampling.cxx index ecbd1414f5308..7d667768f6647 100644 --- a/Framework/Core/test/test_DataSampling.cxx +++ b/Utilities/DataSampling/test/test_DataSampling.cxx @@ -13,10 +13,10 @@ #include -#include "Framework/DataSampling.h" +#include "DataSampling/DataSampling.h" #include "Framework/DataProcessingHeader.h" #include "Framework/ExternalFairMQDeviceProxy.h" -#include "Framework/DataSamplingReadoutAdapter.h" +#include "DataSampling/DataSamplingReadoutAdapter.h" #include "Framework/DataSpecUtils.h" #include "Headers/DataHeader.h" @@ -24,6 +24,7 @@ #include using namespace o2::framework; +using namespace o2::utilities; using namespace o2::configuration; using DataHeader = o2::header::DataHeader; diff --git a/Framework/Core/test/test_DataSampling.json b/Utilities/DataSampling/test/test_DataSampling.json similarity index 100% rename from Framework/Core/test/test_DataSampling.json rename to Utilities/DataSampling/test/test_DataSampling.json diff --git a/Framework/Core/test/test_DataSamplingCondition.cxx b/Utilities/DataSampling/test/test_DataSamplingCondition.cxx similarity index 98% rename from Framework/Core/test/test_DataSamplingCondition.cxx rename to Utilities/DataSampling/test/test_DataSamplingCondition.cxx index e8fe6d7bb6f17..8b77e299df5e7 100644 --- a/Framework/Core/test/test_DataSamplingCondition.cxx +++ b/Utilities/DataSampling/test/test_DataSamplingCondition.cxx @@ -15,13 +15,14 @@ #include #include -#include "Framework/DataSamplingConditionFactory.h" +#include "DataSampling/DataSamplingConditionFactory.h" #include "Framework/DataRef.h" #include "Framework/DataProcessingHeader.h" #include "Headers/DataHeader.h" #include "Headers/Stack.h" using namespace o2::framework; +using namespace o2::utilities; using namespace o2::header; BOOST_AUTO_TEST_CASE(DataSamplingConditionRandom) diff --git a/Framework/Core/test/test_DataSamplingHeader.cxx b/Utilities/DataSampling/test/test_DataSamplingHeader.cxx similarity index 97% rename from Framework/Core/test/test_DataSamplingHeader.cxx rename to Utilities/DataSampling/test/test_DataSamplingHeader.cxx index 1ff6d6fbff3af..44c26270572ba 100644 --- a/Framework/Core/test/test_DataSamplingHeader.cxx +++ b/Utilities/DataSampling/test/test_DataSamplingHeader.cxx @@ -13,11 +13,11 @@ #include -#include "Framework/DataSamplingHeader.h" +#include "DataSampling/DataSamplingHeader.h" #include "Headers/Stack.h" #include "Headers/DataHeader.h" -using namespace o2::framework; +using namespace o2::utilities; using namespace o2::header; BOOST_AUTO_TEST_CASE(DataSamplingHeaderDefault) diff --git a/Framework/Core/test/test_DataSamplingPolicy.cxx b/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx similarity index 97% rename from Framework/Core/test/test_DataSamplingPolicy.cxx rename to Utilities/DataSampling/test/test_DataSamplingPolicy.cxx index b4ff8846331ec..4e81c58868aa0 100644 --- a/Framework/Core/test/test_DataSamplingPolicy.cxx +++ b/Utilities/DataSampling/test/test_DataSamplingPolicy.cxx @@ -14,11 +14,12 @@ #include #include -#include "Framework/DataSamplingPolicy.h" +#include "DataSampling/DataSamplingPolicy.h" #include "Framework/DataRef.h" #include "Framework/DataProcessingHeader.h" using namespace o2::framework; +using namespace o2::utilities; // an example of DataSamplingPolicy JSON object // { diff --git a/Utilities/Mergers/src/FullHistoryMerger.cxx b/Utilities/Mergers/src/FullHistoryMerger.cxx index be2569545b8b4..9504e603e2246 100644 --- a/Utilities/Mergers/src/FullHistoryMerger.cxx +++ b/Utilities/Mergers/src/FullHistoryMerger.cxx @@ -20,7 +20,7 @@ #include "Headers/DataHeader.h" #include "Framework/InputRecordWalker.h" - +#include "Framework/Logger.h" #include using namespace o2::header; diff --git a/Utilities/Mergers/src/IntegratingMerger.cxx b/Utilities/Mergers/src/IntegratingMerger.cxx index 046b804496b3a..0607e0e78888b 100644 --- a/Utilities/Mergers/src/IntegratingMerger.cxx +++ b/Utilities/Mergers/src/IntegratingMerger.cxx @@ -21,6 +21,7 @@ #include #include "Framework/InputRecordWalker.h" +#include "Framework/Logger.h" //#include "Framework/DataRef.h" //using namespace o2; diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index 7f00bd28c0b29..2842c256a7b08 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -46,6 +46,7 @@ list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST Detectors/TOF/prototyping/ConvertRun2CalibrationToO2.C Generators/share/external/hijing.C Generators/share/external/QEDepem.C + Generators/share/external/GenCosmics.C macro/SetIncludePath.C macro/loadExtDepLib.C macro/load_all_libs.C @@ -61,6 +62,7 @@ if(NOT BUILD_SIMULATION) o2_get_list_of_macros(${CMAKE_SOURCE_DIR}/Detectors/gconfig macros) list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST ${macros}) list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST Generators/share/external/QEDLoader.C) + list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST Generators/share/external/GenCosmicsLoader.C) list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST Generators/share/egconfig/pythia8_userhooks_charm.C) list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST Generators/share/external/trigger_mpi.C) endif() diff --git a/macro/build_geometry.C b/macro/build_geometry.C index 5628ff0b512fb..60f63e53834ff 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -88,27 +88,7 @@ void build_geometry(FairRunSim* run = nullptr) run->SetMaterials("media.geo"); // Materials // we need a field to properly init the media - int fld = confref.getConfigData().mField, fldAbs = std::abs(fld); - float fldCoeff; - o2::field::MagFieldParam::BMap_t fldType; - switch (fldAbs) { - case 5: - fldType = o2::field::MagFieldParam::k5kG; - fldCoeff = fld > 0 ? 1. : -1; - break; - case 0: - fldType = o2::field::MagFieldParam::k5kG; - fldCoeff = 0; - break; - case 2: - fldType = o2::field::MagFieldParam::k2kG; - fldCoeff = fld > 0 ? 1. : -1; - break; - default: - LOG(FATAL) << "Field option " << fld << " is not supported, use +-2, +-5 or 0"; - }; - - auto field = new o2::field::MagneticField("Maps", "Maps", fldCoeff, fldCoeff, fldType); + auto field = o2::field::MagneticField::createNominalField(confref.getConfigData().mField); run->SetField(field); // Create geometry diff --git a/run/O2PrimaryServerDevice.h b/run/O2PrimaryServerDevice.h index 9af897b5131a8..655b3fae8b815 100644 --- a/run/O2PrimaryServerDevice.h +++ b/run/O2PrimaryServerDevice.h @@ -27,6 +27,8 @@ #include #include #include +#include "Field/MagneticField.h" +#include #include #include #include @@ -60,6 +62,12 @@ class O2PrimaryServerDevice final : public FairMQDevice TStopwatch timer; timer.Start(); auto& conf = o2::conf::SimConfig::Instance(); + + // init magnetic field as it might be needed by the generator + auto field = o2::field::MagneticField::createNominalField(conf.getConfigData().mField); + TGeoGlobalMagField::Instance()->SetField(field); + TGeoGlobalMagField::Instance()->Lock(); + o2::eventgen::GeneratorFactory::setPrimaryGenerator(conf, &mPrimGen); mPrimGen.SetEvent(&mEventHeader); diff --git a/scripts/profile-compilation-merge b/scripts/profile-compilation-merge new file mode 100755 index 0000000000000..85dadd1cfea4b --- /dev/null +++ b/scripts/profile-compilation-merge @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +"""Combine JSON from multiple -ftime-traces into one. + +scripts/profile-compilation-merge foo.json bar.json. + +results in ./combined.json +""" + +import json +import sys + +if __name__ == '__main__': + start_time = 0 + combined_data = [] + for filename in sys.argv[1:]: + with open(filename, 'r') as f: + file_time = None + for event in json.load(f)['traceEvents']: + # Skip metadata events + # Skip total events + # Filter out shorter events to reduce data size + if event['ph'] == 'M' or \ + event['name'].startswith('Total') or \ + event['dur'] < 5000: + continue + + if event['name'] == 'ExecuteCompiler': + # Find how long this compilation takes + file_time = event['dur'] + # Set the file name in ExecuteCompiler + #event['args']['detail'] = filename + + # Offset start time to make compiles sequential + event['ts'] += start_time + + # Add data to combined + combined_data.append(event) + + # Increase the start time for the next file + # Add 1 to avoid issues with simultaneous events + start_time += file_time + 1 + + with open('combined.json', 'w') as f: + json.dump({'traceEvents': sorted(combined_data, key=lambda k: k['ts'])}, f)